@noodleseed/one 0.172.1 → 0.174.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/dist/commands/solutions-draft-source.d.ts +9 -0
- package/dist/commands/solutions-draft-source.d.ts.map +1 -0
- package/dist/commands/solutions-draft-source.js +67 -0
- package/dist/commands/solutions-draft-source.js.map +1 -0
- package/dist/commands/solutions-drafts.d.ts +5 -0
- package/dist/commands/solutions-drafts.d.ts.map +1 -0
- package/dist/commands/solutions-drafts.js +159 -0
- package/dist/commands/solutions-drafts.js.map +1 -0
- package/dist/commands/solutions-ops-args.d.ts +42 -0
- package/dist/commands/solutions-ops-args.d.ts.map +1 -0
- package/dist/commands/solutions-ops-args.js +47 -0
- package/dist/commands/solutions-ops-args.js.map +1 -0
- package/dist/commands/solutions-ops.d.ts.map +1 -1
- package/dist/commands/solutions-ops.js +12 -46
- package/dist/commands/solutions-ops.js.map +1 -1
- package/dist/commands/solutions-page.d.ts +5 -0
- package/dist/commands/solutions-page.d.ts.map +1 -0
- package/dist/commands/solutions-page.js +85 -0
- package/dist/commands/solutions-page.js.map +1 -0
- package/dist/commands/solutions-workspace.d.ts +5 -0
- package/dist/commands/solutions-workspace.d.ts.map +1 -0
- package/dist/commands/solutions-workspace.js +132 -0
- package/dist/commands/solutions-workspace.js.map +1 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-drafts.js +141 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-page.js +57 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-workspace.js +88 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +6 -0
- package/node_modules/@noodle-borg/service/dist/application-drafts/contracts.js +11 -0
- package/node_modules/@noodle-borg/service/dist/application-drafts/paths.js +26 -0
- package/node_modules/@noodle-borg/service/dist/business-information/business-page-paths.js +14 -0
- package/node_modules/@noodle-borg/service/dist/business-information/business-page.d.ts +39 -0
- package/node_modules/@noodle-borg/service/dist/business-information/business-page.js +81 -0
- package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +2 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-business-pages.js +37 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +3 -0
- package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-executable.js +11 -3
- package/node_modules/@noodle-borg/service/dist/business-workspaces/contracts.js +52 -0
- package/node_modules/@noodle-borg/service/dist/business-workspaces/paths.js +17 -0
- package/node_modules/@noodle-borg/service/dist/routes/application-drafts.js +162 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-authoring-dispatch.js +23 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-channels.js +3 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +16 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-pages.js +158 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-workspaces.js +106 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-probes.js +32 -0
- package/node_modules/@noodle-borg/service/dist/service.js +20 -18
- package/node_modules/@noodle-borg/service/dist/solution-installation-activation.js +3 -3
- package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.d.ts +3 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.js +1 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-drafts.d.ts +322 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-drafts.js +152 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-org-transfer.d.ts +8 -8
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-read.d.ts +5 -5
- package/node_modules/@noodle-borg/wire-contracts/dist/business-page.d.ts +157 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-page.js +105 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-workspaces.d.ts +210 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-workspaces.js +102 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/distribution.d.ts +10 -10
- package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +3 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.js +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { BusinessPageClientResponseSchema, BusinessPageContentSchema, } from '@noodle-borg/wire-contracts';
|
|
2
|
+
import { resolveControlPlaneToken, serviceJson } from '../control-plane.js';
|
|
3
|
+
import { EXIT, printJsonOk } from './output.js';
|
|
4
|
+
import { authRequired, parseCommandFlags, printCliFailure, serviceFailure, usageError, } from './shared.js';
|
|
5
|
+
export async function runSolutionPage(rest, env, location, options) {
|
|
6
|
+
const command = 'solutions page';
|
|
7
|
+
const args = parseCommandFlags(rest, {
|
|
8
|
+
values: {
|
|
9
|
+
'--service': 'service',
|
|
10
|
+
'--auth-token': 'authToken',
|
|
11
|
+
'--org': 'org',
|
|
12
|
+
'--expected-revision': 'revision',
|
|
13
|
+
'--data': 'data',
|
|
14
|
+
},
|
|
15
|
+
booleans: { '--json': 'json', '--confirm': 'confirm' },
|
|
16
|
+
});
|
|
17
|
+
const [operation, installation, ...extra] = args.positional;
|
|
18
|
+
const invalid = (message) => printCliFailure(command, usageError(message, 'noodle solutions page <show|save|publish|unpublish> <installation> --org <org> [--expected-revision <n>] [--data <json>] [--confirm] [--json]'), args.json);
|
|
19
|
+
if (args.parseError ||
|
|
20
|
+
!operation ||
|
|
21
|
+
!['show', 'save', 'publish', 'unpublish'].includes(operation) ||
|
|
22
|
+
!installation ||
|
|
23
|
+
!args.org ||
|
|
24
|
+
extra.length)
|
|
25
|
+
return invalid(args.parseError ?? 'Supply an operation, installation and explicit organization.');
|
|
26
|
+
if ((operation !== 'save' && args.data !== undefined) ||
|
|
27
|
+
(operation === 'show' && args.revision !== undefined) ||
|
|
28
|
+
(['show', 'save'].includes(operation) && args.confirm))
|
|
29
|
+
return invalid('A flag does not apply to this operation.');
|
|
30
|
+
const expectedRevision = Number(args.revision);
|
|
31
|
+
if (operation !== 'show' &&
|
|
32
|
+
(!/^\d{1,10}$/.test(args.revision ?? '') ||
|
|
33
|
+
expectedRevision < (operation === 'save' ? 0 : 1) ||
|
|
34
|
+
expectedRevision > 2_147_483_647))
|
|
35
|
+
return invalid('--expected-revision must identify the current saved revision.');
|
|
36
|
+
if (['publish', 'unpublish'].includes(operation) && !args.confirm)
|
|
37
|
+
return invalid('--confirm is required to change public availability.');
|
|
38
|
+
let content;
|
|
39
|
+
if (operation === 'save') {
|
|
40
|
+
try {
|
|
41
|
+
if (!args.data || Buffer.byteLength(args.data, 'utf8') > 256 * 1024)
|
|
42
|
+
return invalid('--data must contain bounded page content JSON.');
|
|
43
|
+
const parsed = BusinessPageContentSchema.safeParse(JSON.parse(args.data));
|
|
44
|
+
if (!parsed.success)
|
|
45
|
+
return invalid('Page content must contain an introduction and up to eight plain-text sections.');
|
|
46
|
+
content = parsed.data;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return invalid('--data must contain valid page content JSON.');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const resolved = await resolveControlPlaneToken({
|
|
53
|
+
serviceFlag: args.service,
|
|
54
|
+
authFlag: args.authToken,
|
|
55
|
+
env,
|
|
56
|
+
home: location,
|
|
57
|
+
});
|
|
58
|
+
if (!resolved.token)
|
|
59
|
+
return printCliFailure(command, authRequired(), args.json);
|
|
60
|
+
const suffix = ['publish', 'unpublish'].includes(operation) ? `/${operation}` : '';
|
|
61
|
+
const url = `${resolved.serviceUrl}/v1/orgs/${encodeURIComponent(args.org)}/solution-installations/${encodeURIComponent(installation)}/page${suffix}`;
|
|
62
|
+
try {
|
|
63
|
+
const result = await serviceJson(url, resolved.token, {
|
|
64
|
+
method: operation === 'show' ? 'GET' : operation === 'save' ? 'PUT' : 'POST',
|
|
65
|
+
headers: { 'content-type': 'application/json' },
|
|
66
|
+
...(operation === 'show'
|
|
67
|
+
? {}
|
|
68
|
+
: {
|
|
69
|
+
body: JSON.stringify(operation === 'save' ? { expectedRevision, content } : { expectedRevision }),
|
|
70
|
+
}),
|
|
71
|
+
}, options.fetchImpl ?? fetch);
|
|
72
|
+
const parsed = BusinessPageClientResponseSchema.safeParse(result);
|
|
73
|
+
if (!parsed.success)
|
|
74
|
+
throw new Error('The service returned an invalid page response.');
|
|
75
|
+
if (args.json)
|
|
76
|
+
printJsonOk(parsed.data.data);
|
|
77
|
+
else
|
|
78
|
+
console.log(`Page revision ${parsed.data.data.revision} · ${parsed.data.data.published ? 'published snapshot saved' : 'not published'}`);
|
|
79
|
+
return EXIT.OK;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
return printCliFailure(command, serviceFailure(command, error, 'noodle solutions page --help'), args.json);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=solutions-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solutions-page.js","sourceRoot":"","sources":["../../src/commands/solutions-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ConfigLocation } from '../config.js';
|
|
2
|
+
export declare function runSolutionWorkspace(rest: readonly string[], env: NodeJS.ProcessEnv, home: ConfigLocation, options: {
|
|
3
|
+
readonly fetchImpl?: typeof fetch;
|
|
4
|
+
}): Promise<number>;
|
|
5
|
+
//# sourceMappingURL=solutions-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solutions-workspace.d.ts","sourceRoot":"","sources":["../../src/commands/solutions-workspace.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAmBnD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GAC7C,OAAO,CAAC,MAAM,CAAC,CAsIjB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { BusinessWorkspaceAcceptRequestSchema, BusinessWorkspaceClientResponseSchema, BusinessWorkspaceInvitationRequestSchema, BusinessWorkspaceIssuedInvitationClientResponseSchema, BusinessWorkspaceMutationClientResponseSchema, BusinessWorkspaceRevisionRequestSchema, BusinessWorkspaceRoleChangeRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
2
|
+
import { resolveControlPlaneToken, serviceJson } from '../control-plane.js';
|
|
3
|
+
import { EXIT, printJsonOk, printRawJsonForHumanDebug } from './output.js';
|
|
4
|
+
import { authRequired, parseCommandFlags, printCliFailure, serviceFailure, usageError, } from './shared.js';
|
|
5
|
+
const operationFlags = {
|
|
6
|
+
show: [],
|
|
7
|
+
invite: ['email', 'role', 'revision'],
|
|
8
|
+
'set-role': ['subject', 'role', 'revision', 'confirm'],
|
|
9
|
+
remove: ['subject', 'revision', 'confirm'],
|
|
10
|
+
'revoke-invitation': ['invitation', 'revision', 'confirm'],
|
|
11
|
+
accept: ['tokenEnv', 'confirm'],
|
|
12
|
+
};
|
|
13
|
+
export async function runSolutionWorkspace(rest, env, home, options) {
|
|
14
|
+
const command = 'solutions workspace';
|
|
15
|
+
const args = parseCommandFlags(rest, {
|
|
16
|
+
values: {
|
|
17
|
+
'--service': 'service',
|
|
18
|
+
'--auth-token': 'authToken',
|
|
19
|
+
'--org': 'org',
|
|
20
|
+
'--email': 'email',
|
|
21
|
+
'--role': 'role',
|
|
22
|
+
'--subject': 'subject',
|
|
23
|
+
'--expected-revision': 'revision',
|
|
24
|
+
'--invitation': 'invitation',
|
|
25
|
+
'--token-from-env': 'tokenEnv',
|
|
26
|
+
},
|
|
27
|
+
booleans: { '--json': 'json', '--confirm': 'confirm' },
|
|
28
|
+
});
|
|
29
|
+
const invalid = (message) => printCliFailure(command, usageError(message, 'noodle solutions workspace <show|invite|set-role|remove|revoke-invitation|accept> --org <org> [options] [--json]'), args.json);
|
|
30
|
+
const [operation, ...extra] = args.positional;
|
|
31
|
+
if (args.parseError ||
|
|
32
|
+
!operation ||
|
|
33
|
+
!operationFlags[operation] ||
|
|
34
|
+
extra.length ||
|
|
35
|
+
!/^[a-z0-9][a-z0-9-]{0,62}$/.test(args.org ?? ''))
|
|
36
|
+
return invalid('Supply a workspace operation and explicit --org.');
|
|
37
|
+
for (const key of [
|
|
38
|
+
'email',
|
|
39
|
+
'role',
|
|
40
|
+
'subject',
|
|
41
|
+
'revision',
|
|
42
|
+
'invitation',
|
|
43
|
+
'tokenEnv',
|
|
44
|
+
'confirm',
|
|
45
|
+
])
|
|
46
|
+
if (args[key] && !operationFlags[operation].includes(key))
|
|
47
|
+
return invalid('A flag does not apply to this operation.');
|
|
48
|
+
if (!['show', 'invite'].includes(operation) && !args.confirm)
|
|
49
|
+
return invalid('--confirm is required for this workspace change.');
|
|
50
|
+
if (!['show', 'accept'].includes(operation) && !/^[1-9]\d{0,9}$/.test(args.revision ?? ''))
|
|
51
|
+
return invalid('--expected-revision must identify the current workspace revision.');
|
|
52
|
+
const expectedRevision = Number(args.revision);
|
|
53
|
+
let body;
|
|
54
|
+
let suffix = '', method = 'GET';
|
|
55
|
+
if (operation === 'invite') {
|
|
56
|
+
const input = BusinessWorkspaceInvitationRequestSchema.safeParse({
|
|
57
|
+
email: args.email,
|
|
58
|
+
expectedRevision,
|
|
59
|
+
...(args.role === undefined ? {} : { role: args.role }),
|
|
60
|
+
});
|
|
61
|
+
if (!input.success)
|
|
62
|
+
return invalid('Supply a valid email, fixed role and expected revision.');
|
|
63
|
+
body = input.data;
|
|
64
|
+
suffix = '/invitations';
|
|
65
|
+
method = 'POST';
|
|
66
|
+
}
|
|
67
|
+
else if (operation === 'set-role' || operation === 'remove') {
|
|
68
|
+
const input = BusinessWorkspaceRoleChangeRequestSchema.safeParse({
|
|
69
|
+
subject: args.subject,
|
|
70
|
+
expectedRevision,
|
|
71
|
+
role: operation === 'remove' ? null : args.role,
|
|
72
|
+
});
|
|
73
|
+
if (!input.success)
|
|
74
|
+
return invalid('Supply a member subject, fixed role and expected revision.');
|
|
75
|
+
body = input.data;
|
|
76
|
+
suffix = '/members';
|
|
77
|
+
method = 'PATCH';
|
|
78
|
+
}
|
|
79
|
+
else if (operation === 'revoke-invitation') {
|
|
80
|
+
const input = BusinessWorkspaceRevisionRequestSchema.safeParse({ expectedRevision });
|
|
81
|
+
if (!input.success ||
|
|
82
|
+
!/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(args.invitation ?? ''))
|
|
83
|
+
return invalid('Supply --invitation <id> and the expected revision.');
|
|
84
|
+
body = input.data;
|
|
85
|
+
suffix = `/invitations/${args.invitation}`;
|
|
86
|
+
method = 'DELETE';
|
|
87
|
+
}
|
|
88
|
+
else if (operation === 'accept') {
|
|
89
|
+
if (!/^[A-Z_][A-Z0-9_]{0,127}$/.test(args.tokenEnv ?? ''))
|
|
90
|
+
return invalid('Supply --token-from-env <NAME>; do not place the invitation token on the command line.');
|
|
91
|
+
const input = BusinessWorkspaceAcceptRequestSchema.safeParse({
|
|
92
|
+
token: env[args.tokenEnv ?? ''],
|
|
93
|
+
});
|
|
94
|
+
if (!input.success)
|
|
95
|
+
return invalid('The selected environment variable must contain a valid invitation token.');
|
|
96
|
+
body = input.data;
|
|
97
|
+
suffix = '/accept';
|
|
98
|
+
method = 'POST';
|
|
99
|
+
}
|
|
100
|
+
const resolved = await resolveControlPlaneToken({
|
|
101
|
+
serviceFlag: args.service,
|
|
102
|
+
authFlag: args.authToken,
|
|
103
|
+
env,
|
|
104
|
+
home,
|
|
105
|
+
});
|
|
106
|
+
if (!resolved.token)
|
|
107
|
+
return printCliFailure(command, authRequired(), args.json);
|
|
108
|
+
try {
|
|
109
|
+
const response = await serviceJson(`${resolved.serviceUrl}/v1/orgs/${encodeURIComponent(args.org ?? '')}/business-workspace${suffix}`, resolved.token, {
|
|
110
|
+
method,
|
|
111
|
+
headers: { 'content-type': 'application/json' },
|
|
112
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
113
|
+
}, options.fetchImpl ?? fetch);
|
|
114
|
+
const schema = operation === 'show'
|
|
115
|
+
? BusinessWorkspaceClientResponseSchema
|
|
116
|
+
: operation === 'invite'
|
|
117
|
+
? BusinessWorkspaceIssuedInvitationClientResponseSchema
|
|
118
|
+
: BusinessWorkspaceMutationClientResponseSchema;
|
|
119
|
+
const parsed = schema.safeParse(response);
|
|
120
|
+
if (!parsed.success)
|
|
121
|
+
throw new Error('The service returned an invalid workspace response.');
|
|
122
|
+
if (args.json)
|
|
123
|
+
printJsonOk(parsed.data.data);
|
|
124
|
+
else
|
|
125
|
+
printRawJsonForHumanDebug(parsed.data.data, 2);
|
|
126
|
+
return EXIT.OK;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return printCliFailure(command, serviceFailure(command, error, 'noodle solutions workspace --help'), args.json);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=solutions-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solutions-workspace.js","sourceRoot":"","sources":["../../src/commands/solutions-workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oCAAoC,EACpC,qCAAqC,EACrC,wCAAwC,EACxC,qDAAqD,EACrD,6CAA6C,EAC7C,sCAAsC,EACtC,wCAAwC,GACzC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,MAAM,cAAc,GAAgD;IAClE,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC;IACrC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC;IACtD,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC;IAC1C,mBAAmB,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC;IAC1D,MAAM,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;CAChC,CAAC;AACF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAuB,EACvB,GAAsB,EACtB,IAAoB,EACpB,OAA8C;IAE9C,MAAM,OAAO,GAAG,qBAAqB,CAAC;IACtC,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,EAAE;QACnC,MAAM,EAAE;YACN,WAAW,EAAE,SAAS;YACtB,cAAc,EAAE,WAAW;YAC3B,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,OAAO;YAClB,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE,SAAS;YACtB,qBAAqB,EAAE,UAAU;YACjC,cAAc,EAAE,YAAY;YAC5B,kBAAkB,EAAE,UAAU;SAC/B;QACD,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE;KACvD,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE,CAClC,eAAe,CACb,OAAO,EACP,UAAU,CACR,OAAO,EACP,kHAAkH,CACnH,EACD,IAAI,CAAC,IAAI,CACV,CAAC;IACJ,MAAM,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;IAC9C,IACE,IAAI,CAAC,UAAU;QACf,CAAC,SAAS;QACV,CAAC,cAAc,CAAC,SAAS,CAAC;QAC1B,KAAK,CAAC,MAAM;QACZ,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;QAEjD,OAAO,OAAO,CAAC,kDAAkD,CAAC,CAAC;IACrE,KAAK,MAAM,GAAG,IAAI;QAChB,OAAO;QACP,MAAM;QACN,SAAS;QACT,UAAU;QACV,YAAY;QACZ,UAAU;QACV,SAAS;KACD;QACR,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvD,OAAO,OAAO,CAAC,0CAA0C,CAAC,CAAC;IAC/D,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO;QAC1D,OAAO,OAAO,CAAC,kDAAkD,CAAC,CAAC;IACrE,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;QACxF,OAAO,OAAO,CAAC,mEAAmE,CAAC,CAAC;IACtF,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,IAAa,CAAC;IAClB,IAAI,MAAM,GAAG,EAAE,EACb,MAAM,GAAG,KAAK,CAAC;IACjB,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,wCAAwC,CAAC,SAAS,CAAC;YAC/D,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,gBAAgB;YAChB,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;SACxD,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,yDAAyD,CAAC,CAAC;QAC9F,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAClB,MAAM,GAAG,cAAc,CAAC;QACxB,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;SAAM,IAAI,SAAS,KAAK,UAAU,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,wCAAwC,CAAC,SAAS,CAAC;YAC/D,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,gBAAgB;YAChB,IAAI,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI;SAChD,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,OAAO;YAChB,OAAO,OAAO,CAAC,4DAA4D,CAAC,CAAC;QAC/E,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAClB,MAAM,GAAG,UAAU,CAAC;QACpB,MAAM,GAAG,OAAO,CAAC;IACnB,CAAC;SAAM,IAAI,SAAS,KAAK,mBAAmB,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,sCAAsC,CAAC,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACrF,IACE,CAAC,KAAK,CAAC,OAAO;YACd,CAAC,gEAAgE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;YAE7F,OAAO,OAAO,CAAC,qDAAqD,CAAC,CAAC;QACxE,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAClB,MAAM,GAAG,gBAAgB,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3C,MAAM,GAAG,QAAQ,CAAC;IACpB,CAAC;SAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;YACvD,OAAO,OAAO,CACZ,wFAAwF,CACzF,CAAC;QACJ,MAAM,KAAK,GAAG,oCAAoC,CAAC,SAAS,CAAC;YAC3D,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,OAAO;YAChB,OAAO,OAAO,CAAC,0EAA0E,CAAC,CAAC;QAC7F,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAClB,MAAM,GAAG,SAAS,CAAC;QACnB,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC;QAC9C,WAAW,EAAE,IAAI,CAAC,OAAO;QACzB,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,GAAG;QACH,IAAI;KACL,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,KAAK;QAAE,OAAO,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAChC,GAAG,QAAQ,CAAC,UAAU,YAAY,kBAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,sBAAsB,MAAM,EAAE,EAClG,QAAQ,CAAC,KAAK,EACd;YACE,MAAM;YACN,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;SAC9D,EACD,OAAO,CAAC,SAAS,IAAI,KAAK,CAC3B,CAAC;QACF,MAAM,MAAM,GACV,SAAS,KAAK,MAAM;YAClB,CAAC,CAAC,qCAAqC;YACvC,CAAC,CAAC,SAAS,KAAK,QAAQ;gBACtB,CAAC,CAAC,qDAAqD;gBACvD,CAAC,CAAC,6CAA6C,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAC5F,IAAI,IAAI,CAAC,IAAI;YAAE,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YACxC,yBAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CACpB,OAAO,EACP,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,mCAAmC,CAAC,EACnE,IAAI,CAAC,IAAI,CACV,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/** Canonical source-draft operations; imported by the solutions family. Data only. */
|
|
2
|
+
import { EXPECTED_REVISION, IDEMPOTENCY_KEY, OPTIONAL_FLAG, REQUIRED_ARGUMENT, SOLUTION_COMMON_FLAGS, } from './catalog-data-solution-flags.js';
|
|
3
|
+
const common = [
|
|
4
|
+
...SOLUTION_COMMON_FLAGS.map((flag) => flag.name === 'org' ? { ...flag, required: true } : flag),
|
|
5
|
+
{
|
|
6
|
+
...OPTIONAL_FLAG,
|
|
7
|
+
name: 'app',
|
|
8
|
+
type: 'string',
|
|
9
|
+
value: '<slug>',
|
|
10
|
+
required: true,
|
|
11
|
+
summary: 'Application slug.',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
const source = [
|
|
15
|
+
{
|
|
16
|
+
...OPTIONAL_FLAG,
|
|
17
|
+
name: 'source-dir',
|
|
18
|
+
type: 'string',
|
|
19
|
+
value: '<directory>',
|
|
20
|
+
required: true,
|
|
21
|
+
summary: 'Directory containing bounded TypeScript application source; no symlinks or environment files.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
...OPTIONAL_FLAG,
|
|
25
|
+
name: 'entrypoint',
|
|
26
|
+
type: 'string',
|
|
27
|
+
value: '<path>',
|
|
28
|
+
summary: 'Relative TypeScript entrypoint.',
|
|
29
|
+
constraints: { default: 'server.ts' },
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
const draftId = { ...REQUIRED_ARGUMENT, name: 'draft-id', summary: 'Saved draft identifier.' };
|
|
33
|
+
const revision = { ...EXPECTED_REVISION, constraints: { minimum: 1, maximum: 2147483647 } };
|
|
34
|
+
export const SOLUTION_DRAFTS = {
|
|
35
|
+
name: 'drafts',
|
|
36
|
+
summary: 'Save and inspect private application source without publishing it.',
|
|
37
|
+
arguments: [],
|
|
38
|
+
flags: [],
|
|
39
|
+
subcommands: [
|
|
40
|
+
{
|
|
41
|
+
name: 'history',
|
|
42
|
+
summary: 'List source-free revisions, newest first.',
|
|
43
|
+
arguments: [draftId],
|
|
44
|
+
flags: common,
|
|
45
|
+
jsonOutput: { mode: 'single' },
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'diff',
|
|
49
|
+
summary: 'Compare exact source and entrypoints at two revisions.',
|
|
50
|
+
arguments: [draftId],
|
|
51
|
+
flags: [
|
|
52
|
+
...common,
|
|
53
|
+
{ ...revision, name: 'from-revision', summary: 'Revision to compare from.' },
|
|
54
|
+
{ ...revision, name: 'to-revision', summary: 'Revision to compare to.' },
|
|
55
|
+
],
|
|
56
|
+
jsonOutput: { mode: 'single' },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'list',
|
|
60
|
+
summary: 'List source-free draft summaries.',
|
|
61
|
+
arguments: [],
|
|
62
|
+
flags: common,
|
|
63
|
+
jsonOutput: { mode: 'single' },
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'show',
|
|
67
|
+
summary: 'Read an authorized exact draft revision.',
|
|
68
|
+
arguments: [draftId],
|
|
69
|
+
flags: [
|
|
70
|
+
...common,
|
|
71
|
+
{
|
|
72
|
+
...revision,
|
|
73
|
+
name: 'revision',
|
|
74
|
+
required: false,
|
|
75
|
+
summary: 'Revision to read; defaults to the current revision.',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
jsonOutput: { mode: 'single' },
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'create',
|
|
82
|
+
summary: 'Save a new private draft from TypeScript source.',
|
|
83
|
+
arguments: [],
|
|
84
|
+
flags: [
|
|
85
|
+
...common,
|
|
86
|
+
...source,
|
|
87
|
+
IDEMPOTENCY_KEY,
|
|
88
|
+
{
|
|
89
|
+
...OPTIONAL_FLAG,
|
|
90
|
+
name: 'env',
|
|
91
|
+
type: 'string',
|
|
92
|
+
value: '<slug>',
|
|
93
|
+
summary: 'Intended publish environment; saving does not deploy.',
|
|
94
|
+
constraints: { default: 'prod' },
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
jsonOutput: { mode: 'single' },
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'edit',
|
|
101
|
+
summary: 'Append a revision without overwriting concurrent work.',
|
|
102
|
+
arguments: [draftId],
|
|
103
|
+
flags: [...common, ...source, revision, IDEMPOTENCY_KEY],
|
|
104
|
+
jsonOutput: { mode: 'single' },
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'undo',
|
|
108
|
+
summary: 'Restore an earlier source revision as a new revision.',
|
|
109
|
+
arguments: [draftId],
|
|
110
|
+
flags: [
|
|
111
|
+
...common,
|
|
112
|
+
revision,
|
|
113
|
+
IDEMPOTENCY_KEY,
|
|
114
|
+
{
|
|
115
|
+
...revision,
|
|
116
|
+
name: 'target-revision',
|
|
117
|
+
summary: 'Earlier revision whose source will be restored.',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
jsonOutput: { mode: 'single' },
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'delete',
|
|
124
|
+
summary: 'Erase a draft and its source history; published applications are unchanged.',
|
|
125
|
+
arguments: [draftId],
|
|
126
|
+
flags: [
|
|
127
|
+
...common,
|
|
128
|
+
revision,
|
|
129
|
+
{
|
|
130
|
+
...OPTIONAL_FLAG,
|
|
131
|
+
name: 'confirm',
|
|
132
|
+
type: 'boolean',
|
|
133
|
+
required: true,
|
|
134
|
+
summary: 'Confirm erasing the draft source and history.',
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
jsonOutput: { mode: 'single' },
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=catalog-data-solution-drafts.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Hosted-page operator catalog. Pure data; execution remains in the CLI. */
|
|
2
|
+
import { EXPECTED_REVISION, INSTALLATION_ARGUMENT, OPTIONAL_FLAG, SOLUTION_COMMON_FLAGS, } from './catalog-data-solution-flags.js';
|
|
3
|
+
const common = SOLUTION_COMMON_FLAGS.map((flag) => flag.name === 'org' ? { ...flag, required: true } : flag);
|
|
4
|
+
const revision = {
|
|
5
|
+
...EXPECTED_REVISION,
|
|
6
|
+
constraints: { minimum: 1, maximum: 2147483647 },
|
|
7
|
+
};
|
|
8
|
+
const confirm = {
|
|
9
|
+
...OPTIONAL_FLAG,
|
|
10
|
+
name: 'confirm',
|
|
11
|
+
type: 'boolean',
|
|
12
|
+
required: true,
|
|
13
|
+
summary: 'Confirm changing public page availability.',
|
|
14
|
+
};
|
|
15
|
+
export const SOLUTION_PAGE = {
|
|
16
|
+
name: 'page',
|
|
17
|
+
summary: 'Edit and explicitly publish a Noodle Seed-hosted business page.',
|
|
18
|
+
arguments: [],
|
|
19
|
+
flags: [],
|
|
20
|
+
subcommands: [
|
|
21
|
+
{
|
|
22
|
+
name: 'show',
|
|
23
|
+
summary: 'Inspect the private page draft and its published snapshot.',
|
|
24
|
+
arguments: [INSTALLATION_ARGUMENT],
|
|
25
|
+
flags: common,
|
|
26
|
+
jsonOutput: { mode: 'single' },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'save',
|
|
30
|
+
summary: 'Save page content without changing the published page.',
|
|
31
|
+
arguments: [INSTALLATION_ARGUMENT],
|
|
32
|
+
flags: [
|
|
33
|
+
...common,
|
|
34
|
+
{ ...revision, constraints: { minimum: 0, maximum: 2147483647 } },
|
|
35
|
+
{
|
|
36
|
+
...OPTIONAL_FLAG,
|
|
37
|
+
name: 'data',
|
|
38
|
+
type: 'string',
|
|
39
|
+
value: '<json>',
|
|
40
|
+
required: true,
|
|
41
|
+
summary: 'Bounded JSON with introduction and sections containing title/text; plain text only.',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
jsonOutput: { mode: 'single' },
|
|
45
|
+
},
|
|
46
|
+
...['publish', 'unpublish'].map((name) => ({
|
|
47
|
+
name,
|
|
48
|
+
summary: name === 'publish'
|
|
49
|
+
? 'Publish the exact saved page after public-assistant readiness checks.'
|
|
50
|
+
: 'Remove the public page while retaining its private draft.',
|
|
51
|
+
arguments: [INSTALLATION_ARGUMENT],
|
|
52
|
+
flags: [...common, revision, confirm],
|
|
53
|
+
jsonOutput: { mode: 'single' },
|
|
54
|
+
})),
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=catalog-data-solution-page.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** Fixed-role workspace administration. No execution or business permission authority lives here. */
|
|
2
|
+
import { EXPECTED_REVISION, OPTIONAL_FLAG, SOLUTION_COMMON_FLAGS, } from './catalog-data-solution-flags.js';
|
|
3
|
+
const common = SOLUTION_COMMON_FLAGS.map((flag) => flag.name === 'org' ? { ...flag, required: true } : flag);
|
|
4
|
+
const confirm = {
|
|
5
|
+
...OPTIONAL_FLAG,
|
|
6
|
+
name: 'confirm',
|
|
7
|
+
type: 'boolean',
|
|
8
|
+
required: true,
|
|
9
|
+
summary: 'Confirm this workspace access change.',
|
|
10
|
+
};
|
|
11
|
+
const value = (name, summary) => ({
|
|
12
|
+
...OPTIONAL_FLAG,
|
|
13
|
+
name,
|
|
14
|
+
summary,
|
|
15
|
+
type: 'string',
|
|
16
|
+
required: true,
|
|
17
|
+
value: '<value>',
|
|
18
|
+
});
|
|
19
|
+
const role = {
|
|
20
|
+
...value('role', 'One fixed workspace role.'),
|
|
21
|
+
constraints: { choices: ['owner', 'administrator', 'builder', 'operator', 'viewer'] },
|
|
22
|
+
};
|
|
23
|
+
const subject = value('subject', 'Canonical member subject from workspace show.');
|
|
24
|
+
export const SOLUTION_WORKSPACE = {
|
|
25
|
+
name: 'workspace',
|
|
26
|
+
summary: 'Inspect and administer versioned business workspace access.',
|
|
27
|
+
arguments: [],
|
|
28
|
+
flags: [],
|
|
29
|
+
subcommands: [
|
|
30
|
+
{
|
|
31
|
+
name: 'show',
|
|
32
|
+
summary: 'Inspect current workspace members, permissions and pending invitations.',
|
|
33
|
+
arguments: [],
|
|
34
|
+
flags: common,
|
|
35
|
+
jsonOutput: { mode: 'single' },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'invite',
|
|
39
|
+
summary: 'Create a seven-day invitation; the one-time token is returned only here.',
|
|
40
|
+
arguments: [],
|
|
41
|
+
flags: [
|
|
42
|
+
...common,
|
|
43
|
+
EXPECTED_REVISION,
|
|
44
|
+
value('email', 'Verified email address that may claim this invitation.'),
|
|
45
|
+
{ ...role, required: false, constraints: { ...role.constraints, default: 'operator' } },
|
|
46
|
+
],
|
|
47
|
+
jsonOutput: { mode: 'single' },
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'set-role',
|
|
51
|
+
summary: 'Change a member role under current delegation and last-Owner checks.',
|
|
52
|
+
arguments: [],
|
|
53
|
+
flags: [...common, EXPECTED_REVISION, subject, role, confirm],
|
|
54
|
+
jsonOutput: { mode: 'single' },
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'remove',
|
|
58
|
+
summary: 'Remove a workspace member without removing the last Owner.',
|
|
59
|
+
arguments: [],
|
|
60
|
+
flags: [...common, EXPECTED_REVISION, subject, confirm],
|
|
61
|
+
jsonOutput: { mode: 'single' },
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'revoke-invitation',
|
|
65
|
+
summary: 'Revoke an unclaimed invitation.',
|
|
66
|
+
arguments: [],
|
|
67
|
+
flags: [
|
|
68
|
+
...common,
|
|
69
|
+
EXPECTED_REVISION,
|
|
70
|
+
value('invitation', 'Invitation ID from workspace show.'),
|
|
71
|
+
confirm,
|
|
72
|
+
],
|
|
73
|
+
jsonOutput: { mode: 'single' },
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'accept',
|
|
77
|
+
summary: 'Claim an invitation using the signed-in verified email.',
|
|
78
|
+
arguments: [],
|
|
79
|
+
flags: [
|
|
80
|
+
...common,
|
|
81
|
+
value('token-from-env', 'Environment variable containing the one-time invitation token; not the token itself.'),
|
|
82
|
+
confirm,
|
|
83
|
+
],
|
|
84
|
+
jsonOutput: { mode: 'single' },
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=catalog-data-solution-workspace.js.map
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** Solution installation/operator catalog. Imports only dependency-free sibling data. */
|
|
2
|
+
import { SOLUTION_DRAFTS } from './catalog-data-solution-drafts.js';
|
|
2
3
|
import { AUTH_TOKEN, EXPECTED_REVISION, IDEMPOTENCY_KEY, INSTALLATION_ARGUMENT, JSON_FLAG, OPTIONAL_FLAG, PAGING_FLAGS, REQUIRED_ARGUMENT, SERVICE, SOLUTION_COMMON_FLAGS, } from './catalog-data-solution-flags.js';
|
|
4
|
+
import { SOLUTION_PAGE } from './catalog-data-solution-page.js';
|
|
5
|
+
import { SOLUTION_WORKSPACE } from './catalog-data-solution-workspace.js';
|
|
3
6
|
const APP = {
|
|
4
7
|
...OPTIONAL_FLAG,
|
|
5
8
|
name: 'app',
|
|
@@ -129,6 +132,9 @@ export const CATALOG_SOLUTIONS = {
|
|
|
129
132
|
arguments: [],
|
|
130
133
|
flags: [],
|
|
131
134
|
subcommands: [
|
|
135
|
+
SOLUTION_DRAFTS,
|
|
136
|
+
SOLUTION_PAGE,
|
|
137
|
+
SOLUTION_WORKSPACE,
|
|
132
138
|
{
|
|
133
139
|
name: 'installation-options',
|
|
134
140
|
summary: 'List organizations currently authorized to install solutions.',
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export class ApplicationDraftError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
currentRevision;
|
|
4
|
+
constructor(code, currentRevision) {
|
|
5
|
+
super(code);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.currentRevision = currentRevision;
|
|
8
|
+
this.name = 'ApplicationDraftError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { validateSlug } from '@noodle-borg/control-plane/portable';
|
|
2
|
+
import { ApplicationDraftIdSchema } from '@noodle-borg/wire-contracts';
|
|
3
|
+
export function parseApplicationDraftPath(path) {
|
|
4
|
+
const match = /^\/v1\/orgs\/([a-z0-9-]+)\/apps\/([a-z0-9-]+)\/drafts(?:\/([a-f0-9-]+)(?:\/(undo|history|diff))?)?$/.exec(path);
|
|
5
|
+
const org = match?.[1], app = match?.[2], id = match?.[3], action = match?.[4];
|
|
6
|
+
if (!org || !app || (id !== undefined && !ApplicationDraftIdSchema.safeParse(id).success))
|
|
7
|
+
return undefined;
|
|
8
|
+
try {
|
|
9
|
+
validateSlug('org', org);
|
|
10
|
+
validateSlug('app', app);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
return { org, app, ...(id ? { id } : {}), ...(action ? { action } : {}) };
|
|
16
|
+
}
|
|
17
|
+
export function applicationDraftMethods(ref) {
|
|
18
|
+
return ref.action === 'undo'
|
|
19
|
+
? ['POST']
|
|
20
|
+
: ref.action
|
|
21
|
+
? ['GET']
|
|
22
|
+
: ref.id
|
|
23
|
+
? ['GET', 'PATCH', 'DELETE']
|
|
24
|
+
: ['GET', 'POST'];
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function parseBusinessPagePath(path) {
|
|
2
|
+
const match = /^\/v1\/orgs\/([a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?)\/solution-installations\/([a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?)\/page(?:\/(publish|unpublish))?$/.exec(path);
|
|
3
|
+
return match
|
|
4
|
+
? {
|
|
5
|
+
org: match[1],
|
|
6
|
+
installationId: match[2],
|
|
7
|
+
...(match[3] ? { operation: match[3] } : {}),
|
|
8
|
+
}
|
|
9
|
+
: undefined;
|
|
10
|
+
}
|
|
11
|
+
export function businessPageMethods(ref) {
|
|
12
|
+
return ref.operation ? ['POST'] : ['GET', 'PUT'];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=business-page-paths.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type BusinessPageContent, type BusinessPagePublication } from '@noodle-borg/wire-contracts';
|
|
2
|
+
import type { BusinessNoticeRecord } from './business-notice.js';
|
|
3
|
+
import type { InstallationScope } from './contracts.js';
|
|
4
|
+
export interface BusinessPageRecord {
|
|
5
|
+
readonly revision: number;
|
|
6
|
+
readonly draft: BusinessPageContent;
|
|
7
|
+
readonly published: BusinessPagePublication | null;
|
|
8
|
+
readonly updatedAt: string;
|
|
9
|
+
readonly updatedBySubject: string;
|
|
10
|
+
}
|
|
11
|
+
export type BusinessPageChange = {
|
|
12
|
+
readonly operation: 'save';
|
|
13
|
+
readonly expectedRevision: number;
|
|
14
|
+
readonly content: BusinessPageContent;
|
|
15
|
+
} | {
|
|
16
|
+
readonly operation: 'publish' | 'unpublish';
|
|
17
|
+
readonly expectedRevision: number;
|
|
18
|
+
};
|
|
19
|
+
export interface BusinessPageInput {
|
|
20
|
+
readonly scope: InstallationScope;
|
|
21
|
+
readonly actorSubject: string;
|
|
22
|
+
readonly change: BusinessPageChange;
|
|
23
|
+
}
|
|
24
|
+
/** Server-only readiness check, never supplied by a browser or persisted as authority. */
|
|
25
|
+
export type BusinessPageReadiness = () => Promise<{
|
|
26
|
+
readonly deploymentId: string;
|
|
27
|
+
}>;
|
|
28
|
+
export interface BusinessPageStore {
|
|
29
|
+
get(scope: InstallationScope): Promise<BusinessPageRecord | undefined>;
|
|
30
|
+
update(input: BusinessPageInput, assertReady?: BusinessPageReadiness): Promise<BusinessPageRecord>;
|
|
31
|
+
}
|
|
32
|
+
export declare class BusinessPageError extends Error {
|
|
33
|
+
readonly code: 'business_page_forbidden' | 'business_page_conflict' | 'business_page_not_ready';
|
|
34
|
+
constructor(code: 'business_page_forbidden' | 'business_page_conflict' | 'business_page_not_ready');
|
|
35
|
+
}
|
|
36
|
+
export declare function nextBusinessPage(current: BusinessPageRecord | undefined, input: BusinessPageInput, now: string, notice: BusinessNoticeRecord | undefined, assertReady?: BusinessPageReadiness): Promise<BusinessPageRecord>;
|
|
37
|
+
/** Validate decrypted storage without surfacing parser excerpts or business text in errors. */
|
|
38
|
+
export declare function decodeBusinessPage(value: unknown, expectedRevision: number): BusinessPageRecord;
|
|
39
|
+
//# sourceMappingURL=business-page.d.ts.map
|