@factorialco/fcode-cli 2.4.0 → 3.0.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.
- package/README.md +331 -118
- package/dist/commands/clone.d.ts +0 -12
- package/dist/commands/clone.js +22 -135
- package/dist/commands/{settings → config}/get.d.ts +1 -1
- package/dist/commands/{settings → config}/get.js +7 -7
- package/dist/commands/{settings → config}/remove.d.ts +1 -1
- package/dist/commands/{settings → config}/remove.js +6 -6
- package/dist/commands/{settings → config}/set.d.ts +1 -1
- package/dist/commands/{settings → config}/set.js +8 -8
- package/dist/commands/dependencies/diff.d.ts +9 -0
- package/dist/commands/dependencies/diff.js +15 -0
- package/dist/commands/dependencies/pull.d.ts +9 -0
- package/dist/commands/dependencies/pull.js +44 -1
- package/dist/commands/diff.d.ts +12 -0
- package/dist/commands/diff.js +48 -0
- package/dist/commands/http.d.ts +1 -1
- package/dist/commands/http.js +7 -7
- package/dist/commands/i18n/diff.d.ts +9 -0
- package/dist/commands/i18n/diff.js +15 -0
- package/dist/commands/i18n/status.d.ts +3 -0
- package/dist/commands/i18n/status.js +1 -0
- package/dist/commands/modules/diff.d.ts +9 -0
- package/dist/commands/modules/diff.js +15 -0
- package/dist/commands/modules/status.d.ts +3 -0
- package/dist/commands/modules/status.js +1 -0
- package/dist/commands/processes/diff.d.ts +9 -0
- package/dist/commands/processes/diff.js +15 -0
- package/dist/commands/processes/status.d.ts +3 -0
- package/dist/commands/processes/status.js +1 -0
- package/dist/commands/pull.js +2 -2
- package/dist/commands/push.js +2 -2
- package/dist/commands/{team → settings}/aliases/delete.d.ts +1 -1
- package/dist/commands/{team → settings}/aliases/delete.js +6 -6
- package/dist/commands/{team → settings}/aliases/list.d.ts +1 -1
- package/dist/commands/{team → settings}/aliases/list.js +8 -8
- package/dist/commands/{team → settings}/aliases/set.d.ts +1 -1
- package/dist/commands/{team → settings}/aliases/set.js +8 -8
- package/dist/commands/settings/diff.d.ts +8 -0
- package/dist/commands/settings/diff.js +39 -0
- package/dist/commands/settings/pull.d.ts +11 -0
- package/dist/commands/settings/pull.js +41 -0
- package/dist/commands/{team → settings}/push.d.ts +4 -4
- package/dist/commands/{team → settings}/push.js +39 -39
- package/dist/commands/settings/status.d.ts +8 -0
- package/dist/commands/settings/status.js +46 -0
- package/dist/commands/{team → settings}/versions/create.d.ts +1 -1
- package/dist/commands/{team → settings}/versions/create.js +13 -10
- package/dist/commands/{team → settings}/versions/delete.d.ts +1 -1
- package/dist/commands/{team → settings}/versions/delete.js +10 -10
- package/dist/commands/{team → settings}/versions/list.d.ts +1 -1
- package/dist/commands/{team → settings}/versions/list.js +8 -8
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +10 -7
- package/dist/commands/team/clone.d.ts +14 -0
- package/dist/commands/team/clone.js +91 -0
- package/dist/commands/team/pull.d.ts +3 -7
- package/dist/commands/team/pull.js +25 -30
- package/dist/commands/team/status.d.ts +3 -4
- package/dist/commands/team/status.js +34 -33
- package/dist/commands/variables/diff.d.ts +9 -0
- package/dist/commands/variables/diff.js +15 -0
- package/dist/commands/variables/status.d.ts +3 -0
- package/dist/commands/variables/status.js +1 -0
- package/dist/config/dev-team.d.ts +48 -0
- package/dist/config/dev-team.js +62 -0
- package/dist/config/workspace.d.ts +2 -2
- package/dist/config/workspace.js +4 -2
- package/dist/core/commands/base-command.js +5 -0
- package/dist/core/commands/dependency-command.d.ts +2 -1
- package/dist/core/commands/dependency-command.js +3 -0
- package/dist/core/commands/i18n-command.js +2 -0
- package/dist/core/commands/modules-command.js +2 -0
- package/dist/core/commands/processes-command.js +2 -0
- package/dist/core/commands/resource-command.d.ts +26 -1
- package/dist/core/commands/resource-command.js +100 -3
- package/dist/core/commands/variables-command.d.ts +7 -0
- package/dist/core/commands/variables-command.js +13 -0
- package/dist/core/executors/javascript-execution-task.js +25 -3
- package/dist/core/types.d.ts +30 -7
- package/dist/core/types.js +38 -10
- package/dist/repositories/process.d.ts +8 -2
- package/dist/repositories/process.js +28 -18
- package/dist/repositories/programming-language-manifest.d.ts +15 -1
- package/dist/repositories/programming-language-manifest.js +45 -1
- package/dist/repositories/settings.d.ts +52 -0
- package/dist/repositories/settings.js +214 -0
- package/dist/runtime/libs/python/fcode/context.py +29 -2
- package/dist/services/dashboard-client.d.ts +31 -0
- package/dist/services/dashboard-client.js +99 -0
- package/dist/services/dev-team-service.d.ts +41 -0
- package/dist/services/dev-team-service.js +162 -0
- package/dist/services/fcode-graphql-client.d.ts +16 -2
- package/dist/services/fcode-graphql-client.js +56 -7
- package/dist/services/locale-resolver.d.ts +16 -5
- package/dist/services/locale-resolver.js +60 -12
- package/dist/services/resource-differ.d.ts +60 -0
- package/dist/services/resource-differ.js +135 -0
- package/dist/services/skills-installer.d.ts +16 -0
- package/dist/services/skills-installer.js +77 -0
- package/dist/services/team-versioning.d.ts +4 -4
- package/dist/services/team-versioning.js +4 -4
- package/dist/services/webhook-auth.js +1 -1
- package/dist/services/workspace-cloner.d.ts +31 -0
- package/dist/services/workspace-cloner.js +95 -0
- package/dist/utils/dev-slug.d.ts +12 -0
- package/dist/utils/dev-slug.js +37 -0
- package/dist/utils/diff.d.ts +19 -0
- package/dist/utils/diff.js +58 -0
- package/dist/utils/slugify.d.ts +17 -0
- package/dist/utils/slugify.js +41 -0
- package/oclif.manifest.json +428 -116
- package/package.json +12 -7
- package/dist/repositories/team.d.ts +0 -41
- package/dist/repositories/team.js +0 -170
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import ProcessesCommand from '../../core/commands/processes-command';
|
|
2
|
+
export default class ProcessesDiff extends ProcessesCommand {
|
|
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,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const types_1 = require("../../core/types");
|
|
4
|
+
const processes_command_1 = require("../../core/commands/processes-command");
|
|
5
|
+
class ProcessesDiff extends processes_command_1.default {
|
|
6
|
+
async run() {
|
|
7
|
+
if (await this.resourcesDiff()) {
|
|
8
|
+
this.exit(1);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
ProcessesDiff.description = 'Show a unified diff between local processes and the cloud. Exits 1 when they differ';
|
|
13
|
+
ProcessesDiff.examples = ['$ fcode processes:diff', '$ fcode processes:diff hello-world'];
|
|
14
|
+
ProcessesDiff.args = types_1.ResourceSlugArg;
|
|
15
|
+
exports.default = ProcessesDiff;
|
|
@@ -6,6 +6,9 @@ export default class ProcessesStatus extends ProcessesCommand {
|
|
|
6
6
|
static args: {
|
|
7
7
|
resourceSlug: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
8
|
};
|
|
9
|
+
static flags: {
|
|
10
|
+
showInherited: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
9
12
|
resourcesTableLog(resources: Array<MergedResource>): Promise<void>;
|
|
10
13
|
run(): Promise<void>;
|
|
11
14
|
}
|
|
@@ -55,4 +55,5 @@ class ProcessesStatus extends processes_command_1.default {
|
|
|
55
55
|
ProcessesStatus.description = 'List all processes status';
|
|
56
56
|
ProcessesStatus.examples = ['$ fcode processes:status'];
|
|
57
57
|
ProcessesStatus.args = types_1.ResourceSlugArg;
|
|
58
|
+
ProcessesStatus.flags = types_1.ShowInheritedFlag;
|
|
58
59
|
exports.default = ProcessesStatus;
|
package/dist/commands/pull.js
CHANGED
|
@@ -6,7 +6,7 @@ const pull_2 = require("./processes/pull");
|
|
|
6
6
|
const pull_3 = require("./variables/pull");
|
|
7
7
|
const pull_4 = require("./i18n/pull");
|
|
8
8
|
const pull_5 = require("./dependencies/pull");
|
|
9
|
-
const pull_6 = require("./
|
|
9
|
+
const pull_6 = require("./settings/pull");
|
|
10
10
|
const types_1 = require("../core/types");
|
|
11
11
|
const gitignore_1 = require("../utils/gitignore");
|
|
12
12
|
class PullCommand extends base_command_1.default {
|
|
@@ -21,7 +21,7 @@ class PullCommand extends base_command_1.default {
|
|
|
21
21
|
await pull_3.default.run(args);
|
|
22
22
|
await pull_4.default.run(args);
|
|
23
23
|
await pull_5.default.run(args);
|
|
24
|
-
//
|
|
24
|
+
// Workspace settings are pulled last so process metadata is available to resolve the
|
|
25
25
|
// error-handler process id to its slug.
|
|
26
26
|
await pull_6.default.run(args);
|
|
27
27
|
// Keep inherited resources out of git now that all resource metadata is saved.
|
package/dist/commands/push.js
CHANGED
|
@@ -6,7 +6,7 @@ const push_2 = require("./processes/push");
|
|
|
6
6
|
const push_3 = require("./variables/push");
|
|
7
7
|
const push_4 = require("./i18n/push");
|
|
8
8
|
const push_5 = require("./dependencies/push");
|
|
9
|
-
const push_6 = require("./
|
|
9
|
+
const push_6 = require("./settings/push");
|
|
10
10
|
const types_1 = require("../core/types");
|
|
11
11
|
class PushCommand extends base_command_1.default {
|
|
12
12
|
async run() {
|
|
@@ -20,7 +20,7 @@ class PushCommand extends base_command_1.default {
|
|
|
20
20
|
await push_3.default.run(args);
|
|
21
21
|
await push_4.default.run(args);
|
|
22
22
|
await push_5.default.run(args);
|
|
23
|
-
//
|
|
23
|
+
// Workspace settings are pushed last so the error-handler process exists to resolve
|
|
24
24
|
// its slug to an id.
|
|
25
25
|
await push_6.default.run(args);
|
|
26
26
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ApiClientCommand from '../../../core/commands/api-client-command';
|
|
2
|
-
export default class
|
|
2
|
+
export default class SettingsAliasesDeleteCommand extends ApiClientCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -5,9 +5,9 @@ const color_1 = require("@oclif/color");
|
|
|
5
5
|
const api_client_command_1 = require("../../../core/commands/api-client-command");
|
|
6
6
|
const pull_1 = require("../pull");
|
|
7
7
|
const cli_1 = require("../../../utils/cli");
|
|
8
|
-
class
|
|
8
|
+
class SettingsAliasesDeleteCommand extends api_client_command_1.default {
|
|
9
9
|
async run() {
|
|
10
|
-
const { args: { name }, } = await this.parse(
|
|
10
|
+
const { args: { name }, } = await this.parse(SettingsAliasesDeleteCommand);
|
|
11
11
|
const aliases = await this._fcodeGraphQLClient.allTeamVersionAliases();
|
|
12
12
|
const alias = aliases.find((candidate) => candidate.name === name);
|
|
13
13
|
if (!alias) {
|
|
@@ -20,9 +20,9 @@ class TeamAliasesDeleteCommand extends api_client_command_1.default {
|
|
|
20
20
|
await pull_1.default.run([]);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
SettingsAliasesDeleteCommand.description = 'Delete a workspace version alias and the per-entity aliases carrying its name on every owned process and module';
|
|
24
|
+
SettingsAliasesDeleteCommand.examples = ['$ fcode settings:aliases:delete production'];
|
|
25
|
+
SettingsAliasesDeleteCommand.args = {
|
|
26
26
|
name: core_1.Args.string({ description: 'alias name to delete', required: true }),
|
|
27
27
|
};
|
|
28
|
-
exports.default =
|
|
28
|
+
exports.default = SettingsAliasesDeleteCommand;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ApiClientCommand from '../../../core/commands/api-client-command';
|
|
2
|
-
export default class
|
|
2
|
+
export default class SettingsAliasesListCommand extends ApiClientCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
run(): Promise<void>;
|
|
@@ -3,21 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const color_1 = require("@oclif/color");
|
|
4
4
|
const api_client_command_1 = require("../../../core/commands/api-client-command");
|
|
5
5
|
const cli_1 = require("../../../utils/cli");
|
|
6
|
-
class
|
|
6
|
+
class SettingsAliasesListCommand extends api_client_command_1.default {
|
|
7
7
|
async run() {
|
|
8
|
-
await this.parse(
|
|
8
|
+
await this.parse(SettingsAliasesListCommand);
|
|
9
9
|
const aliases = await this._fcodeGraphQLClient.allTeamVersionAliases();
|
|
10
10
|
if (aliases.length === 0) {
|
|
11
|
-
cli_1.default.log('📋 No
|
|
12
|
-
cli_1.default.log(`Create one with ${color_1.default.cyan('fcode
|
|
11
|
+
cli_1.default.log('📋 No workspace version aliases yet.');
|
|
12
|
+
cli_1.default.log(`Create one with ${color_1.default.cyan('fcode settings:aliases:set [name] [tag]')}`);
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
|
-
cli_1.default.log('🔗
|
|
15
|
+
cli_1.default.log('🔗 Workspace version aliases:\n');
|
|
16
16
|
for (const alias of aliases) {
|
|
17
17
|
cli_1.default.log(` ${color_1.default.cyan(alias.name)} → ${alias.tag}`);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exports.default =
|
|
21
|
+
SettingsAliasesListCommand.description = 'List the workspace version aliases of the active workspace';
|
|
22
|
+
SettingsAliasesListCommand.examples = ['$ fcode settings:aliases:list'];
|
|
23
|
+
exports.default = SettingsAliasesListCommand;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ApiClientCommand from '../../../core/commands/api-client-command';
|
|
2
|
-
export default class
|
|
2
|
+
export default class SettingsAliasesSetCommand extends ApiClientCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -5,21 +5,21 @@ const color_1 = require("@oclif/color");
|
|
|
5
5
|
const api_client_command_1 = require("../../../core/commands/api-client-command");
|
|
6
6
|
const pull_1 = require("../pull");
|
|
7
7
|
const cli_1 = require("../../../utils/cli");
|
|
8
|
-
class
|
|
8
|
+
class SettingsAliasesSetCommand extends api_client_command_1.default {
|
|
9
9
|
async run() {
|
|
10
|
-
const { args: { name, tag }, } = await this.parse(
|
|
10
|
+
const { args: { name, tag }, } = await this.parse(SettingsAliasesSetCommand);
|
|
11
11
|
cli_1.default.log(color_1.default.cyan(`\n🔗 pointing alias ${name} at ${tag}...`));
|
|
12
12
|
await this._fcodeGraphQLClient.createTeamVersionAlias(name, tag);
|
|
13
13
|
cli_1.default.log(color_1.default.green(`✅ alias ${name} → ${tag}`));
|
|
14
|
-
// Aliases have no folder representation; refreshing
|
|
14
|
+
// Aliases have no folder representation; refreshing settings.json is enough.
|
|
15
15
|
await pull_1.default.run([]);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
SettingsAliasesSetCommand.description = 'Create or re-point a workspace version alias, upserting the per-entity alias on every owned ' +
|
|
19
19
|
'process and module that has the target tag published';
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
SettingsAliasesSetCommand.examples = ['$ fcode settings:aliases:set production v1.0.0'];
|
|
21
|
+
SettingsAliasesSetCommand.args = {
|
|
22
22
|
name: core_1.Args.string({ description: 'alias name (e.g. production)', required: true }),
|
|
23
|
-
tag: core_1.Args.string({ description: '
|
|
23
|
+
tag: core_1.Args.string({ description: 'workspace version tag the alias points at', required: true }),
|
|
24
24
|
};
|
|
25
|
-
exports.default =
|
|
25
|
+
exports.default = SettingsAliasesSetCommand;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import ApiClientCommand from '../../core/commands/api-client-command';
|
|
2
|
+
import SettingsRepository from '../../repositories/settings';
|
|
3
|
+
export default class SettingsDiffCommand extends ApiClientCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
_settingsRepository: SettingsRepository;
|
|
7
|
+
run(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const color_1 = require("@oclif/color");
|
|
4
|
+
const api_client_command_1 = require("../../core/commands/api-client-command");
|
|
5
|
+
const settings_1 = require("../../repositories/settings");
|
|
6
|
+
const cli_1 = require("../../utils/cli");
|
|
7
|
+
const diff_1 = require("../../utils/diff");
|
|
8
|
+
const resource_differ_1 = require("../../services/resource-differ");
|
|
9
|
+
class SettingsDiffCommand extends api_client_command_1.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this._settingsRepository = new settings_1.default();
|
|
13
|
+
}
|
|
14
|
+
async run() {
|
|
15
|
+
await this.parse(SettingsDiffCommand);
|
|
16
|
+
cli_1.default.log(color_1.default.cyan('\nsettings diff'));
|
|
17
|
+
const [raw, versions, aliases] = await Promise.all([
|
|
18
|
+
this._fcodeGraphQLClient.team(),
|
|
19
|
+
this._fcodeGraphQLClient.allTeamVersions(),
|
|
20
|
+
this._fcodeGraphQLClient.allTeamVersionAliases(),
|
|
21
|
+
]);
|
|
22
|
+
const remote = await this._settingsRepository.fromRaw(raw);
|
|
23
|
+
this._settingsRepository.applyCloudVersioning(remote, versions, aliases);
|
|
24
|
+
const local = this._settingsRepository.exists() ? await this._settingsRepository.find() : undefined;
|
|
25
|
+
// Gated on the content hash rather than on the rendered bytes: a version's server-assigned
|
|
26
|
+
// createdAt is in settings.json but not in the hash, and it must not read as a local change.
|
|
27
|
+
if (local && local.contentHash === remote.contentHash) {
|
|
28
|
+
cli_1.default.log(color_1.default.green('✅ workspace settings up to date'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const file = (0, resource_differ_1.settingsDiffFile)(this._settingsRepository.toFile(remote), local && this._settingsRepository.toFile(local));
|
|
32
|
+
cli_1.default.log('');
|
|
33
|
+
cli_1.default.log((0, diff_1.colorizeDiff)((0, diff_1.renderUnifiedDiff)(file)));
|
|
34
|
+
this.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
SettingsDiffCommand.description = 'Show a unified diff between local workspace settings (settings.json) and the cloud. Exits 1 when they differ';
|
|
38
|
+
SettingsDiffCommand.examples = ['$ fcode settings:diff'];
|
|
39
|
+
exports.default = SettingsDiffCommand;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import ApiClientCommand from '../../core/commands/api-client-command';
|
|
2
|
+
import SettingsRepository from '../../repositories/settings';
|
|
3
|
+
export default class SettingsPullCommand extends ApiClientCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
_settingsRepository: SettingsRepository;
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const color_1 = require("@oclif/color");
|
|
4
|
+
const api_client_command_1 = require("../../core/commands/api-client-command");
|
|
5
|
+
const settings_1 = require("../../repositories/settings");
|
|
6
|
+
const types_1 = require("../../core/types");
|
|
7
|
+
const cli_1 = require("../../utils/cli");
|
|
8
|
+
class SettingsPullCommand extends api_client_command_1.default {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this._settingsRepository = new settings_1.default();
|
|
12
|
+
}
|
|
13
|
+
async run() {
|
|
14
|
+
const { flags: { force }, } = await this.parse(SettingsPullCommand);
|
|
15
|
+
cli_1.default.log(color_1.default.cyan('\n🗄️ pulling workspace settings...'));
|
|
16
|
+
// Local edits (a version tag added, an alias re-pointed) would be silently wiped by the
|
|
17
|
+
// overwrite below, so an unpushed settings.json blocks the pull. No stored hash means there is
|
|
18
|
+
// no baseline to have diverged from (fresh workspace), so the pull proceeds.
|
|
19
|
+
if (!force && this._settingsRepository.exists()) {
|
|
20
|
+
const local = await this._settingsRepository.find();
|
|
21
|
+
const storedHash = await this.workspaceConfig.getSettingsStoredHash();
|
|
22
|
+
if (storedHash !== undefined && storedHash !== local.contentHash) {
|
|
23
|
+
cli_1.default.log(color_1.default.yellow('🔺 settings.json has unpushed local changes — run fcode settings:push first, or fcode settings:pull --force to overwrite them'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const [raw, versions, aliases] = await Promise.all([
|
|
28
|
+
this._fcodeGraphQLClient.team(),
|
|
29
|
+
this._fcodeGraphQLClient.allTeamVersions(),
|
|
30
|
+
this._fcodeGraphQLClient.allTeamVersionAliases(),
|
|
31
|
+
]);
|
|
32
|
+
const settings = await this._settingsRepository.fromRaw(raw);
|
|
33
|
+
this._settingsRepository.applyCloudVersioning(settings, versions, aliases);
|
|
34
|
+
this._settingsRepository.save(settings);
|
|
35
|
+
await this.workspaceConfig.setSettingsStoredHash(settings.contentHash);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
SettingsPullCommand.description = 'Fetch workspace settings (timezone, error handler, inheritance) and workspace versions/aliases from cloud into settings.json';
|
|
39
|
+
SettingsPullCommand.examples = ['$ fcode settings:pull'];
|
|
40
|
+
SettingsPullCommand.flags = types_1.ForceFlag;
|
|
41
|
+
exports.default = SettingsPullCommand;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import ApiClientCommand from '../../core/commands/api-client-command';
|
|
2
|
-
import
|
|
3
|
-
export default class
|
|
2
|
+
import SettingsRepository from '../../repositories/settings';
|
|
3
|
+
export default class SettingsPushCommand extends ApiClientCommand {
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
7
7
|
force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
_settingsRepository: SettingsRepository;
|
|
10
10
|
run(): Promise<void>;
|
|
11
|
-
/** Makes the cloud's
|
|
11
|
+
/** Makes the cloud's versions/aliases match settings.json; returns failed manifest entries. */
|
|
12
12
|
private syncVersioning;
|
|
13
13
|
}
|
|
@@ -2,87 +2,87 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const color_1 = require("@oclif/color");
|
|
4
4
|
const api_client_command_1 = require("../../core/commands/api-client-command");
|
|
5
|
-
const
|
|
5
|
+
const settings_1 = require("../../repositories/settings");
|
|
6
6
|
const types_1 = require("../../core/types");
|
|
7
7
|
const team_versioning_1 = require("../../services/team-versioning");
|
|
8
8
|
const cli_1 = require("../../utils/cli");
|
|
9
|
-
class
|
|
9
|
+
class SettingsPushCommand extends api_client_command_1.default {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
|
-
this.
|
|
12
|
+
this._settingsRepository = new settings_1.default();
|
|
13
13
|
}
|
|
14
14
|
async run() {
|
|
15
|
-
const { flags: { force }, } = await this.parse(
|
|
16
|
-
if (!this.
|
|
15
|
+
const { flags: { force }, } = await this.parse(SettingsPushCommand);
|
|
16
|
+
if (!this._settingsRepository.exists()) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
cli_1.default.log(color_1.default.cyan('\n☁️ pushing
|
|
20
|
-
const
|
|
21
|
-
const storedHash = await this.workspaceConfig.
|
|
22
|
-
if (!force && storedHash ===
|
|
23
|
-
cli_1.default.log('
|
|
19
|
+
cli_1.default.log(color_1.default.cyan('\n☁️ pushing workspace settings...'));
|
|
20
|
+
const settings = await this._settingsRepository.find();
|
|
21
|
+
const storedHash = await this.workspaceConfig.getSettingsStoredHash();
|
|
22
|
+
if (!force && storedHash === settings.contentHash) {
|
|
23
|
+
cli_1.default.log('Workspace settings already up to date');
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
const update = {
|
|
27
|
-
if (
|
|
28
|
-
update.zoneId =
|
|
26
|
+
const update = { parentTeams: settings.parentTeams };
|
|
27
|
+
if (settings.zoneId !== undefined) {
|
|
28
|
+
update.zoneId = settings.zoneId;
|
|
29
29
|
}
|
|
30
|
-
if (
|
|
31
|
-
const processId = await this.
|
|
32
|
-
update.executionErrorHandlerConfig = { processId, tag:
|
|
30
|
+
if (settings.errorHandlerConfig) {
|
|
31
|
+
const processId = await this._settingsRepository.resolveSlugToId(settings.errorHandlerConfig.processSlug);
|
|
32
|
+
update.executionErrorHandlerConfig = { processId, tag: settings.errorHandlerConfig.tag ?? null };
|
|
33
33
|
}
|
|
34
|
-
// Sent unconditionally, null arm included:
|
|
34
|
+
// Sent unconditionally, null arm included: settings.json is the source of truth, so removing
|
|
35
35
|
// webhookAuth from it must clear the cloud configuration rather than leave it dangling.
|
|
36
|
-
update.webhookAuth =
|
|
37
|
-
? { headerName:
|
|
36
|
+
update.webhookAuth = settings.webhookAuth
|
|
37
|
+
? { headerName: settings.webhookAuth.headerName ?? null, variableKey: settings.webhookAuth.variableKey }
|
|
38
38
|
: { variableKey: null };
|
|
39
|
-
// Sent unconditionally for the same reason as webhookAuth:
|
|
39
|
+
// Sent unconditionally for the same reason as webhookAuth: settings.json is the source of truth,
|
|
40
40
|
// so removing primaryLocale from it must clear the cloud setting. Empty string is the clear.
|
|
41
|
-
update.primaryLocale =
|
|
41
|
+
update.primaryLocale = settings.primaryLocale ?? '';
|
|
42
42
|
await this._fcodeGraphQLClient.pushTeam(update);
|
|
43
|
-
const failedEntities = await this.syncVersioning(
|
|
43
|
+
const failedEntities = await this.syncVersioning(settings, force);
|
|
44
44
|
// Re-read the cloud state so server-assigned fields (createdAt) and declined deletions
|
|
45
|
-
// land back in
|
|
45
|
+
// land back in settings.json, then hash exactly what was written.
|
|
46
46
|
const [versions, aliases] = await Promise.all([
|
|
47
47
|
this._fcodeGraphQLClient.allTeamVersions(),
|
|
48
48
|
this._fcodeGraphQLClient.allTeamVersionAliases(),
|
|
49
49
|
]);
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
52
|
-
await this.workspaceConfig.
|
|
53
|
-
cli_1.default.log(color_1.default.green('✅
|
|
50
|
+
this._settingsRepository.applyCloudVersioning(settings, versions, aliases);
|
|
51
|
+
this._settingsRepository.save(settings);
|
|
52
|
+
await this.workspaceConfig.setSettingsStoredHash(settings.contentHash);
|
|
53
|
+
cli_1.default.log(color_1.default.green('✅ workspace settings pushed'));
|
|
54
54
|
// Release pipelines must be able to detect an incomplete version. Re-running the
|
|
55
55
|
// command converges: it publishes only what is still missing.
|
|
56
56
|
if (failedEntities > 0) {
|
|
57
|
-
this.error(`
|
|
57
|
+
this.error(`workspace versions pushed with ${failedEntities} failed entities`, { exit: 1 });
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
/** Makes the cloud's
|
|
61
|
-
async syncVersioning(
|
|
60
|
+
/** Makes the cloud's versions/aliases match settings.json; returns failed manifest entries. */
|
|
61
|
+
async syncVersioning(settings, force) {
|
|
62
62
|
const [cloudVersions, cloudAliases] = await Promise.all([
|
|
63
63
|
this._fcodeGraphQLClient.allTeamVersions(),
|
|
64
64
|
this._fcodeGraphQLClient.allTeamVersionAliases(),
|
|
65
65
|
]);
|
|
66
|
-
const plan = (0, team_versioning_1.planTeamVersioningSync)(
|
|
66
|
+
const plan = (0, team_versioning_1.planTeamVersioningSync)(settings, cloudVersions, cloudAliases);
|
|
67
67
|
if ((0, team_versioning_1.teamVersioningSyncPlanIsEmpty)(plan)) {
|
|
68
68
|
return 0;
|
|
69
69
|
}
|
|
70
70
|
let failedEntities = 0;
|
|
71
71
|
for (const version of plan.createVersions) {
|
|
72
|
-
cli_1.default.log(color_1.default.cyan(`🏷️ publishing
|
|
72
|
+
cli_1.default.log(color_1.default.cyan(`🏷️ publishing workspace version ${version.tag}...`));
|
|
73
73
|
const teamVersion = await this._fcodeGraphQLClient.createTeamVersion(version.tag, version.comment);
|
|
74
74
|
failedEntities += (0, team_versioning_1.logTeamVersionManifest)(teamVersion);
|
|
75
75
|
}
|
|
76
76
|
for (const version of plan.deleteVersions) {
|
|
77
77
|
if (!force) {
|
|
78
|
-
const confirmed = await cli_1.default.confirm(`
|
|
78
|
+
const confirmed = await cli_1.default.confirm(`Workspace version ${version.tag} exists in the cloud but not in settings.json. Deleting it also deletes ` +
|
|
79
79
|
'every process/module version with that tag, plus the aliases, executions and schedules ' +
|
|
80
80
|
'referencing them. Delete it?');
|
|
81
81
|
if (!confirmed) {
|
|
82
82
|
continue;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
cli_1.default.log(color_1.default.cyan(`🗑️ deleting
|
|
85
|
+
cli_1.default.log(color_1.default.cyan(`🗑️ deleting workspace version ${version.tag}...`));
|
|
86
86
|
await this._fcodeGraphQLClient.deleteTeamVersion(version.tag);
|
|
87
87
|
}
|
|
88
88
|
for (const alias of plan.setAliases) {
|
|
@@ -96,8 +96,8 @@ class TeamPushCommand extends api_client_command_1.default {
|
|
|
96
96
|
return failedEntities;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
|
|
100
|
-
'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
exports.default =
|
|
99
|
+
SettingsPushCommand.description = 'Update cloud workspace settings (timezone, error handler, inheritance, webhook auth) and sync ' +
|
|
100
|
+
'workspace versions/aliases from settings.json';
|
|
101
|
+
SettingsPushCommand.examples = ['$ fcode settings:push'];
|
|
102
|
+
SettingsPushCommand.flags = types_1.ForceFlag;
|
|
103
|
+
exports.default = SettingsPushCommand;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import ApiClientCommand from '../../core/commands/api-client-command';
|
|
2
|
+
import SettingsRepository from '../../repositories/settings';
|
|
3
|
+
export default class SettingsStatusCommand extends ApiClientCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
_settingsRepository: SettingsRepository;
|
|
7
|
+
run(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const color_1 = require("@oclif/color");
|
|
4
|
+
const api_client_command_1 = require("../../core/commands/api-client-command");
|
|
5
|
+
const settings_1 = require("../../repositories/settings");
|
|
6
|
+
const cli_1 = require("../../utils/cli");
|
|
7
|
+
class SettingsStatusCommand extends api_client_command_1.default {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this._settingsRepository = new settings_1.default();
|
|
11
|
+
}
|
|
12
|
+
async run() {
|
|
13
|
+
await this.parse(SettingsStatusCommand);
|
|
14
|
+
cli_1.default.log(color_1.default.cyan('\nsettings status'));
|
|
15
|
+
if (!this._settingsRepository.exists()) {
|
|
16
|
+
cli_1.default.log('No settings.json found');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const local = await this._settingsRepository.find();
|
|
20
|
+
const storedHash = await this.workspaceConfig.getSettingsStoredHash();
|
|
21
|
+
const [raw, versions, aliases] = await Promise.all([
|
|
22
|
+
this._fcodeGraphQLClient.team(),
|
|
23
|
+
this._fcodeGraphQLClient.allTeamVersions(),
|
|
24
|
+
this._fcodeGraphQLClient.allTeamVersionAliases(),
|
|
25
|
+
]);
|
|
26
|
+
const remote = await this._settingsRepository.fromRaw(raw);
|
|
27
|
+
this._settingsRepository.applyCloudVersioning(remote, versions, aliases);
|
|
28
|
+
const localChanged = storedHash !== local.contentHash;
|
|
29
|
+
const remoteChanged = storedHash !== remote.contentHash;
|
|
30
|
+
if (localChanged && remoteChanged) {
|
|
31
|
+
cli_1.default.log(color_1.default.red('🔥 workspace settings conflict (changed both locally and in the cloud)'));
|
|
32
|
+
}
|
|
33
|
+
else if (localChanged) {
|
|
34
|
+
cli_1.default.log(color_1.default.yellow('🔺 workspace settings modified locally (run fcode settings:push)'));
|
|
35
|
+
}
|
|
36
|
+
else if (remoteChanged) {
|
|
37
|
+
cli_1.default.log(color_1.default.yellow('🔻 workspace settings out of date (run fcode settings:pull)'));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
cli_1.default.log(color_1.default.green('✅ workspace settings up to date'));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
SettingsStatusCommand.description = 'Show whether workspace settings (timezone, error handler, inheritance) or workspace versions/aliases differ from the cloud';
|
|
45
|
+
SettingsStatusCommand.examples = ['$ fcode settings:status'];
|
|
46
|
+
exports.default = SettingsStatusCommand;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ApiClientCommand from '../../../core/commands/api-client-command';
|
|
2
|
-
export default class
|
|
2
|
+
export default class SettingsVersionsCreateCommand extends ApiClientCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -6,28 +6,31 @@ const api_client_command_1 = require("../../../core/commands/api-client-command"
|
|
|
6
6
|
const pull_1 = require("../../pull");
|
|
7
7
|
const team_versioning_1 = require("../../../services/team-versioning");
|
|
8
8
|
const cli_1 = require("../../../utils/cli");
|
|
9
|
-
class
|
|
9
|
+
class SettingsVersionsCreateCommand extends api_client_command_1.default {
|
|
10
10
|
async run() {
|
|
11
|
-
const { args: { tag }, flags: { comment }, } = await this.parse(
|
|
12
|
-
cli_1.default.log(color_1.default.cyan(`\n🏷️ publishing
|
|
11
|
+
const { args: { tag }, flags: { comment }, } = await this.parse(SettingsVersionsCreateCommand);
|
|
12
|
+
cli_1.default.log(color_1.default.cyan(`\n🏷️ publishing workspace version ${tag}...`));
|
|
13
13
|
const teamVersion = await this._fcodeGraphQLClient.createTeamVersion(tag, comment);
|
|
14
14
|
const failedCount = (0, team_versioning_1.logTeamVersionManifest)(teamVersion);
|
|
15
|
-
// Refresh the local workspace: per-entity versions/<tag>/ folders and
|
|
15
|
+
// Refresh the local workspace: per-entity versions/<tag>/ folders and settings.json.
|
|
16
16
|
await pull_1.default.run([]);
|
|
17
17
|
// Release pipelines must be able to detect an incomplete version. Re-running the
|
|
18
18
|
// command converges: it publishes only what is still missing.
|
|
19
19
|
if (failedCount > 0) {
|
|
20
|
-
this.error(`
|
|
20
|
+
this.error(`workspace version ${tag} published with ${failedCount} failed entities`, { exit: 1 });
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
SettingsVersionsCreateCommand.description = 'Publish a workspace version: creates a version with the tag on every owned process and module ' +
|
|
25
25
|
'(existing tags are skipped) and pins bare module imports in the published snapshots';
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
SettingsVersionsCreateCommand.examples = [
|
|
27
|
+
'$ fcode settings:versions:create v1.0.0',
|
|
28
|
+
'$ fcode settings:versions:create v1.0.0 --comment "First stable release"',
|
|
29
|
+
];
|
|
30
|
+
SettingsVersionsCreateCommand.args = {
|
|
28
31
|
tag: core_1.Args.string({ description: 'version tag to publish (e.g. v1.0.0)', required: true }),
|
|
29
32
|
};
|
|
30
|
-
|
|
33
|
+
SettingsVersionsCreateCommand.flags = {
|
|
31
34
|
comment: core_1.Flags.string({ char: 'c', description: 'comment describing the version' }),
|
|
32
35
|
};
|
|
33
|
-
exports.default =
|
|
36
|
+
exports.default = SettingsVersionsCreateCommand;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ApiClientCommand from '../../../core/commands/api-client-command';
|
|
2
|
-
export default class
|
|
2
|
+
export default class SettingsVersionsDeleteCommand extends ApiClientCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -6,27 +6,27 @@ const api_client_command_1 = require("../../../core/commands/api-client-command"
|
|
|
6
6
|
const pull_1 = require("../../pull");
|
|
7
7
|
const types_1 = require("../../../core/types");
|
|
8
8
|
const cli_1 = require("../../../utils/cli");
|
|
9
|
-
class
|
|
9
|
+
class SettingsVersionsDeleteCommand extends api_client_command_1.default {
|
|
10
10
|
async run() {
|
|
11
|
-
const { args: { tag }, flags: { force }, } = await this.parse(
|
|
11
|
+
const { args: { tag }, flags: { force }, } = await this.parse(SettingsVersionsDeleteCommand);
|
|
12
12
|
if (!force) {
|
|
13
|
-
const confirmed = await cli_1.default.confirm(`Deleting
|
|
13
|
+
const confirmed = await cli_1.default.confirm(`Deleting workspace version ${tag} also deletes every process/module version with that tag, plus the aliases, executions and schedules referencing them. Continue?`);
|
|
14
14
|
if (!confirmed) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
cli_1.default.log(color_1.default.cyan(`\n🗑️ deleting
|
|
18
|
+
cli_1.default.log(color_1.default.cyan(`\n🗑️ deleting workspace version ${tag}...`));
|
|
19
19
|
await this._fcodeGraphQLClient.deleteTeamVersion(tag);
|
|
20
|
-
cli_1.default.log(color_1.default.green(`✅
|
|
20
|
+
cli_1.default.log(color_1.default.green(`✅ workspace version ${tag} deleted`));
|
|
21
21
|
// Refresh the local workspace so removed versions/<tag>/ folders disappear.
|
|
22
22
|
await pull_1.default.run([]);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
SettingsVersionsDeleteCommand.description = 'Delete a workspace version. CASCADES: every owned process/module version with the tag is deleted, ' +
|
|
26
26
|
'together with the aliases, executions and schedules that reference them';
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
SettingsVersionsDeleteCommand.examples = ['$ fcode settings:versions:delete v1.0.0'];
|
|
28
|
+
SettingsVersionsDeleteCommand.args = {
|
|
29
29
|
tag: core_1.Args.string({ description: 'version tag to delete', required: true }),
|
|
30
30
|
};
|
|
31
|
-
|
|
32
|
-
exports.default =
|
|
31
|
+
SettingsVersionsDeleteCommand.flags = types_1.ForceFlag;
|
|
32
|
+
exports.default = SettingsVersionsDeleteCommand;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ApiClientCommand from '../../../core/commands/api-client-command';
|
|
2
|
-
export default class
|
|
2
|
+
export default class SettingsVersionsListCommand extends ApiClientCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
run(): Promise<void>;
|