@factorialco/fcode-cli 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +128 -2
  2. package/dist/commands/add.js +3 -1
  3. package/dist/commands/clone.d.ts +1 -0
  4. package/dist/commands/clone.js +19 -1
  5. package/dist/commands/i18n/add.d.ts +9 -0
  6. package/dist/commands/i18n/add.js +13 -0
  7. package/dist/commands/i18n/pull.d.ts +12 -0
  8. package/dist/commands/i18n/pull.js +14 -0
  9. package/dist/commands/i18n/push.d.ts +12 -0
  10. package/dist/commands/i18n/push.js +14 -0
  11. package/dist/commands/i18n/remove.d.ts +9 -0
  12. package/dist/commands/i18n/remove.js +19 -0
  13. package/dist/commands/i18n/reset.d.ts +9 -0
  14. package/dist/commands/i18n/reset.js +13 -0
  15. package/dist/commands/i18n/status.d.ts +11 -0
  16. package/dist/commands/i18n/status.js +42 -0
  17. package/dist/commands/pull.js +5 -3
  18. package/dist/commands/push.js +5 -3
  19. package/dist/commands/reset.js +3 -1
  20. package/dist/commands/run.d.ts +1 -0
  21. package/dist/commands/run.js +5 -2
  22. package/dist/commands/status.js +4 -2
  23. package/dist/commands/team/push.js +3 -0
  24. package/dist/config/remote.js +1 -1
  25. package/dist/config/workspace.js +10 -0
  26. package/dist/core/commands/api-client-command.d.ts +1 -0
  27. package/dist/core/commands/api-client-command.js +5 -0
  28. package/dist/core/commands/base-command.d.ts +2 -0
  29. package/dist/core/commands/base-command.js +31 -0
  30. package/dist/core/commands/i18n-command.d.ts +5 -0
  31. package/dist/core/commands/i18n-command.js +16 -0
  32. package/dist/core/errors.d.ts +10 -0
  33. package/dist/core/errors.js +34 -1
  34. package/dist/core/executors/execution-task.js +4 -0
  35. package/dist/core/executors/javascript-execution-task.js +26 -1
  36. package/dist/core/resource-pusher.js +15 -0
  37. package/dist/core/types.d.ts +29 -1
  38. package/dist/core/types.js +46 -3
  39. package/dist/repositories/locale.d.ts +24 -0
  40. package/dist/repositories/locale.js +102 -0
  41. package/dist/repositories/resource.js +4 -1
  42. package/dist/repositories/team.js +5 -2
  43. package/dist/runtime/libs/python/fcode/__init__.py +1 -0
  44. package/dist/runtime/libs/python/fcode/context.py +43 -1
  45. package/dist/services/auth-service.d.ts +1 -0
  46. package/dist/services/auth-service.js +12 -0
  47. package/dist/services/fcode-graphql-client.d.ts +13 -1
  48. package/dist/services/fcode-graphql-client.js +136 -0
  49. package/dist/services/locale-merger.d.ts +23 -0
  50. package/dist/services/locale-merger.js +114 -0
  51. package/dist/services/locale-resolver.d.ts +18 -0
  52. package/dist/services/locale-resolver.js +120 -0
  53. package/dist/services/process-runner.d.ts +1 -0
  54. package/dist/services/process-runner.js +2 -2
  55. package/dist/services/team-access.d.ts +13 -0
  56. package/dist/services/team-access.js +45 -0
  57. package/dist/utils/gitignore.d.ts +1 -1
  58. package/dist/utils/gitignore.js +4 -1
  59. package/oclif.manifest.json +194 -1
  60. package/package.json +2 -1
package/README.md CHANGED
@@ -20,7 +20,7 @@ $ npm install -g @factorialco/fcode-cli
20
20
  $ fcode COMMAND
21
21
  running command...
22
22
  $ fcode (--version)
