Skip to content

Commit 82266e0

Browse files
Merge pull request #10 from contentstack/fix/enh-4442
Fixed seed command for existing stack
2 parents d03658d + a50257d commit 82266e0

File tree

12 files changed

+99
-73
lines changed

12 files changed

+99
-73
lines changed

packages/contentstack-bootstrap/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $ npm install -g @contentstack/cli-cm-bootstrap
1515
$ csdx COMMAND
1616
running command...
1717
$ csdx (--version)
18-
@contentstack/cli-cm-bootstrap/1.18.2 darwin-arm64 node-v24.13.0
18+
@contentstack/cli-cm-bootstrap/1.18.4 darwin-arm64 node-v22.14.0
1919
$ csdx --help [COMMAND]
2020
USAGE
2121
$ csdx COMMAND
@@ -44,14 +44,14 @@ Bootstrap contentstack apps
4444

4545
```
4646
USAGE
47-
$ csdx cm:bootstrap [--app-name <value>] [--project-dir <value>] [-k <value> | --org <value> | -n <value>] [-y
48-
<value>] [--run-dev-server] [-a <value>]
47+
$ csdx cm:bootstrap [--app-name <value>] [--project-dir <value>] [-k <value> | --org <value> | -n <value>] [-y]
48+
[--run-dev-server] [-a <value>]
4949
5050
FLAGS
5151
-a, --alias=<value> Alias of the management token
5252
-k, --stack-api-key=<value> Provide stack API key to seed content
5353
-n, --stack-name=<value> Name of the new stack that will be created.
54-
-y, --yes=<value> [Optional] Skip stack confirmation
54+
-y, --yes [Optional] Skip stack confirmation
5555
--app-name=<value> App name, kickstart-next, kickstart-next-ssr, kickstart-next-ssg, kickstart-next-graphql,
5656
kickstart-next-middleware, kickstart-nuxt, kickstart-nuxt-ssr
5757
--org=<value> Provide organization UID to create a new stack

packages/contentstack-bootstrap/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@contentstack/cli-cm-bootstrap",
33
"description": "Bootstrap contentstack apps",
4-
"version": "1.19.0-beta.0",
4+
"version": "1.18.4",
55
"author": "Contentstack",
66
"bugs": "https://github.com/contentstack/cli/issues",
77
"scripts": {
@@ -16,10 +16,10 @@
1616
"test:report": "nyc --reporter=lcov mocha \"test/**/*.test.js\""
1717
},
1818
"dependencies": {
19-
"@contentstack/cli-cm-seed": "~1.15.0-beta.0",
20-
"@contentstack/cli-command": "~1.8.0-beta.0",
21-
"@contentstack/cli-config": "~1.20.0-beta.0",
22-
"@contentstack/cli-utilities": "~1.18.0-beta.0",
19+
"@contentstack/cli-cm-seed": "~1.14.3",
20+
"@contentstack/cli-command": "~1.7.2",
21+
"@contentstack/cli-config": "~1.19.0",
22+
"@contentstack/cli-utilities": "~1.17.4",
2323
"@oclif/core": "^4.3.0",
2424
"@oclif/plugin-help": "^6.2.37",
2525
"inquirer": "8.2.7",

packages/contentstack-bootstrap/src/bootstrap/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface SeedParams {
2828
stackAPIKey?: string;
2929
org?: string;
3030
stackName?: string;
31-
yes?: string;
31+
yes?: boolean;
3232
managementTokenAlias?: string | undefined;
3333
managementToken?: string | undefined;
3434
}
@@ -95,7 +95,7 @@ export default class Bootstrap {
9595
cmd.push('-n', this.options.seedParams.stackName);
9696
}
9797
if (this.options.seedParams.yes) {
98-
cmd.push('-y', this.options.seedParams.yes);
98+
cmd.push('-y');
9999
}
100100
if (this.options.seedParams.managementTokenAlias) {
101101
cmd.push('--alias', this.options.seedParams.managementTokenAlias);

packages/contentstack-bootstrap/src/bootstrap/utils.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ export const setupEnvironments = async (
4040
if (!managementToken) {
4141
const managementBody = {
4242
token: {
43-
name: 'sample app',
44-
description: 'This is a sample management token.',
43+
name: 'Compass Starter App',
44+
description: 'This is a compass starter app management token.',
4545
scope: [
4646
{
47-
module: 'content_type',
47+
module: '$all',
4848
acl: {
4949
read: true,
5050
write: true,
@@ -58,8 +58,9 @@ export const setupEnvironments = async (
5858
},
5959
},
6060
],
61-
expires_on: '3000-01-01',
61+
expires_on: null,
6262
is_email_notification_enabled: false,
63+
rate_limit_enabled: false,
6364
},
6465
};
6566
managementTokenResult = await managementAPIClient
@@ -313,7 +314,7 @@ const envFileHandler = async (
313314
}CONTENTSTACK_ENVIRONMENT=${environmentVariables.environment}${!isUSRegion && !customHost ? '\nCONTENTSTACK_REGION=' + region.name : ''
314315
}\nCONTENTSTACK_LIVE_PREVIEW=${livePreviewEnabled}\nCONTENTSTACK_LIVE_EDIT_TAGS=false\nCONTENTSTACK_API_HOST=${customHost ? customHost : managementAPIHost
315316
}${!isUSRegion && !customHost ? '\nCONTENTSTACK_REGION=' + region.name : ''
316-
}\nCONTENTSTACK_APP_HOST=${appHost}\nCONTENTSTACK_MANAGEMENT_TOKEN=${managementTokenResult.uid
317+
}\nCONTENTSTACK_APP_HOST=${appHost}\nCONTENTSTACK_MANAGEMENT_TOKEN=${managementTokenResult.token
317318
}\nCONTENTSTACK_HOST=${cdnHost}`;
318319
result = await writeEnvFile(content, filePath);
319320
break;

