Skip to content

Commit 24655a2

Browse files
committed
feat(cli): ignite tenant on install
1 parent e4ab127 commit 24655a2

7 files changed

Lines changed: 89 additions & 16 deletions

File tree

.github/workflows/cli-ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: ⎔ Setup bun
2121
uses: oven-sh/setup-bun@v2
2222
with:
23-
bun-version: latest
23+
bun-version: 1.1.45
2424

2525
- name: 📥 Download deps
2626
working-directory: components/cli

components/cli/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

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

5+
## [5.3.0]
6+
7+
- fix tenantId that was not setup on the .env file after installation
8+
- add discovery api tenant ignition
9+
510
## [5.2.2]
611

712
- fix bug introduced in the 5.2.1 for tenant create command

components/cli/Makefile

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
YELLOW=$(shell echo "\033[00;33m")
55
RED=$(shell echo "\033[00;31m")
66
RESTORE=$(shell echo "\033[0m")
7+
BUN=bun
8+
# BUN=/opt/homebrew/Cellar/bun@1.1.45/1.1.45/bin/bun
79

810
.DEFAULT_GOAL := list
911

@@ -16,23 +18,32 @@ list:
1618

1719
.PHONY: codeclean
1820
codeclean: ## Code Clean
19-
@bun prettier --write .
21+
@$(BUN) prettier --write .
22+
23+
.PHONY: run
24+
run: ## Run ARGS=""
25+
@LOG_LEVELS=info,debug $(BUN) src/index.ts $$ARGS
26+
27+
28+
.PHONY: staging-run
29+
staging-run: ## Run ARGS=""
30+
@CRYSTALLIZE_ENVIRONMENT=staging LOG_LEVELS=info,debug $(BUN) src/index.ts $$ARGS
2031

2132
.PHONY: build
2233
build: ## Build
23-
@bun build --bundle src/index.ts --outfile crystallize.js --target=bun
24-
@bun shim.ts
25-
@bun build --compile --minify crystallize.js --outfile crystallize
34+
@$(BUN) build --bundle src/index.ts --outfile crystallize.js --target=bun
35+
@$(BUN) shim.ts
36+
@$(BUN) build --compile --minify crystallize.js --outfile crystallize
2637
@rm crystallize.js
2738
@rm -f ./.*.bun-build
2839

2940

3041
.PHONY: build-all
3142
build-all:
32-
@bun build --bundle src/index.ts --outfile crystallize.js --target=bun
33-
@bun shim.ts
43+
@$(BUN) build --bundle src/index.ts --outfile crystallize.js --target=bun
44+
@$(BUN) shim.ts
3445
for target in bun-linux-x64 bun-linux-arm64 bun-windows-x64 bun-darwin-x64 bun-darwin-arm64; do \
35-
bun build --compile --minify crystallize.js --outfile crystallize-$$target --target=$$target; \
46+
$(BUN) build --compile --minify crystallize.js --outfile crystallize-$$target --target=$$target; \
3647
done
3748
@rm crystallize.js
3849
@rm -f ./.*.bun-build

components/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@crystallize/cli",
3-
"version": "5.2.2",
3+
"version": "5.3.0",
44
"description": "Crystallize CLI",
55
"module": "src/index.ts",
66
"repository": "https://github.com/CrystallizeAPI/crystallize-cli",

components/cli/src/domain/use-cases/create-clean-tenant.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import type { FlySystem } from '../contracts/fly-system';
99
import type { Operations } from '@crystallize/schema/mass-operation';
1010
import type { Logger } from '../contracts/logger';
1111
import { getMassOperationBulkTask } from '../../command/mass-operation/run';
12+
import type { InstallBoilerplateStore } from '../../ui/journeys/install-boilerplate/create-store';
1213

