@sanity/runtime-cli 14.11.0 → 14.12.1
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 +45 -43
- package/dist/actions/blueprints/blueprint.d.ts +49 -16
- package/dist/actions/blueprints/blueprint.js +97 -139
- package/dist/actions/blueprints/resolve.d.ts +51 -0
- package/dist/actions/blueprints/resolve.js +52 -0
- package/dist/actions/blueprints/resources.js +35 -12
- package/dist/actions/functions/dev.d.ts +1 -2
- package/dist/actions/functions/dev.js +2 -2
- package/dist/baseCommands.d.ts +47 -30
- package/dist/baseCommands.js +187 -72
- package/dist/commands/blueprints/add.d.ts +3 -2
- package/dist/commands/blueprints/add.js +3 -2
- package/dist/commands/blueprints/config.d.ts +3 -2
- package/dist/commands/blueprints/config.js +3 -2
- package/dist/commands/blueprints/deploy.d.ts +3 -2
- package/dist/commands/blueprints/deploy.js +4 -3
- package/dist/commands/blueprints/destroy.d.ts +3 -2
- package/dist/commands/blueprints/destroy.js +3 -2
- package/dist/commands/blueprints/doctor.d.ts +0 -1
- package/dist/commands/blueprints/doctor.js +2 -3
- package/dist/commands/blueprints/info.d.ts +4 -2
- package/dist/commands/blueprints/info.js +6 -3
- package/dist/commands/blueprints/init.d.ts +0 -1
- package/dist/commands/blueprints/init.js +1 -2
- package/dist/commands/blueprints/logs.d.ts +3 -2
- package/dist/commands/blueprints/logs.js +4 -3
- package/dist/commands/blueprints/plan.d.ts +3 -2
- package/dist/commands/blueprints/plan.js +5 -3
- package/dist/commands/blueprints/promote.d.ts +3 -2
- package/dist/commands/blueprints/promote.js +3 -2
- package/dist/commands/blueprints/stacks.d.ts +3 -2
- package/dist/commands/blueprints/stacks.js +3 -2
- package/dist/commands/functions/add.d.ts +3 -2
- package/dist/commands/functions/add.js +4 -3
- package/dist/commands/functions/build.d.ts +3 -2
- package/dist/commands/functions/build.js +3 -2
- package/dist/commands/functions/dev.d.ts +3 -2
- package/dist/commands/functions/dev.js +3 -2
- package/dist/commands/functions/env/add.d.ts +3 -2
- package/dist/commands/functions/env/add.js +3 -2
- package/dist/commands/functions/env/list.d.ts +3 -2
- package/dist/commands/functions/env/list.js +3 -2
- package/dist/commands/functions/env/remove.d.ts +3 -2
- package/dist/commands/functions/env/remove.js +3 -2
- package/dist/commands/functions/logs.d.ts +3 -2
- package/dist/commands/functions/logs.js +4 -3
- package/dist/commands/functions/test.d.ts +3 -2
- package/dist/commands/functions/test.js +3 -2
- package/dist/constants.d.ts +15 -2
- package/dist/constants.js +14 -10
- package/dist/cores/blueprints/config.js +9 -4
- package/dist/cores/blueprints/destroy.js +78 -56
- package/dist/cores/blueprints/doctor.js +19 -5
- package/dist/cores/blueprints/init.js +2 -2
- package/dist/cores/functions/add.js +11 -7
- package/dist/cores/functions/dev.js +1 -1
- package/dist/server/app.d.ts +1 -2
- package/dist/server/app.js +16 -8
- package/dist/server/handlers/invoke.d.ts +1 -2
- package/dist/server/handlers/invoke.js +4 -4
- package/dist/server/static/components/rule-panel.js +8 -10
- package/oclif.manifest.json +503 -73
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class AddCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
export default class AddCommand extends ResolvedCommand<typeof AddCommand> {
|
|
3
|
+
static needs: readonly ["blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static examples: string[];
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
3
3
|
import { FUNCTION_TYPES } from '../../constants.js';
|
|
4
4
|
import { functionAddCore } from '../../cores/functions/index.js';
|
|
5
5
|
import { Logger } from '../../utils/logger.js';
|
|
6
6
|
import { INSTALLER_OPTIONS } from '../../utils/types.js';
|
|
7
|
-
export default class AddCommand extends
|
|
7
|
+
export default class AddCommand extends ResolvedCommand {
|
|
8
|
+
static needs = ['blueprint'];
|
|
8
9
|
static summary = 'Add a Function to your Blueprint';
|
|
9
10
|
static description = `Scaffolds a new Function in the functions/ folder and templates a resource for your Blueprint manifest.
|
|
10
11
|
|
|
11
|
-
Functions are serverless handlers triggered by document events (create, update, delete, publish)
|
|
12
|
+
Functions are serverless handlers triggered by document, live content or media-library events (create, update, delete, publish).
|
|
12
13
|
|
|
13
14
|
After adding, use 'functions dev' to test locally, then 'blueprints deploy' to publish.`;
|
|
14
15
|
static examples = [
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class BuildCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
export default class BuildCommand extends ResolvedCommand<typeof BuildCommand> {
|
|
3
|
+
static needs: readonly ["blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static hidden: boolean;
|
|
5
6
|
static args: {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
3
3
|
import { functionBuildCore } from '../../cores/functions/build.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
import { INSTALLER_OPTIONS } from '../../utils/types.js';
|
|
6
|
-
export default class BuildCommand extends
|
|
6
|
+
export default class BuildCommand extends ResolvedCommand {
|
|
7
|
+
static needs = ['blueprint'];
|
|
7
8
|
static summary = 'Build Sanity Function(s) to zip archives';
|
|
8
9
|
static hidden = true;
|
|
9
10
|
static args = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class DevCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
export default class DevCommand extends ResolvedCommand<typeof DevCommand> {
|
|
3
|
+
static needs: readonly ["blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static examples: string[];
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
3
3
|
import { functionDevCore } from '../../cores/functions/dev.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
|
-
export default class DevCommand extends
|
|
5
|
+
export default class DevCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['blueprint'];
|
|
6
7
|
static summary = 'Start the Sanity Function emulator';
|
|
7
8
|
static description = `Runs a local, web-based development server to test your functions before deploying.
|
|
8
9
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class EnvAddCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../../baseCommands.js';
|
|
2
|
+
export default class EnvAddCommand extends ResolvedCommand<typeof EnvAddCommand> {
|
|
3
|
+
static needs: readonly ["deployedStack", "blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static args: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand } from '../../../baseCommands.js';
|
|
3
3
|
import { functionEnvAddCore } from '../../../cores/functions/env/add.js';
|
|
4
4
|
import { Logger } from '../../../utils/logger.js';
|
|
5
|
-
export default class EnvAddCommand extends
|
|
5
|
+
export default class EnvAddCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['deployedStack', 'blueprint'];
|
|
6
7
|
static summary = 'Add or set an environment variable for a deployed function';
|
|
7
8
|
static description = `Sets an environment variable in a deployed Sanity Function. If the variable already exists, its value is updated.
|
|
8
9
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class EnvListCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../../baseCommands.js';
|
|
2
|
+
export default class EnvListCommand extends ResolvedCommand<typeof EnvListCommand> {
|
|
3
|
+
static needs: readonly ["deployedStack", "blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static args: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand } from '../../../baseCommands.js';
|
|
3
3
|
import { functionEnvListCore } from '../../../cores/functions/env/list.js';
|
|
4
4
|
import { Logger } from '../../../utils/logger.js';
|
|
5
|
-
export default class EnvListCommand extends
|
|
5
|
+
export default class EnvListCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['deployedStack', 'blueprint'];
|
|
6
7
|
static summary = 'List environment variables for a deployed function';
|
|
7
8
|
static description = `Displays all environment variables (keys only) configured in a deployed Sanity Function.
|
|
8
9
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class EnvRemoveCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../../baseCommands.js';
|
|
2
|
+
export default class EnvRemoveCommand extends ResolvedCommand<typeof EnvRemoveCommand> {
|
|
3
|
+
static needs: readonly ["deployedStack", "blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static args: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand } from '../../../baseCommands.js';
|
|
3
3
|
import { functionEnvRemoveCore } from '../../../cores/functions/env/remove.js';
|
|
4
4
|
import { Logger } from '../../../utils/logger.js';
|
|
5
|
-
export default class EnvRemoveCommand extends
|
|
5
|
+
export default class EnvRemoveCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['deployedStack', 'blueprint'];
|
|
6
7
|
static summary = 'Remove an environment variable from a deployed function';
|
|
7
8
|
static description = `Deletes an environment variable from a deployed Sanity Function. The change takes effect on the next function invocation.
|
|
8
9
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class LogsCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
export default class LogsCommand extends ResolvedCommand<typeof LogsCommand> {
|
|
3
|
+
static needs: readonly ["deployedStack", "blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static args: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedCommand, stackFlagConfig } from '../../baseCommands.js';
|
|
3
3
|
import { functionLogsCore } from '../../cores/functions/logs.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
|
-
export default class LogsCommand extends
|
|
5
|
+
export default class LogsCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['deployedStack', 'blueprint'];
|
|
6
7
|
static summary = 'Retrieve or delete logs for a Sanity Function';
|
|
7
8
|
static description = `Fetches execution logs from a deployed function, useful for debugging production issues or monitoring activity.
|
|
8
9
|
|
|
@@ -17,7 +18,7 @@ Use --watch (-w) to stream logs in real-time. Use --delete to clear all logs for
|
|
|
17
18
|
'<%= config.bin %> <%= command.id %> <name> --delete',
|
|
18
19
|
];
|
|
19
20
|
static flags = {
|
|
20
|
-
stack:
|
|
21
|
+
stack: Flags.string({ ...stackFlagConfig }),
|
|
21
22
|
limit: Flags.integer({
|
|
22
23
|
char: 'l',
|
|
23
24
|
description: 'Total number of log entries to retrieve',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class TestCommand extends
|
|
1
|
+
import { ResolvedCommand } from '../../baseCommands.js';
|
|
2
|
+
export default class TestCommand extends ResolvedCommand<typeof TestCommand> {
|
|
3
|
+
static needs: readonly ["blueprint"];
|
|
3
4
|
static summary: string;
|
|
4
5
|
static description: string;
|
|
5
6
|
static args: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand } from '../../baseCommands.js';
|
|
3
3
|
import { functionTestCore } from '../../cores/functions/test.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
|
-
export default class TestCommand extends
|
|
5
|
+
export default class TestCommand extends ResolvedCommand {
|
|
6
|
+
static needs = ['blueprint'];
|
|
6
7
|
static summary = 'Invoke a local Sanity Function';
|
|
7
8
|
static description = `Executes a function locally with the provided payload, simulating how it would run when deployed. Use this to test your function logic before deploying.
|
|
8
9
|
|
package/dist/constants.d.ts
CHANGED
|
@@ -17,8 +17,20 @@ export declare const EVENT_MEDIA_LIBRARY_ASSET_CREATE = "media-library-asset-cre
|
|
|
17
17
|
export declare const EVENT_MEDIA_LIBRARY_ASSET_UPDATE = "media-library-asset-update";
|
|
18
18
|
export declare const EVENT_MEDIA_LIBRARY_ASSET_DELETE = "media-library-asset-delete";
|
|
19
19
|
export declare const EVENT_SCHEDULED = "scheduled-function";
|
|
20
|
-
export declare const
|
|
21
|
-
export
|
|
20
|
+
export declare const EVENT_SYNC_TAG_INVALIDATE = "sync-tag-invalidate";
|
|
21
|
+
export declare const MAP_EVENT_TO_FUNCTION_TYPE: {
|
|
22
|
+
readonly "document-publish": "sanity.function.document";
|
|
23
|
+
readonly "document-create": "sanity.function.document";
|
|
24
|
+
readonly "document-delete": "sanity.function.document";
|
|
25
|
+
readonly "document-update": "sanity.function.document";
|
|
26
|
+
readonly "media-library-asset-create": "sanity.function.media-library.asset";
|
|
27
|
+
readonly "media-library-asset-delete": "sanity.function.media-library.asset";
|
|
28
|
+
readonly "media-library-asset-update": "sanity.function.media-library.asset";
|
|
29
|
+
readonly "scheduled-function": "sanity.function.cron";
|
|
30
|
+
readonly "sync-tag-invalidate": "sanity.function.sync-tag-invalidate";
|
|
31
|
+
};
|
|
32
|
+
export declare const FUNCTION_TYPES: (keyof typeof MAP_EVENT_TO_FUNCTION_TYPE)[];
|
|
33
|
+
export type ARRAY_OF_FUNCTION_TYPES = typeof FUNCTION_TYPES;
|
|
22
34
|
export declare const PROJECT_SCOPED_FUNCTION_TYPES: ReadonlySet<string>;
|
|
23
35
|
export declare const ORGANIZATION_SCOPED_FUNCTION_TYPES: ReadonlySet<string>;
|
|
24
36
|
export declare const MAX_ASSET_SIZE = 209715200;
|
|
@@ -30,3 +42,4 @@ export declare const LABEL_MEDIA_LIBRARY_ASSET_CREATE = "Media Library Asset Cre
|
|
|
30
42
|
export declare const LABEL_MEDIA_LIBRARY_ASSET_UPDATE = "Media Library Asset Update";
|
|
31
43
|
export declare const LABEL_MEDIA_LIBRARY_ASSET_DELETE = "Media Library Asset Delete";
|
|
32
44
|
export declare const LABEL_SCHEDULED = "Scheduled";
|
|
45
|
+
export declare const LABEL_SYNC_TAG_INVALIDATE = "Sync Tag Invalidate";
|
package/dist/constants.js
CHANGED
|
@@ -17,16 +17,19 @@ export const EVENT_MEDIA_LIBRARY_ASSET_CREATE = 'media-library-asset-create';
|
|
|
17
17
|
export const EVENT_MEDIA_LIBRARY_ASSET_UPDATE = 'media-library-asset-update';
|
|
18
18
|
export const EVENT_MEDIA_LIBRARY_ASSET_DELETE = 'media-library-asset-delete';
|
|
19
19
|
export const EVENT_SCHEDULED = 'scheduled-function';
|
|
20
|
-
export const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
EVENT_DOCUMENT_DELETE,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
EVENT_MEDIA_LIBRARY_ASSET_DELETE,
|
|
28
|
-
|
|
29
|
-
]
|
|
20
|
+
export const EVENT_SYNC_TAG_INVALIDATE = 'sync-tag-invalidate';
|
|
21
|
+
export const MAP_EVENT_TO_FUNCTION_TYPE = {
|
|
22
|
+
[EVENT_DOCUMENT_PUBLISH]: SANITY_FUNCTION_DOCUMENT,
|
|
23
|
+
[EVENT_DOCUMENT_CREATE]: SANITY_FUNCTION_DOCUMENT,
|
|
24
|
+
[EVENT_DOCUMENT_DELETE]: SANITY_FUNCTION_DOCUMENT,
|
|
25
|
+
[EVENT_DOCUMENT_UPDATE]: SANITY_FUNCTION_DOCUMENT,
|
|
26
|
+
[EVENT_MEDIA_LIBRARY_ASSET_CREATE]: SANITY_FUNCTION_MEDIA_LIBRARY_ASSET,
|
|
27
|
+
[EVENT_MEDIA_LIBRARY_ASSET_DELETE]: SANITY_FUNCTION_MEDIA_LIBRARY_ASSET,
|
|
28
|
+
[EVENT_MEDIA_LIBRARY_ASSET_UPDATE]: SANITY_FUNCTION_MEDIA_LIBRARY_ASSET,
|
|
29
|
+
[EVENT_SCHEDULED]: SANITY_FUNCTION_SCHEDULED,
|
|
30
|
+
[EVENT_SYNC_TAG_INVALIDATE]: SANITY_FUNCTION_SYNC_TAG_INVALIDATE,
|
|
31
|
+
};
|
|
32
|
+
export const FUNCTION_TYPES = Object.keys(MAP_EVENT_TO_FUNCTION_TYPE);
|
|
30
33
|
export const PROJECT_SCOPED_FUNCTION_TYPES = new Set([
|
|
31
34
|
SANITY_FUNCTION_DOCUMENT,
|
|
32
35
|
SANITY_FUNCTION_MEDIA_LIBRARY_ASSET,
|
|
@@ -44,3 +47,4 @@ export const LABEL_MEDIA_LIBRARY_ASSET_CREATE = 'Media Library Asset Create';
|
|
|
44
47
|
export const LABEL_MEDIA_LIBRARY_ASSET_UPDATE = 'Media Library Asset Update';
|
|
45
48
|
export const LABEL_MEDIA_LIBRARY_ASSET_DELETE = 'Media Library Asset Delete';
|
|
46
49
|
export const LABEL_SCHEDULED = 'Scheduled';
|
|
50
|
+
export const LABEL_SYNC_TAG_INVALIDATE = 'Sync Tag Invalidate';
|
|
@@ -9,10 +9,15 @@ export async function blueprintConfigCore(options) {
|
|
|
9
9
|
const providedConfigFlag = [flagProjectId, flagStack, flagOrganizationId].some(Boolean);
|
|
10
10
|
const { stackId: configStackId, scopeType: configScopeType, scopeId: configScopeId, blueprintConfig, fileInfo, } = blueprint;
|
|
11
11
|
const blueprintFilePath = fileInfo.blueprintFilePath;
|
|
12
|
+
const hasConfigFile = !!blueprintConfig;
|
|
12
13
|
if (!configStackId && !configScopeType && !configScopeId) {
|
|
13
|
-
|
|
14
|
+
if (hasConfigFile) {
|
|
15
|
+
log(warn('Incomplete configuration.'));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
log('No configuration file found.');
|
|
19
|
+
}
|
|
14
20
|
if (!editConfig) {
|
|
15
|
-
// blueprint.json exists but no config JSON
|
|
16
21
|
log(`Run \`npx ${bin} blueprints doctor\` for diagnostics.`);
|
|
17
22
|
return { success: true }; // not necessarily fatal
|
|
18
23
|
}
|
|
@@ -61,7 +66,7 @@ export async function blueprintConfigCore(options) {
|
|
|
61
66
|
// creates a new config file with the given properties
|
|
62
67
|
try {
|
|
63
68
|
const newConfig = writeConfigFile(blueprintFilePath, configUpdate);
|
|
64
|
-
printConfig({ configLabel: 'Updated', log, config: newConfig });
|
|
69
|
+
printConfig({ configLabel: hasConfigFile ? 'Updated' : 'New', log, config: newConfig });
|
|
65
70
|
return { success: true, json: { config: newConfig } };
|
|
66
71
|
}
|
|
67
72
|
catch {
|
|
@@ -98,7 +103,7 @@ export async function blueprintConfigCore(options) {
|
|
|
98
103
|
projectId: updatedProjectId,
|
|
99
104
|
stackId: updatedStackId,
|
|
100
105
|
});
|
|
101
|
-
printConfig({ configLabel: 'Updated', log, config: newConfig });
|
|
106
|
+
printConfig({ configLabel: hasConfigFile ? 'Updated' : 'New', log, config: newConfig });
|
|
102
107
|
return { success: true, json: { config: newConfig } };
|
|
103
108
|
}
|
|
104
109
|
catch {
|
|
@@ -8,7 +8,7 @@ import { styleText } from '../../utils/style-text.js';
|
|
|
8
8
|
export async function blueprintDestroyCore(options) {
|
|
9
9
|
const { bin = 'sanity', log, token, blueprint, flags } = options;
|
|
10
10
|
const { force = false, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, stack: flagStack, 'no-wait': noWait = false, verbose: _verbose = false, } = flags;
|
|
11
|
-
// 3-flag combo:
|
|
11
|
+
// 3-flag combo: destroy without needing a local blueprint config
|
|
12
12
|
if ((flagProjectId || flagOrganizationId) && flagStack && force) {
|
|
13
13
|
let scopeType;
|
|
14
14
|
let scopeId;
|
|
@@ -25,6 +25,7 @@ export async function blueprintDestroyCore(options) {
|
|
|
25
25
|
}
|
|
26
26
|
const auth = { token, scopeType, scopeId };
|
|
27
27
|
const resolvedId = await resolveStackIdByNameOrId(flagStack, auth, log);
|
|
28
|
+
const isoNow = new Date().toISOString();
|
|
28
29
|
const { ok, error, stack } = await destroyStack({
|
|
29
30
|
stackId: resolvedId,
|
|
30
31
|
auth,
|
|
@@ -32,8 +33,18 @@ export async function blueprintDestroyCore(options) {
|
|
|
32
33
|
});
|
|
33
34
|
if (!ok)
|
|
34
35
|
return { success: false, error: error || 'Failed to destroy Stack deployment' };
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
if (noWait) {
|
|
37
|
+
log(styleText(['bold', 'magenta'], 'Stack destruction started!'));
|
|
38
|
+
return { success: true, json: { stackId: stack.id, stackName: stack.name } };
|
|
39
|
+
}
|
|
40
|
+
return waitForDestruction({
|
|
41
|
+
stackId: stack.id,
|
|
42
|
+
stackName: stack.name,
|
|
43
|
+
auth,
|
|
44
|
+
log,
|
|
45
|
+
bin,
|
|
46
|
+
since: isoNow,
|
|
47
|
+
});
|
|
37
48
|
}
|
|
38
49
|
const { scopeType, scopeId, stackId } = blueprint;
|
|
39
50
|
if (!scopeType || !scopeId)
|
|
@@ -103,62 +114,73 @@ export async function blueprintDestroyCore(options) {
|
|
|
103
114
|
log(styleText(['bold', 'magenta'], 'Stack destruction started!'));
|
|
104
115
|
return { success: true, json: { stackId: stack.id, stackName: stack.name } };
|
|
105
116
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
after: isoNow,
|
|
115
|
-
auth,
|
|
116
|
-
log,
|
|
117
|
-
onActivity: () => {
|
|
118
|
-
lastLogAt = Date.now();
|
|
119
|
-
},
|
|
120
|
-
onLogEntry: (logEntry) => logHints.inspect(logEntry),
|
|
121
|
-
});
|
|
122
|
-
while (true) {
|
|
123
|
-
const { ok, stack: currentStack } = await getStack({ stackId: stack.id, auth, logger: log });
|
|
124
|
-
const operation = currentStack?.recentOperation;
|
|
125
|
-
if (!ok || !operation || operation?.status === 'COMPLETED') {
|
|
126
|
-
// Operation is also marked destroyed when stack is deleted;
|
|
127
|
-
// it's possible that the operation is "gone" or available and "COMPLETED"
|
|
128
|
-
if (logStreamCleanup)
|
|
129
|
-
logStreamCleanup();
|
|
130
|
-
log(styleText(['bold', 'magenta'], 'Stack destruction completed!'));
|
|
131
|
-
return { success: true, json: { stackId: stack.id, stackName: stack.name } };
|
|
132
|
-
}
|
|
133
|
-
if (operation.status === 'FAILED') {
|
|
134
|
-
if (logStreamCleanup)
|
|
135
|
-
logStreamCleanup();
|
|
136
|
-
return {
|
|
137
|
-
success: false,
|
|
138
|
-
error: 'Stack destruction failed',
|
|
139
|
-
suggestions: [
|
|
140
|
-
...logHints.getSuggestions(),
|
|
141
|
-
`Run \`npx ${bin} blueprints logs\` to review destruction logs.`,
|
|
142
|
-
`Run \`npx ${bin} blueprints info\` to view current Stack status.`,
|
|
143
|
-
],
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
147
|
-
log(`No new activity for 60 seconds. The destruction is still running on Sanity servers.`);
|
|
148
|
-
log(`You can safely exit and check status later with \`npx ${bin} blueprints info\`.`);
|
|
149
|
-
idleMessageShown = true;
|
|
150
|
-
}
|
|
151
|
-
await sleep(1500);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
catch (error) {
|
|
155
|
-
if (logStreamCleanup)
|
|
156
|
-
logStreamCleanup();
|
|
157
|
-
throw error;
|
|
158
|
-
}
|
|
117
|
+
return waitForDestruction({
|
|
118
|
+
stackId: stack.id,
|
|
119
|
+
stackName: stack.name,
|
|
120
|
+
auth,
|
|
121
|
+
log,
|
|
122
|
+
bin,
|
|
123
|
+
since: isoNow,
|
|
124
|
+
});
|
|
159
125
|
}
|
|
160
126
|
catch (error) {
|
|
161
127
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
162
128
|
return { success: false, error: errorMessage };
|
|
163
129
|
}
|
|
164
130
|
}
|
|
131
|
+
async function waitForDestruction(options) {
|
|
132
|
+
const { stackId, stackName, auth, log, bin, since } = options;
|
|
133
|
+
log(styleText('dim', 'Stack destruction progress:'));
|
|
134
|
+
const logHints = createLogHintCollector(bin);
|
|
135
|
+
let logStreamCleanup = null;
|
|
136
|
+
try {
|
|
137
|
+
let lastLogAt = Date.now();
|
|
138
|
+
let idleMessageShown = false;
|
|
139
|
+
logStreamCleanup = await setupLogStreaming({
|
|
140
|
+
stackId,
|
|
141
|
+
after: since,
|
|
142
|
+
auth,
|
|
143
|
+
log,
|
|
144
|
+
onActivity: () => {
|
|
145
|
+
lastLogAt = Date.now();
|
|
146
|
+
},
|
|
147
|
+
onLogEntry: (logEntry) => logHints.inspect(logEntry),
|
|
148
|
+
});
|
|
149
|
+
while (true) {
|
|
150
|
+
const { ok, stack: currentStack } = await getStack({ stackId, auth, logger: log });
|
|
151
|
+
const operation = currentStack?.recentOperation;
|
|
152
|
+
if (!ok || !operation || operation?.status === 'COMPLETED') {
|
|
153
|
+
// Operation is also marked destroyed when stack is deleted;
|
|
154
|
+
// it's possible that the operation is "gone" or available and "COMPLETED"
|
|
155
|
+
if (logStreamCleanup)
|
|
156
|
+
logStreamCleanup();
|
|
157
|
+
log(styleText(['bold', 'magenta'], 'Stack destruction completed!'));
|
|
158
|
+
return { success: true, json: { stackId, stackName } };
|
|
159
|
+
}
|
|
160
|
+
if (operation.status === 'FAILED') {
|
|
161
|
+
if (logStreamCleanup)
|
|
162
|
+
logStreamCleanup();
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
error: 'Stack destruction failed',
|
|
166
|
+
suggestions: [
|
|
167
|
+
...logHints.getSuggestions(),
|
|
168
|
+
`Run \`npx ${bin} blueprints logs\` to review destruction logs.`,
|
|
169
|
+
`Run \`npx ${bin} blueprints info\` to view current Stack status.`,
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
174
|
+
log(`No new activity for 60 seconds. The destruction is still running on Sanity servers.`);
|
|
175
|
+
log(`You can safely exit and check status later with \`npx ${bin} blueprints info\`.`);
|
|
176
|
+
idleMessageShown = true;
|
|
177
|
+
}
|
|
178
|
+
await sleep(1500);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (logStreamCleanup)
|
|
183
|
+
logStreamCleanup();
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -2,7 +2,9 @@ import { readFileSync } from 'node:fs';
|
|
|
2
2
|
import { arch, cwd, env, version as nodeVersion, platform } from 'node:process';
|
|
3
3
|
import * as resolve from 'empathic/resolve';
|
|
4
4
|
import ora from 'ora';
|
|
5
|
-
import {
|
|
5
|
+
import { loadAndParseBlueprint, } from '../../actions/blueprints/blueprint.js';
|
|
6
|
+
import { readConfigFile } from '../../actions/blueprints/config.js';
|
|
7
|
+
import { resolveIds } from '../../actions/blueprints/resolve.js';
|
|
6
8
|
import { getStack } from '../../actions/blueprints/stacks.js';
|
|
7
9
|
import config, { RUNTIME_CLI_VERSION } from '../../config.js';
|
|
8
10
|
import { check, filePathRelativeToCwd, niceId, renderSection, severe, unsure, } from '../../utils/display/presenters.js';
|
|
@@ -76,15 +78,27 @@ export async function blueprintDoctorCore(options) {
|
|
|
76
78
|
// --- BLUEPRINT ---
|
|
77
79
|
let localBlueprint;
|
|
78
80
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
const blueprint = await loadAndParseBlueprint(path, {
|
|
82
|
+
validateResources: options.validateResources || false,
|
|
83
|
+
});
|
|
84
|
+
const blueprintConfig = readConfigFile(blueprint.fileInfo.blueprintFilePath);
|
|
85
|
+
const resolved = resolveIds({
|
|
86
|
+
module: blueprint.module,
|
|
87
|
+
config: blueprintConfig,
|
|
88
|
+
});
|
|
89
|
+
localBlueprint = {
|
|
90
|
+
...blueprint,
|
|
91
|
+
blueprintConfig,
|
|
92
|
+
...resolved,
|
|
93
|
+
};
|
|
94
|
+
envRows.push(['Blueprint', filePathRelativeToCwd(blueprint.fileInfo.blueprintFilePath)]);
|
|
95
|
+
if (blueprint.errors.length === 0) {
|
|
82
96
|
diagnostics.blueprintValid = { status: true };
|
|
83
97
|
}
|
|
84
98
|
else {
|
|
85
99
|
diagnostics.blueprintValid = {
|
|
86
100
|
status: false,
|
|
87
|
-
detail: `${
|
|
101
|
+
detail: `${blueprint.errors.length} error(s)`,
|
|
88
102
|
};
|
|
89
103
|
}
|
|
90
104
|
}
|
|
@@ -17,7 +17,7 @@ const SCOPE_PROJECT = 'project';
|
|
|
17
17
|
const SCOPE_ORGANIZATION = 'organization';
|
|
18
18
|
export async function blueprintInitCore(options) {
|
|
19
19
|
const { bin = 'sanity', log, token, knownProjectId, args, flags, validateResources } = options;
|
|
20
|
-
const { dir: flagDir, example: flagExample, 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, 'stack-id': flagStackId, 'stack-name': flagStackName, verbose
|
|
20
|
+
const { dir: flagDir, example: flagExample, 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, 'stack-id': flagStackId, 'stack-name': flagStackName, verbose = false, } = flags;
|
|
21
21
|
const { dir: argDir } = args;
|
|
22
22
|
const userProvidedDirName = argDir || flagDir;
|
|
23
23
|
const blueprintDir = userProvidedDirName || '.';
|
|
@@ -44,7 +44,7 @@ export async function blueprintInitCore(options) {
|
|
|
44
44
|
flagOrganizationId,
|
|
45
45
|
flagStackId,
|
|
46
46
|
flagStackName,
|
|
47
|
-
verbose
|
|
47
|
+
verbose,
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
// --example flag → scaffold from an example template
|
|
@@ -5,26 +5,29 @@ import { checkbox, confirm, input, select } from '@inquirer/prompts';
|
|
|
5
5
|
import { highlight } from 'cardinal';
|
|
6
6
|
import { createFunctionResource } from '../../actions/blueprints/resources.js';
|
|
7
7
|
import { verifyExampleExists, writeExample } from '../../actions/sanity/examples.js';
|
|
8
|
-
import { EVENT_DOCUMENT_CREATE, EVENT_DOCUMENT_DELETE, EVENT_DOCUMENT_UPDATE, EVENT_MEDIA_LIBRARY_ASSET_CREATE, EVENT_MEDIA_LIBRARY_ASSET_DELETE, EVENT_MEDIA_LIBRARY_ASSET_UPDATE,
|
|
8
|
+
import { EVENT_DOCUMENT_CREATE, EVENT_DOCUMENT_DELETE, EVENT_DOCUMENT_UPDATE, EVENT_MEDIA_LIBRARY_ASSET_CREATE, EVENT_MEDIA_LIBRARY_ASSET_DELETE, EVENT_MEDIA_LIBRARY_ASSET_UPDATE, EVENT_SYNC_TAG_INVALIDATE,
|
|
9
9
|
// EVENT_SCHEDULED,
|
|
10
|
-
FUNCTION_TYPES, LABEL_DOCUMENT_CREATE, LABEL_DOCUMENT_DELETE, LABEL_DOCUMENT_UPDATE, LABEL_MEDIA_LIBRARY_ASSET_CREATE, LABEL_MEDIA_LIBRARY_ASSET_DELETE, LABEL_MEDIA_LIBRARY_ASSET_UPDATE, LABEL_SCHEDULED, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED, } from '../../constants.js';
|
|
10
|
+
FUNCTION_TYPES, LABEL_DOCUMENT_CREATE, LABEL_DOCUMENT_DELETE, LABEL_DOCUMENT_UPDATE, LABEL_MEDIA_LIBRARY_ASSET_CREATE, LABEL_MEDIA_LIBRARY_ASSET_DELETE, LABEL_MEDIA_LIBRARY_ASSET_UPDATE, LABEL_SCHEDULED, LABEL_SYNC_TAG_INVALIDATE, MAP_EVENT_TO_FUNCTION_TYPE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, } from '../../constants.js';
|
|
11
11
|
import { check, indent, warn } from '../../utils/display/presenters.js';
|
|
12
12
|
import { styleText } from '../../utils/style-text.js';
|
|
13
13
|
import { validateFunctionName } from '../../utils/validate/resource.js';
|
|
14
14
|
export const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) => {
|
|
15
|
-
const functionType =
|
|
15
|
+
const functionType = MAP_EVENT_TO_FUNCTION_TYPE[eventNames[0]];
|
|
16
16
|
let definer = '';
|
|
17
17
|
const eventOns = eventNames.map((e) => `'${e.substring(e.lastIndexOf('-') + 1)}'`);
|
|
18
18
|
switch (functionType) {
|
|
19
|
-
case
|
|
19
|
+
case SANITY_FUNCTION_DOCUMENT:
|
|
20
20
|
definer = `defineDocumentFunction({name: '${fnName}', event: {on: [${eventOns.join(', ')}]}}), // ← add this line`;
|
|
21
21
|
break;
|
|
22
|
-
case
|
|
22
|
+
case SANITY_FUNCTION_MEDIA_LIBRARY_ASSET:
|
|
23
23
|
definer = `defineMediaLibraryAssetFunction({name: '${fnName}', event: {on: [${eventOns.join(', ')}], resource: {type: 'media-library', id: 'my-media-library-id'}}}), // ← add this line`;
|
|
24
24
|
break;
|
|
25
|
-
case
|
|
25
|
+
case SANITY_FUNCTION_SCHEDULED:
|
|
26
26
|
definer = `defineScheduledFunction({name: '${fnName}', event: {expression: '0 0 * * *'}}), // ← add this line`;
|
|
27
27
|
break;
|
|
28
|
+
case SANITY_FUNCTION_SYNC_TAG_INVALIDATE:
|
|
29
|
+
definer = `defineSyncTagInvalidateFunction({name: '${fnName}'}), // ← add this line`;
|
|
30
|
+
break;
|
|
28
31
|
}
|
|
29
32
|
return `
|
|
30
33
|
export default defineBlueprint({
|
|
@@ -154,7 +157,7 @@ export async function functionAddCore(options) {
|
|
|
154
157
|
}
|
|
155
158
|
const eventSources = new Set(fnTypes.map((t) => t.substring(0, t.lastIndexOf('-'))));
|
|
156
159
|
if (eventSources.size > 1) {
|
|
157
|
-
throw new Error('Invalid function type. Cannot mix document-*, media-library-asset-*, and/or scheduled-* types.');
|
|
160
|
+
throw new Error('Invalid function type. Cannot mix document-*, media-library-asset-*, sync-tag-* and/or scheduled-* types.');
|
|
158
161
|
}
|
|
159
162
|
let addHelpers;
|
|
160
163
|
let installCommand;
|
|
@@ -238,6 +241,7 @@ async function promptForFunctionType() {
|
|
|
238
241
|
{ name: LABEL_MEDIA_LIBRARY_ASSET_CREATE, value: EVENT_MEDIA_LIBRARY_ASSET_CREATE },
|
|
239
242
|
{ name: LABEL_MEDIA_LIBRARY_ASSET_UPDATE, value: EVENT_MEDIA_LIBRARY_ASSET_UPDATE },
|
|
240
243
|
{ name: LABEL_MEDIA_LIBRARY_ASSET_DELETE, value: EVENT_MEDIA_LIBRARY_ASSET_DELETE },
|
|
244
|
+
{ name: LABEL_SYNC_TAG_INVALIDATE, value: EVENT_SYNC_TAG_INVALIDATE },
|
|
241
245
|
// {name: LABEL_SCHEDULED, value: EVENT_SCHEDULED},
|
|
242
246
|
],
|
|
243
247
|
validate(choices) {
|
|
@@ -7,7 +7,7 @@ export async function functionDevCore(options) {
|
|
|
7
7
|
? { timeout }
|
|
8
8
|
: undefined;
|
|
9
9
|
try {
|
|
10
|
-
await dev(host, Number(port),
|
|
10
|
+
await dev(host, Number(port), options.validateResources || false, executionOptions);
|
|
11
11
|
log(`Server is running on http://${host}:${port}\n`);
|
|
12
12
|
return {
|
|
13
13
|
success: true,
|
package/dist/server/app.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { Logger } from '../utils/logger.js';
|
|
2
1
|
import { type InvokeExecutionOptions } from '../utils/types.js';
|
|
3
|
-
declare const app: (host: string, port: number,
|
|
2
|
+
declare const app: (host: string, port: number, validateResources: boolean, executionOptions?: Partial<InvokeExecutionOptions>) => void;
|
|
4
3
|
declare function parseDocumentUrl(url: string): {
|
|
5
4
|
projectId: string;
|
|
6
5
|
dataset: string;
|