packages/contentstack-bootstrap/src/commands/cm/bootstrap.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default class BootstrapCommand extends Command {
7373
required: false,
7474
exclusive: ['stack-api-key'],
7575
}),
76-
yes: flags.string({
76+
yes: flags.boolean({
7777
description: '[Optional] Skip stack confirmation',
7878
char: 'y',
7979
required: false,
@@ -157,7 +157,7 @@ export default class BootstrapCommand extends Command {
157157
});
158158
}
159159

160-
const yes = bootstrapCommandFlags.yes as string;
160+
const yes = bootstrapCommandFlags.yes as boolean;
161161

162162
const appConfig: AppConfig = getAppLevelConfigByName(selectedAppName || selectedApp.configKey);
163163
const master_locale = appConfig.master_locale || DEFAULT_MASTER_LOCALE;
@@ -181,7 +181,7 @@ export default class BootstrapCommand extends Command {
181181
if (stackAPIKey) seedParams.stackAPIKey = stackAPIKey;
182182
if (org) seedParams.org = org;
183183
if (stackName) seedParams.stackName = stackName;
184-
if (yes) seedParams.yes = yes;
184+
if (yes) seedParams.yes = true;
185185
if (managementTokenAlias) {
186186
seedParams.managementTokenAlias = managementTokenAlias;
187187
const listOfTokens = configHandler.get('tokens');

packages/contentstack-seed/README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ To import content to your stack, you can choose from the following two sources:
1010
<!-- usagestop -->
1111
## Commands
1212
<!-- commands -->
13-
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y-value--s-value---locale-value)
14-
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y-value--s-value---locale-value)
13+
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y--s-value---locale-value)
14+
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y--s-value---locale-value)
1515

16-
## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`
16+
## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`
1717

1818
Create a stack from existing content types, entries, assets, etc
1919

