Skip to content

Commit

Permalink
feat(cli): ignite tenant on install
Browse files Browse the repository at this point in the history
  • Loading branch information
Plopix committed Feb 3, 2025
1 parent 22070d6 commit 870cfb8
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 15 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project will be documented in this file.

## [5.3.0]

- fix tenantId that was not setup on the .env file after installation
- add discovery api tenant ignition

## [5.2.2]

- fix bug introduced in the 5.2.1 for tenant create command
Expand Down
25 changes: 18 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
YELLOW=$(shell echo "\033[00;33m")
RED=$(shell echo "\033[00;31m")
RESTORE=$(shell echo "\033[0m")
BUN=bun
# BUN=/opt/homebrew/Cellar/bun@1.1.45/1.1.45/bin/bun

.DEFAULT_GOAL := list

Expand All @@ -16,23 +18,32 @@ list:

.PHONY: codeclean
codeclean: ## Code Clean
@bun prettier --write .
@$(BUN) prettier --write .

.PHONY: run
run: ## Run ARGS=""
@LOG_LEVELS=info,debug $(BUN) src/index.ts $$ARGS


.PHONY: staging-run
staging-run: ## Run ARGS=""
@CRYSTALLIZE_ENVIRONMENT=staging LOG_LEVELS=info,debug $(BUN) src/index.ts $$ARGS

.PHONY: build
build: ## Build
@bun build --bundle src/index.ts --outfile crystallize.js --target=bun
@bun shim.ts
@bun build --compile --minify crystallize.js --outfile crystallize
@$(BUN) build --bundle src/index.ts --outfile crystallize.js --target=bun
@$(BUN) shim.ts
@$(BUN) build --compile --minify crystallize.js --outfile crystallize
@rm crystallize.js
@rm -f ./.*.bun-build


.PHONY: build-all
build-all:
@bun build --bundle src/index.ts --outfile crystallize.js --target=bun
@bun shim.ts
@$(BUN) build --bundle src/index.ts --outfile crystallize.js --target=bun
@$(BUN) shim.ts
for target in bun-linux-x64 bun-linux-arm64 bun-windows-x64 bun-darwin-x64 bun-darwin-arm64; do \
bun build --compile --minify crystallize.js --outfile crystallize-$$target --target=$$target; \
$(BUN) build --compile --minify crystallize.js --outfile crystallize-$$target --target=$$target; \
done
@rm crystallize.js
@rm -f ./.*.bun-build
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@crystallize/cli",
"version": "5.2.2",
"version": "5.3.0",
"description": "Crystallize CLI",
"module": "src/index.ts",
"repository": "https://github.com/CrystallizeAPI/crystallize-cli",
Expand Down
49 changes: 45 additions & 4 deletions src/domain/use-cases/create-clean-tenant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import type { FlySystem } from '../contracts/fly-system';
import type { Operations } from '@crystallize/schema/mass-operation';
import type { Logger } from '../contracts/logger';
import { getMassOperationBulkTask } from '../../command/mass-operation/run';
import type { InstallBoilerplateStore } from '../../ui/journeys/install-boilerplate/create-store';

type Deps = {
createCrystallizeClient: typeof createClient;
runMassOperation: ReturnType<typeof createRunMassOperationHandler>;
credentialsRetriever: CredentialRetriever;
crystallizeEnvironment: 'staging' | 'production';
installBoilerplateCommandStore: InstallBoilerplateStore;
flySystem: FlySystem;
logger: Logger;
};
Expand All @@ -29,13 +32,27 @@ export type CreateCleanTenantHandlerDefinition = CommandHandlerDefinition<
Awaited<ReturnType<typeof handler>>
>;

const sleep = (second: number) => new Promise((resolve) => setTimeout(resolve, second * 1000));

