@sanity/runtime-cli 17.15.0-next.ge190195 → 17.16.0-app-functions.ge0a25ea
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 +19 -19
- package/dist/actions/blueprints/assets.d.ts +3 -3
- package/dist/actions/blueprints/assets.js +3 -3
- package/dist/actions/blueprints/pre-deploy.js +3 -3
- package/dist/actions/blueprints/process-assets.js +3 -2
- package/dist/actions/blueprints/stacks.d.ts +7 -2
- package/dist/actions/blueprints/stacks.js +10 -6
- package/dist/actions/blueprints/wait-for-operation.d.ts +1 -0
- package/dist/actions/blueprints/wait-for-operation.js +1 -1
- package/dist/cores/blueprints/deploy.d.ts +8 -0
- package/dist/cores/blueprints/deploy.js +12 -4
- package/dist/cores/functions/test.js +15 -4
- package/dist/functions/artifacts.d.ts +13 -0
- package/dist/functions/artifacts.js +26 -0
- package/dist/functions/build.d.ts +15 -0
- package/dist/functions/build.js +27 -0
- package/dist/functions/contractPlugin.d.ts +7 -0
- package/dist/functions/contractPlugin.js +32 -0
- package/dist/functions/contracts/schema.d.ts +22 -0
- package/dist/functions/contracts/schema.js +99 -0
- package/dist/functions/contracts/validation.d.ts +3 -0
- package/dist/functions/contracts/validation.js +66 -0
- package/dist/functions/contracts.d.ts +20 -0
- package/dist/functions/contracts.js +119 -0
- package/dist/functions/deploy.d.ts +15 -0
- package/dist/functions/deploy.js +60 -0
- package/dist/functions/stack.d.ts +18 -0
- package/dist/functions/stack.js +84 -0
- package/dist/server/app.js +2 -2
- package/dist/utils/blueprints/group-resources.d.ts +2 -1
- package/dist/utils/blueprints/group-resources.js +3 -3
- package/dist/utils/blueprints/resolve-deployed-resources.d.ts +2 -2
- package/dist/utils/blueprints/resolve-deployed-resources.js +4 -4
- package/dist/utils/bundles/prepare-asset.d.ts +3 -3
- package/dist/utils/bundles/prepare-asset.js +8 -7
- package/dist/utils/functions/child-runtime/durable.js +99 -22
- package/dist/utils/functions/child-runtime/step-history.d.ts +15 -0
- package/dist/utils/functions/child-runtime/step-history.js +52 -0
- package/dist/utils/functions/invoke/local.js +19 -8
- package/dist/utils/functions/invoke/resolve-invoke-type.d.ts +2 -2
- package/dist/utils/functions/invoke/resolve-invoke-type.js +2 -2
- package/dist/utils/functions/transpile/function.d.ts +7 -1
- package/dist/utils/functions/transpile/function.js +15 -9
- package/dist/utils/types.d.ts +19 -12
- package/dist/utils/types.js +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +23 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {performance} from 'node:perf_hooks'
|
|
2
2
|
import {inspect} from 'node:util'
|
|
3
|
+
import {createStepHistory} from './step-history.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
*
|
|
@@ -26,7 +27,9 @@ const formatArgs = (args) =>
|
|
|
26
27
|
* @param io
|
|
27
28
|
*/
|
|
28
29
|
export async function runDurable(handler, {context, event}, io) {
|
|
30
|
+
const history = createStepHistory()
|
|
29
31
|
let currentStep = null
|
|
32
|
+
|
|
30
33
|
const streamLog = (level, args) => {
|
|
31
34
|
const date = new Date()
|
|
32
35
|
const timestamp = `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
|
|
@@ -41,7 +44,6 @@ export async function runDurable(handler, {context, event}, io) {
|
|
|
41
44
|
})
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
// @todo: need to throw error for use of `console.log` in a durable function
|
|
45
47
|
const logger = {
|
|
46
48
|
log: (...a) => streamLog('info', a),
|
|
47
49
|
info: (...a) => streamLog('info', a),
|
|
@@ -49,24 +51,57 @@ export async function runDurable(handler, {context, event}, io) {
|
|
|
49
51
|
error: (...a) => streamLog('error', a),
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const emitFailure = (pending) => {
|
|
55
|
+
history.settle(pending)
|
|
56
|
+
io.emit(pending.event)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const settleUnretried = () => {
|
|
60
|
+
const pending = history.getPending()
|
|
61
|
+
if (pending !== null) {
|
|
62
|
+
emitFailure(pending)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const track = async (name, kind, produce, retry) => {
|
|
67
|
+
settleUnretried()
|
|
68
|
+
const {index, saved} = history.nextStep()
|
|
69
|
+
|
|
70
|
+
if (saved?.phase === 'complete') {
|
|
71
|
+
return saved.output
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const maxAttempts = retry?.maxAttempts ?? 1
|
|
75
|
+
const retries = Math.max((retry?.maxAttempts ?? 1) - 1, 0)
|
|
76
|
+
const waitingOnRetry = typeof saved?.retryDelayMs === 'number'
|
|
77
|
+
|
|
78
|
+
if (saved?.phase === 'error' && !waitingOnRetry) {
|
|
79
|
+
throw saved.output
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const attempt = (saved?.attempt ?? 0) + 1
|
|
55
83
|
const prev = currentStep
|
|
56
84
|
currentStep = name
|
|
57
85
|
|
|
86
|
+
io.emit({name, kind, phase: 'start'})
|
|
87
|
+
const startedAt = performance.now()
|
|
88
|
+
|
|
58
89
|
try {
|
|
59
|
-
const value = await produce()
|
|
60
|
-
|
|
90
|
+
const value = await produce(attempt)
|
|
91
|
+
const completeEvent = {
|
|
61
92
|
name,
|
|
62
93
|
kind,
|
|
63
94
|
phase: 'complete',
|
|
64
95
|
output: value,
|
|
65
96
|
durationMs: performance.now() - startedAt,
|
|
66
|
-
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
history.recordSuccess(index, completeEvent)
|
|
100
|
+
io.emit(completeEvent)
|
|
101
|
+
|
|
67
102
|
return value
|
|
68
103
|
} catch (err) {
|
|
69
|
-
|
|
104
|
+
const errorEvent = {
|
|
70
105
|
name,
|
|
71
106
|
kind,
|
|
72
107
|
phase: 'error',
|
|
@@ -76,7 +111,21 @@ export async function runDurable(handler, {context, event}, io) {
|
|
|
76
111
|
stack: err?.stack ?? '',
|
|
77
112
|
},
|
|
78
113
|
durationMs: performance.now() - startedAt,
|
|
114
|
+
attempt,
|
|
115
|
+
retries,
|
|
116
|
+
maxAttempts,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const retryPending = history.recordFailure(index, {
|
|
120
|
+
event: errorEvent,
|
|
121
|
+
error: err,
|
|
122
|
+
delayMs: retry?.delay ? durationToMs(retry.delay) : 0,
|
|
79
123
|
})
|
|
124
|
+
|
|
125
|
+
if (!retryPending) {
|
|
126
|
+
io.emit(errorEvent)
|
|
127
|
+
}
|
|
128
|
+
|
|
80
129
|
throw err
|
|
81
130
|
} finally {
|
|
82
131
|
currentStep = prev
|
|
@@ -84,12 +133,21 @@ export async function runDurable(handler, {context, event}, io) {
|
|
|
84
133
|
}
|
|
85
134
|
|
|
86
135
|
const step = {
|
|
87
|
-
run: ({name, handler: fn
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
136
|
+
run: ({name, handler: fn, retry}) =>
|
|
137
|
+
track(name || '', 'run', (attempt) => fn({logger, attempt}), retry),
|
|
138
|
+
delegate: ({name, handler, event, retry}) =>
|
|
139
|
+
track(
|
|
140
|
+
name || '',
|
|
141
|
+
'delegate',
|
|
142
|
+
() => {
|
|
143
|
+
const fn = typeof handler === 'string' ? handler : handler?.name
|
|
144
|
+
if (!fn) {
|
|
145
|
+
throw new Error('No function name provided for delegation')
|
|
146
|
+
}
|
|
147
|
+
return io.invoke(fn, event?.data ?? {})
|
|
148
|
+
},
|
|
149
|
+
retry,
|
|
150
|
+
),
|
|
93
151
|
waitForCondition: ({name, initial, poller, next}) =>
|
|
94
152
|
track(name || '', 'wait-for-condition', async () => {
|
|
95
153
|
let state = initial
|
|
@@ -107,15 +165,34 @@ export async function runDurable(handler, {context, event}, io) {
|
|
|
107
165
|
}
|
|
108
166
|
return state
|
|
109
167
|
}),
|
|
110
|
-
|
|
111
|
-
track(name || '', '
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
throw new Error('No function name provided for delegation')
|
|
115
|
-
}
|
|
116
|
-
return io.invoke(fn, event)
|
|
168
|
+
wait: ({name, duration}) =>
|
|
169
|
+
track(name || '', 'wait', async () => {
|
|
170
|
+
await io.wait(durationToMs(duration))
|
|
171
|
+
return undefined
|
|
117
172
|
}),
|
|
118
173
|
}
|
|
119
174
|
|
|
120
|
-
|
|
175
|
+
let result
|
|
176
|
+
let done = false
|
|
177
|
+
while (!done) {
|
|
178
|
+
history.startRun()
|
|
179
|
+
try {
|
|
180
|
+
result = await handler({context, event, step, logger})
|
|
181
|
+
settleUnretried()
|
|
182
|
+
done = true
|
|
183
|
+
} catch (err) {
|
|
184
|
+
const pending = history.getPending()
|
|
185
|
+
if (pending === null) {
|
|
186
|
+
throw err
|
|
187
|
+
}
|
|
188
|
+
if (err?.name === 'UnrecoverableError') {
|
|
189
|
+
emitFailure(pending)
|
|
190
|
+
throw err
|
|
191
|
+
}
|
|
192
|
+
io.emit({...pending.event, retryDelayMs: pending.delayMs})
|
|
193
|
+
await io.wait(pending.delayMs)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return result
|
|
121
198
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type {DurableStepEvent} from './types'
|
|
2
|
+
|
|
3
|
+
type PendingRetry = {index: number; event: DurableStepEvent; delayMs: number}
|
|
4
|
+
|
|
5
|
+
export function createStepHistory(): {
|
|
6
|
+
startRun: () => void
|
|
7
|
+
nextStep: () => {index: number; saved: DurableStepEvent | undefined}
|
|
8
|
+
recordSuccess: (index: number, event: DurableStepEvent) => void
|
|
9
|
+
recordFailure: (
|
|
10
|
+
index: number,
|
|
11
|
+
failure: {event: DurableStepEvent; error: unknown; delayMs: number},
|
|
12
|
+
) => boolean
|
|
13
|
+
getPending: () => PendingRetry | null
|
|
14
|
+
settle: (pending: PendingRetry) => void
|
|
15
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const createStepHistory = () => {
|
|
2
|
+
const history = new Map([])
|
|
3
|
+
let cursor = 0
|
|
4
|
+
let pending = null
|
|
5
|
+
|
|
6
|
+
const startRun = () => {
|
|
7
|
+
cursor = 0
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const nextStep = () => {
|
|
11
|
+
const index = cursor
|
|
12
|
+
cursor++
|
|
13
|
+
return {index, saved: history.get(index)}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const recordSuccess = (index, event) => {
|
|
17
|
+
history.set(index, event)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const recordFailure = (index, {event, error, delayMs}) => {
|
|
21
|
+
const retryable = event.attempt <= event.retries && error?.name !== 'UnrecoverableError'
|
|
22
|
+
|
|
23
|
+
if (retryable) {
|
|
24
|
+
history.set(index, {...event, output: error, retryDelayMs: delayMs})
|
|
25
|
+
pending = {index, event, delayMs}
|
|
26
|
+
} else {
|
|
27
|
+
history.set(index, {...event, output: error})
|
|
28
|
+
}
|
|
29
|
+
return retryable
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const getPending = () => {
|
|
33
|
+
const item = pending
|
|
34
|
+
pending = null
|
|
35
|
+
return item
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const settle = ({index, event}) => {
|
|
39
|
+
history.set(index, {...event, output: history.get(index).output})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
startRun,
|
|
44
|
+
nextStep,
|
|
45
|
+
recordSuccess,
|
|
46
|
+
recordFailure,
|
|
47
|
+
getPending,
|
|
48
|
+
settle,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {createStepHistory}
|
|
@@ -64,10 +64,11 @@ export default async function invoke(resource, payload, context, options) {
|
|
|
64
64
|
// Apply the GROQ rule before preparing a build so a filtered-out event skips
|
|
65
65
|
// the (potentially expensive) transpile entirely.
|
|
66
66
|
if (isGroqInvocation(resource)) {
|
|
67
|
-
if (!
|
|
67
|
+
if (!('clientOptions' in context)) {
|
|
68
68
|
throw new Error('GROQ-based functions require a context with clientOptions');
|
|
69
69
|
}
|
|
70
|
-
const
|
|
70
|
+
const projectId = 'projectId' in context.clientOptions ? context.clientOptions.projectId : undefined;
|
|
71
|
+
const dataset = 'dataset' in context.clientOptions ? context.clientOptions.dataset : undefined;
|
|
71
72
|
if ('before' in payload) {
|
|
72
73
|
filteredData = await applyGroqRule(resource, payload, projectId, dataset);
|
|
73
74
|
const filter = resource.event && 'filter' in resource.event ? resource.event.filter : '';
|
|
@@ -173,12 +174,22 @@ export default async function invoke(resource, payload, context, options) {
|
|
|
173
174
|
// of `nested.error`. The error isn't lost: it travels back in the returned
|
|
174
175
|
// result and is logged/streamed to the UI by the caller (app/test core).
|
|
175
176
|
if (child && !child.killed) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
// step.delegate errors need to be surfaced to the caller for retry behavior and for the durable step to be marked as failed.
|
|
178
|
+
const origin = metadata?.origin || undefined;
|
|
179
|
+
const error = nested.error || undefined;
|
|
180
|
+
const response = origin === 'step.delegate' && error
|
|
181
|
+
? {
|
|
182
|
+
type: 'invoke-response',
|
|
183
|
+
id,
|
|
184
|
+
ok: false,
|
|
185
|
+
error,
|
|
186
|
+
}
|
|
187
|
+
: {
|
|
188
|
+
type: 'invoke-response',
|
|
189
|
+
id,
|
|
190
|
+
ok: true,
|
|
191
|
+
result: { json: nested.json },
|
|
192
|
+
};
|
|
182
193
|
child.send(JSON.stringify(response));
|
|
183
194
|
}
|
|
184
195
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BlueprintResource } from '@sanity/blueprints';
|
|
2
2
|
import type { Logger } from '../../logger.js';
|
|
3
|
-
import type { EventType, FunctionGroqResource, FunctionResource, FunctionTestFlags, InvokeContextOptions, InvokePayloadOptions } from '../../types.js';
|
|
3
|
+
import type { EventType, FunctionGroqResource, FunctionResource, FunctionTestFlags, InvokeContextOptions, InvokePayloadOptions, ResolvedResource } from '../../types.js';
|
|
4
4
|
import buildPayload from '../build-payload.js';
|
|
5
5
|
import { fetchAsset, fetchDocument } from '../fetch-document.js';
|
|
6
6
|
export type InvocationPlan = {
|
|
@@ -23,7 +23,7 @@ export type InputContext = {
|
|
|
23
23
|
apiHost: string;
|
|
24
24
|
token?: string;
|
|
25
25
|
withUserToken?: boolean;
|
|
26
|
-
|
|
26
|
+
resolvedResources: ResolvedResource<BlueprintResource>[];
|
|
27
27
|
blueprintFileDir: string;
|
|
28
28
|
log: Logger;
|
|
29
29
|
};
|
|
@@ -51,7 +51,7 @@ export const buildContext = (plan, input) => {
|
|
|
51
51
|
if (plan.kind === 'plain') {
|
|
52
52
|
return {
|
|
53
53
|
clientOptions: { ...withToken },
|
|
54
|
-
resources: input.
|
|
54
|
+
resources: input.resolvedResources,
|
|
55
55
|
blueprintFileDir: input.blueprintFileDir,
|
|
56
56
|
};
|
|
57
57
|
}
|
|
@@ -69,7 +69,7 @@ export const buildContext = (plan, input) => {
|
|
|
69
69
|
'',
|
|
70
70
|
functionResourceType: 'project',
|
|
71
71
|
functionResourceId: input.projectId || '',
|
|
72
|
-
resources: input.
|
|
72
|
+
resources: input.resolvedResources,
|
|
73
73
|
blueprintFileDir: input.blueprintFileDir,
|
|
74
74
|
};
|
|
75
75
|
};
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
1
2
|
import type { FunctionResource, InstallerType } from '../../types.js';
|
|
2
3
|
export declare const resolveViteRoot: (entry: string) => string;
|
|
3
|
-
export declare function transpileFunction({ resource, functionPath, entryPoint, installer, }: {
|
|
4
|
+
export declare function transpileFunction({ resource, functionPath, entryPoint, installer, workDir, outDir, outputFileName, bundle: bundleDependencies, plugins: extraPlugins, }: {
|
|
4
5
|
resource: FunctionResource;
|
|
5
6
|
functionPath: string;
|
|
6
7
|
entryPoint: string;
|
|
7
8
|
installer?: InstallerType;
|
|
9
|
+
workDir?: string;
|
|
10
|
+
outDir?: string;
|
|
11
|
+
outputFileName?: string;
|
|
12
|
+
bundle?: boolean;
|
|
13
|
+
plugins?: Plugin[];
|
|
8
14
|
}): Promise<{
|
|
9
15
|
type: string;
|
|
10
16
|
outputDir: string;
|
|
@@ -13,7 +13,7 @@ export const resolveViteRoot = (entry) => {
|
|
|
13
13
|
const nodeModulesDir = find.dir('node_modules', { cwd: entry });
|
|
14
14
|
return nodeModulesDir ? path.dirname(nodeModulesDir) : entry;
|
|
15
15
|
};
|
|
16
|
-
export async function transpileFunction({ resource, functionPath, entryPoint, installer, }) {
|
|
16
|
+
export async function transpileFunction({ resource, functionPath, entryPoint, installer, workDir = cwd(), outDir, outputFileName = getOutputFilename(entryPoint), bundle: bundleDependencies, plugins: extraPlugins = [], }) {
|
|
17
17
|
if (!resource.src)
|
|
18
18
|
throw new Error('Resource src is required');
|
|
19
19
|
if (!resource.name)
|
|
@@ -23,8 +23,8 @@ export async function transpileFunction({ resource, functionPath, entryPoint, in
|
|
|
23
23
|
const stats = await stat(functionPath);
|
|
24
24
|
const entryDir = stats.isFile() ? path.dirname(functionPath) : functionPath;
|
|
25
25
|
const outputPathStart = performance.now();
|
|
26
|
-
const outputDir = await getTranspileOutputPath(entryDir, resource.name);
|
|
27
|
-
const outputFile = path.join(outputDir,
|
|
26
|
+
const outputDir = await getTranspileOutputPath(entryDir, resource.name, outDir);
|
|
27
|
+
const outputFile = path.join(outputDir, outputFileName);
|
|
28
28
|
const fnRootDir = resolveViteRoot(entryDir);
|
|
29
29
|
timings['transpile:setupOutput'] = performance.now() - outputPathStart;
|
|
30
30
|
async function cleanupTmpDir() {
|
|
@@ -34,7 +34,8 @@ export async function transpileFunction({ resource, functionPath, entryPoint, in
|
|
|
34
34
|
try {
|
|
35
35
|
const viteStart = performance.now();
|
|
36
36
|
// Always bundle the code if pnpm usage is detected or specified by the user
|
|
37
|
-
const bundle =
|
|
37
|
+
const bundle = bundleDependencies ??
|
|
38
|
+
(!!find.file('pnpm-workspace.yaml', { cwd: workDir }) || installer === 'pnpm');
|
|
38
39
|
const result = await viteBuild({
|
|
39
40
|
root: fnRootDir,
|
|
40
41
|
logLevel: 'silent',
|
|
@@ -49,7 +50,7 @@ export async function transpileFunction({ resource, functionPath, entryPoint, in
|
|
|
49
50
|
input: entryPoint,
|
|
50
51
|
output: {
|
|
51
52
|
format: 'esm',
|
|
52
|
-
entryFileNames:
|
|
53
|
+
entryFileNames: outputFileName,
|
|
53
54
|
...(bundle
|
|
54
55
|
? {}
|
|
55
56
|
: {
|
|
@@ -71,7 +72,10 @@ export async function transpileFunction({ resource, functionPath, entryPoint, in
|
|
|
71
72
|
conditions: ['node'],
|
|
72
73
|
},
|
|
73
74
|
},
|
|
74
|
-
plugins:
|
|
75
|
+
plugins: [
|
|
76
|
+
...(bundle ? [detectNativeModulesPlugin(), pnpmResolvePlugin(workDir)] : []),
|
|
77
|
+
...extraPlugins,
|
|
78
|
+
],
|
|
75
79
|
});
|
|
76
80
|
timings['transpile:build'] = performance.now() - viteStart;
|
|
77
81
|
const verifyStart = performance.now();
|
|
@@ -81,7 +85,7 @@ export async function transpileFunction({ resource, functionPath, entryPoint, in
|
|
|
81
85
|
await writeTranspiledPackageJson(entryDir, outputFile);
|
|
82
86
|
timings['transpile:writePackage'] = performance.now() - pkgStart;
|
|
83
87
|
const cleanupStart = performance.now();
|
|
84
|
-
await cleanupSourceMaps(
|
|
88
|
+
await cleanupSourceMaps(entryDir, outputDir);
|
|
85
89
|
timings['transpile:cleanupMaps'] = performance.now() - cleanupStart;
|
|
86
90
|
timings.bundle = performance.now() - transpileStart;
|
|
87
91
|
return {
|
|
@@ -148,8 +152,10 @@ async function writeTranspiledPackageJson(inputDir, outputFilePath) {
|
|
|
148
152
|
const pkgJsonOutputPath = path.join(path.dirname(outputFilePath), 'package.json');
|
|
149
153
|
await writeFile(pkgJsonOutputPath, JSON.stringify(bundled, null, 2));
|
|
150
154
|
}
|
|
151
|
-
async function getTranspileOutputPath(entryDir, fnName) {
|
|
152
|
-
const tmpPath =
|
|
155
|
+
async function getTranspileOutputPath(entryDir, fnName, outDir) {
|
|
156
|
+
const tmpPath = outDir
|
|
157
|
+
? path.resolve(outDir)
|
|
158
|
+
: path.resolve(entryDir, '.build', `function-${fnName}`);
|
|
153
159
|
await rm(tmpPath, { recursive: true, force: true }).catch(logCleanupFailure);
|
|
154
160
|
await mkdir(tmpPath, { recursive: true });
|
|
155
161
|
return tmpPath;
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -40,6 +40,11 @@ export interface BlueprintResourceRecord extends BlueprintResource {
|
|
|
40
40
|
export interface DeployedResource extends BlueprintResourceRecord {
|
|
41
41
|
externalId: string;
|
|
42
42
|
}
|
|
43
|
+
/** Wrap a resource and its externalId if it has one. */
|
|
44
|
+
export interface ResolvedResource<R extends BlueprintResource> {
|
|
45
|
+
resource: R;
|
|
46
|
+
externalId?: string;
|
|
47
|
+
}
|
|
43
48
|
export declare function isLocalFunctionResource(r: BlueprintResource): r is FunctionResource;
|
|
44
49
|
export declare function hasEventSource(r: FunctionResource): r is EventFunctionResource;
|
|
45
50
|
export declare function isScheduleEvent(e: unknown): e is BlueprintScheduledFunctionResource['event'];
|
|
@@ -134,8 +139,14 @@ export type InvokePayloadMetadata = Pick<InvokeGroqPayloadOptions, 'event' | 'be
|
|
|
134
139
|
export type EventType = 'create' | 'update' | 'delete';
|
|
135
140
|
export type NonGroqEventType = 'plain' | 'nested' | 'durable';
|
|
136
141
|
export declare function isEventType(arg: string): arg is EventType;
|
|
142
|
+
interface BaseContextOptions {
|
|
143
|
+
/** All resources declared by the blueprint, used to populate `context.resources` at invoke time. */
|
|
144
|
+
resources?: ResolvedResource<BlueprintResource>[];
|
|
145
|
+
/** The directory where the blueprint manifest is located. */
|
|
146
|
+
blueprintFileDir: string;
|
|
147
|
+
}
|
|
137
148
|
/** @internal */
|
|
138
|
-
export interface InvokeGroqContextOptions {
|
|
149
|
+
export interface InvokeGroqContextOptions extends BaseContextOptions {
|
|
139
150
|
clientOptions: {
|
|
140
151
|
apiVersion?: string;
|
|
141
152
|
dataset?: string;
|
|
@@ -151,20 +162,12 @@ export interface InvokeGroqContextOptions {
|
|
|
151
162
|
functionResourceType: string;
|
|
152
163
|
/** The resource ID of the function container; resource ID that houses the function. */
|
|
153
164
|
functionResourceId: string;
|
|
154
|
-
/** All resources declared by the blueprint, used to populate `context.resources` at invoke time. */
|
|
155
|
-
resources?: BlueprintResource[];
|
|
156
|
-
/** The directory where the blueprint manifest is located. */
|
|
157
|
-
blueprintFileDir: string;
|
|
158
165
|
}
|
|
159
166
|
/** @internal */
|
|
160
|
-
export interface InvokeScheduleContextOptions {
|
|
167
|
+
export interface InvokeScheduleContextOptions extends BaseContextOptions {
|
|
161
168
|
clientOptions: {
|
|
162
169
|
token?: string;
|
|
163
170
|
};
|
|
164
|
-
/** All resources declared by the blueprint, used to populate `context.resources` at invoke time. */
|
|
165
|
-
resources?: BlueprintResource[];
|
|
166
|
-
/** The directory where the blueprint manifest is located. */
|
|
167
|
-
blueprintFileDir: string;
|
|
168
171
|
}
|
|
169
172
|
export type InvokeContextOptions = InvokeGroqContextOptions | InvokeScheduleContextOptions;
|
|
170
173
|
export declare function isGroqContextOptions(context: InvokeContextOptions): context is InvokeGroqContextOptions;
|
|
@@ -338,7 +341,7 @@ export type AssetPrepResult = {
|
|
|
338
341
|
error: string;
|
|
339
342
|
};
|
|
340
343
|
export type PrepAssetFn<R extends BlueprintResource> = (options: {
|
|
341
|
-
|
|
344
|
+
resolvedResource: ResolvedResource<R>;
|
|
342
345
|
blueprintFileDir: string;
|
|
343
346
|
installer?: InstallerType;
|
|
344
347
|
}) => Promise<AssetPrepResult>;
|
|
@@ -355,7 +358,7 @@ export type PreDeployConfig = {
|
|
|
355
358
|
prepareResource?: PrepResourceFn<BlueprintResource>;
|
|
356
359
|
};
|
|
357
360
|
export type AssetResource<R extends BlueprintResource> = {
|
|
358
|
-
resource: R
|
|
361
|
+
resource: ResolvedResource<R>;
|
|
359
362
|
prepareAsset: PrepAssetFn<R>;
|
|
360
363
|
};
|
|
361
364
|
export type Warning = {
|
|
@@ -376,6 +379,10 @@ export interface DurableStepEvent {
|
|
|
376
379
|
output?: unknown;
|
|
377
380
|
error?: InvocationError;
|
|
378
381
|
durationMs?: number;
|
|
382
|
+
retryDelayMs?: number;
|
|
383
|
+
attempt?: number;
|
|
384
|
+
retries?: number;
|
|
385
|
+
maxAttempts?: number;
|
|
379
386
|
}
|
|
380
387
|
export interface DurableLogEvent {
|
|
381
388
|
kind: 'log';
|
package/dist/utils/types.js
CHANGED
|
@@ -38,7 +38,7 @@ export function isEventType(arg) {
|
|
|
38
38
|
return ['create', 'update', 'delete'].includes(arg);
|
|
39
39
|
}
|
|
40
40
|
export function isGroqContextOptions(context) {
|
|
41
|
-
return '
|
|
41
|
+
return 'eventResourceType' in context;
|
|
42
42
|
}
|
|
43
43
|
/** @internal */
|
|
44
44
|
export var BlueprintParserErrorType;
|
package/oclif.manifest.json
CHANGED
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.16.0-app-functions.ge0a25ea",
|
|
5
5
|
"author": "Sanity Runtime Team",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -14,6 +14,26 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"types": "dist/index.d.ts",
|
|
16
16
|
"exports": {
|
|
17
|
+
"./functions/stack": {
|
|
18
|
+
"types": "./dist/functions/stack.d.ts",
|
|
19
|
+
"import": "./dist/functions/stack.js",
|
|
20
|
+
"require": "./dist/functions/stack.js"
|
|
21
|
+
},
|
|
22
|
+
"./functions/contracts": {
|
|
23
|
+
"types": "./dist/functions/contracts.d.ts",
|
|
24
|
+
"import": "./dist/functions/contracts.js",
|
|
25
|
+
"require": "./dist/functions/contracts.js"
|
|
26
|
+
},
|
|
27
|
+
"./functions/deploy": {
|
|
28
|
+
"types": "./dist/functions/deploy.d.ts",
|
|
29
|
+
"import": "./dist/functions/deploy.js",
|
|
30
|
+
"require": "./dist/functions/deploy.js"
|
|
31
|
+
},
|
|
32
|
+
"./functions/build": {
|
|
33
|
+
"types": "./dist/functions/build.d.ts",
|
|
34
|
+
"import": "./dist/functions/build.js",
|
|
35
|
+
"require": "./dist/functions/build.js"
|
|
36
|
+
},
|
|
17
37
|
".": {
|
|
18
38
|
"types": "./dist/index.d.ts",
|
|
19
39
|
"import": "./dist/index.js",
|
|
@@ -86,6 +106,7 @@
|
|
|
86
106
|
"strip-ansi": "^7.2.0",
|
|
87
107
|
"tar-fs": "^3.1.3",
|
|
88
108
|
"tar-stream": "^3.2.1",
|
|
109
|
+
"typescript-compiler": "npm:typescript@^6.0.3",
|
|
89
110
|
"vite": "^8.3.0",
|
|
90
111
|
"ws": "^8.21.3",
|
|
91
112
|
"xdg-basedir": "^5.1.0"
|
|
@@ -100,7 +121,7 @@
|
|
|
100
121
|
"@oclif/test": "^4.2.0",
|
|
101
122
|
"@playwright/test": "^1.63.0",
|
|
102
123
|
"@sanity-labs/design-tokens": "^0.0.2-alpha.2",
|
|
103
|
-
"@sanity/functions": "^1.
|
|
124
|
+
"@sanity/functions": "^1.8.1",
|
|
104
125
|
"@types/cardinal": "^2.1.1",
|
|
105
126
|
"@types/mime-types": "^3.0.1",
|
|
106
127
|
"@types/node": "^22",
|