@sanity/runtime-cli 17.8.0 → 17.9.0-blueprinit.g14aaebd
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 +28 -22
- package/dist/actions/blueprinit/manifest.d.ts +46 -0
- package/dist/actions/blueprinit/manifest.js +121 -0
- package/dist/actions/blueprinit/quote.d.ts +6 -0
- package/dist/actions/blueprinit/quote.js +8 -0
- package/dist/actions/blueprinit/studio.d.ts +6 -0
- package/dist/actions/blueprinit/studio.js +43 -0
- package/dist/actions/blueprinit/templates.d.ts +73 -0
- package/dist/actions/blueprinit/templates.js +138 -0
- package/dist/actions/blueprinit/versions.d.ts +8 -0
- package/dist/actions/blueprinit/versions.js +11 -0
- package/dist/actions/blueprinit/workspace.d.ts +27 -0
- package/dist/actions/blueprinit/workspace.js +145 -0
- package/dist/actions/blueprints/pre-deploy.js +2 -0
- package/dist/actions/blueprints/stacks.d.ts +3 -0
- package/dist/actions/blueprints/stacks.js +1 -0
- package/dist/actions/sanity/create-project.d.ts +19 -0
- package/dist/actions/sanity/create-project.js +32 -0
- package/dist/actions/sanity/datasets.d.ts +15 -0
- package/dist/actions/sanity/datasets.js +26 -0
- package/dist/actions/sanity/projects.d.ts +11 -0
- package/dist/actions/sanity/projects.js +48 -22
- package/dist/baseCommands.d.ts +6 -0
- package/dist/baseCommands.js +9 -1
- package/dist/commands/blueprints/stacks.d.ts +2 -1
- package/dist/commands/blueprints/stacks.js +14 -6
- package/dist/commands/functions/test.d.ts +1 -0
- package/dist/commands/functions/test.js +5 -0
- package/dist/commands/init.d.ts +21 -0
- package/dist/commands/init.js +82 -0
- package/dist/cores/blueprinit/adopt.d.ts +6 -0
- package/dist/cores/blueprinit/adopt.js +137 -0
- package/dist/cores/blueprinit/columns.d.ts +26 -0
- package/dist/cores/blueprinit/columns.js +27 -0
- package/dist/cores/blueprinit/finish.d.ts +15 -0
- package/dist/cores/blueprinit/finish.js +72 -0
- package/dist/cores/blueprinit/fresh.d.ts +3 -0
- package/dist/cores/blueprinit/fresh.js +219 -0
- package/dist/cores/blueprinit/naming.d.ts +27 -0
- package/dist/cores/blueprinit/naming.js +43 -0
- package/dist/cores/blueprinit/preview.d.ts +34 -0
- package/dist/cores/blueprinit/preview.js +110 -0
- package/dist/cores/blueprinit/project-choice.d.ts +28 -0
- package/dist/cores/blueprinit/project-choice.js +82 -0
- package/dist/cores/blueprinit/prompts.d.ts +13 -0
- package/dist/cores/blueprinit/prompts.js +42 -0
- package/dist/cores/blueprinit/results.d.ts +8 -0
- package/dist/cores/blueprinit/results.js +4 -0
- package/dist/cores/blueprinit/selection.d.ts +15 -0
- package/dist/cores/blueprinit/selection.js +90 -0
- package/dist/cores/blueprinit/stack-name.d.ts +39 -0
- package/dist/cores/blueprinit/stack-name.js +56 -0
- package/dist/cores/blueprinit/target.d.ts +33 -0
- package/dist/cores/blueprinit/target.js +80 -0
- package/dist/cores/blueprinit/types.d.ts +20 -0
- package/dist/cores/blueprinit/types.js +1 -0
- package/dist/cores/blueprinit.d.ts +7 -0
- package/dist/cores/blueprinit.js +64 -0
- package/dist/cores/blueprints/stacks.d.ts +8 -3
- package/dist/cores/blueprints/stacks.js +282 -85
- package/dist/cores/functions/test.d.ts +2 -19
- package/dist/cores/functions/test.js +63 -138
- package/dist/server/app.js +4 -6
- package/dist/server/static/components/payload-panel.js +1 -1
- package/dist/utils/display/intro.d.ts +6 -0
- package/dist/utils/display/intro.js +63 -0
- package/dist/utils/display/prompt.d.ts +4 -1
- package/dist/utils/display/prompt.js +16 -2
- package/dist/utils/functions/child-process-wrapper.js +3 -2
- package/dist/utils/functions/child-runtime/durable.d.ts +2 -2
- package/dist/utils/functions/child-runtime/durable.js +53 -3
- package/dist/utils/functions/durable-logs.d.ts +16 -0
- package/dist/utils/functions/durable-logs.js +52 -0
- package/dist/utils/functions/invoke/local.js +16 -8
- package/dist/utils/functions/invoke/resolve-invoke-type.d.ts +51 -0
- package/dist/utils/functions/invoke/resolve-invoke-type.js +131 -0
- package/dist/utils/types.d.ts +39 -6
- package/oclif.manifest.json +177 -5
- package/package.json +1 -1
- package/skills/blueprints-stacks.md +14 -2
- package/skills/init.md +199 -0
|
@@ -9,6 +9,7 @@ import { SANITY_FUNCTION_DURABLE } from '../../../constants.js';
|
|
|
9
9
|
import { groupBlueprintResources } from '../../blueprints/group-resources.js';
|
|
10
10
|
import { isGroqContextOptions, } from '../../types.js';
|
|
11
11
|
import { acquireFunctionBuild } from './prepare.js';
|
|
12
|
+
import { isGroqInvocation } from './resolve-invoke-type.js';
|
|
12
13
|
function getChildProcessWrapperPath() {
|
|
13
14
|
return fileURLToPath(new URL('../child-process-wrapper.js', import.meta.url));
|
|
14
15
|
}
|
|
@@ -17,13 +18,16 @@ export function sanitizeLogs(logs) {
|
|
|
17
18
|
}
|
|
18
19
|
export async function applyGroqRule(resource, payload, projectId, dataset) {
|
|
19
20
|
const { before, after, payload: data = null } = payload;
|
|
21
|
+
const event = resource.event;
|
|
20
22
|
// If there is no rule set return everything
|
|
21
|
-
if (!
|
|
23
|
+
if (!event)
|
|
22
24
|
return data;
|
|
23
25
|
// default groq rule is: gimme full doc content. otherwise, parse + eval custom rule
|
|
24
26
|
// applying the GROQ filter may result in a slimmer set of documents
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
const filter = 'filter' in event ? event.filter : undefined;
|
|
28
|
+
const projection = 'projection' in event ? event.projection : undefined;
|
|
29
|
+
if (filter || projection) {
|
|
30
|
+
const query = `*[${filter || ''}]${projection || ''}`;
|
|
27
31
|
try {
|
|
28
32
|
const rule = groq.parse(query, { mode: 'delta' });
|
|
29
33
|
const sanity = projectId && dataset ? { projectId, dataset } : undefined;
|
|
@@ -43,21 +47,24 @@ export default async function invoke(resource, payload, context, options) {
|
|
|
43
47
|
if (!resource.src) {
|
|
44
48
|
throw new Error(`Function resource "${resource.name}" is missing the 'src' property.`);
|
|
45
49
|
}
|
|
46
|
-
const { forceColor = true, timeout = 10, onNestedInvoke, depth = 0, callStack = [], onStepEvent = () => { }, } = options;
|
|
50
|
+
const { forceColor = true, timeout = 10, onNestedInvoke, depth = 0, callStack = [], onStepEvent = () => { }, noWait = false, } = options;
|
|
51
|
+
// `payload.payload` is the event body for every function type: the document for
|
|
52
|
+
// GROQ-based events, whatever the producer sent for the rest. The handler always
|
|
53
|
+
// receives it as `event.data` (see the `payload` built in `start()` below).
|
|
54
|
+
let filteredData = payload?.payload || {};
|
|
47
55
|
// Apply the GROQ rule before preparing a build so a filtered-out event skips
|
|
48
56
|
// the (potentially expensive) transpile entirely.
|
|
49
|
-
|
|
50
|
-
if (resource.type === 'sanity.function.document' ||
|
|
51
|
-
resource.type === 'sanity.function.media-library.asset') {
|
|
57
|
+
if (isGroqInvocation(resource)) {
|
|
52
58
|
if (!isGroqContextOptions(context)) {
|
|
53
59
|
throw new Error('GROQ-based functions require a context with clientOptions');
|
|
54
60
|
}
|
|
55
61
|
const { projectId, dataset } = context.clientOptions;
|
|
56
62
|
if ('before' in payload) {
|
|
57
63
|
filteredData = await applyGroqRule(resource, payload, projectId, dataset);
|
|
64
|
+
const filter = resource.event && 'filter' in resource.event ? resource.event.filter : '';
|
|
58
65
|
if (typeof filteredData === 'undefined') {
|
|
59
66
|
return {
|
|
60
|
-
logs: `⚠️ Filter "${
|
|
67
|
+
logs: `⚠️ Filter "${filter}" returned an empty result. Skipping invoke.`,
|
|
61
68
|
error: undefined,
|
|
62
69
|
json: undefined,
|
|
63
70
|
};
|
|
@@ -299,6 +306,7 @@ export default async function invoke(resource, payload, context, options) {
|
|
|
299
306
|
srcPath: functionPath,
|
|
300
307
|
payload,
|
|
301
308
|
isDurable: resource.type === SANITY_FUNCTION_DURABLE,
|
|
309
|
+
noWait,
|
|
302
310
|
};
|
|
303
311
|
child.send(JSON.stringify(startMessage));
|
|
304
312
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { BlueprintResource } from '@sanity/blueprints';
|
|
2
|
+
import type { Logger } from '../../logger.js';
|
|
3
|
+
import type { EventType, FunctionGroqResource, FunctionResource, FunctionTestFlags, InvokeContextOptions, InvokePayloadOptions } from '../../types.js';
|
|
4
|
+
import buildPayload from '../build-payload.js';
|
|
5
|
+
import { fetchAsset, fetchDocument } from '../fetch-document.js';
|
|
6
|
+
export type InvocationPlan = {
|
|
7
|
+
kind: 'groq';
|
|
8
|
+
inputSource: 'document' | 'media';
|
|
9
|
+
isDurable: boolean;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'plain';
|
|
12
|
+
isDurable: false;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'durable';
|
|
15
|
+
inputSource: 'payload';
|
|
16
|
+
isDurable: true;
|
|
17
|
+
};
|
|
18
|
+
export type InputContext = {
|
|
19
|
+
flags: FunctionTestFlags;
|
|
20
|
+
projectId?: string;
|
|
21
|
+
organizationId?: string;
|
|
22
|
+
api?: string;
|
|
23
|
+
apiHost: string;
|
|
24
|
+
token?: string;
|
|
25
|
+
withUserToken?: boolean;
|
|
26
|
+
resources: BlueprintResource[];
|
|
27
|
+
blueprintFileDir: string;
|
|
28
|
+
log: Logger;
|
|
29
|
+
};
|
|
30
|
+
type InvocationDeps = {
|
|
31
|
+
fetchDocument: typeof fetchDocument;
|
|
32
|
+
fetchAsset: typeof fetchAsset;
|
|
33
|
+
buildPayload: typeof buildPayload;
|
|
34
|
+
};
|
|
35
|
+
export declare const defaultInvocationDeps: InvocationDeps;
|
|
36
|
+
export interface InvokeInput {
|
|
37
|
+
payload: Record<string, unknown>;
|
|
38
|
+
before: Record<string, unknown> | null;
|
|
39
|
+
after: Record<string, unknown> | null;
|
|
40
|
+
}
|
|
41
|
+
export declare const resolveInvocationPlan: (resource: FunctionResource) => InvocationPlan;
|
|
42
|
+
/**
|
|
43
|
+
* True when the function's event is delivered through a GROQ rule (a document or
|
|
44
|
+
* media-library event, whether plain or durable), so its payload is a document the
|
|
45
|
+
* rule may narrow before the handler sees it.
|
|
46
|
+
*/
|
|
47
|
+
export declare const isGroqInvocation: (resource: FunctionResource) => resource is FunctionGroqResource;
|
|
48
|
+
export declare const collectInvokeInput: (plan: InvocationPlan, input: InputContext, deps: InvocationDeps) => Promise<InvokeInput>;
|
|
49
|
+
export declare const buildContext: (plan: InvocationPlan, input: InputContext) => InvokeContextOptions;
|
|
50
|
+
export declare const buildInvokeOptions: (plan: InvocationPlan, invokeInput: InvokeInput, eventType: EventType) => InvokePayloadOptions;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { cwd } from 'node:process';
|
|
4
|
+
import { SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, } from '../../../constants.js';
|
|
5
|
+
import { parseJsonObject } from '../../parse-json-object.js';
|
|
6
|
+
import buildPayload from '../build-payload.js';
|
|
7
|
+
import { fetchAsset, fetchDocument } from '../fetch-document.js';
|
|
8
|
+
export const defaultInvocationDeps = { fetchDocument, fetchAsset, buildPayload };
|
|
9
|
+
const assertNever = (resource) => {
|
|
10
|
+
throw new Error(`No invocation plan for function type: ${resource.type}`);
|
|
11
|
+
};
|
|
12
|
+
const resolveDurableInvocationPlan = (event) => {
|
|
13
|
+
switch (event?.type) {
|
|
14
|
+
case 'document':
|
|
15
|
+
return { kind: 'groq', inputSource: 'document', isDurable: true };
|
|
16
|
+
case 'media-library':
|
|
17
|
+
return { kind: 'groq', inputSource: 'media', isDurable: true };
|
|
18
|
+
case 'sync-tag-invalidate':
|
|
19
|
+
case undefined:
|
|
20
|
+
return { kind: 'durable', inputSource: 'payload', isDurable: true };
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const resolveInvocationPlan = (resource) => {
|
|
24
|
+
switch (resource.type) {
|
|
25
|
+
case SANITY_FUNCTION_DOCUMENT:
|
|
26
|
+
return { kind: 'groq', inputSource: 'document', isDurable: false };
|
|
27
|
+
case SANITY_FUNCTION_MEDIA_LIBRARY_ASSET:
|
|
28
|
+
return { kind: 'groq', inputSource: 'media', isDurable: false };
|
|
29
|
+
case SANITY_FUNCTION_DURABLE:
|
|
30
|
+
return resolveDurableInvocationPlan(resource.event);
|
|
31
|
+
case SANITY_FUNCTION_SCHEDULED:
|
|
32
|
+
case SANITY_FUNCTION_PUBSUB:
|
|
33
|
+
case SANITY_FUNCTION_SYNC_TAG_INVALIDATE:
|
|
34
|
+
return { kind: 'plain', isDurable: false };
|
|
35
|
+
default:
|
|
36
|
+
return assertNever(resource);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* True when the function's event is delivered through a GROQ rule (a document or
|
|
41
|
+
* media-library event, whether plain or durable), so its payload is a document the
|
|
42
|
+
* rule may narrow before the handler sees it.
|
|
43
|
+
*/
|
|
44
|
+
export const isGroqInvocation = (resource) => resolveInvocationPlan(resource).kind === 'groq';
|
|
45
|
+
export const collectInvokeInput = async (plan, input, deps) => {
|
|
46
|
+
const source = plan.kind === 'groq' ? plan.inputSource : 'none';
|
|
47
|
+
return resolveInvokeInput(source, input, deps);
|
|
48
|
+
};
|
|
49
|
+
export const buildContext = (plan, input) => {
|
|
50
|
+
const withToken = input.withUserToken ? { token: input.token } : {};
|
|
51
|
+
if (plan.kind === 'plain') {
|
|
52
|
+
return {
|
|
53
|
+
clientOptions: { ...withToken },
|
|
54
|
+
resources: input.resources,
|
|
55
|
+
blueprintFileDir: input.blueprintFileDir,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const isMedia = plan.kind === 'groq' && plan.inputSource === 'media';
|
|
59
|
+
return {
|
|
60
|
+
clientOptions: {
|
|
61
|
+
apiVersion: input.api,
|
|
62
|
+
dataset: input.flags.dataset,
|
|
63
|
+
projectId: input.projectId,
|
|
64
|
+
organizationId: input.organizationId,
|
|
65
|
+
...withToken,
|
|
66
|
+
},
|
|
67
|
+
eventResourceType: isMedia ? 'media-library' : 'dataset',
|
|
68
|
+
eventResourceId: (isMedia ? input.flags['media-library-id'] : `${input.projectId}.${input.flags.dataset}`) ||
|
|
69
|
+
'',
|
|
70
|
+
functionResourceType: 'project',
|
|
71
|
+
functionResourceId: input.projectId || '',
|
|
72
|
+
resources: input.resources,
|
|
73
|
+
blueprintFileDir: input.blueprintFileDir,
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
export const buildInvokeOptions = (plan, invokeInput, eventType) => {
|
|
77
|
+
switch (plan.kind) {
|
|
78
|
+
case 'groq':
|
|
79
|
+
return {
|
|
80
|
+
event: eventType,
|
|
81
|
+
payload: invokeInput.payload,
|
|
82
|
+
before: invokeInput.before,
|
|
83
|
+
after: invokeInput.after,
|
|
84
|
+
};
|
|
85
|
+
case 'plain':
|
|
86
|
+
// Cron functions have no payload, but pubsub and sync-tag-invalidate carry
|
|
87
|
+
// whatever the producer sent, so pass it through for all of them.
|
|
88
|
+
return { event: 'plain', payload: invokeInput.payload };
|
|
89
|
+
case 'durable':
|
|
90
|
+
return { event: 'durable', payload: invokeInput.payload };
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const resolveInvokeInput = async (source, input, deps) => {
|
|
94
|
+
const { flags } = input;
|
|
95
|
+
const fetchById = (id) => source === 'document'
|
|
96
|
+
? deps.fetchDocument(id, {
|
|
97
|
+
projectId: input.projectId,
|
|
98
|
+
dataset: flags.dataset,
|
|
99
|
+
apiVersion: input.api,
|
|
100
|
+
apiHost: input.apiHost,
|
|
101
|
+
token: input.token,
|
|
102
|
+
}, input.log)
|
|
103
|
+
: deps.fetchAsset(id, {
|
|
104
|
+
mediaLibraryId: flags['media-library-id'],
|
|
105
|
+
apiVersion: input.api,
|
|
106
|
+
apiHost: input.apiHost,
|
|
107
|
+
token: input.token,
|
|
108
|
+
}, input.log);
|
|
109
|
+
let before = null;
|
|
110
|
+
let after = null;
|
|
111
|
+
if (flags['data-before'] && flags['data-after']) {
|
|
112
|
+
before = parseJsonObject(flags['data-before']);
|
|
113
|
+
after = parseJsonObject(flags['data-after']);
|
|
114
|
+
}
|
|
115
|
+
else if (flags['file-before'] && flags['file-after']) {
|
|
116
|
+
before = parseJsonObject(readFileSync(join(cwd(), flags['file-before']), 'utf8'));
|
|
117
|
+
after = parseJsonObject(readFileSync(join(cwd(), flags['file-after']), 'utf8'));
|
|
118
|
+
}
|
|
119
|
+
else if (flags['document-id-before'] && flags['document-id-after']) {
|
|
120
|
+
before = await fetchById(flags['document-id-before']);
|
|
121
|
+
after = await fetchById(flags['document-id-after']);
|
|
122
|
+
}
|
|
123
|
+
let payload;
|
|
124
|
+
if (after)
|
|
125
|
+
payload = after;
|
|
126
|
+
else if (flags['document-id'])
|
|
127
|
+
payload = await fetchById(flags['document-id']);
|
|
128
|
+
else
|
|
129
|
+
payload = deps.buildPayload({ data: flags.data, file: flags.file });
|
|
130
|
+
return { payload, before, after };
|
|
131
|
+
};
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface ActionResponse {
|
|
|
14
14
|
error: string | null;
|
|
15
15
|
}
|
|
16
16
|
/** @internal */
|
|
17
|
-
export type FunctionGroqResource = BlueprintDocumentFunctionResource | BlueprintMediaLibraryAssetFunctionResource;
|
|
17
|
+
export type FunctionGroqResource = BlueprintDocumentFunctionResource | BlueprintMediaLibraryAssetFunctionResource | BlueprintDurableFunctionResource;
|
|
18
18
|
export type FunctionResource = FunctionGroqResource | BlueprintPubSubFunctionResource | BlueprintScheduledFunctionResource | BlueprintSyncTagInvalidateFunctionResource | BlueprintDurableFunctionResource;
|
|
19
19
|
/** Function resources that declare an `event`; PubSub functions are triggered by other functions */
|
|
20
20
|
export type EventFunctionResource = Exclude<FunctionResource, BlueprintPubSubFunctionResource>;
|
|
@@ -111,7 +111,7 @@ export interface InvokeNonGroqPayloadOptions {
|
|
|
111
111
|
export type InvokePayloadOptions = InvokeGroqPayloadOptions | InvokeNonGroqPayloadOptions;
|
|
112
112
|
export type InvokePayloadMetadata = Pick<InvokeGroqPayloadOptions, 'event' | 'before' | 'after'> | Pick<InvokeNonGroqPayloadOptions, 'event'>;
|
|
113
113
|
export type EventType = 'create' | 'update' | 'delete';
|
|
114
|
-
export type NonGroqEventType = '
|
|
114
|
+
export type NonGroqEventType = 'plain' | 'nested' | 'durable';
|
|
115
115
|
export declare function isEventType(arg: string): arg is EventType;
|
|
116
116
|
/** @internal */
|
|
117
117
|
export interface InvokeGroqContextOptions {
|
|
@@ -162,7 +162,9 @@ export interface InvokeExecutionOptions {
|
|
|
162
162
|
/** Function names already on the invoke call stack (innermost last), used to detect cycles. @internal */
|
|
163
163
|
callStack?: string[];
|
|
164
164
|
/** Stream a durable step transition to the caller. @internal */
|
|
165
|
-
onStepEvent?: (event:
|
|
165
|
+
onStepEvent?: (event: DurableRuntimeEvent) => void;
|
|
166
|
+
/** Don't wait the full duration during a wait durable event @internal */
|
|
167
|
+
noWait?: boolean;
|
|
166
168
|
}
|
|
167
169
|
/**
|
|
168
170
|
* Re-entrant callback that executes a named function from the blueprint on behalf
|
|
@@ -181,6 +183,7 @@ export type ParentToChildMessage = {
|
|
|
181
183
|
srcPath: string;
|
|
182
184
|
payload: unknown;
|
|
183
185
|
isDurable?: boolean;
|
|
186
|
+
noWait?: boolean;
|
|
184
187
|
} | {
|
|
185
188
|
type: 'invoke-response';
|
|
186
189
|
id: string;
|
|
@@ -195,7 +198,7 @@ export type ParentToChildMessage = {
|
|
|
195
198
|
error: InvocationError;
|
|
196
199
|
} | {
|
|
197
200
|
type: 'step-event';
|
|
198
|
-
event:
|
|
201
|
+
event: DurableRuntimeEvent;
|
|
199
202
|
};
|
|
200
203
|
/**
|
|
201
204
|
* IPC messages sent from a function child process back up to the parent.
|
|
@@ -217,7 +220,7 @@ export type ChildToParentMessage = {
|
|
|
217
220
|
error?: InvocationError;
|
|
218
221
|
} | {
|
|
219
222
|
type: 'step-event';
|
|
220
|
-
event:
|
|
223
|
+
event: DurableRuntimeEvent;
|
|
221
224
|
};
|
|
222
225
|
/** @internal */
|
|
223
226
|
export interface InvocationResponse {
|
|
@@ -301,7 +304,7 @@ export type Warning = {
|
|
|
301
304
|
suggestions: string[];
|
|
302
305
|
};
|
|
303
306
|
/** @internal */
|
|
304
|
-
export type DurableOperationSteps = 'run';
|
|
307
|
+
export type DurableOperationSteps = 'run' | 'wait';
|
|
305
308
|
/** @internal */
|
|
306
309
|
export type DurableStepPhase = 'start' | 'complete' | 'error';
|
|
307
310
|
/**
|
|
@@ -315,4 +318,34 @@ export interface DurableStepEvent {
|
|
|
315
318
|
error?: InvocationError;
|
|
316
319
|
durationMs?: number;
|
|
317
320
|
}
|
|
321
|
+
export interface DurableLogEvent {
|
|
322
|
+
kind: 'log';
|
|
323
|
+
phase: 'log';
|
|
324
|
+
step: string | null;
|
|
325
|
+
level: 'info' | 'warn' | 'error';
|
|
326
|
+
message: string;
|
|
327
|
+
timestamp?: string;
|
|
328
|
+
}
|
|
329
|
+
export type DurableRuntimeEvent = DurableStepEvent | DurableLogEvent;
|
|
330
|
+
export interface FunctionTestFlags {
|
|
331
|
+
data?: string;
|
|
332
|
+
event?: string;
|
|
333
|
+
file?: string;
|
|
334
|
+
timeout?: number;
|
|
335
|
+
api?: string;
|
|
336
|
+
dataset?: string;
|
|
337
|
+
'project-id'?: string;
|
|
338
|
+
'organization-id'?: string;
|
|
339
|
+
'document-id'?: string;
|
|
340
|
+
'with-user-token'?: boolean;
|
|
341
|
+
'data-before'?: string;
|
|
342
|
+
'data-after'?: string;
|
|
343
|
+
'file-before'?: string;
|
|
344
|
+
'file-after'?: string;
|
|
345
|
+
'document-id-before'?: string;
|
|
346
|
+
'document-id-after'?: string;
|
|
347
|
+
'media-library-id'?: string;
|
|
348
|
+
'no-wait'?: boolean;
|
|
349
|
+
json?: boolean;
|
|
350
|
+
}
|
|
318
351
|
export {};
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,156 @@
|
|
|
1
1
|
{
|
|
2
2
|
"commands": {
|
|
3
|
+
"init": {
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"args": {
|
|
6
|
+
"directory": {
|
|
7
|
+
"description": "Directory to initialize. Interactive runs are asked for one instead.",
|
|
8
|
+
"name": "directory",
|
|
9
|
+
"required": false
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"description": "Scaffolds a Blueprint, Studio, and starter function around a Sanity project.\n\nUse a project you already have, or create one with --create-project. A new project has no\ndatasets, so the Blueprint creates the dataset rather than attaching it.\n\nPass a directory to scaffold into it. Without one, an interactive run asks where the files go.\n\nThis hidden command is an experiment; its interface and generated files are not stable.",
|
|
13
|
+
"examples": [
|
|
14
|
+
"<%= config.bin %> <%= command.id %>",
|
|
15
|
+
"<%= config.bin %> <%= command.id %> ./my-workspace",
|
|
16
|
+
"<%= config.bin %> <%= command.id %> --yes",
|
|
17
|
+
"<%= config.bin %> <%= command.id %> --project-id <id> --dataset <name> --yes",
|
|
18
|
+
"<%= config.bin %> <%= command.id %> --create-project \"My Shop\" --yes"
|
|
19
|
+
],
|
|
20
|
+
"flags": {
|
|
21
|
+
"json": {
|
|
22
|
+
"description": "Format output as json",
|
|
23
|
+
"name": "json",
|
|
24
|
+
"allowNo": false,
|
|
25
|
+
"type": "boolean"
|
|
26
|
+
},
|
|
27
|
+
"path": {
|
|
28
|
+
"aliases": [
|
|
29
|
+
"blueprint-path"
|
|
30
|
+
],
|
|
31
|
+
"char": "p",
|
|
32
|
+
"description": "Path to a Blueprint file or directory containing one",
|
|
33
|
+
"env": "SANITY_BLUEPRINT_PATH",
|
|
34
|
+
"hidden": true,
|
|
35
|
+
"name": "path",
|
|
36
|
+
"hasDynamicHelp": false,
|
|
37
|
+
"multiple": false,
|
|
38
|
+
"type": "option"
|
|
39
|
+
},
|
|
40
|
+
"trace": {
|
|
41
|
+
"description": "Trace output",
|
|
42
|
+
"hidden": true,
|
|
43
|
+
"name": "trace",
|
|
44
|
+
"allowNo": false,
|
|
45
|
+
"type": "boolean"
|
|
46
|
+
},
|
|
47
|
+
"validate-resources": {
|
|
48
|
+
"description": "Validate resources",
|
|
49
|
+
"hidden": true,
|
|
50
|
+
"name": "validate-resources",
|
|
51
|
+
"allowNo": true,
|
|
52
|
+
"type": "boolean"
|
|
53
|
+
},
|
|
54
|
+
"verbose": {
|
|
55
|
+
"description": "Verbose output",
|
|
56
|
+
"hidden": true,
|
|
57
|
+
"name": "verbose",
|
|
58
|
+
"allowNo": false,
|
|
59
|
+
"type": "boolean"
|
|
60
|
+
},
|
|
61
|
+
"llms": {
|
|
62
|
+
"aliases": [
|
|
63
|
+
"skill"
|
|
64
|
+
],
|
|
65
|
+
"description": "Show agent-oriented guidance for this command",
|
|
66
|
+
"hidden": true,
|
|
67
|
+
"name": "llms",
|
|
68
|
+
"allowNo": false,
|
|
69
|
+
"type": "boolean"
|
|
70
|
+
},
|
|
71
|
+
"yes": {
|
|
72
|
+
"char": "y",
|
|
73
|
+
"description": "Skip confirmation prompts",
|
|
74
|
+
"name": "yes",
|
|
75
|
+
"allowNo": false,
|
|
76
|
+
"type": "boolean"
|
|
77
|
+
},
|
|
78
|
+
"organization-id": {
|
|
79
|
+
"aliases": [
|
|
80
|
+
"organization",
|
|
81
|
+
"organizationId",
|
|
82
|
+
"org"
|
|
83
|
+
],
|
|
84
|
+
"description": "Organization to use when the account has several",
|
|
85
|
+
"name": "organization-id",
|
|
86
|
+
"hasDynamicHelp": false,
|
|
87
|
+
"multiple": false,
|
|
88
|
+
"type": "option"
|
|
89
|
+
},
|
|
90
|
+
"project-id": {
|
|
91
|
+
"aliases": [
|
|
92
|
+
"project",
|
|
93
|
+
"projectId"
|
|
94
|
+
],
|
|
95
|
+
"description": "Project to use when the organization has several",
|
|
96
|
+
"name": "project-id",
|
|
97
|
+
"hasDynamicHelp": false,
|
|
98
|
+
"multiple": false,
|
|
99
|
+
"type": "option"
|
|
100
|
+
},
|
|
101
|
+
"create-project": {
|
|
102
|
+
"aliases": [
|
|
103
|
+
"createProject",
|
|
104
|
+
"new-project"
|
|
105
|
+
],
|
|
106
|
+
"description": "Create a project with this display name instead of using an existing one",
|
|
107
|
+
"exclusive": [
|
|
108
|
+
"project-id"
|
|
109
|
+
],
|
|
110
|
+
"name": "create-project",
|
|
111
|
+
"hasDynamicHelp": false,
|
|
112
|
+
"multiple": false,
|
|
113
|
+
"type": "option"
|
|
114
|
+
},
|
|
115
|
+
"dataset": {
|
|
116
|
+
"description": "Dataset to attach, or to create alongside a new project",
|
|
117
|
+
"name": "dataset",
|
|
118
|
+
"hasDynamicHelp": false,
|
|
119
|
+
"multiple": false,
|
|
120
|
+
"type": "option"
|
|
121
|
+
},
|
|
122
|
+
"stack-name": {
|
|
123
|
+
"description": "Name for the new organization-scoped Stack, and the hosted Studio slug",
|
|
124
|
+
"name": "stack-name",
|
|
125
|
+
"hasDynamicHelp": false,
|
|
126
|
+
"multiple": false,
|
|
127
|
+
"type": "option"
|
|
128
|
+
},
|
|
129
|
+
"studio-name": {
|
|
130
|
+
"description": "Blueprint-local name for the Studio resource and its directory",
|
|
131
|
+
"name": "studio-name",
|
|
132
|
+
"hasDynamicHelp": false,
|
|
133
|
+
"multiple": false,
|
|
134
|
+
"type": "option"
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"hasDynamicHelp": false,
|
|
138
|
+
"hidden": true,
|
|
139
|
+
"hiddenAliases": [],
|
|
140
|
+
"id": "init",
|
|
141
|
+
"pluginAlias": "@sanity/runtime-cli",
|
|
142
|
+
"pluginName": "@sanity/runtime-cli",
|
|
143
|
+
"pluginType": "core",
|
|
144
|
+
"strict": true,
|
|
145
|
+
"summary": "Experimental blueprints-first project init",
|
|
146
|
+
"enableJsonFlag": true,
|
|
147
|
+
"isESM": true,
|
|
148
|
+
"relativePath": [
|
|
149
|
+
"dist",
|
|
150
|
+
"commands",
|
|
151
|
+
"init.js"
|
|
152
|
+
]
|
|
153
|
+
},
|
|
3
154
|
"blueprints:add": {
|
|
4
155
|
"aliases": [],
|
|
5
156
|
"args": {
|
|
@@ -1556,9 +1707,10 @@
|
|
|
1556
1707
|
"blueprints:stacks": {
|
|
1557
1708
|
"aliases": [],
|
|
1558
1709
|
"args": {},
|
|
1559
|
-
"description": "Shows all Stacks associated with a project or organization. By default, lists Stacks scoped to the local Blueprint.\n\nUse this to discover existing Stacks you can scope a local Blueprint to (using 'blueprints config --edit'), or to audit what's deployed across your project.\n\
|
|
1710
|
+
"description": "Shows all Stacks associated with a project or organization. By default, lists Stacks scoped to the local Blueprint.\n\nUse this to discover existing Stacks you can scope a local Blueprint to (using 'blueprints config --edit'), or to audit what's deployed across your project.\n\nWithout a scope, prompts for an organization or project. Use --all to list Stacks across every organization and project you can access, or --include-projects with --organization-id for one organization and its projects.",
|
|
1560
1711
|
"examples": [
|
|
1561
1712
|
"<%= config.bin %> <%= command.id %>",
|
|
1713
|
+
"<%= config.bin %> <%= command.id %> --all",
|
|
1562
1714
|
"<%= config.bin %> <%= command.id %> --project-id <projectId>",
|
|
1563
1715
|
"<%= config.bin %> <%= command.id %> --organization-id <organizationId>",
|
|
1564
1716
|
"<%= config.bin %> <%= command.id %> --organization-id <organizationId> --include-projects"
|
|
@@ -1620,7 +1772,8 @@
|
|
|
1620
1772
|
"description": "Sanity project ID used to scope Blueprint and Stack",
|
|
1621
1773
|
"exclusive": [
|
|
1622
1774
|
"organization-id",
|
|
1623
|
-
"include-projects"
|
|
1775
|
+
"include-projects",
|
|
1776
|
+
"all"
|
|
1624
1777
|
],
|
|
1625
1778
|
"name": "project-id",
|
|
1626
1779
|
"hasDynamicHelp": false,
|
|
@@ -1635,7 +1788,8 @@
|
|
|
1635
1788
|
],
|
|
1636
1789
|
"description": "Sanity organization ID used to scope Blueprint and Stack",
|
|
1637
1790
|
"exclusive": [
|
|
1638
|
-
"project-id"
|
|
1791
|
+
"project-id",
|
|
1792
|
+
"all"
|
|
1639
1793
|
],
|
|
1640
1794
|
"name": "organization-id",
|
|
1641
1795
|
"hasDynamicHelp": false,
|
|
@@ -1650,6 +1804,17 @@
|
|
|
1650
1804
|
"name": "include-projects",
|
|
1651
1805
|
"allowNo": false,
|
|
1652
1806
|
"type": "boolean"
|
|
1807
|
+
},
|
|
1808
|
+
"all": {
|
|
1809
|
+
"description": "List Stacks from every organization and project you have access to",
|
|
1810
|
+
"exclusive": [
|
|
1811
|
+
"project-id",
|
|
1812
|
+
"organization-id",
|
|
1813
|
+
"include-projects"
|
|
1814
|
+
],
|
|
1815
|
+
"name": "all",
|
|
1816
|
+
"allowNo": false,
|
|
1817
|
+
"type": "boolean"
|
|
1653
1818
|
}
|
|
1654
1819
|
},
|
|
1655
1820
|
"hasDynamicHelp": false,
|
|
@@ -1662,7 +1827,7 @@
|
|
|
1662
1827
|
"summary": "List remote Stack deployments for your project or organization",
|
|
1663
1828
|
"enableJsonFlag": true,
|
|
1664
1829
|
"needs": [
|
|
1665
|
-
"
|
|
1830
|
+
"token"
|
|
1666
1831
|
],
|
|
1667
1832
|
"isESM": true,
|
|
1668
1833
|
"relativePath": [
|
|
@@ -2741,6 +2906,13 @@
|
|
|
2741
2906
|
"hasDynamicHelp": false,
|
|
2742
2907
|
"multiple": false,
|
|
2743
2908
|
"type": "option"
|
|
2909
|
+
},
|
|
2910
|
+
"no-wait": {
|
|
2911
|
+
"description": "Skip durable wait delays instead of sleeping",
|
|
2912
|
+
"name": "no-wait",
|
|
2913
|
+
"required": false,
|
|
2914
|
+
"allowNo": false,
|
|
2915
|
+
"type": "boolean"
|
|
2744
2916
|
}
|
|
2745
2917
|
},
|
|
2746
2918
|
"hasDynamicHelp": false,
|
|
@@ -3127,5 +3299,5 @@
|
|
|
3127
3299
|
]
|
|
3128
3300
|
}
|
|
3129
3301
|
},
|
|
3130
|
-
"version": "17.
|
|
3302
|
+
"version": "17.9.0-blueprinit.g14aaebd"
|
|
3131
3303
|
}
|
package/package.json
CHANGED
|
@@ -17,7 +17,9 @@ npx @sanity/cli blueprints stacks --project-id PROJECT_ID --json
|
|
|
17
17
|
npx @sanity/cli blueprints stacks --organization-id ORGANIZATION_ID --json
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Always pass a scope flag or `--all` when automating. With no scope to resolve the command prompts for an organization, then for a project if you pick project scope; without a terminal, or with `--json`, it fails with a missing-scope error instead.
|
|
21
|
+
|
|
22
|
+
The JSON result contains `stacks`, `scopeType`, and `scopeId`; each entry carries `resourceCount` rather than a full `resources` array. Zero results prints `No stacks found`, and under `--json` returns an empty `stacks` array. Match both the Stack and its scope; names alone may be ambiguous.
|
|
21
23
|
|
|
22
24
|
To also include Stacks scoped to the organization's projects:
|
|
23
25
|
|
|
@@ -25,4 +27,14 @@ To also include Stacks scoped to the organization's projects:
|
|
|
25
27
|
npx @sanity/cli blueprints stacks --organization-id ORGANIZATION_ID --include-projects --json
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
`--include-projects` requires `--organization-id`, cannot be combined with `--project-id`, and only queries the organization's first 50 projects.
|
|
30
|
+
`--include-projects` requires `--organization-id`, cannot be combined with `--project-id`, and only queries the organization's first 50 projects.
|
|
31
|
+
|
|
32
|
+
To sweep every organization and project the token can reach:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npx @sanity/cli blueprints stacks --all --json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`--all` cannot be combined with the scope flags or `--include-projects`. It is best effort: scopes that return an error are skipped and reported as a count, and only the first 200 projects are queried. Its JSON result contains `stacks` and no top-level `scopeType`/`scopeId`; read each entry's own `scopeType` and `scopeId` instead.
|
|
39
|
+
|
|
40
|
+
This command does not change the local Blueprint target; use `blueprints config --edit` for that.
|