2020
```
2121
USAGE
22-
$ csdx cm:seed cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s
23-
<value>] [--locale <value>]
22+
$ csdx cm:seed cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>]
23+
[--locale <value>]
2424
2525
FLAGS
2626
-a, --alias=<value> Alias of the management token
@@ -29,7 +29,7 @@ FLAGS
2929
-o, --org=<value> Provide Organization UID to create a new stack
3030
-r, --repo=<value> GitHub organization name or GitHub user name/repository name.
3131
-s, --stack=<value> Provide the stack UID to seed content.
32-
-y, --yes=<value> [Optional] Skip the stack confirmation.
32+
-y, --yes [Optional] Skip the stack confirmation.
3333
3434
DESCRIPTION
3535
Create a stack from existing content types, entries, assets, etc
@@ -49,14 +49,14 @@ EXAMPLES
4949
$ csdx cm:stacks:seed --repo "account/repository" --org "your-org-uid" --stack-name "stack-name" //create a new stack in given org uid
5050
```
5151

52-
## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`
52+
## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`
5353

5454
Create a stack from existing content types, entries, assets, etc
5555

5656
```
5757
USAGE
58-
$ csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>]
59-
[--locale <value>]
58+
$ csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale
59+
<value>]
6060
6161
FLAGS
6262
-a, --alias=<value> Alias of the management token
@@ -65,7 +65,7 @@ FLAGS
6565
-o, --org=<value> Provide Organization UID to create a new stack
6666
-r, --repo=<value> GitHub organization name or GitHub user name/repository name.
6767
-s, --stack=<value> Provide the stack UID to seed content.
68-
-y, --yes=<value> [Optional] Skip the stack confirmation.
68+
-y, --yes [Optional] Skip the stack confirmation.
6969
7070
DESCRIPTION
7171
Create a stack from existing content types, entries, assets, etc

packages/contentstack-seed/src/commands/cm/stacks/seed.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default class SeedCommand extends Command {
2020
'$ csdx cm:stacks:seed --repo "account/repository" --org "your-org-uid" --stack-name "stack-name" //create a new stack in given org uid',
2121
];
2222

23-
static usage = 'cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]';
23+
static usage = 'cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]';
2424

2525
static flags: FlagInput = {
2626
repo: flags.string({
@@ -59,7 +59,7 @@ export default class SeedCommand extends Command {
5959
required: false,
6060
hidden: true,
6161
}),
62-
yes: flags.string({
62+
yes: flags.boolean({
6363
char: 'y',
6464
required: false,
6565
description: '[Optional] Skip the stack confirmation.',
@@ -80,6 +80,7 @@ export default class SeedCommand extends Command {
8080
}),
8181
locale: flags.string({
8282
description: 'Master Locale of the stack',
83+
default: 'en-us',
8384
hidden: true,
8485
}),
8586
};
@@ -106,7 +107,7 @@ export default class SeedCommand extends Command {
106107
stackUid: seedFlags['stack-api-key'] || seedFlags.stack,
107108
stackName: seedFlags['stack-name'],
108109
fetchLimit: seedFlags['fetch-limit'],
109-
skipStackConfirmation: seedFlags['yes'],
110+
skipStackConfirmation: seedFlags.yes,
110111
isAuthenticated: isAuthenticated(),
111112
alias: managementTokenAlias,
112113
master_locale: seedFlags['locale'],

packages/contentstack-seed/src/seed/github/client.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@ export default class GitHubClient {
118118
return false;
119119
}
120120

121+
async getMasterLocaleFromRepo(repo: string): Promise<string | null> {
122+
try {
123+
const response = await this.httpClient.get(
124+
`https://raw.githubusercontent.com/${this.username}/${repo}/main/stack/locales/master-locale.json`,
125+
);
126+
127+
if (response.data) {
128+
const localeData = response.data;
129+
const localeKey = Object.keys(localeData)[0];
130+
if (localeKey && localeData[localeKey]?.code) {
131+
return localeData[localeKey].code;
132+
}
133+
}
134+
} catch (error) {
135+
console.log('Could not fetch master locale from repository', error);
136+
}
137+
138+
return null;
139+
}
140+
121141
async getLatestTarballUrl(repo: string) {
122142
try {
123143
const response = await this.httpClient.get(`${this.gitHubRepoUrl}/${repo}/releases/latest`);

packages/contentstack-seed/src/seed/importer.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as fs from 'fs';
12
import * as process from 'process';
23
import * as path from 'path';
34
import ImportCommand from '@contentstack/cli-cm-import';
@@ -16,7 +17,13 @@ export interface ImporterOptions {
1617
}
1718

1819
export async function run(options: ImporterOptions) {
19-
const importPath = pathValidator(path.resolve(sanitizePath(options.tmpPath), STACK_FOLDER));
20+
const tmpPathResolved = path.resolve(sanitizePath(options.tmpPath));
21+
const stackPath = path.join(tmpPathResolved, STACK_FOLDER);
22+
23+
// Support both structures: repo with stack/ folder (per docs) or content at root
24+
const importPath = fs.existsSync(stackPath)
25+
? pathValidator(stackPath)
26+
: pathValidator(tmpPathResolved);
2027

2128
const args = options.alias
2229
? ['-k', options.api_key, '-d', importPath, '--alias', options.alias!]

packages/contentstack-seed/src/seed/index.ts

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export interface ContentModelSeederOptions {
2727
stackUid: string | undefined;
2828
stackName: string | undefined;
2929
fetchLimit: string | undefined;
30-
skipStackConfirmation: string | undefined;
30+
skipStackConfirmation: boolean | undefined;
3131
isAuthenticated: boolean | false;
3232
managementToken?: string | undefined;
3333
alias?: string | undefined;
@@ -181,52 +181,24 @@ export default class ContentModelSeeder {
181181
}
182182

183183
async shouldProceed(api_key: string) {
184-
let count;
185184
const stack_details = await this.csClient.getStack(api_key);
186-
if(this.options.master_locale != stack_details.master_locale){
187-
cliux.print(`Compass app requires the master locale to be set to English (en).`,{
188-
color: "yellow",
189-
bold: true,
190-
});
191-
return false;
192-
}
193-
const managementBody = {
194-
"name":"Checking roles for creating management token",
195-
"description":"This is a compass app management token.",
196-
"scope":[
197-
{
198-
"module":"content_type",
199-
"acl":{
200-
"read":true,
201-
"write":true
202-
}
203-
},
204-
{
205-
"module":"branch",
206-
"branches":[
207-
"main"
208-
],
209-
"acl":{
210-
"read":true
211-
}
212-
}
213-
],
214-
"expires_on": "3000-01-01",
215-
"is_email_notification_enabled":false
216-
}
217-
let managementTokenResult = await this.csClient.createManagementToken(api_key, this.managementToken, managementBody);
218-
if(managementTokenResult?.response_code == "161" || managementTokenResult?.response_code == "401"){
185+
const repoMasterLocale = await this.ghClient.getMasterLocaleFromRepo(this.ghRepo as string);
186+
const expectedLocale = repoMasterLocale || this.options.master_locale || ENGLISH_LOCALE;
187+
188+
if (stack_details.master_locale !== expectedLocale) {
219189
cliux.print(
220-
`Info: Failed to generate a management token.\nNote: Management token is not available in your plan. Please contact the admin for support.`,
190+
`Repository '${this.ghRepo}' requires the master locale to be set to '${expectedLocale}', but your stack has '${stack_details.master_locale}'.`,
221191
{
222-
color: 'red',
192+
color: 'yellow',
193+
bold: true,
223194
},
224195
);
225196
return false;
226-
}
227-
count = await this.csClient.getContentTypeCount(api_key, this.managementToken);
197+
}
198+
199+
const count = await this.csClient.getContentTypeCount(api_key, this.managementToken);
228200

229-
if (count > 0 && this._options.skipStackConfirmation !== 'yes') {
201+
if (count > 0 && !this._options.skipStackConfirmation) {
230202
const proceed = await inquireProceed();
231203

232204
if (!proceed) {

0 commit comments

Comments
 (0)