1314
type Deps = {
1415
createCrystallizeClient: typeof createClient;
1516
runMassOperation: ReturnType<typeof createRunMassOperationHandler>;
1617
credentialsRetriever: CredentialRetriever;
18+
crystallizeEnvironment: 'staging' | 'production';
19+
installBoilerplateCommandStore: InstallBoilerplateStore;
1720
flySystem: FlySystem;
1821
logger: Logger;
1922
};
@@ -29,13 +32,27 @@ export type CreateCleanTenantHandlerDefinition = CommandHandlerDefinition<
2932
Awaited<ReturnType<typeof handler>>
3033
>;
3134

35+
const sleep = (second: number) => new Promise((resolve) => setTimeout(resolve, second * 1000));
36+
3237
const handler = async (
3338
envelope: Envelope<Command>,
34-
{ createCrystallizeClient, credentialsRetriever, runMassOperation, flySystem, logger }: Deps,
39+
{
40+
createCrystallizeClient,
41+
credentialsRetriever,
42+
runMassOperation,
43+
flySystem,
44+
logger,
45+
crystallizeEnvironment,
46+
installBoilerplateCommandStore,
47+
}: Deps,
3548
): Promise<{
3649
id: string;
3750
identifier: string;
3851
}> => {
52+
const { storage, atoms } = installBoilerplateCommandStore;
53+
const addTraceLog = (log: string) => storage.set(atoms.addTraceLogAtom, log);
54+
const addTraceError = (log: string) => storage.set(atoms.addTraceErrorAtom, log);
55+
3956
const { tenant, credentials } = envelope.message;
4057
const finalCredentials = credentials || (await credentialsRetriever.getCredentials());
4158
const client = createCrystallizeClient({
@@ -67,6 +84,7 @@ const handler = async (
6784
},
6885
);
6986
const { id, identifier } = createResult.tenant.create;
87+
addTraceLog(`Tenant created with id: ${id}.`);
7088
const shapeIdentifiers = ['default-product', 'default-folder', 'default-document'];
7189
const mutation = {
7290
shape: shapeIdentifiers.reduce((memo: Record<string, any>, shapeIdentifier: string) => {
@@ -85,6 +103,7 @@ const handler = async (
85103
};
86104
const query = jsonToGraphQLQuery({ mutation });
87105
await client.pimApi(query);
106+
addTraceLog(`Shape cleaned.`);
88107

89108
// if we have a folder, we check that folder for .crystallize folder and convention
90109
const { folder } = envelope.message;
@@ -115,18 +134,23 @@ const handler = async (
115134
},
116135
} as Envelope<RunMassOperationCommand>);
117136
logger.debug('Mass operation task created', startedTask);
137+
addTraceLog(`Mass operation task created: ${startedTask?.id}`);
138+
await sleep(10); // we have an easy 10 sec sleep here to let the task start
118139
while (startedTask?.status !== 'complete') {
119-
await new Promise((resolve) => setTimeout(resolve, 1000));
120140
const get = await cClient.nextPimApi(getMassOperationBulkTask, { id: startedTask?.id });
121141
if (get.bulkTask.error) {
122142
throw new Error(get.data.bulkTask.error);
123143
}
124144
startedTask = get.bulkTask;
145+
await sleep(3); // then we check every 3 seconds
125146
}
126147
} catch (e) {
148+
addTraceError(`Failed to run mass operation.`);
127149
logger.error('Failed to run mass operation', e);
128150
}
151+
addTraceLog(`Mass operation completed.`);
129152

153+
// now the extra mutations
130154
try {
131155
const results = await cClient.pimApi(`#graphql
132156
query {
@@ -156,15 +180,32 @@ const handler = async (
156180
}[];
157181

158182
for (const { mutation, sets } of Object.values(extraMutations)) {
159-
await Promise.all([
183+
await Promise.all(
160184
sets.map(async (set) => {
161185
await cClient.pimApi(mutation, set);
162186
}),
163-
]);
187+
);
164188
}
165189
} catch (e) {
190+
addTraceError(`Failed to run extra mutations.`);
166191
logger.error('Failed to run extra mutations', e);
167192
}
193+
194+
// now the index
195+
await cClient.nextPimApi(`mutation { igniteTenant }`);
196+
// check the 404
197+
198+
const discoHost = crystallizeEnvironment === 'staging' ? 'api-dev.crystallize.digital' : 'api.crystallize.com';
199+
let discoApiPingResponseCode = 404;
200+
201+
await sleep(15); // easy 15 sec sleep to let the index finish
202+
do {
203+
const discoApiPingResponse = await fetch(`https://${discoHost}/${identifier}/discovery`);
204+
discoApiPingResponseCode = discoApiPingResponse.status;
205+
sleep(5); // then every 5 seconds
206+
} while (discoApiPingResponseCode === 404);
207+
208+
addTraceLog(`Tenant ignited in Discovery API.`);
168209
return {
169210
id,
170211
identifier,

components/cli/src/domain/use-cases/setup-boilerplate-project.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import type { Logger } from '../contracts/logger';
66
import type { Runner } from '../../core/create-runner';
77
import type { InstallBoilerplateStore } from '../../ui/journeys/install-boilerplate/create-store';
88
import type { CredentialRetriever } from '../contracts/credential-retriever';
9+
import type { createClient } from '@crystallize/js-api-client';
910

1011
type Deps = {
1112
flySystem: FlySystem;
1213
logger: Logger;
1314
runner: Runner;
1415
installBoilerplateCommandStore: InstallBoilerplateStore;
1516
credentialsRetriever: CredentialRetriever;
17+
createCrystallizeClient: typeof createClient;
1618
};
1719

1820
type Command = {
@@ -28,7 +30,7 @@ export type SetupBoilerplateProjectHandlerDefinition = CommandHandlerDefinition<
2830
>;
2931

3032
const handler = async (envelope: Envelope<Command>, deps: Deps) => {
31-
const { flySystem, logger, runner, installBoilerplateCommandStore } = deps;
33+
const { flySystem, logger, runner, installBoilerplateCommandStore, createCrystallizeClient } = deps;
3234
const { folder, tenant, credentials } = envelope.message;
3335
const { storage, atoms } = installBoilerplateCommandStore;
3436

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

4244
logger.log(`Setting up boilerplate project in ${folder} for tenant ${tenant.identifier}`);
45+
const apiClient = createCrystallizeClient({
46+
tenantIdentifier: tenant.identifier,
47+
accessTokenId: finalCredentials?.ACCESS_TOKEN_ID,
48+
accessTokenSecret: finalCredentials?.ACCESS_TOKEN_SECRET,
49+
});
50+
51+
// let's get the Tenant Id
52+
const tenantInfo = await apiClient.nextPimApi(
53+
`query { tenant(identifier:"${tenant.identifier}") { ... on Tenant { id } } }`,
54+
);
55+
const tenantId = tenantInfo.tenant.id;
4356

4457
if (await flySystem.isFileExists(`${crytallizeHiddenFolder}/env`)) {
4558
try {
@@ -50,7 +63,7 @@ const handler = async (envelope: Envelope<Command>, deps: Deps) => {
5063
},
5164
{
5265
search: '##CRYSTALLIZE_TENANT_ID##',
53-
replace: '',
66+
replace: tenantId,
5467
},
5568
{
5669
search: '##CRYSTALLIZE_TENANT_IDENTIFIER##',

components/cli/src/ui/journeys/install-boilerplate/actions/execute-recipes.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ const feedbacks = [
1414
'Preparing files for install...',
1515
'Installing...',
1616
'Still installing...',
17+
'Setting up tenant...',
18+
'Discovering the meaning of life...',
1719
'Daydreaming...',
20+
'Indexing...',
1821
'Growing that node_modules...',
1922
'Looking for car keys...',
2023
'Looking for the car...',
@@ -87,7 +90,7 @@ export const ExecuteRecipes = ({ store, commandBus, logger }: ExecuteRecipesProp
8790
<>
8891
<Text>
8992
<Spinner />
90-
Importing tenant data
93+
Importing tenant data, it can take several minutes...
9194
</Text>
9295
</>
9396
)}

0 commit comments

Comments
 (0)