@sanity/runtime-cli 17.4.0 → 17.5.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 +50 -47
- package/SKILL.md +59 -0
- package/dist/actions/blueprints/pre-deploy.d.ts +15 -6
- package/dist/actions/blueprints/pre-deploy.js +29 -70
- package/dist/actions/blueprints/process-assets.d.ts +29 -0
- package/dist/actions/blueprints/process-assets.js +80 -0
- package/dist/commands/blueprints/deploy.js +3 -1
- package/dist/commands/blueprints/destroy.js +1 -1
- package/dist/commands/blueprints/info.d.ts +1 -0
- package/dist/commands/blueprints/info.js +5 -0
- package/dist/commands/blueprints/init.js +1 -2
- package/dist/commands/blueprints/logs.js +1 -0
- package/dist/commands/functions/add.js +3 -3
- package/dist/commands/functions/dev.js +2 -2
- package/dist/commands/functions/logs.d.ts +1 -1
- package/dist/commands/functions/logs.js +3 -0
- package/dist/cores/blueprints/deploy.js +69 -19
- package/dist/cores/functions/add.js +1 -1
- package/dist/utils/display/blueprints-formatting.js +3 -3
- package/dist/utils/style-text.js +1 -0
- package/oclif.manifest.json +20 -15
- package/package.json +29 -15
- package/skills/_functions-build.md +23 -0
- package/skills/_functions-list.md +28 -0
- package/skills/blueprints-add.md +8 -0
- package/skills/blueprints-config.md +33 -0
- package/skills/blueprints-deploy.md +36 -0
- package/skills/blueprints-destroy.md +30 -0
- package/skills/blueprints-doctor.md +31 -0
- package/skills/blueprints-info.md +23 -0
- package/skills/blueprints-init.md +48 -0
- package/skills/blueprints-logs.md +33 -0
- package/skills/blueprints-mint-deploy-token.md +25 -0
- package/skills/blueprints-plan.md +28 -0
- package/skills/blueprints-promote.md +31 -0
- package/skills/blueprints-stacks.md +28 -0
- package/skills/functions-add.md +35 -0
- package/skills/functions-dev.md +21 -0
- package/skills/functions-env-add.md +29 -0
- package/skills/functions-env-list.md +21 -0
- package/skills/functions-env-remove.md +22 -0
- package/skills/functions-logs.md +39 -0
- package/skills/functions-test.md +31 -0
|
@@ -14,7 +14,9 @@ Use --no-wait to queue the deployment and return immediately without waiting for
|
|
|
14
14
|
|
|
15
15
|
Use --fn-installer to force which package manager to use when deploying functions.
|
|
16
16
|
|
|
17
|
-
Set SANITY_ASSET_TIMEOUT (seconds) to override the
|
|
17
|
+
Set SANITY_ASSET_TIMEOUT (seconds) to override the 180-second timeout for processing resource assets.
|
|
18
|
+
|
|
19
|
+
Set SANITY_ASSET_CONCURRENCY to override how many resource assets are processed at once (default 4).
|
|
18
20
|
|
|
19
21
|
Exit codes: 0 deployed, 2 deployment failed, 75 deployment accepted but completion could not be confirmed (rerun 'blueprints info' to check).`;
|
|
20
22
|
static examples = [
|
|
@@ -19,7 +19,7 @@ Exit codes: 0 destroyed, 2 destruction failed, 75 destruction accepted but compl
|
|
|
19
19
|
static flags = {
|
|
20
20
|
force: Flags.boolean({
|
|
21
21
|
description: 'Force Stack destruction (skip confirmation)',
|
|
22
|
-
|
|
22
|
+
char: 'f',
|
|
23
23
|
default: false,
|
|
24
24
|
}),
|
|
25
25
|
'project-id': Flags.string({
|
|
@@ -8,6 +8,7 @@ export default class InfoCommand extends ResolvedCommand<typeof InfoCommand> {
|
|
|
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
10
|
'organization-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<Record<string, unknown> | undefined>;
|
|
13
14
|
}
|
|
@@ -23,6 +23,11 @@ Run 'blueprints stacks' to see all available Stacks in your project or organizat
|
|
|
23
23
|
}),
|
|
24
24
|
'project-id': Flags.string({ ...projectIdFlagConfig }),
|
|
25
25
|
'organization-id': Flags.string({ ...organizationIdFlagConfig }),
|
|
26
|
+
verbose: Flags.boolean({
|
|
27
|
+
char: 'v',
|
|
28
|
+
description: 'Show resource and external IDs',
|
|
29
|
+
default: false,
|
|
30
|
+
}),
|
|
26
31
|
};
|
|
27
32
|
async run() {
|
|
28
33
|
const result = await blueprintInfoCore({
|
|
@@ -6,10 +6,9 @@ import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
|
|
|
6
6
|
export default class InitCommand extends RuntimeCommand {
|
|
7
7
|
static summary = 'Initialize a Blueprint and create a remote Stack';
|
|
8
8
|
static description = `A Blueprint is your local infrastructure-as-code configuration that defines Sanity resources (datasets, functions, etc.). A Stack is the remote deployment target where your Blueprint is applied.
|
|
9
|
-
[NOTE: Currently, accounts are limited to three (3) Stacks per project scope.]
|
|
10
9
|
|
|
11
10
|
This is typically the first command you run in a new project. It creates a local Blueprint manifest file (sanity.blueprint.ts, .js, or .json) and provisions a new remote Stack.
|
|
12
|
-
Additionally, a Blueprint configuration file is created in .sanity/ containing the scope and Stack IDs.
|
|
11
|
+
Additionally, a Blueprint configuration file is created in .sanity/ containing the scope and Stack IDs. A .gitignore covering node_modules, .env, and Function build output is created or updated; the .sanity/ config itself is not ignored.
|
|
13
12
|
|
|
14
13
|
After initialization, use 'blueprints plan' to preview changes, then 'blueprints deploy' to apply them.
|
|
15
14
|
|
|
@@ -23,7 +23,7 @@ After adding, use 'functions dev' to test locally, then 'blueprints deploy' to p
|
|
|
23
23
|
example: Flags.string({
|
|
24
24
|
description: 'Example to use for the Function',
|
|
25
25
|
aliases: ['recipe'],
|
|
26
|
-
exclusive: ['name', '
|
|
26
|
+
exclusive: ['name', 'type', 'language', 'javascript', 'helpers', 'installer', 'install'],
|
|
27
27
|
}),
|
|
28
28
|
name: Flags.string({
|
|
29
29
|
description: 'Name of the Function to add',
|
|
@@ -56,9 +56,9 @@ After adding, use 'functions dev' to test locally, then 'blueprints deploy' to p
|
|
|
56
56
|
options: ['skip', ...INSTALLER_OPTIONS],
|
|
57
57
|
}),
|
|
58
58
|
install: Flags.boolean({
|
|
59
|
-
description: 'Shortcut for --
|
|
59
|
+
description: 'Shortcut for --installer npm',
|
|
60
60
|
char: 'i',
|
|
61
|
-
exclusive: ['
|
|
61
|
+
exclusive: ['installer'],
|
|
62
62
|
}),
|
|
63
63
|
};
|
|
64
64
|
async run() {
|
|
@@ -9,11 +9,11 @@ export default class DevCommand extends ResolvedCommand {
|
|
|
9
9
|
|
|
10
10
|
Open the emulator in your browser to interactively test your functions with the payload editor.
|
|
11
11
|
|
|
12
|
-
Optionally, set the host and port with the --host and --port flags. Function timeout can be configured with the --timeout flag.
|
|
12
|
+
Optionally, set the host and port with the --host and --port flags. Port 8974 is reserved for the emulator's live-reload WebSocket server. Function timeout can be configured with the --timeout flag.
|
|
13
13
|
|
|
14
14
|
To invoke a function with the CLI, use 'functions test'.`;
|
|
15
15
|
static examples = [
|
|
16
|
-
'<%= config.bin %> <%= command.id %> --host 127.0.0.1 --port
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --host 127.0.0.1 --port 3333',
|
|
17
17
|
'<%= config.bin %> <%= command.id %> --timeout 60',
|
|
18
18
|
];
|
|
19
19
|
static flags = {
|
|
@@ -15,5 +15,5 @@ export default class LogsCommand extends ResolvedCommand<typeof LogsCommand> {
|
|
|
15
15
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
16
|
watch: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
17
|
};
|
|
18
|
-
run(): Promise<Record<string, unknown
|
|
18
|
+
run(): Promise<void | Record<string, unknown>>;
|
|
19
19
|
}
|
|
@@ -46,6 +46,7 @@ Use --watch (-w) to stream logs in real-time. Use --delete to clear all logs for
|
|
|
46
46
|
char: 'w',
|
|
47
47
|
description: 'Watch for new logs (streaming mode)',
|
|
48
48
|
aliases: ['follow'],
|
|
49
|
+
exclusive: ['json'],
|
|
49
50
|
}),
|
|
50
51
|
};
|
|
51
52
|
async run() {
|
|
@@ -67,6 +68,8 @@ Use --watch (-w) to stream logs in real-time. Use --delete to clear all logs for
|
|
|
67
68
|
});
|
|
68
69
|
if (!result.success)
|
|
69
70
|
this.coreError(result);
|
|
71
|
+
if (result.streaming)
|
|
72
|
+
return result.streaming;
|
|
70
73
|
return result.json;
|
|
71
74
|
}
|
|
72
75
|
}
|
|
@@ -4,21 +4,21 @@ import { getStack, updateStack } from '../../actions/blueprints/stacks.js';
|
|
|
4
4
|
import { waitForOperation } from '../../actions/blueprints/wait-for-operation.js';
|
|
5
5
|
import { checkUserPermission } from '../../actions/sanity/access.js';
|
|
6
6
|
import { createHintCollector } from '../../utils/blueprints/hints.js';
|
|
7
|
-
import { niceId } from '../../utils/display/presenters.js';
|
|
7
|
+
import { check, niceId, severe } from '../../utils/display/presenters.js';
|
|
8
8
|
import { CODE_OPERATION_UNCONFIRMED, EXIT_OPERATION_UNCONFIRMED } from '../../utils/exit-codes.js';
|
|
9
9
|
import { styleText } from '../../utils/style-text.js';
|
|
10
10
|
import { getWarnings } from '../../utils/warnings.js';
|
|
11
11
|
export async function blueprintDeployCore(options) {
|
|
12
|
-
const { bin = 'sanity', log, auth, stackId, scopeType, scopeId, deployedStack, blueprint, flags, } = options;
|
|
12
|
+
const { bin = 'sanity', log: logger, auth, stackId, scopeType, scopeId, deployedStack, blueprint, flags, } = options;
|
|
13
13
|
const { verbose } = flags;
|
|
14
14
|
const noWait = flags['no-wait'] || false;
|
|
15
15
|
const stackName = flags['new-stack-name'] ?? deployedStack.name;
|
|
16
16
|
const installer = flags['fn-installer'] || undefined;
|
|
17
17
|
const blueprintFileDir = dirname(blueprint.fileInfo.blueprintFilePath);
|
|
18
18
|
const workspaceWarnings = getWarnings({ dir: blueprintFileDir });
|
|
19
|
-
|
|
19
|
+
logger(`Deploying "${stackName}" ${niceId(deployedStack.id)}...`);
|
|
20
20
|
try {
|
|
21
|
-
const { ok: checkOk, stack: currentStack } = await getStack({ stackId, auth, logger
|
|
21
|
+
const { ok: checkOk, stack: currentStack } = await getStack({ stackId, auth, logger });
|
|
22
22
|
if (!checkOk) {
|
|
23
23
|
return { success: false, error: 'Failed to check current Stack status' };
|
|
24
24
|
}
|
|
@@ -37,20 +37,20 @@ export async function blueprintDeployCore(options) {
|
|
|
37
37
|
const preDeployResult = await preDeploy({
|
|
38
38
|
scopeType,
|
|
39
39
|
scopeId,
|
|
40
|
-
resources,
|
|
40
|
+
resources, // mutated by preDeploy
|
|
41
41
|
stackId,
|
|
42
42
|
stackName,
|
|
43
43
|
auth,
|
|
44
44
|
blueprintFileDir,
|
|
45
45
|
installer,
|
|
46
|
-
|
|
46
|
+
logger,
|
|
47
47
|
bin,
|
|
48
48
|
verbose,
|
|
49
|
+
onAssetEvent: createAssetEventHandler(logger),
|
|
49
50
|
});
|
|
50
|
-
if (!preDeployResult?.success)
|
|
51
|
+
if (!preDeployResult?.success)
|
|
51
52
|
return preDeployResult;
|
|
52
|
-
|
|
53
|
-
const spinner = log.ora('Deploying...').start();
|
|
53
|
+
const deploySpinner = logger.ora('Deploying...').start();
|
|
54
54
|
const { ok: deployOk, stack, error: deployError, } = await updateStack({
|
|
55
55
|
stackId,
|
|
56
56
|
stackMutation: {
|
|
@@ -61,10 +61,10 @@ export async function blueprintDeployCore(options) {
|
|
|
61
61
|
userMessage: flags.message,
|
|
62
62
|
},
|
|
63
63
|
auth,
|
|
64
|
-
logger
|
|
64
|
+
logger,
|
|
65
65
|
});
|
|
66
66
|
if (!deployOk) {
|
|
67
|
-
|
|
67
|
+
deploySpinner.fail(`${styleText('red', 'Failed')} to update Stack deployment`);
|
|
68
68
|
const hints = createHintCollector(bin);
|
|
69
69
|
if (deployError) {
|
|
70
70
|
hints.inspectMessage(deployError);
|
|
@@ -79,18 +79,18 @@ export async function blueprintDeployCore(options) {
|
|
|
79
79
|
],
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
deploySpinner.stop().clear();
|
|
83
83
|
const legacyPermissionsNoticePromise = CHECK_LEGACY_DEPLOY_PERMISSION
|
|
84
84
|
? checkLegacyDeployPermission({
|
|
85
85
|
auth,
|
|
86
86
|
scopeType,
|
|
87
87
|
scopeId,
|
|
88
|
-
log,
|
|
88
|
+
log: logger,
|
|
89
89
|
})
|
|
90
90
|
: Promise.resolve(null);
|
|
91
91
|
if (noWait) {
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
logger(styleText(['bold', 'green'], 'Stack deployment started!'));
|
|
93
|
+
logger(`Use \`npx ${bin} blueprints info\` to check status`);
|
|
94
94
|
const legacyWarning = await legacyPermissionsNoticePromise;
|
|
95
95
|
const warnings = [...(legacyWarning ? [legacyWarning] : []), ...workspaceWarnings];
|
|
96
96
|
return {
|
|
@@ -100,19 +100,19 @@ export async function blueprintDeployCore(options) {
|
|
|
100
100
|
warnings: warnings.length ? warnings : undefined,
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
logger(styleText('dim', 'Stack deployment progress:'));
|
|
104
|
+
logger('');
|
|
105
105
|
const outcome = await waitForOperation({
|
|
106
106
|
stackId,
|
|
107
107
|
operationId: stack.operationId,
|
|
108
108
|
auth,
|
|
109
|
-
log,
|
|
109
|
+
log: logger,
|
|
110
110
|
bin,
|
|
111
111
|
verbose,
|
|
112
112
|
progressNoun: 'deployment',
|
|
113
113
|
});
|
|
114
114
|
if (outcome.type === 'completed') {
|
|
115
|
-
|
|
115
|
+
logger(styleText(['bold', 'green'], 'Stack deployment completed!'));
|
|
116
116
|
const legacyWarning = await legacyPermissionsNoticePromise;
|
|
117
117
|
const warnings = [...(legacyWarning ? [legacyWarning] : []), ...workspaceWarnings];
|
|
118
118
|
return {
|
|
@@ -151,6 +151,56 @@ export async function blueprintDeployCore(options) {
|
|
|
151
151
|
return { success: false, error: errorMessage };
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
+
function createAssetEventHandler(logger) {
|
|
155
|
+
let spinner;
|
|
156
|
+
const results = [];
|
|
157
|
+
return (event) => {
|
|
158
|
+
switch (event.type) {
|
|
159
|
+
case 'progress': {
|
|
160
|
+
const { completed, total, slow } = event.progress;
|
|
161
|
+
const text = [
|
|
162
|
+
`Processing assets (${completed}/${total})`,
|
|
163
|
+
slow ? ', this can take a moment' : '',
|
|
164
|
+
].join('');
|
|
165
|
+
if (spinner)
|
|
166
|
+
spinner.text = text;
|
|
167
|
+
else
|
|
168
|
+
spinner = logger.ora(text).start();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
case 'result': {
|
|
172
|
+
results.push(event.result);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
case 'complete': {
|
|
176
|
+
spinner?.stop();
|
|
177
|
+
spinner = undefined;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// done. print report
|
|
182
|
+
for (const result of results) {
|
|
183
|
+
const { resource } = result;
|
|
184
|
+
if (!result.success) {
|
|
185
|
+
const summary = result.failureKind === 'upload'
|
|
186
|
+
? `Failed uploading ${resource.name} asset`
|
|
187
|
+
: `Failed processing ${resource.name} asset`;
|
|
188
|
+
logger(` ${severe(summary)}`);
|
|
189
|
+
logger.error(` ${result.error}`);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
logger(` ${check(`${resource.name} ${niceId(resource.src)}`)}`);
|
|
193
|
+
logger(` Source: ${resource.src}`);
|
|
194
|
+
if (result.hash) {
|
|
195
|
+
const hash = result.hash;
|
|
196
|
+
const h = hash.length > 24 ? `${hash.slice(0, 8)}...${hash.slice(-12)}` : hash;
|
|
197
|
+
logger.verbose(` Hash: ${h}`);
|
|
198
|
+
}
|
|
199
|
+
if (result.exists)
|
|
200
|
+
logger.verbose(' Asset unchanged');
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
154
204
|
const CHECK_LEGACY_DEPLOY_PERMISSION = false;
|
|
155
205
|
const BLUEPRINTS_PERMISSION_ENFORCEMENT_DATE = 'July 1, 2026';
|
|
156
206
|
async function checkLegacyDeployPermission({ auth, scopeType, scopeId, log, }) {
|
|
@@ -224,7 +224,7 @@ async function promptForFunctionName() {
|
|
|
224
224
|
const functionName = await input({
|
|
225
225
|
message: 'Enter function name:',
|
|
226
226
|
validate: (input) => validateFunctionName(input) ||
|
|
227
|
-
'Invalid function name. Must be
|
|
227
|
+
'Invalid function name. Must be 3+ characters, no special characters, no spaces',
|
|
228
228
|
});
|
|
229
229
|
return functionName;
|
|
230
230
|
}
|
|
@@ -72,15 +72,15 @@ function resourceName(res, displayNameAttribute) {
|
|
|
72
72
|
nameParts.push(styleText('green', `"${displayName}"`));
|
|
73
73
|
return nameParts.join(' ');
|
|
74
74
|
}
|
|
75
|
-
function deployedResourceName(res, displayNameAttribute,
|
|
75
|
+
function deployedResourceName(res, displayNameAttribute, verbose = false) {
|
|
76
76
|
const nameParts = [styleText(['bold', 'green'], res.name)];
|
|
77
77
|
const displayName = displayNameAttribute &&
|
|
78
78
|
typeof res.parameters[displayNameAttribute] === 'string' &&
|
|
79
79
|
res.parameters[displayNameAttribute];
|
|
80
80
|
if (displayName && displayName !== res.name)
|
|
81
81
|
nameParts.push(styleText('green', `"${displayName}"`));
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
if (verbose)
|
|
83
|
+
nameParts.push(idList(res));
|
|
84
84
|
return nameParts.join(' ');
|
|
85
85
|
}
|
|
86
86
|
function idList(res) {
|
package/dist/utils/style-text.js
CHANGED
package/oclif.manifest.json
CHANGED
|
@@ -373,7 +373,7 @@
|
|
|
373
373
|
"blueprints:deploy": {
|
|
374
374
|
"aliases": [],
|
|
375
375
|
"args": {},
|
|
376
|
-
"description": "Applies your local Blueprint to the remote Stack, creating, updating, or removing resources as needed. This is the primary command for applying infrastructure changes.\n\nBefore deploying, run 'blueprints plan' to preview changes. After deployment, use 'blueprints info' to verify Stack status or 'blueprints logs' to monitor activity.\n\nUse --no-wait to queue the deployment and return immediately without waiting for completion.\n\nUse --fn-installer to force which package manager to use when deploying functions.\n\nSet SANITY_ASSET_TIMEOUT (seconds) to override the
|
|
376
|
+
"description": "Applies your local Blueprint to the remote Stack, creating, updating, or removing resources as needed. This is the primary command for applying infrastructure changes.\n\nBefore deploying, run 'blueprints plan' to preview changes. After deployment, use 'blueprints info' to verify Stack status or 'blueprints logs' to monitor activity.\n\nUse --no-wait to queue the deployment and return immediately without waiting for completion.\n\nUse --fn-installer to force which package manager to use when deploying functions.\n\nSet SANITY_ASSET_TIMEOUT (seconds) to override the 180-second timeout for processing resource assets.\n\nSet SANITY_ASSET_CONCURRENCY to override how many resource assets are processed at once (default 4).\n\nExit codes: 0 deployed, 2 deployment failed, 75 deployment accepted but completion could not be confirmed (rerun 'blueprints info' to check).",
|
|
377
377
|
"examples": [
|
|
378
378
|
"<%= config.bin %> <%= command.id %>",
|
|
379
379
|
"<%= config.bin %> <%= command.id %> --message \"Enable staging dataset\"",
|
|
@@ -629,9 +629,7 @@
|
|
|
629
629
|
"type": "option"
|
|
630
630
|
},
|
|
631
631
|
"force": {
|
|
632
|
-
"
|
|
633
|
-
"f"
|
|
634
|
-
],
|
|
632
|
+
"char": "f",
|
|
635
633
|
"description": "Force Stack destruction (skip confirmation)",
|
|
636
634
|
"name": "force",
|
|
637
635
|
"allowNo": false,
|
|
@@ -781,8 +779,8 @@
|
|
|
781
779
|
"type": "boolean"
|
|
782
780
|
},
|
|
783
781
|
"verbose": {
|
|
784
|
-
"
|
|
785
|
-
"
|
|
782
|
+
"char": "v",
|
|
783
|
+
"description": "Show resource and external IDs",
|
|
786
784
|
"name": "verbose",
|
|
787
785
|
"allowNo": false,
|
|
788
786
|
"type": "boolean"
|
|
@@ -855,7 +853,7 @@
|
|
|
855
853
|
"name": "dir"
|
|
856
854
|
}
|
|
857
855
|
},
|
|
858
|
-
"description": "A Blueprint is your local infrastructure-as-code configuration that defines Sanity resources (datasets, functions, etc.). A Stack is the remote deployment target where your Blueprint is applied.\n
|
|
856
|
+
"description": "A Blueprint is your local infrastructure-as-code configuration that defines Sanity resources (datasets, functions, etc.). A Stack is the remote deployment target where your Blueprint is applied.\n\nThis is typically the first command you run in a new project. It creates a local Blueprint manifest file (sanity.blueprint.ts, .js, or .json) and provisions a new remote Stack.\nAdditionally, a Blueprint configuration file is created in .sanity/ containing the scope and Stack IDs. A .gitignore covering node_modules, .env, and Function build output is created or updated; the .sanity/ config itself is not ignored.\n\nAfter initialization, use 'blueprints plan' to preview changes, then 'blueprints deploy' to apply them.\n\nRunning without a directory prompts to confirm the current directory. Run 'blueprints init .' to initialize in the current directory without a prompt.",
|
|
859
857
|
"examples": [
|
|
860
858
|
"<%= config.bin %> <%= command.id %>",
|
|
861
859
|
"<%= config.bin %> <%= command.id %> .",
|
|
@@ -1132,6 +1130,9 @@
|
|
|
1132
1130
|
],
|
|
1133
1131
|
"char": "w",
|
|
1134
1132
|
"description": "Watch for new Stack logs",
|
|
1133
|
+
"exclusive": [
|
|
1134
|
+
"json"
|
|
1135
|
+
],
|
|
1135
1136
|
"name": "watch",
|
|
1136
1137
|
"allowNo": false,
|
|
1137
1138
|
"type": "boolean"
|
|
@@ -1768,11 +1769,12 @@
|
|
|
1768
1769
|
"description": "Example to use for the Function",
|
|
1769
1770
|
"exclusive": [
|
|
1770
1771
|
"name",
|
|
1771
|
-
"
|
|
1772
|
+
"type",
|
|
1772
1773
|
"language",
|
|
1773
1774
|
"javascript",
|
|
1774
|
-
"
|
|
1775
|
-
"
|
|
1775
|
+
"helpers",
|
|
1776
|
+
"installer",
|
|
1777
|
+
"install"
|
|
1776
1778
|
],
|
|
1777
1779
|
"name": "example",
|
|
1778
1780
|
"hasDynamicHelp": false,
|
|
@@ -1856,9 +1858,9 @@
|
|
|
1856
1858
|
},
|
|
1857
1859
|
"install": {
|
|
1858
1860
|
"char": "i",
|
|
1859
|
-
"description": "Shortcut for --
|
|
1861
|
+
"description": "Shortcut for --installer npm",
|
|
1860
1862
|
"exclusive": [
|
|
1861
|
-
"
|
|
1863
|
+
"installer"
|
|
1862
1864
|
],
|
|
1863
1865
|
"name": "install",
|
|
1864
1866
|
"allowNo": false,
|
|
@@ -2024,9 +2026,9 @@
|
|
|
2024
2026
|
"functions:dev": {
|
|
2025
2027
|
"aliases": [],
|
|
2026
2028
|
"args": {},
|
|
2027
|
-
"description": "Runs a local, web-based development server to test your functions before deploying.\n\nOpen the emulator in your browser to interactively test your functions with the payload editor.\n\nOptionally, set the host and port with the --host and --port flags. Function timeout can be configured with the --timeout flag.\n\nTo invoke a function with the CLI, use 'functions test'.",
|
|
2029
|
+
"description": "Runs a local, web-based development server to test your functions before deploying.\n\nOpen the emulator in your browser to interactively test your functions with the payload editor.\n\nOptionally, set the host and port with the --host and --port flags. Port 8974 is reserved for the emulator's live-reload WebSocket server. Function timeout can be configured with the --timeout flag.\n\nTo invoke a function with the CLI, use 'functions test'.",
|
|
2028
2030
|
"examples": [
|
|
2029
|
-
"<%= config.bin %> <%= command.id %> --host 127.0.0.1 --port
|
|
2031
|
+
"<%= config.bin %> <%= command.id %> --host 127.0.0.1 --port 3333",
|
|
2030
2032
|
"<%= config.bin %> <%= command.id %> --timeout 60"
|
|
2031
2033
|
],
|
|
2032
2034
|
"flags": {
|
|
@@ -2410,6 +2412,9 @@
|
|
|
2410
2412
|
],
|
|
2411
2413
|
"char": "w",
|
|
2412
2414
|
"description": "Watch for new logs (streaming mode)",
|
|
2415
|
+
"exclusive": [
|
|
2416
|
+
"json"
|
|
2417
|
+
],
|
|
2413
2418
|
"name": "watch",
|
|
2414
2419
|
"allowNo": false,
|
|
2415
2420
|
"type": "boolean"
|
|
@@ -3120,5 +3125,5 @@
|
|
|
3120
3125
|
]
|
|
3121
3126
|
}
|
|
3122
3127
|
},
|
|
3123
|
-
"version": "17.
|
|
3128
|
+
"version": "17.5.0"
|
|
3124
3129
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/runtime-cli",
|
|
3
3
|
"description": "Sanity's Runtime CLI for Blueprints and Functions",
|
|
4
|
-
"version": "17.
|
|
4
|
+
"version": "17.5.0",
|
|
5
5
|
"author": "Sanity Runtime Team",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
"files": [
|
|
27
27
|
"./bin",
|
|
28
28
|
"./dist",
|
|
29
|
+
"./SKILL.md",
|
|
30
|
+
"./skills",
|
|
29
31
|
"./oclif.manifest.json"
|
|
30
32
|
],
|
|
31
33
|
"bin": {
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
"lint:fix": "npm run lint:write",
|
|
49
51
|
"prepare": "npm run build",
|
|
50
52
|
"postpack": "shx rm -f oclif.manifest.json",
|
|
51
|
-
"test": "vitest run && npm run test:depmgmt && npm run lint",
|
|
53
|
+
"test": "npm run typecheck && vitest run && npm run test:depmgmt && npm run lint",
|
|
52
54
|
"test:depmgmt": "vitest run --config ./test-depmgmt/vitest.config.ts",
|
|
53
55
|
"test:coverage": "vitest run --coverage --coverage.include \"runtime-cli/src/**/*\"",
|
|
54
56
|
"test:scenarios": "vitest run test/scenarios",
|
|
@@ -63,19 +65,20 @@
|
|
|
63
65
|
"@architect/hydrate": "~6.0.2",
|
|
64
66
|
"@architect/inventory": "~6.1.0",
|
|
65
67
|
"@inquirer/prompts": "^8.5.2",
|
|
66
|
-
"@oclif/core": "^4.13.
|
|
67
|
-
"@oclif/plugin-help": "^6.2.
|
|
68
|
+
"@oclif/core": "^4.13.3",
|
|
69
|
+
"@oclif/plugin-help": "^6.2.56",
|
|
68
70
|
"@sanity-labs/design-tokens": "^0.0.2-alpha.2",
|
|
69
|
-
"@sanity/
|
|
71
|
+
"@sanity-labs/oclif-plugin-skills-flag": "^0.2.1",
|
|
72
|
+
"@sanity/blueprints": "^0.23.2",
|
|
70
73
|
"@sanity/blueprints-parser": "^0.4.0",
|
|
71
74
|
"@sanity/cli-build": "^5.1.0",
|
|
72
|
-
"@sanity/cli-core": "^2.
|
|
73
|
-
"@sanity/client": "^7.26.
|
|
75
|
+
"@sanity/cli-core": "^2.8.1",
|
|
76
|
+
"@sanity/client": "^7.26.2",
|
|
74
77
|
"adm-zip": "^0.6.0",
|
|
75
78
|
"array-treeify": "^0.1.5",
|
|
76
79
|
"cardinal": "^2.1.1",
|
|
77
80
|
"empathic": "^2.0.1",
|
|
78
|
-
"eventsource": "^4.1.
|
|
81
|
+
"eventsource": "^4.1.1",
|
|
79
82
|
"groq-js": "^2.0.0",
|
|
80
83
|
"jiti": "^2.7.0",
|
|
81
84
|
"mime-types": "^3.0.2",
|
|
@@ -84,12 +87,12 @@
|
|
|
84
87
|
"strip-ansi": "^7.2.0",
|
|
85
88
|
"tar-fs": "^3.1.3",
|
|
86
89
|
"tar-stream": "^3.2.0",
|
|
87
|
-
"vite": "^8.1
|
|
88
|
-
"ws": "^8.21.
|
|
90
|
+
"vite": "^8.2.1",
|
|
91
|
+
"ws": "^8.21.3",
|
|
89
92
|
"xdg-basedir": "^5.1.0"
|
|
90
93
|
},
|
|
91
94
|
"devDependencies": {
|
|
92
|
-
"@biomejs/biome": "2.5.
|
|
95
|
+
"@biomejs/biome": "2.5.7",
|
|
93
96
|
"@codemirror/lang-json": "^6.0.2",
|
|
94
97
|
"@codemirror/state": "^6.7.1",
|
|
95
98
|
"@enhance/store": "^1.0.2",
|
|
@@ -97,7 +100,7 @@
|
|
|
97
100
|
"@oclif/test": "^4.1.21",
|
|
98
101
|
"@playwright/test": "^1.62.1",
|
|
99
102
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
100
|
-
"@sanity/functions": "^1.
|
|
103
|
+
"@sanity/functions": "^1.6.0",
|
|
101
104
|
"@types/adm-zip": "^0.5.8",
|
|
102
105
|
"@types/cardinal": "^2.1.1",
|
|
103
106
|
"@types/mime-types": "^3.0.1",
|
|
@@ -108,10 +111,10 @@
|
|
|
108
111
|
"@vitest/coverage-v8": "4.1.10",
|
|
109
112
|
"codemirror": "^6.0.2",
|
|
110
113
|
"mentoss": "^0.13.0",
|
|
111
|
-
"oclif": "^4.23.
|
|
114
|
+
"oclif": "^4.23.30",
|
|
112
115
|
"pretty-bytes": "^7.1.1",
|
|
113
116
|
"pretty-ms": "^9.3.0",
|
|
114
|
-
"rollup": "^4.62.
|
|
117
|
+
"rollup": "^4.62.4",
|
|
115
118
|
"shx": "^0.4.0",
|
|
116
119
|
"typescript": "^7.0.2",
|
|
117
120
|
"vitest": "4.1.10"
|
|
@@ -121,7 +124,8 @@
|
|
|
121
124
|
"dirname": "sanity-run",
|
|
122
125
|
"commands": "./dist/commands",
|
|
123
126
|
"plugins": [
|
|
124
|
-
"@oclif/plugin-help"
|
|
127
|
+
"@oclif/plugin-help",
|
|
128
|
+
"@sanity-labs/oclif-plugin-skills-flag"
|
|
125
129
|
],
|
|
126
130
|
"topicSeparator": " ",
|
|
127
131
|
"topics": {
|
|
@@ -133,6 +137,16 @@
|
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
},
|
|
140
|
+
"oclif-plugin-skills-flag": {
|
|
141
|
+
"flag": "skill",
|
|
142
|
+
"aliases": [
|
|
143
|
+
"agent",
|
|
144
|
+
"llm",
|
|
145
|
+
"llms",
|
|
146
|
+
"skills"
|
|
147
|
+
],
|
|
148
|
+
"directory": "skills"
|
|
149
|
+
},
|
|
136
150
|
"publishConfig": {
|
|
137
151
|
"access": "public",
|
|
138
152
|
"provenance": false
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# `npx @sanity/cli functions build`
|
|
2
|
+
|
|
3
|
+
Build local Functions into zip archives. This command is hidden from generated help; use it when archive artifacts are explicitly needed, not as a required step before `blueprints deploy`.
|
|
4
|
+
|
|
5
|
+
## Build
|
|
6
|
+
|
|
7
|
+
Build every local Function in the Blueprint:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npx @sanity/cli functions build --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Build one Function into a chosen directory:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx @sanity/cli functions build process-order --out-dir artifacts/functions --json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Without `--out-dir`, archives are written to `.build/` beside the Blueprint manifest. An existing archive with the same Function name is replaced.
|
|
20
|
+
|
|
21
|
+
The JSON result contains `built`, `errors`, and `outDir`. A run can succeed when some Functions build and others fail, so inspect `errors` even when the exit code is zero. If every build fails, the command exits with an error.
|
|
22
|
+
|
|
23
|
+
The `.gitignore` written by `blueprints init` covers `functions/**/.build/`, not the top-level `.build/` these archives land in, so exclude the output directory before committing.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# `npx @sanity/cli functions list`
|
|
2
|
+
|
|
3
|
+
List Functions deployed in a project or organization scope. This command is hidden from generated help. Results cover the whole scope rather than one Stack; use `blueprints info` for the resources of a single Stack.
|
|
4
|
+
|
|
5
|
+
## Run
|
|
6
|
+
|
|
7
|
+
Use the locally configured scope:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npx @sanity/cli functions list --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Select a scope explicitly when working outside a local Blueprint:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx @sanity/cli functions list --project-id PROJECT_ID --json
|
|
17
|
+
npx @sanity/cli functions list --organization-id ORGANIZATION_ID --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The two flags are mutually exclusive. No Blueprint manifest is required: the scope resolves from those flags, from `SANITY_PROJECT_ID` or `SANITY_ORGANIZATION_ID`, or from `.sanity/blueprint.config.json`, and the command fails with `Missing scope` when none of them do. The scope is sent with the request, so a project and its organization return different sets: scheduled Functions are organization-scoped, every other type is project-scoped.
|
|
21
|
+
|
|
22
|
+
## Read the result
|
|
23
|
+
|
|
24
|
+
The JSON result contains `functions`, `scopeType`, and `scopeId`. Each entry carries `id`, `name`, `displayName`, `type`, `runtime`, `status`, `memory`, `storage`, `timeout`, `resourceType`, `resourceId`, `url`, `createdAt`, and `updatedAt`. An empty scope still emits `{"functions": []}` and exits `0`, so check the array length rather than the exit code.
|
|
25
|
+
|
|
26
|
+
Default output is one line per Function with its name, ID, type, and last update time. `--verbose` (`-v`) instead prints the type, update time, memory, timeout, and event rule of each.
|
|
27
|
+
|
|
28
|
+
Treat this as an inspection command. `functions logs`, `functions env add`, and `functions env remove` address a Function by its Blueprint resource name resolved through the deployed Stack, not by the `id` shown here.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# `npx @sanity/cli blueprints add`
|
|
2
|
+
|
|
3
|
+
Treat this command as legacy compatibility only. It is deprecated and supports only the `function` resource type. Prefer `npx @sanity/cli functions add` for new work.
|
|
4
|
+
|
|
5
|
+
## Agent guidance
|
|
6
|
+
|
|
7
|
+
- Warn that the command is deprecated before adding new usage to scripts or documentation.
|
|
8
|
+
- Migrate existing legacy invocations to `npx @sanity/cli functions add`.
|