23
- @factorialco/fcode-cli/2.1.0 linux-x64 node-v22.22.3
23
+ @factorialco/fcode-cli/2.3.0 linux-x64 node-v22.22.3
24
24
  $ fcode --help [COMMAND]
25
25
  USAGE
26
26
  $ fcode COMMAND
@@ -40,6 +40,12 @@ USAGE
40
40
  * [`fcode dependencies:status [RESOURCESLUG]`](#fcode-dependenciesstatus-resourceslug)
41
41
  * [`fcode help [COMMAND]`](#fcode-help-command)
42
42
  * [`fcode http`](#fcode-http)
43
+ * [`fcode i18n:add [RESOURCESLUG]`](#fcode-i18nadd-resourceslug)
44
+ * [`fcode i18n:pull [RESOURCESLUG]`](#fcode-i18npull-resourceslug)
45
+ * [`fcode i18n:push [RESOURCESLUG]`](#fcode-i18npush-resourceslug)
46
+ * [`fcode i18n:remove [RESOURCESLUG]`](#fcode-i18nremove-resourceslug)
47
+ * [`fcode i18n:reset [RESOURCESLUG]`](#fcode-i18nreset-resourceslug)
48
+ * [`fcode i18n:status [RESOURCESLUG]`](#fcode-i18nstatus-resourceslug)
43
49
  * [`fcode login`](#fcode-login)
44
50
  * [`fcode logout`](#fcode-logout)
45
51
  * [`fcode modules:add [RESOURCESLUG]`](#fcode-modulesadd-resourceslug)
@@ -290,6 +296,124 @@ EXAMPLES
290
296
  $ fcode http --auth-user admin --auth-password secret
291
297
  ```
292
298
 
299
+ ## `fcode i18n:add [RESOURCESLUG]`
300
+
301
+ Keeps track of new local locales
302
+
303
+ ```
304
+ USAGE
305
+ $ fcode i18n:add [RESOURCESLUG]
306
+
307
+ ARGUMENTS
308
+ [RESOURCESLUG] Resource slug
309
+
310
+ DESCRIPTION
311
+ Keeps track of new local locales
312
+
313
+ EXAMPLES
314
+ $ fcode i18n:add
315
+
316
+ $ fcode i18n:add pt-BR
317
+ ```
318
+
319
+ ## `fcode i18n:pull [RESOURCESLUG]`
320
+
321
+ Fetch all locales from cloud and save them locally
322
+
323
+ ```
324
+ USAGE
325
+ $ fcode i18n:pull [RESOURCESLUG] [-f]
326
+
327
+ ARGUMENTS
328
+ [RESOURCESLUG] Resource slug
329
+
330
+ FLAGS
331
+ -f, --force Force command
332
+
333
+ DESCRIPTION
334
+ Fetch all locales from cloud and save them locally
335
+
336
+ EXAMPLES
337
+ $ fcode i18n:pull
338
+ ```
339
+
340
+ ## `fcode i18n:push [RESOURCESLUG]`
341
+
342
+ Create or update cloud locales from local ones
343
+
344
+ ```
345
+ USAGE
346
+ $ fcode i18n:push [RESOURCESLUG] [-f]
347
+
348
+ ARGUMENTS
349
+ [RESOURCESLUG] Resource slug
350
+
351
+ FLAGS
352
+ -f, --force Force command
353
+
354
+ DESCRIPTION
355
+ Create or update cloud locales from local ones
356
+
357
+ EXAMPLES
358
+ $ fcode i18n:push
359
+
360
+ $ fcode i18n:push pt-BR
361
+ ```
362
+
363
+ ## `fcode i18n:remove [RESOURCESLUG]`
364
+
365
+ Remove track of a local locale
366
+
367
+ ```
368
+ USAGE
369
+ $ fcode i18n:remove [RESOURCESLUG]
370
+
371
+ ARGUMENTS
372
+ [RESOURCESLUG] Resource slug
373
+
374
+ DESCRIPTION
375
+ Remove track of a local locale
376
+
377
+ EXAMPLES
378
+ $ fcode i18n:remove pt-BR
379
+ ```
380
+
381
+ ## `fcode i18n:reset [RESOURCESLUG]`
382
+
383
+ Reset locales with contents from current remote
384
+
385
+ ```
386
+ USAGE
387
+ $ fcode i18n:reset [RESOURCESLUG]
388
+
389
+ ARGUMENTS
390
+ [RESOURCESLUG] Resource slug
391
+
392
+ DESCRIPTION
393
+ Reset locales with contents from current remote
394
+
395
+ EXAMPLES
396
+ $ fcode i18n:reset
397
+ ```
398
+
399
+ ## `fcode i18n:status [RESOURCESLUG]`
400
+
401
+ List all locales status
402
+
403
+ ```
404
+ USAGE
405
+ $ fcode i18n:status [RESOURCESLUG]
406
+
407
+ ARGUMENTS
408
+ [RESOURCESLUG] Resource slug
409
+
410
+ DESCRIPTION
411
+ List all locales status
412
+
413
+ EXAMPLES
414
+ $ fcode i18n:status
415
+ ```
416
+
293
417
  ## `fcode login`
294
418
 
295
419
  Login with your Factorial Code credentials (browser OAuth or email/password)
@@ -701,7 +825,8 @@ Run Factorial Code processes locally
701
825
 
702
826
  ```
703
827
  USAGE
704
- $ fcode run SLUG [-p <value>] [-v <value>] [-l DEBUG|INFO|WARNING|ERROR] [-j] [-e <value>]
828
+ $ fcode run SLUG [-p <value>] [-v <value>] [-l DEBUG|INFO|WARNING|ERROR] [-j] [--locale <value>] [-e
829
+ <value>]
705
830
 
706
831
  ARGUMENTS
707
832
  SLUG Process slug
@@ -713,6 +838,7 @@ FLAGS
713
838
  <options: DEBUG|INFO|WARNING|ERROR>
714
839
  -p, --parameters=<value> Parameters: stringified JSON or file path
715
840
  -v, --version=<value> Process version
841
+ --locale=<value> Locale fcode.i18n resolves against (defaults to the workspace primaryLocale)
716
842
 
717
843
  DESCRIPTION
718
844
  Run Factorial Code processes locally
@@ -4,7 +4,8 @@ const base_command_1 = require("../core/commands/base-command");
4
4
  const add_1 = require("./processes/add");
5
5
  const add_2 = require("./modules/add");
6
6
  const add_3 = require("./variables/add");
7
- const add_4 = require("./dependencies/add");
7
+ const add_4 = require("./i18n/add");
8
+ const add_5 = require("./dependencies/add");
8
9
  const cli_1 = require("../utils/cli");
9
10
  class AddCommand extends base_command_1.default {
10
11
  async run() {
@@ -15,6 +16,7 @@ class AddCommand extends base_command_1.default {
15
16
  await add_2.default.run([]);
16
17
  await add_3.default.run([]);
17
18
  await add_4.default.run([]);
19
+ await add_5.default.run([]);
18
20
  }
19
21
  }
20
22
  AddCommand.description = 'Keeps track of new local components';
@@ -13,6 +13,7 @@ export default class Clone extends Command {
13
13
  checkWorkspaceIsEmpty(slug: string): Promise<void>;
14
14
  cloneTeam(origin: TeamOrigin, skipSkillsSetup?: boolean): Promise<void>;
15
15
  createWorkspaceConfig(origin: TeamOrigin): Promise<void>;
16
+ createWorkspaceI18n(slug: string): void;
16
17
  createWorkspaceDatastore(slug: string): void;
17
18
  createWorkspaceStorage(slug: string): void;
18
19
  createWorkspaceGitIgnore(slug: string): Promise<void>;
@@ -7,6 +7,7 @@ const path = require("node:path");
7
7
  const global_1 = require("../config/global");
8
8
  const workspace_1 = require("../config/workspace");
9
9
  const pull_1 = require("./pull");
10
+ const team_access_1 = require("../services/team-access");
10
11
  const types_1 = require("../core/types");
11
12
  const cli_1 = require("../utils/cli");
12
13
  const settings_1 = require("../config/settings");
@@ -50,6 +51,7 @@ class Clone extends core_1.Command {
50
51
  await this.mkdirWorkspace(origin.slug);
51
52
  await this.createWorkspaceConfig(origin);
52
53
  await this.createWorkspaceGitIgnore(origin.slug);
54
+ this.createWorkspaceI18n(origin.slug);
53
55
  this.createWorkspaceDatastore(origin.slug);
54
56
  this.createWorkspaceStorage(origin.slug);
55
57
  await this.createWorkspaceLocalVariables(origin.slug);
@@ -63,6 +65,10 @@ class Clone extends core_1.Command {
63
65
  const config = new workspace_1.default(path.join(process.cwd(), origin.slug));
64
66
  await config.init(origin);
65
67
  }
68
+ // Created empty so `i18n:add` has somewhere to look before the first locale is pulled.
69
+ createWorkspaceI18n(slug) {
70
+ fs.mkdirpSync(path.join(slug, 'i18n'));
71
+ }
66
72
  createWorkspaceDatastore(slug) {
67
73
  fs.outputFileSync(path.join(slug, 'datastore.json'), '{}');
68
74
  }
@@ -115,6 +121,7 @@ class Clone extends core_1.Command {
115
121
  });
116
122
  }
117
123
  async catch(error) {
124
+ process.exitCode = 1;
118
125
  const suggestions = error?.suggestions ?? [];
119
126
  const hint = suggestions.length > 0 ? ` Try this: ${suggestions.map((suggestion) => `'${suggestion}'`).join('\n')} \n` : '';
120
127
  cli_1.default.error(error.message + hint);
@@ -175,8 +182,19 @@ class Clone extends core_1.Command {
175
182
  if (skipSkillsSetup === undefined) {
176
183
  skipSkillsSetup = (await new global_1.default().getSetting(settings_1.SettingKeys.SKIP_SKILLS_SETUP)) === 'true';
177
184
  }
185
+ // Pre-flight access check so a session without access to the team fails here,
186
+ // before any workspace directory, config, or skills are created.
187
+ await team_access_1.default.ensureTeamAccess(url, slug);
178
188
  await this.cloneTeam({ url, slug }, skipSkillsSetup);
179
- cli_1.default.log(`\n🎉 ${args.team} team workspace cloned successfully!\n`);
189
+ // Failed pulls don't abort the clone: each sub-pull reports through
190
+ // BaseCommand.catch, which prints and sets a non-zero exit code.
191
+ if (process.exitCode) {
192
+ cli_1.default.log(`\n⚠️ '${args.team}' team workspace cloned with errors — some resources failed to pull.`);
193
+ cli_1.default.log(` Fix the errors above, then run 'fcode pull' inside the workspace.\n`);
194
+ }
195
+ else {
196
+ cli_1.default.log(`\n🎉 ${args.team} team workspace cloned successfully!\n`);
197
+ }
180
198
  cli_1.default.log(`$ cd ${slug}\n`);
181
199
  }
182
200
  }
@@ -0,0 +1,9 @@
1
+ import I18nCommand from '../../core/commands/i18n-command';
2
+ export default class I18nAdd extends I18nCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const i18n_command_1 = require("../../core/commands/i18n-command");
4
+ const types_1 = require("../../core/types");
5
+ class I18nAdd extends i18n_command_1.default {
6
+ async run() {
7
+ await super.addResources();
8
+ }
9
+ }
10
+ I18nAdd.description = 'Keeps track of new local locales';
11
+ I18nAdd.examples = ['$ fcode i18n:add', '$ fcode i18n:add pt-BR'];
12
+ I18nAdd.args = types_1.ResourceSlugArg;
13
+ exports.default = I18nAdd;
@@ -0,0 +1,12 @@
1
+ import I18nCommand from '../../core/commands/i18n-command';
2
+ export default class I18nPull extends I18nCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const i18n_command_1 = require("../../core/commands/i18n-command");
4
+ const types_1 = require("../../core/types");
5
+ class I18nPull extends i18n_command_1.default {
6
+ async run() {
7
+ await super.pullResources();
8
+ }
9
+ }
10
+ I18nPull.description = 'Fetch all locales from cloud and save them locally';
11
+ I18nPull.examples = ['$ fcode i18n:pull'];
12
+ I18nPull.args = types_1.ResourceSlugArg;
13
+ I18nPull.flags = types_1.ForceFlag;
14
+ exports.default = I18nPull;
@@ -0,0 +1,12 @@
1
+ import I18nCommand from '../../core/commands/i18n-command';
2
+ export default class I18nPush extends I18nCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const i18n_command_1 = require("../../core/commands/i18n-command");
4
+ const types_1 = require("../../core/types");
5
+ class I18nPush extends i18n_command_1.default {
6
+ async run() {
7
+ await super.pushResources();
8
+ }
9
+ }
10
+ I18nPush.description = 'Create or update cloud locales from local ones';
11
+ I18nPush.examples = ['$ fcode i18n:push', '$ fcode i18n:push pt-BR'];
12
+ I18nPush.args = types_1.ResourceSlugArg;
13
+ I18nPush.flags = types_1.ForceFlag;
14
+ exports.default = I18nPush;
@@ -0,0 +1,9 @@
1
+ import I18nCommand from '../../core/commands/i18n-command';
2
+ export default class I18nRemove extends I18nCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const color_1 = require("@oclif/color");
4
+ const i18n_command_1 = require("../../core/commands/i18n-command");
5
+ const types_1 = require("../../core/types");
6
+ const cli_1 = require("../../utils/cli");
7
+ class I18nRemove extends i18n_command_1.default {
8
+ async run() {
9
+ if (!this.resourceSlug) {
10
+ cli_1.default.log(color_1.default.red(`You must specify a locale`));
11
+ return;
12
+ }
13
+ await super.removeResource(this.resourceSlug);
14
+ }
15
+ }
16
+ I18nRemove.description = 'Remove track of a local locale';
17
+ I18nRemove.examples = ['$ fcode i18n:remove pt-BR'];
18
+ I18nRemove.args = types_1.ResourceSlugArg;
19
+ exports.default = I18nRemove;
@@ -0,0 +1,9 @@
1
+ import I18nCommand from '../../core/commands/i18n-command';
2
+ export default class I18nReset extends I18nCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const i18n_command_1 = require("../../core/commands/i18n-command");
4
+ const types_1 = require("../../core/types");
5
+ class I18nReset extends i18n_command_1.default {
6
+ async run() {
7
+ await super.resetResources();
8
+ }
9
+ }
10
+ I18nReset.description = 'Reset locales with contents from current remote';
11
+ I18nReset.examples = ['$ fcode i18n:reset'];
12
+ I18nReset.args = types_1.ResourceSlugArg;
13
+ exports.default = I18nReset;
@@ -0,0 +1,11 @@
1
+ import I18nCommand from '../../core/commands/i18n-command';
2
+ import { MergedResource } from '../../core/types';
3
+ export default class I18nStatus extends I18nCommand {
4
+ static description: string;
5
+ static examples: string[];
6
+ static args: {
7
+ resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
+ };
9
+ resourcesTableLog(resources: Array<MergedResource>): Promise<void>;
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const i18n_command_1 = require("../../core/commands/i18n-command");
4
+ const types_1 = require("../../core/types");
5
+ const colorize_resource_1 = require("../../utils/colorize-resource");
6
+ const cli_1 = require("../../utils/cli");
7
+ class I18nStatus extends i18n_command_1.default {
8
+ async resourcesTableLog(resources) {
9
+ const hasInherited = resources.some((resource) => resource.resolvingTeamSlug);
10
+ cli_1.cli.table(resources, {
11
+ locale: {
12
+ // The identifier, not the slug: an inherited file is tracked as `en.inherited`, and the
13
+ // workspace it comes from already has its own column.
14
+ get({ locale, slug, status }) {
15
+ return (0, colorize_resource_1.colorizeByStatus)(String(locale ?? slug), status);
16
+ },
17
+ header: 'locale',
18
+ },
19
+ ...(hasInherited && {
20
+ inherited: {
21
+ get(resource) {
22
+ return (0, colorize_resource_1.colorizeByStatus)(resource.resolvingTeamSlug ? `🔗 ${resource.resolvingTeamSlug}` : '', resource.status);
23
+ },
24
+ header: 'inherited',
25
+ },
26
+ }),
27
+ status: {
28
+ get({ status }) {
29
+ return (0, colorize_resource_1.colorizeByStatus)(status, status);
30
+ },
31
+ header: 'status',
32
+ },
33
+ }, { sort: 'locale' });
34
+ }
35
+ async run() {
36
+ await this.resourcesLog();
37
+ }
38
+ }
39
+ I18nStatus.description = 'List all locales status';
40
+ I18nStatus.examples = ['$ fcode i18n:status'];
41
+ I18nStatus.args = types_1.ResourceSlugArg;
42
+ exports.default = I18nStatus;
@@ -4,8 +4,9 @@ const base_command_1 = require("../core/commands/base-command");
4
4
  const pull_1 = require("./modules/pull");
5
5
  const pull_2 = require("./processes/pull");
6
6
  const pull_3 = require("./variables/pull");
7
- const pull_4 = require("./dependencies/pull");
8
- const pull_5 = require("./team/pull");
7
+ const pull_4 = require("./i18n/pull");
8
+ const pull_5 = require("./dependencies/pull");
9
+ const pull_6 = require("./team/pull");
9
10
  const types_1 = require("../core/types");
10
11
  const gitignore_1 = require("../utils/gitignore");
11
12
  class PullCommand extends base_command_1.default {
@@ -19,9 +20,10 @@ class PullCommand extends base_command_1.default {
19
20
  await pull_1.default.run(args);
20
21
  await pull_3.default.run(args);
21
22
  await pull_4.default.run(args);
23
+ await pull_5.default.run(args);
22
24
  // Team settings are pulled last so process metadata is available to resolve the
23
25
  // error-handler process id to its slug.
24
- await pull_5.default.run([]);
26
+ await pull_6.default.run([]);
25
27
  // Keep inherited resources out of git now that all resource metadata is saved.
26
28
  await (0, gitignore_1.syncInheritedGitignore)();
27
29
  }
@@ -4,8 +4,9 @@ const base_command_1 = require("../core/commands/base-command");
4
4
  const push_1 = require("./modules/push");
5
5
  const push_2 = require("./processes/push");
6
6
  const push_3 = require("./variables/push");
7
- const push_4 = require("./dependencies/push");
8
- const push_5 = require("./team/push");
7
+ const push_4 = require("./i18n/push");
8
+ const push_5 = require("./dependencies/push");
9
+ const push_6 = require("./team/push");
9
10
  const types_1 = require("../core/types");
10
11
  class PushCommand extends base_command_1.default {
11
12
  async run() {
@@ -18,9 +19,10 @@ class PushCommand extends base_command_1.default {
18
19
  await push_1.default.run(args);
19
20
  await push_3.default.run(args);
20
21
  await push_4.default.run(args);
22
+ await push_5.default.run(args);
21
23
  // Team settings are pushed last so the error-handler process exists to resolve
22
24
  // its slug to an id.
23
- await push_5.default.run(args);
25
+ await push_6.default.run(args);
24
26
  }
25
27
  }
26
28
  PushCommand.description = 'Update cloud team workspace with local workspace';
@@ -4,7 +4,8 @@ const core_1 = require("@oclif/core");
4
4
  const reset_1 = require("./processes/reset");
5
5
  const reset_2 = require("./modules/reset");
6
6
  const reset_3 = require("./variables/reset");
7
- const reset_4 = require("./dependencies/reset");
7
+ const reset_4 = require("./i18n/reset");
8
+ const reset_5 = require("./dependencies/reset");
8
9
  class Reset extends core_1.Command {
9
10
  async run() {
10
11
  await this.parse(Reset);
@@ -12,6 +13,7 @@ class Reset extends core_1.Command {
12
13
  await reset_2.default.run([]);
13
14
  await reset_3.default.run([]);
14
15
  await reset_4.default.run([]);
16
+ await reset_5.default.run([]);
15
17
  }
16
18
  }
17
19
  Reset.description = 'Reset team workspace with contents from current remote';
@@ -10,6 +10,7 @@ export default class Run extends Command {
10
10
  version: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
11
  logLevel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
12
12
  jsonLogs: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ locale: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
14
  variablesFile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
15
  };
15
16
  run(): Promise<void>;
@@ -6,7 +6,7 @@ const core_2 = require("@oclif/core");
6
6
  const process_runner_1 = require("../services/process-runner");
7
7
  class Run extends core_2.Command {
8
8
  async run() {
9
- const { args: { slug }, flags: { parameters: parametersFlag, version, logLevel, jsonLogs, variablesFile }, } = await this.parse(Run);
9
+ const { args: { slug }, flags: { parameters: parametersFlag, version, logLevel, jsonLogs, variablesFile, locale }, } = await this.parse(Run);
10
10
  let parameters;
11
11
  if (parametersFlag) {
12
12
  try {
@@ -16,7 +16,7 @@ class Run extends core_2.Command {
16
16
  parameters = await Promise.resolve(`${path.resolve(parametersFlag)}`).then(s => require(s));
17
17
  }
18
18
  }
19
- await (0, process_runner_1.runProcess)({ slug, parameters, version, logLevel, jsonLogs, extraVariablesFile: variablesFile });
19
+ await (0, process_runner_1.runProcess)({ slug, parameters, version, logLevel, jsonLogs, extraVariablesFile: variablesFile, locale });
20
20
  }
21
21
  }
22
22
  Run.args = {
@@ -48,6 +48,9 @@ Run.flags = {
48
48
  description: 'Output process logs as newline-delimited JSON (NDJSON)',
49
49
  default: false,
50
50
  }),
51
+ locale: core_1.Flags.string({
52
+ description: 'Locale fcode.i18n resolves against (defaults to the workspace primaryLocale)',
53
+ }),
51
54
  variablesFile: core_1.Flags.string({
52
55
  char: 'e',
53
56
  description: 'Path to a .env file whose variables override workspace variables',
@@ -4,8 +4,9 @@ const base_command_1 = require("../core/commands/base-command");
4
4
  const status_1 = require("./modules/status");
5
5
  const status_2 = require("./processes/status");
6
6
  const status_3 = require("./variables/status");
7
- const status_4 = require("./dependencies/status");
8
- const status_5 = require("./team/status");
7
+ const status_4 = require("./i18n/status");
8
+ const status_5 = require("./dependencies/status");
9
+ const status_6 = require("./team/status");
9
10
  class Status extends base_command_1.default {
10
11
  async run() {
11
12
  await this.parse(Status);
@@ -15,6 +16,7 @@ class Status extends base_command_1.default {
15
16
  await status_3.default.run([]);
16
17
  await status_4.default.run([]);
17
18
  await status_5.default.run([]);
19
+ await status_6.default.run([]);
18
20
  }
19
21
  }
20
22
  Status.description = 'Show team workspace status';
@@ -38,6 +38,9 @@ class TeamPushCommand extends api_client_command_1.default {
38
38
  update.webhookAuth = team.webhookAuth
39
39
  ? { headerName: team.webhookAuth.headerName ?? null, variableKey: team.webhookAuth.variableKey }
40
40
  : { variableKey: null };
41
+ // Sent unconditionally for the same reason as webhookAuth: team.json is the source of truth,
42
+ // so removing primaryLocale from it must clear the cloud setting. Empty string is the clear.
43
+ update.primaryLocale = team.primaryLocale ?? '';
41
44
  await this._fcodeGraphQLClient.pushTeam(update);
42
45
  await this.workspaceConfig.setTeamStoredHash(team.contentHash);
43
46
  cli_1.default.log(color_1.default.green('✅ team settings pushed'));
@@ -47,7 +47,7 @@ class RemoteConfig {
47
47
  return this;
48
48
  }
49
49
  init() {
50
- fs.writeJsonSync(this.configPath, { slug: this.remote, modules: {}, processes: {}, variables: {}, dependencies: {}, team: {} }, { spaces: 2 });
50
+ fs.writeJsonSync(this.configPath, { slug: this.remote, modules: {}, processes: {}, variables: {}, i18n: {}, dependencies: {}, team: {} }, { spaces: 2 });
51
51
  }
52
52
  createDir(configPath) {
53
53
  if (!fs.pathExistsSync(configPath)) {
@@ -85,6 +85,12 @@ class WorkspaceConfig extends index_1.default {
85
85
  else if (resourceType === 'variables') {
86
86
  return team.variables;
87
87
  }
88
+ else if (resourceType === 'i18n') {
89
+ // Defaulted rather than required: workspaces cloned before locales existed have no `i18n`
90
+ // key in their sync metadata, and pulling should populate it instead of failing.
91
+ team.i18n ||= {};
92
+ return team.i18n;
93
+ }
88
94
  else if (resourceType === 'dependencies') {
89
95
  return team.dependencies;
90
96
  }
@@ -100,6 +106,10 @@ class WorkspaceConfig extends index_1.default {
100
106
  else if (resource instanceof types_1.Variable) {
101
107
  return team.variables;
102
108
  }
109
+ else if (resource instanceof types_1.Locale) {
110
+ team.i18n ||= {};
111
+ return team.i18n;
112
+ }
103
113
  else if (resource instanceof types_1.ProgrammingLanguageManifest) {
104
114
  return team.dependencies;
105
115
  }
@@ -3,4 +3,5 @@ import FcodeGraphQLClient from '../../services/fcode-graphql-client';
3
3
  export default abstract class ApiClientCommand extends BaseCommand {
4
4
  _fcodeGraphQLClient: FcodeGraphQLClient;
5
5
  init(): Promise<void>;
6
+ protected onSessionRefreshed(): Promise<void>;
6
7
  }
@@ -26,5 +26,10 @@ class ApiClientCommand extends base_command_1.default {
26
26
  throw error;
27
27
  }
28
28
  }
29
+ async onSessionRefreshed() {
30
+ const { url } = await this.workspaceConfig.getTeamOrigin();
31
+ const { token: { access_token: accessToken }, } = await this.globalConfig.getAuthInfo(url);
32
+ this._fcodeGraphQLClient.setAccessToken(accessToken);
33
+ }
29
34
  }
30
35
  exports.default = ApiClientCommand;
@@ -5,7 +5,9 @@ export default abstract class BaseCommand extends Command {
5
5
  url?: string;
6
6
  globalConfig: GlobalConfig;
7
7
  workspaceConfig: WorkspaceConfig;
8
+ private sessionRefreshRetried;
8
9
  catch(error: any): Promise<any>;
9
10
  init(url?: string): Promise<void>;
11
+ protected onSessionRefreshed(): Promise<void>;
10
12
  protected logActiveTeam(): Promise<void>;
11
13
  }