@sanity/runtime-cli 14.13.3 → 15.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 +215 -118
- package/dist/actions/blueprints/blueprint.js +13 -11
- package/dist/actions/blueprints/logs.d.ts +2 -1
- package/dist/actions/blueprints/logs.js +4 -5
- package/dist/actions/blueprints/resources.js +1 -0
- package/dist/actions/blueprints/stacks.d.ts +3 -1
- package/dist/actions/blueprints/stacks.js +11 -2
- package/dist/actions/functions/test.js +1 -1
- package/dist/actions/sanity/access.d.ts +38 -0
- package/dist/actions/sanity/access.js +23 -0
- package/dist/actions/sanity/projects.d.ts +1 -1
- package/dist/baseCommands.d.ts +2 -0
- package/dist/baseCommands.js +8 -5
- package/dist/commands/blueprints/add.js +1 -1
- package/dist/commands/blueprints/deploy.d.ts +2 -0
- package/dist/commands/blueprints/deploy.js +6 -2
- package/dist/commands/blueprints/destroy.js +0 -2
- package/dist/commands/blueprints/info.d.ts +1 -0
- package/dist/commands/blueprints/info.js +3 -1
- package/dist/commands/blueprints/init.js +2 -0
- package/dist/commands/blueprints/logs.d.ts +5 -0
- package/dist/commands/blueprints/logs.js +26 -3
- package/dist/commands/blueprints/mint-deploy-token.d.ts +14 -0
- package/dist/commands/blueprints/mint-deploy-token.js +47 -0
- package/dist/commands/blueprints/plan.d.ts +2 -0
- package/dist/commands/blueprints/plan.js +8 -2
- package/dist/commands/blueprints/promote.d.ts +2 -1
- package/dist/commands/blueprints/promote.js +7 -2
- package/dist/commands/blueprints/stacks.js +1 -1
- package/dist/commands/functions/add.js +1 -1
- package/dist/cores/blueprints/config.js +34 -34
- package/dist/cores/blueprints/doctor.js +7 -7
- package/dist/cores/blueprints/init.js +99 -76
- package/dist/cores/blueprints/logs.d.ts +3 -0
- package/dist/cores/blueprints/logs.js +15 -9
- package/dist/cores/blueprints/mint-deploy-token.d.ts +15 -0
- package/dist/cores/blueprints/mint-deploy-token.js +111 -0
- package/dist/cores/blueprints/promote.d.ts +1 -0
- package/dist/cores/blueprints/promote.js +25 -4
- package/dist/cores/functions/add.js +4 -5
- package/dist/cores/index.d.ts +1 -2
- package/dist/cores/index.js +1 -3
- package/dist/index.d.ts +0 -18
- package/dist/index.js +0 -20
- package/dist/utils/clipboard.d.ts +14 -0
- package/dist/utils/clipboard.js +73 -0
- package/dist/utils/display/errors.d.ts +5 -1
- package/dist/utils/display/prompt.d.ts +55 -15
- package/dist/utils/display/prompt.js +271 -45
- package/oclif.manifest.json +320 -18
- package/package.json +21 -67
- package/dist/actions/blueprints/index.d.ts +0 -16
- package/dist/actions/blueprints/index.js +0 -10
- package/dist/actions/functions/index.d.ts +0 -4
- package/dist/actions/functions/index.js +0 -4
- package/dist/actions/sanity/index.d.ts +0 -1
- package/dist/actions/sanity/index.js +0 -1
- package/dist/cores/blueprints/index.d.ts +0 -20
- package/dist/cores/blueprints/index.js +0 -10
- package/dist/cores/functions/index.d.ts +0 -16
- package/dist/cores/functions/index.js +0 -8
- package/dist/utils/display/index.d.ts +0 -5
- package/dist/utils/display/index.js +0 -5
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.js +0 -8
|
@@ -87,11 +87,11 @@ export async function loadBlueprintFile(fileInfo) {
|
|
|
87
87
|
break;
|
|
88
88
|
}
|
|
89
89
|
default:
|
|
90
|
-
throw Error(`Unsupported
|
|
90
|
+
throw Error(`Unsupported Blueprint manifest extension: ${extension}`);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
catch (err) {
|
|
94
|
-
throw Error(`
|
|
94
|
+
throw Error(`Could not parse Blueprint manifest: ${fileName}\n${err}`);
|
|
95
95
|
}
|
|
96
96
|
// Dynamic modules: extract attached properties, then execute to get raw blueprint
|
|
97
97
|
if (blueprintModule) {
|
|
@@ -100,15 +100,15 @@ export async function loadBlueprintFile(fileInfo) {
|
|
|
100
100
|
rawBlueprint = blueprintModule();
|
|
101
101
|
}
|
|
102
102
|
catch {
|
|
103
|
-
throw Error(`Error executing Blueprint
|
|
103
|
+
throw Error(`Error executing Blueprint manifest: ${fileName}`);
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
else {
|
|
107
|
-
throw Error(`Blueprint ${fileName} must export a default function
|
|
107
|
+
throw Error(`Blueprint manifest ${fileName} must export a default function.`);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
if (typeof rawBlueprint === 'undefined') {
|
|
111
|
-
throw Error('
|
|
111
|
+
throw Error('Could not read Blueprint manifest.');
|
|
112
112
|
}
|
|
113
113
|
return { rawBlueprint, module: blueprintModule };
|
|
114
114
|
}
|
|
@@ -148,8 +148,9 @@ export function parseBlueprintContent(rawBlueprint, options) {
|
|
|
148
148
|
*/
|
|
149
149
|
export async function loadAndParseBlueprint(blueprintPath, options = { validateResources: true }) {
|
|
150
150
|
const fileInfo = findBlueprintFile(blueprintPath);
|
|
151
|
-
if (!fileInfo)
|
|
152
|
-
throw Error('Could not find Blueprint
|
|
151
|
+
if (!fileInfo) {
|
|
152
|
+
throw Error('Could not find a Blueprint manifest (sanity.blueprint.ts, .js, or .json). Run `blueprints init` to create one.');
|
|
153
|
+
}
|
|
153
154
|
const loaded = await loadBlueprintFile(fileInfo);
|
|
154
155
|
const parsed = parseBlueprintContent(loaded.rawBlueprint, options);
|
|
155
156
|
return {
|
|
@@ -169,8 +170,9 @@ export async function loadAndParseBlueprint(blueprintPath, options = { validateR
|
|
|
169
170
|
*/
|
|
170
171
|
export async function readLocalBlueprint(logger, validate, blueprintPath) {
|
|
171
172
|
const fileInfo = findBlueprintFile(blueprintPath);
|
|
172
|
-
if (!fileInfo)
|
|
173
|
-
throw Error('Could not find Blueprint
|
|
173
|
+
if (!fileInfo) {
|
|
174
|
+
throw Error('Could not find a Blueprint manifest (sanity.blueprint.ts, .js, or .json). Run `blueprints init` to create one.');
|
|
175
|
+
}
|
|
174
176
|
// 1. Load blueprint from disk
|
|
175
177
|
const loaded = await loadBlueprintFile(fileInfo);
|
|
176
178
|
const { rawBlueprint } = loaded;
|
|
@@ -226,7 +228,7 @@ export function writeBlueprintToDisk({ blueprintFilePath, jsonContent = JSON_BLU
|
|
|
226
228
|
break;
|
|
227
229
|
}
|
|
228
230
|
default: {
|
|
229
|
-
throw Error(`Unsupported
|
|
231
|
+
throw Error(`Unsupported Blueprint manifest extension: ${extension}`);
|
|
230
232
|
}
|
|
231
233
|
}
|
|
232
234
|
mkdirSync(dir, { recursive: true });
|
|
@@ -236,7 +238,7 @@ export function writeBlueprintToDisk({ blueprintFilePath, jsonContent = JSON_BLU
|
|
|
236
238
|
export function addResourceToBlueprint({ blueprintFilePath, resource, }) {
|
|
237
239
|
const blueprintFile = findBlueprintFile(blueprintFilePath);
|
|
238
240
|
if (!blueprintFile)
|
|
239
|
-
throw Error('Could not find Blueprint
|
|
241
|
+
throw Error('Could not find a Blueprint manifest.');
|
|
240
242
|
const { blueprintFilePath: foundPath, extension } = blueprintFile;
|
|
241
243
|
// modify .json files directly
|
|
242
244
|
if (extension === '.json') {
|
|
@@ -6,8 +6,9 @@ export interface GetLogsParams {
|
|
|
6
6
|
operationId?: string;
|
|
7
7
|
limit?: number;
|
|
8
8
|
before?: string;
|
|
9
|
+
after?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare function getLogs(params: GetLogsParams, auth: AuthParams, logger: Logger): Promise<ActionResponse & {
|
|
11
12
|
logs: BlueprintLog[];
|
|
13
|
+
hasMore: boolean;
|
|
12
14
|
}>;
|
|
13
|
-
export declare function getRecentLogs(logs: BlueprintLog[], limit?: number): BlueprintLog[];
|
|
@@ -14,19 +14,18 @@ export async function getLogs(params, auth, logger) {
|
|
|
14
14
|
url.searchParams.append('limit', String(params.limit));
|
|
15
15
|
if (params.before)
|
|
16
16
|
url.searchParams.append('before', params.before);
|
|
17
|
+
if (params.after)
|
|
18
|
+
url.searchParams.append('after', params.after);
|
|
17
19
|
const response = await fetchFn(url.toString(), {
|
|
18
20
|
headers: getHeaders(auth),
|
|
19
21
|
method: 'GET',
|
|
20
22
|
});
|
|
21
23
|
const result = await response.json();
|
|
24
|
+
const hasMore = response.headers.get('X-Has-More') === 'true';
|
|
22
25
|
return {
|
|
23
26
|
ok: response.ok,
|
|
24
27
|
error: response.ok ? null : result.message || 'Unknown error',
|
|
25
28
|
logs: response.ok ? result : [],
|
|
29
|
+
hasMore: response.ok ? hasMore : false,
|
|
26
30
|
};
|
|
27
31
|
}
|
|
28
|
-
// Get most recent logs, up to a limit
|
|
29
|
-
export function getRecentLogs(logs, limit = 10) {
|
|
30
|
-
const sortedLogs = [...logs].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
31
|
-
return sortedLogs.slice(-limit);
|
|
32
|
-
}
|
|
@@ -107,11 +107,13 @@ interface PromoteStackResponse extends ActionResponse {
|
|
|
107
107
|
stack: Stack & {
|
|
108
108
|
alreadyPromoted: boolean;
|
|
109
109
|
};
|
|
110
|
+
response?: Response;
|
|
110
111
|
}
|
|
111
|
-
export declare function promoteStack({ stackId, auth, logger, }: {
|
|
112
|
+
export declare function promoteStack({ stackId, auth, logger, name, }: {
|
|
112
113
|
stackId: string;
|
|
113
114
|
auth: AuthParams;
|
|
114
115
|
logger: Logger;
|
|
116
|
+
name?: string;
|
|
115
117
|
}): Promise<PromoteStackResponse>;
|
|
116
118
|
export declare function destroyStack({ stackId, auth, logger, }: {
|
|
117
119
|
stackId: string;
|
|
@@ -45,6 +45,11 @@ export async function createStack({ stackMutation, auth, logger, }) {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
export async function createEmptyStack({ token, scopeType, scopeId, name, logger, }) {
|
|
48
|
+
if (!scopeId) {
|
|
49
|
+
const scopeLabel = scopeType === 'organization' ? 'organization' : 'project';
|
|
50
|
+
throw new Error(`Cannot create Stack: no ${scopeLabel} ID provided. ` +
|
|
51
|
+
'Provide --project-id or --organization-id, or select a scope.');
|
|
52
|
+
}
|
|
48
53
|
const stackMutation = {
|
|
49
54
|
name,
|
|
50
55
|
scopeType,
|
|
@@ -57,7 +62,8 @@ export async function createEmptyStack({ token, scopeType, scopeId, name, logger
|
|
|
57
62
|
logger,
|
|
58
63
|
});
|
|
59
64
|
if (!response.ok) {
|
|
60
|
-
|
|
65
|
+
const scopeLabel = scopeType === 'organization' ? 'organization' : 'project';
|
|
66
|
+
throw new Error(response.error || `Failed to create Stack "${name}" for ${scopeLabel} "${scopeId}".`);
|
|
61
67
|
}
|
|
62
68
|
return response.stack;
|
|
63
69
|
}
|
|
@@ -105,17 +111,20 @@ export async function resolveStackIdByNameOrId(value, auth, logger) {
|
|
|
105
111
|
throw new Error(`No stack found with name "${value}"`);
|
|
106
112
|
return match.id;
|
|
107
113
|
}
|
|
108
|
-
export async function promoteStack({ stackId, auth, logger, }) {
|
|
114
|
+
export async function promoteStack({ stackId, auth, logger, name, }) {
|
|
109
115
|
const fetchFn = createTracedFetch(logger);
|
|
116
|
+
const hasName = typeof name === 'string' && name.length > 0;
|
|
110
117
|
const response = await fetchFn(`${stacksUrl}/${stackId}/promote`, {
|
|
111
118
|
method: 'POST',
|
|
112
119
|
headers: getHeaders(auth),
|
|
120
|
+
body: hasName ? JSON.stringify({ name }) : undefined,
|
|
113
121
|
});
|
|
114
122
|
const data = await response.json();
|
|
115
123
|
return {
|
|
116
124
|
ok: response.ok,
|
|
117
125
|
error: response.ok ? null : data.message,
|
|
118
126
|
stack: data,
|
|
127
|
+
response,
|
|
119
128
|
};
|
|
120
129
|
}
|
|
121
130
|
export async function destroyStack({ stackId, auth, logger, }) {
|
|
@@ -2,7 +2,7 @@ import invoke from '../../utils/invoke-local.js';
|
|
|
2
2
|
export async function testAction(resource, payload, context, options) {
|
|
3
3
|
try {
|
|
4
4
|
const { json, logs, error } = await invoke(resource, payload, context, options);
|
|
5
|
-
return { error
|
|
5
|
+
return { error, json, logs };
|
|
6
6
|
}
|
|
7
7
|
catch (error) {
|
|
8
8
|
return { error: error, json: undefined, logs: undefined };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Logger } from '../../utils/logger.js';
|
|
2
|
+
import type { ActionResponse, AuthParams, ScopeType } from '../../utils/types.js';
|
|
3
|
+
export declare const accessApiVersion = "v2025-07-11";
|
|
4
|
+
export declare const accessApiPath: string;
|
|
5
|
+
export interface RobotMembership {
|
|
6
|
+
resourceType: ScopeType;
|
|
7
|
+
resourceId: string;
|
|
8
|
+
roleNames: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface CreateRobotInput {
|
|
11
|
+
label: string;
|
|
12
|
+
memberships: RobotMembership[];
|
|
13
|
+
}
|
|
14
|
+
export interface RobotResponse {
|
|
15
|
+
token: string;
|
|
16
|
+
id: string;
|
|
17
|
+
tokenId: string;
|
|
18
|
+
label: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
expiresAt: string;
|
|
21
|
+
memberships: Array<RobotMembership & {
|
|
22
|
+
addedAt: string;
|
|
23
|
+
lastSeenAt?: string;
|
|
24
|
+
resourceUserId?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
interface CreateRobotResponse extends ActionResponse {
|
|
28
|
+
robot: RobotResponse | null;
|
|
29
|
+
}
|
|
30
|
+
/** Create a robot token via the Access API. */
|
|
31
|
+
export declare function createRobotToken({ auth, resourceType, resourceId, body, logger, }: {
|
|
32
|
+
auth: AuthParams;
|
|
33
|
+
resourceType: ScopeType;
|
|
34
|
+
resourceId: string;
|
|
35
|
+
body: CreateRobotInput;
|
|
36
|
+
logger: Logger;
|
|
37
|
+
}): Promise<CreateRobotResponse>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import config from '../../config.js';
|
|
2
|
+
import getHeaders from '../../utils/get-headers.js';
|
|
3
|
+
import { createTracedFetch } from '../../utils/traced-fetch.js';
|
|
4
|
+
const { apiUrl } = config;
|
|
5
|
+
export const accessApiVersion = 'v2025-07-11';
|
|
6
|
+
export const accessApiPath = `${apiUrl}${accessApiVersion}/access`;
|
|
7
|
+
/** Create a robot token via the Access API. */
|
|
8
|
+
export async function createRobotToken({ auth, resourceType, resourceId, body, logger, }) {
|
|
9
|
+
const fetchFn = createTracedFetch(logger);
|
|
10
|
+
const url = `${accessApiPath}/${resourceType}/${encodeURIComponent(resourceId)}/robots`;
|
|
11
|
+
const response = await fetchFn(url, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: getHeaders(auth),
|
|
14
|
+
body: JSON.stringify(body),
|
|
15
|
+
});
|
|
16
|
+
const raw = await response.json().catch(() => null);
|
|
17
|
+
const data = (raw && typeof raw === 'object' ? raw : {});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
const errMessage = data.message || data.error?.message || response.statusText;
|
|
20
|
+
return { ok: false, error: errMessage, robot: null };
|
|
21
|
+
}
|
|
22
|
+
return { ok: true, error: null, robot: raw };
|
|
23
|
+
}
|
|
@@ -25,7 +25,7 @@ export declare function listProjects({ token, organizationId, logger, }: {
|
|
|
25
25
|
interface GroupedProjectsByOrganizationResponse extends ActionResponse {
|
|
26
26
|
organizations: GroupedProjects[];
|
|
27
27
|
}
|
|
28
|
-
interface GroupedProjects {
|
|
28
|
+
export interface GroupedProjects {
|
|
29
29
|
organization: {
|
|
30
30
|
id: string;
|
|
31
31
|
name: string;
|
package/dist/baseCommands.d.ts
CHANGED
|
@@ -24,10 +24,12 @@ export declare const stackFlagConfig: {
|
|
|
24
24
|
export declare const projectIdFlagConfig: {
|
|
25
25
|
description: string;
|
|
26
26
|
aliases: string[];
|
|
27
|
+
exclusive: string[];
|
|
27
28
|
};
|
|
28
29
|
export declare const organizationIdFlagConfig: {
|
|
29
30
|
description: string;
|
|
30
31
|
aliases: string[];
|
|
32
|
+
exclusive: string[];
|
|
31
33
|
};
|
|
32
34
|
/**
|
|
33
35
|
* Guarantees flags and args.
|
package/dist/baseCommands.js
CHANGED
|
@@ -40,6 +40,7 @@ export const baseFlags = {
|
|
|
40
40
|
description: 'Validate resources',
|
|
41
41
|
default: true,
|
|
42
42
|
allowNo: true,
|
|
43
|
+
hidden: true,
|
|
43
44
|
}),
|
|
44
45
|
verbose: OclifFlags.boolean({
|
|
45
46
|
description: 'Verbose output',
|
|
@@ -53,10 +54,12 @@ export const stackFlagConfig = {
|
|
|
53
54
|
export const projectIdFlagConfig = {
|
|
54
55
|
description: 'Sanity project ID used to scope Blueprint and Stack',
|
|
55
56
|
aliases: ['project', 'projectId'],
|
|
57
|
+
exclusive: ['organization-id'],
|
|
56
58
|
};
|
|
57
59
|
export const organizationIdFlagConfig = {
|
|
58
60
|
description: 'Sanity organization ID used to scope Blueprint and Stack',
|
|
59
61
|
aliases: ['organization', 'organizationId', 'org'],
|
|
62
|
+
exclusive: ['project-id'],
|
|
60
63
|
};
|
|
61
64
|
/**
|
|
62
65
|
* Guarantees flags and args.
|
|
@@ -216,7 +219,7 @@ export class ResolvedCommand extends RuntimeCommand {
|
|
|
216
219
|
let blueprintModule;
|
|
217
220
|
if (needsBlueprint) {
|
|
218
221
|
if (!blueprintFileInfo) {
|
|
219
|
-
this.error('Could not find Blueprint
|
|
222
|
+
this.error('Could not find a Blueprint manifest (sanity.blueprint.ts, .js, or .json).', {
|
|
220
223
|
suggestions: [
|
|
221
224
|
`Run \`${this.config.bin} blueprints init\` to create one.`,
|
|
222
225
|
`Run \`${this.config.bin} blueprints doctor\` to check your configuration.`,
|
|
@@ -229,9 +232,9 @@ export class ResolvedCommand extends RuntimeCommand {
|
|
|
229
232
|
});
|
|
230
233
|
if (parsed.errors.length > 0) {
|
|
231
234
|
log(presentBlueprintParserErrors(parsed.errors));
|
|
232
|
-
this.error('Blueprint
|
|
235
|
+
this.error('Blueprint manifest contains errors.', {
|
|
233
236
|
suggestions: [
|
|
234
|
-
'Fix the
|
|
237
|
+
'Fix the manifest errors listed above.',
|
|
235
238
|
`Run \`${this.config.bin} blueprints doctor\` to check your configuration.`,
|
|
236
239
|
],
|
|
237
240
|
});
|
|
@@ -285,7 +288,7 @@ export class ResolvedCommand extends RuntimeCommand {
|
|
|
285
288
|
// 5. Scope
|
|
286
289
|
if (needsScope) {
|
|
287
290
|
if (!resolved.scopeType || !resolved.scopeId) {
|
|
288
|
-
this.error('Missing scope: provide --project-id or --organization-id, or
|
|
291
|
+
this.error('Missing scope: provide --project-id or --organization-id, or run `blueprints init` to create a Blueprint config (.sanity/blueprint.config.json).', {
|
|
289
292
|
suggestions: [
|
|
290
293
|
`Run \`${this.config.bin} blueprints doctor\` to check your configuration.`,
|
|
291
294
|
],
|
|
@@ -307,7 +310,7 @@ export class ResolvedCommand extends RuntimeCommand {
|
|
|
307
310
|
stackId = await resolveStackIdByNameOrId(stackOverride, auth, log);
|
|
308
311
|
}
|
|
309
312
|
if (!stackId) {
|
|
310
|
-
this.error(
|
|
313
|
+
this.error(`Missing Stack: provide --stack, or set a Stack in your Blueprint config (\`${this.config.bin} blueprints config --edit\`).`, {
|
|
311
314
|
suggestions: [
|
|
312
315
|
`Run \`${this.config.bin} blueprints doctor\` to check your configuration.`,
|
|
313
316
|
],
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { Args, Flags } from '@oclif/core';
|
|
6
6
|
import { ResolvedCommand } from '../../baseCommands.js';
|
|
7
7
|
import { FUNCTION_TYPES } from '../../constants.js';
|
|
8
|
-
import { functionAddCore } from '../../cores/functions/
|
|
8
|
+
import { functionAddCore } from '../../cores/functions/add.js';
|
|
9
9
|
import { warn } from '../../utils/display/presenters.js';
|
|
10
10
|
import { Logger } from '../../utils/logger.js';
|
|
11
11
|
import { INSTALLER_OPTIONS } from '../../utils/types.js';
|
|
@@ -6,6 +6,8 @@ export default class DeployCommand extends ResolvedCommand<typeof DeployCommand>
|
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
8
|
stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'organization-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
message: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
'fn-installer': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
13
|
'no-wait': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import { ResolvedCommand, stackFlagConfig } from '../../baseCommands.js';
|
|
2
|
+
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand, stackFlagConfig, } from '../../baseCommands.js';
|
|
3
3
|
import { blueprintDeployCore } from '../../cores/blueprints/deploy.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
import { INSTALLER_OPTIONS } from '../../utils/types.js';
|
|
@@ -20,9 +20,14 @@ Set SANITY_ASSET_TIMEOUT (seconds) to override the 60-second timeout for process
|
|
|
20
20
|
'<%= config.bin %> <%= command.id %> --message "Enable staging dataset"',
|
|
21
21
|
'<%= config.bin %> <%= command.id %> --no-wait',
|
|
22
22
|
'<%= config.bin %> <%= command.id %> --fn-installer npm',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> --stack <name-or-id>',
|
|
24
|
+
'<%= config.bin %> <%= command.id %> --organization-id <orgId> --stack <name-or-id>',
|
|
25
|
+
'<%= config.bin %> <%= command.id %> --new-stack-name <new-name>',
|
|
23
26
|
];
|
|
24
27
|
static flags = {
|
|
25
28
|
stack: Flags.string({ ...stackFlagConfig }),
|
|
29
|
+
'project-id': Flags.string({ ...projectIdFlagConfig }),
|
|
30
|
+
'organization-id': Flags.string({ ...organizationIdFlagConfig }),
|
|
26
31
|
message: Flags.string({
|
|
27
32
|
description: 'Message describing the deployment (e.g. reason for change)',
|
|
28
33
|
char: 'm',
|
|
@@ -39,7 +44,6 @@ Set SANITY_ASSET_TIMEOUT (seconds) to override the 60-second timeout for process
|
|
|
39
44
|
}),
|
|
40
45
|
'new-stack-name': Flags.string({
|
|
41
46
|
description: 'Set a new name for the Stack',
|
|
42
|
-
hidden: true,
|
|
43
47
|
}),
|
|
44
48
|
};
|
|
45
49
|
async run() {
|
|
@@ -23,12 +23,10 @@ Use this to clean up test environments or decommission a Stack you no longer nee
|
|
|
23
23
|
'project-id': Flags.string({
|
|
24
24
|
...projectIdFlagConfig,
|
|
25
25
|
dependsOn: ['stack', 'force'],
|
|
26
|
-
exclusive: ['organization-id'],
|
|
27
26
|
}),
|
|
28
27
|
'organization-id': Flags.string({
|
|
29
28
|
...organizationIdFlagConfig,
|
|
30
29
|
dependsOn: ['stack', 'force'],
|
|
31
|
-
exclusive: ['project-id'],
|
|
32
30
|
}),
|
|
33
31
|
stack: Flags.string({
|
|
34
32
|
description: 'Stack name or ID to destroy (defaults to the locally configured Stack)',
|
|
@@ -7,6 +7,7 @@ export default class InfoCommand extends ResolvedCommand<typeof InfoCommand> {
|
|
|
7
7
|
static flags: {
|
|
8
8
|
stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'organization-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
11
|
};
|
|
11
12
|
run(): Promise<Record<string, unknown> | undefined>;
|
|
12
13
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import { projectIdFlagConfig, ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand } from '../../baseCommands.js';
|
|
3
3
|
import { blueprintInfoCore } from '../../cores/blueprints/info.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
export default class InfoCommand extends ResolvedCommand {
|
|
@@ -14,6 +14,7 @@ Run 'blueprints stacks' to see all available Stacks in your project or organizat
|
|
|
14
14
|
'<%= config.bin %> <%= command.id %>',
|
|
15
15
|
'<%= config.bin %> <%= command.id %> --stack <name-or-id>',
|
|
16
16
|
'<%= config.bin %> <%= command.id %> --project-id <id> --stack <name-or-id>',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> --organization-id <orgId> --stack <name-or-id>',
|
|
17
18
|
];
|
|
18
19
|
static flags = {
|
|
19
20
|
stack: Flags.string({
|
|
@@ -21,6 +22,7 @@ Run 'blueprints stacks' to see all available Stacks in your project or organizat
|
|
|
21
22
|
aliases: ['id'],
|
|
22
23
|
}),
|
|
23
24
|
'project-id': Flags.string({ ...projectIdFlagConfig }),
|
|
25
|
+
'organization-id': Flags.string({ ...organizationIdFlagConfig }),
|
|
24
26
|
};
|
|
25
27
|
async run() {
|
|
26
28
|
const result = await blueprintInfoCore({
|
|
@@ -44,11 +44,13 @@ After initialization, use 'blueprints plan' to preview changes, then 'blueprints
|
|
|
44
44
|
description: 'Existing Stack ID used to scope local Blueprint',
|
|
45
45
|
aliases: ['stackId'],
|
|
46
46
|
exclusive: ['stack-name'],
|
|
47
|
+
relationships: [{ type: 'some', flags: ['project-id', 'organization-id'] }],
|
|
47
48
|
}),
|
|
48
49
|
'stack-name': Flags.string({
|
|
49
50
|
description: 'Name to use for a new Stack provisioned during initialization',
|
|
50
51
|
aliases: ['name'],
|
|
51
52
|
exclusive: ['stack-id'],
|
|
53
|
+
relationships: [{ type: 'some', flags: ['project-id', 'organization-id'] }],
|
|
52
54
|
}),
|
|
53
55
|
};
|
|
54
56
|
async run() {
|
|
@@ -6,7 +6,12 @@ export default class LogsCommand extends ResolvedCommand<typeof LogsCommand> {
|
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
8
|
stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'organization-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
watch: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
limit: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
since: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
before: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
15
|
};
|
|
11
16
|
run(): Promise<void | Record<string, unknown>>;
|
|
12
17
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import { ResolvedCommand, stackFlagConfig } from '../../baseCommands.js';
|
|
2
|
+
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand, stackFlagConfig, } from '../../baseCommands.js';
|
|
3
3
|
import { blueprintLogsCore } from '../../cores/blueprints/logs.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
export default class LogsCommand extends ResolvedCommand {
|
|
@@ -7,20 +7,43 @@ export default class LogsCommand extends ResolvedCommand {
|
|
|
7
7
|
static summary = "Display logs for the current Blueprint's Stack deployment";
|
|
8
8
|
static description = `Retrieves Stack deployment logs, useful for debugging and monitoring deployment activity.
|
|
9
9
|
|
|
10
|
-
Use --watch (-w) to
|
|
10
|
+
Use --watch (-w) to tail logs in real-time.
|
|
11
|
+
|
|
12
|
+
Use --limit, --since, or --before to narrow the result set when not watching.
|
|
11
13
|
|
|
12
14
|
If you're not seeing expected logs, verify your Stack is deployed with 'blueprints info'.`;
|
|
13
15
|
static examples = [
|
|
14
16
|
'<%= config.bin %> <%= command.id %>',
|
|
15
17
|
'<%= config.bin %> <%= command.id %> --watch',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --stack <name-or-id>',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> --limit 500',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --since 2026-05-01T00:00:00Z',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --before 2026-05-01T00:00:00Z',
|
|
16
22
|
];
|
|
17
23
|
static flags = {
|
|
18
24
|
stack: Flags.string({ ...stackFlagConfig }),
|
|
25
|
+
'project-id': Flags.string({ ...projectIdFlagConfig }),
|
|
26
|
+
'organization-id': Flags.string({ ...organizationIdFlagConfig }),
|
|
19
27
|
watch: Flags.boolean({
|
|
20
28
|
char: 'w',
|
|
21
|
-
description: 'Watch for new Stack logs
|
|
29
|
+
description: 'Watch for new Stack logs',
|
|
22
30
|
aliases: ['follow'],
|
|
23
31
|
}),
|
|
32
|
+
limit: Flags.integer({
|
|
33
|
+
char: 'l',
|
|
34
|
+
description: 'Maximum number of log entries to retrieve (1-500)',
|
|
35
|
+
min: 1,
|
|
36
|
+
max: 500,
|
|
37
|
+
exclusive: ['watch'],
|
|
38
|
+
}),
|
|
39
|
+
since: Flags.string({
|
|
40
|
+
description: 'Only show logs after this ISO 8601 timestamp',
|
|
41
|
+
exclusive: ['watch'],
|
|
42
|
+
}),
|
|
43
|
+
before: Flags.string({
|
|
44
|
+
description: 'Only show logs before this ISO 8601 timestamp',
|
|
45
|
+
exclusive: ['watch'],
|
|
46
|
+
}),
|
|
24
47
|
};
|
|
25
48
|
async run() {
|
|
26
49
|
const result = await blueprintLogsCore({
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
export default class MintDeployTokenCommand extends ResolvedCommand<typeof MintDeployTokenCommand> {
|
|
3
|
+
static needs: readonly ["scope"];
|
|
4
|
+
static summary: string;
|
|
5
|
+
static description: string;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
label: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'organization-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
print: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<Record<string, unknown> | undefined>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand } from '../../baseCommands.js';
|
|
3
|
+
import { blueprintMintDeployTokenCore } from '../../cores/blueprints/mint-deploy-token.js';
|
|
4
|
+
import { Logger } from '../../utils/logger.js';
|
|
5
|
+
export default class MintDeployTokenCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['scope'];
|
|
7
|
+
static summary = 'Create a robot API token for deploying Blueprints from CI/CD';
|
|
8
|
+
static description = `Mints a long-lived robot token with the role required to plan, deploy, and destroy Blueprints in this project or organization.
|
|
9
|
+
|
|
10
|
+
By default the command runs interactively and asks how you want to receive the token (clipboard, print, or exit). Use --print to emit only the raw token for shell pipelines, or --json for full API output.
|
|
11
|
+
|
|
12
|
+
The minted token is also visible in your Sanity Manage UI under Robots, where it can be revoked.`;
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %>',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> --label "ci-deploy"',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --print',
|
|
17
|
+
'export SANITY_AUTH_TOKEN=$(<%= config.bin %> <%= command.id %> --print)',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --json',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> --project-id <projectId>',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --organization-id <orgId>',
|
|
21
|
+
];
|
|
22
|
+
static flags = {
|
|
23
|
+
label: Flags.string({
|
|
24
|
+
description: 'Human-readable label for the robot. Defaults to a generated value.',
|
|
25
|
+
}),
|
|
26
|
+
'project-id': Flags.string({ ...projectIdFlagConfig }),
|
|
27
|
+
'organization-id': Flags.string({ ...organizationIdFlagConfig }),
|
|
28
|
+
print: Flags.boolean({
|
|
29
|
+
char: 'P',
|
|
30
|
+
description: 'Print only the raw token to stdout (suitable for shell substitution)',
|
|
31
|
+
exclusive: ['json'],
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
async run() {
|
|
35
|
+
const result = await blueprintMintDeployTokenCore({
|
|
36
|
+
bin: this.config.bin,
|
|
37
|
+
log: Logger(this.log.bind(this), this.flags),
|
|
38
|
+
auth: this.auth,
|
|
39
|
+
scopeType: this.scopeType,
|
|
40
|
+
scopeId: this.scopeId,
|
|
41
|
+
flags: this.flags,
|
|
42
|
+
});
|
|
43
|
+
if (!result.success)
|
|
44
|
+
this.coreError(result);
|
|
45
|
+
return result.json;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -6,6 +6,8 @@ export default class PlanCommand extends ResolvedCommand<typeof PlanCommand> {
|
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
8
|
stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'organization-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
};
|
|
10
12
|
run(): Promise<Record<string, unknown> | undefined>;
|
|
11
13
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import { ResolvedCommand, stackFlagConfig } from '../../baseCommands.js';
|
|
2
|
+
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand, stackFlagConfig, } from '../../baseCommands.js';
|
|
3
3
|
import { blueprintPlanCore } from '../../cores/blueprints/plan.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
export default class PlanCommand extends ResolvedCommand {
|
|
@@ -8,9 +8,15 @@ export default class PlanCommand extends ResolvedCommand {
|
|
|
8
8
|
static description = `Use this command to preview what changes will be applied to your remote Stack before deploying. This is a safe, read-only operation—no resources are created, modified, or deleted.
|
|
9
9
|
|
|
10
10
|
Run 'blueprints plan' after making local changes to your Blueprint manifest to verify the expected diff. When ready, run 'blueprints deploy' to apply changes.`;
|
|
11
|
-
static examples = [
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> <%= command.id %>',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --stack <name-or-id>',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> --organization-id <orgId> --stack <name-or-id>',
|
|
15
|
+
];
|
|
12
16
|
static flags = {
|
|
13
17
|
stack: Flags.string({ ...stackFlagConfig }),
|
|
18
|
+
'project-id': Flags.string({ ...projectIdFlagConfig }),
|
|
19
|
+
'organization-id': Flags.string({ ...organizationIdFlagConfig }),
|
|
14
20
|
};
|
|
15
21
|
async run() {
|
|
16
22
|
const result = await blueprintPlanCore({
|
|
@@ -3,11 +3,12 @@ export default class PromoteCommand extends ResolvedCommand<typeof PromoteComman
|
|
|
3
3
|
static needs: readonly ["deployedStack", "blueprint"];
|
|
4
4
|
static summary: string;
|
|
5
5
|
static description: string;
|
|
6
|
-
static hidden: boolean;
|
|
7
6
|
static examples: string[];
|
|
8
7
|
static flags: {
|
|
9
8
|
stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
'new-stack-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<Record<string, unknown> | undefined>;
|
|
13
14
|
}
|