const handler = async (
envelope: Envelope<Command>,
{ createCrystallizeClient, credentialsRetriever, runMassOperation, flySystem, logger }: Deps,
{
createCrystallizeClient,
credentialsRetriever,
runMassOperation,
flySystem,
logger,
crystallizeEnvironment,
installBoilerplateCommandStore,
}: Deps,
): Promise<{
id: string;
identifier: string;
}> => {
const { storage, atoms } = installBoilerplateCommandStore;
const addTraceLog = (log: string) => storage.set(atoms.addTraceLogAtom, log);
const addTraceError = (log: string) => storage.set(atoms.addTraceErrorAtom, log);

const { tenant, credentials } = envelope.message;
const finalCredentials = credentials || (await credentialsRetriever.getCredentials());
const client = createCrystallizeClient({
Expand Down Expand Up @@ -67,6 +84,7 @@ const handler = async (
},
);
const { id, identifier } = createResult.tenant.create;
addTraceLog(`Tenant created with id: ${id}.`);
const shapeIdentifiers = ['default-product', 'default-folder', 'default-document'];
const mutation = {
shape: shapeIdentifiers.reduce((memo: Record<string, any>, shapeIdentifier: string) => {
Expand All @@ -85,6 +103,7 @@ const handler = async (
};
const query = jsonToGraphQLQuery({ mutation });
await client.pimApi(query);
addTraceLog(`Shape cleaned.`);

// if we have a folder, we check that folder for .crystallize folder and convention
const { folder } = envelope.message;
Expand Down Expand Up @@ -115,18 +134,23 @@ const handler = async (
},
} as Envelope<RunMassOperationCommand>);
logger.debug('Mass operation task created', startedTask);
addTraceLog(`Mass operation task created: ${startedTask?.id}`);
await sleep(10); // we have an easy 10 sec sleep here to let the task start
while (startedTask?.status !== 'complete') {
await new Promise((resolve) => setTimeout(resolve, 1000));
const get = await cClient.nextPimApi(getMassOperationBulkTask, { id: startedTask?.id });
if (get.bulkTask.error) {
throw new Error(get.data.bulkTask.error);
}
startedTask = get.bulkTask;
await sleep(3); // then we check every 3 seconds
}
} catch (e) {
addTraceError(`Failed to run mass operation.`);
logger.error('Failed to run mass operation', e);
}
addTraceLog(`Mass operation completed.`);

// now the extra mutations
try {
const results = await cClient.pimApi(`#graphql
query {
Expand Down Expand Up @@ -156,15 +180,32 @@ const handler = async (
}[];

for (const { mutation, sets } of Object.values(extraMutations)) {
await Promise.all([
await Promise.all(
sets.map(async (set) => {
await cClient.pimApi(mutation, set);
}),
]);
);
}
} catch (e) {
addTraceError(`Failed to run extra mutations.`);
logger.error('Failed to run extra mutations', e);
}

// now the index
await cClient.nextPimApi(`mutation { igniteTenant }`);
// check the 404

const discoHost = crystallizeEnvironment === 'staging' ? 'api-dev.crystallize.digital' : 'api.crystallize.com';
let discoApiPingResponseCode = 404;

await sleep(15); // easy 15 sec sleep to let the index finish
do {
const discoApiPingResponse = await fetch(`https://${discoHost}/${identifier}/discovery`);
discoApiPingResponseCode = discoApiPingResponse.status;
sleep(5); // then every 5 seconds
} while (discoApiPingResponseCode === 404);

addTraceLog(`Tenant ignited in Discovery API.`);
return {
id,
identifier,
Expand Down
17 changes: 15 additions & 2 deletions src/domain/use-cases/setup-boilerplate-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import type { Logger } from '../contracts/logger';
import type { Runner } from '../../core/create-runner';
import type { InstallBoilerplateStore } from '../../ui/journeys/install-boilerplate/create-store';
import type { CredentialRetriever } from '../contracts/credential-retriever';
import type { createClient } from '@crystallize/js-api-client';

type Deps = {
flySystem: FlySystem;
logger: Logger;
runner: Runner;
installBoilerplateCommandStore: InstallBoilerplateStore;
credentialsRetriever: CredentialRetriever;
createCrystallizeClient: typeof createClient;
};

type Command = {
Expand All @@ -28,7 +30,7 @@ export type SetupBoilerplateProjectHandlerDefinition = CommandHandlerDefinition<
>;

const handler = async (envelope: Envelope<Command>, deps: Deps) => {
const { flySystem, logger, runner, installBoilerplateCommandStore } = deps;
const { flySystem, logger, runner, installBoilerplateCommandStore, createCrystallizeClient } = deps;
const { folder, tenant, credentials } = envelope.message;
const { storage, atoms } = installBoilerplateCommandStore;

Expand All @@ -40,6 +42,17 @@ const handler = async (envelope: Envelope<Command>, deps: Deps) => {
const finalCredentials = credentials || (await deps.credentialsRetriever.getCredentials());

logger.log(`Setting up boilerplate project in ${folder} for tenant ${tenant.identifier}`);
const apiClient = createCrystallizeClient({
tenantIdentifier: tenant.identifier,
accessTokenId: finalCredentials?.ACCESS_TOKEN_ID,
accessTokenSecret: finalCredentials?.ACCESS_TOKEN_SECRET,
});

// let's get the Tenant Id
const tenantInfo = await apiClient.nextPimApi(
`query { tenant(identifier:"${tenant.identifier}") { ... on Tenant { id } } }`,
);
const tenantId = tenantInfo.tenant.id;

if (await flySystem.isFileExists(`${crytallizeHiddenFolder}/env`)) {
try {
Expand All @@ -50,7 +63,7 @@ const handler = async (envelope: Envelope<Command>, deps: Deps) => {
},
{
search: '##CRYSTALLIZE_TENANT_ID##',
replace: '',
replace: tenantId,
},
{
search: '##CRYSTALLIZE_TENANT_IDENTIFIER##',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ const feedbacks = [
'Preparing files for install...',
'Installing...',
'Still installing...',
'Setting up tenant...',
'Discovering the meaning of life...',
'Daydreaming...',
'Indexing...',
'Growing that node_modules...',
'Looking for car keys...',
'Looking for the car...',
Expand Down Expand Up @@ -87,7 +90,7 @@ export const ExecuteRecipes = ({ store, commandBus, logger }: ExecuteRecipesProp
<>
<Text>
<Spinner />
Importing tenant data
Importing tenant data, it can take several minutes...
</Text>
</>
)}
Expand Down

0 comments on commit 870cfb8

Please sign in to comment.