@sanity/runtime-cli 17.6.2 → 17.7.0-blueprinit.ga49bda6
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 +20 -20
- package/dist/actions/blueprinit/manifest.d.ts +15 -0
- package/dist/actions/blueprinit/manifest.js +82 -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 +34 -0
- package/dist/actions/blueprinit/templates.js +83 -0
- package/dist/actions/blueprinit/workspace.d.ts +16 -0
- package/dist/actions/blueprinit/workspace.js +143 -0
- package/dist/actions/blueprints/wait-for-operation.js +30 -5
- package/dist/actions/sanity/datasets.d.ts +15 -0
- package/dist/actions/sanity/datasets.js +26 -0
- package/dist/commands/init.d.ts +17 -0
- package/dist/commands/init.js +59 -0
- package/dist/cores/blueprinit/adopt.d.ts +6 -0
- package/dist/cores/blueprinit/adopt.js +119 -0
- package/dist/cores/blueprinit/finish.d.ts +14 -0
- package/dist/cores/blueprinit/finish.js +64 -0
- package/dist/cores/blueprinit/fresh.d.ts +3 -0
- package/dist/cores/blueprinit/fresh.js +120 -0
- package/dist/cores/blueprinit/preview.d.ts +15 -0
- package/dist/cores/blueprinit/preview.js +14 -0
- package/dist/cores/blueprinit/prompts.d.ts +5 -0
- package/dist/cores/blueprinit/prompts.js +22 -0
- package/dist/cores/blueprinit/selection.d.ts +15 -0
- package/dist/cores/blueprinit/selection.js +90 -0
- package/dist/cores/blueprinit/types.d.ts +16 -0
- package/dist/cores/blueprinit/types.js +1 -0
- package/dist/cores/blueprinit.d.ts +7 -0
- package/dist/cores/blueprinit.js +48 -0
- package/dist/utils/display/blueprints-formatting.js +18 -7
- package/dist/utils/display/resources-formatting.d.ts +3 -2
- package/dist/utils/display/resources-formatting.js +27 -12
- package/dist/utils/functions/resolve-auth.js +17 -4
- package/dist/utils/types.d.ts +3 -0
- package/oclif.manifest.json +130 -1
- package/package.json +13 -13
- package/skills/init.md +155 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
export async function chooseOrganization(groups, organizationId, interactive) {
|
|
3
|
+
if (groups.length === 0) {
|
|
4
|
+
return failure('No organizations found for this account.');
|
|
5
|
+
}
|
|
6
|
+
if (organizationId) {
|
|
7
|
+
const organization = groups.find((group) => group.organization.id === organizationId);
|
|
8
|
+
return organization
|
|
9
|
+
? { ok: true, value: organization }
|
|
10
|
+
: failure(`No organization "${organizationId}" found for this account.`);
|
|
11
|
+
}
|
|
12
|
+
if (groups.length === 1)
|
|
13
|
+
return { ok: true, value: groups[0] };
|
|
14
|
+
if (!interactive) {
|
|
15
|
+
return failure('Multiple organizations found.', ['Pass --organization-id <id> to choose one.']);
|
|
16
|
+
}
|
|
17
|
+
const selectedId = await select({
|
|
18
|
+
message: 'Choose a Sanity organization:',
|
|
19
|
+
choices: groups.map(({ organization, projects }) => ({
|
|
20
|
+
name: organization.name,
|
|
21
|
+
value: organization.id,
|
|
22
|
+
description: `${projects?.length ?? 0} projects`,
|
|
23
|
+
})),
|
|
24
|
+
});
|
|
25
|
+
const selected = groups.find(({ organization }) => organization.id === selectedId);
|
|
26
|
+
return selected ? { ok: true, value: selected } : failure('Organization not found.');
|
|
27
|
+
}
|
|
28
|
+
export async function chooseProject(projects, projectId, organizationName, interactive) {
|
|
29
|
+
if (projects.length === 0) {
|
|
30
|
+
return failure(`No projects found in ${organizationName}.`);
|
|
31
|
+
}
|
|
32
|
+
if (projectId) {
|
|
33
|
+
const project = projects.find(({ id }) => id === projectId);
|
|
34
|
+
return project
|
|
35
|
+
? { ok: true, value: project }
|
|
36
|
+
: failure(`No project "${projectId}" found in ${organizationName}.`);
|
|
37
|
+
}
|
|
38
|
+
if (projects.length === 1)
|
|
39
|
+
return { ok: true, value: projects[0] };
|
|
40
|
+
if (!interactive) {
|
|
41
|
+
return failure('Multiple projects found.', ['Pass --project-id <id> to choose one.']);
|
|
42
|
+
}
|
|
43
|
+
const selectedId = await select({
|
|
44
|
+
message: 'Choose a Sanity project:',
|
|
45
|
+
choices: projects.map((project) => ({ name: project.displayName, value: project.id })),
|
|
46
|
+
});
|
|
47
|
+
const selected = projects.find(({ id }) => id === selectedId);
|
|
48
|
+
return selected ? { ok: true, value: selected } : failure('Project not found.');
|
|
49
|
+
}
|
|
50
|
+
export async function chooseDataset(datasets, datasetName, projectName, interactive) {
|
|
51
|
+
if (datasets.length === 0) {
|
|
52
|
+
return failure(`No datasets found in ${projectName}.`);
|
|
53
|
+
}
|
|
54
|
+
if (datasetName) {
|
|
55
|
+
const dataset = datasets.find(({ name }) => name === datasetName);
|
|
56
|
+
return dataset
|
|
57
|
+
? { ok: true, value: dataset }
|
|
58
|
+
: failure(`No dataset "${datasetName}" found in ${projectName}.`);
|
|
59
|
+
}
|
|
60
|
+
if (datasets.length === 1)
|
|
61
|
+
return { ok: true, value: datasets[0] };
|
|
62
|
+
if (!interactive) {
|
|
63
|
+
return failure('Multiple datasets found.', ['Pass --dataset <name> to choose one.']);
|
|
64
|
+
}
|
|
65
|
+
const production = datasets.find(({ name }) => name === 'production');
|
|
66
|
+
const orderedDatasets = production
|
|
67
|
+
? [production, ...datasets.filter(({ name }) => name !== 'production')]
|
|
68
|
+
: datasets;
|
|
69
|
+
const selectedName = await select({
|
|
70
|
+
message: 'Choose a Sanity dataset:',
|
|
71
|
+
choices: orderedDatasets.map((dataset) => ({
|
|
72
|
+
name: dataset.name,
|
|
73
|
+
value: dataset.name,
|
|
74
|
+
description: dataset.aclMode,
|
|
75
|
+
})),
|
|
76
|
+
});
|
|
77
|
+
const selected = datasets.find(({ name }) => name === selectedName);
|
|
78
|
+
return selected ? { ok: true, value: selected } : failure('Dataset not found.');
|
|
79
|
+
}
|
|
80
|
+
export function findProject(groups, projectId) {
|
|
81
|
+
for (const { organization, projects = [] } of groups) {
|
|
82
|
+
const project = projects.find(({ id }) => id === projectId);
|
|
83
|
+
if (project)
|
|
84
|
+
return { organization, project };
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
function failure(message, suggestions) {
|
|
89
|
+
return { ok: false, error: { message, suggestions } };
|
|
90
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Logger } from '../../utils/logger.js';
|
|
2
|
+
export interface BlueprinitFlags {
|
|
3
|
+
yes?: boolean;
|
|
4
|
+
organizationId?: string;
|
|
5
|
+
projectId?: string;
|
|
6
|
+
datasetName?: string;
|
|
7
|
+
stackName?: string;
|
|
8
|
+
studioName?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface BlueprinitFlowOptions {
|
|
11
|
+
bin: string;
|
|
12
|
+
dir: string;
|
|
13
|
+
flags: BlueprinitFlags;
|
|
14
|
+
log: Logger;
|
|
15
|
+
token: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BlueprinitFlags } from './blueprinit/types.js';
|
|
2
|
+
import type { CoreConfig, CoreResult } from './index.js';
|
|
3
|
+
export interface BlueprinitOptions extends CoreConfig {
|
|
4
|
+
dir?: string;
|
|
5
|
+
flags?: BlueprinitFlags;
|
|
6
|
+
}
|
|
7
|
+
export declare function blueprinitCore(options: BlueprinitOptions): Promise<CoreResult>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { cwd } from 'node:process';
|
|
2
|
+
import { detectStudio } from '../actions/blueprinit/studio.js';
|
|
3
|
+
import { findBlueprintFile } from '../actions/blueprints/blueprint.js';
|
|
4
|
+
import { readConfigFile } from '../actions/blueprints/config.js';
|
|
5
|
+
import { validTokenOrErrorMessage } from '../utils/validated-token.js';
|
|
6
|
+
import { adoptFlow } from './blueprinit/adopt.js';
|
|
7
|
+
import { freshFlow } from './blueprinit/fresh.js';
|
|
8
|
+
export async function blueprinitCore(options) {
|
|
9
|
+
const { bin, log, flags = {}, dir = cwd() } = options;
|
|
10
|
+
try {
|
|
11
|
+
const existingBlueprint = findBlueprintFile(dir);
|
|
12
|
+
if (existingBlueprint) {
|
|
13
|
+
const blueprintConfig = readConfigFile(existingBlueprint.blueprintFilePath);
|
|
14
|
+
if (!blueprintConfig?.stackId) {
|
|
15
|
+
return {
|
|
16
|
+
success: false,
|
|
17
|
+
error: `A Blueprint exists here (${existingBlueprint.fileName}), but it is not connected to a Stack.`,
|
|
18
|
+
suggestions: [`Finish setup with: npx ${bin} blueprints init`],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
log(`A blueprint already exists here (${existingBlueprint.fileName}).`);
|
|
22
|
+
log('');
|
|
23
|
+
log('Use these instead:');
|
|
24
|
+
log(` npx ${bin} blueprints config --edit`);
|
|
25
|
+
log(` npx ${bin} blueprints doctor`);
|
|
26
|
+
return {
|
|
27
|
+
success: true,
|
|
28
|
+
json: { alreadyInitialized: true, blueprintFile: existingBlueprint.fileName },
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const tokenCheck = await validTokenOrErrorMessage(log);
|
|
32
|
+
if (!tokenCheck.ok) {
|
|
33
|
+
return {
|
|
34
|
+
success: false,
|
|
35
|
+
error: 'No Sanity session found.',
|
|
36
|
+
suggestions: ['Sign in first: npx sanity login', 'Then run init again.'],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
log('Setting up your Sanity workspace.');
|
|
40
|
+
log('');
|
|
41
|
+
const flowOptions = { bin, dir, flags, log, token: tokenCheck.value };
|
|
42
|
+
const studio = detectStudio(dir);
|
|
43
|
+
return studio ? await adoptFlow({ ...flowOptions, studio }) : await freshFlow(flowOptions);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { treeify } from 'array-treeify';
|
|
2
|
-
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, } from '../../constants.js';
|
|
2
|
+
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, SANITY_STUDIO, } from '../../constants.js';
|
|
3
3
|
import { styleText } from '../style-text.js';
|
|
4
|
-
import { isCorsOriginResource, isDatasetResource, isRobotResource, isRoleResource, isWebhookResource, } from '../types.js';
|
|
4
|
+
import { isCorsOriginResource, isDatasetResource, isRobotResource, isRoleResource, isStudioResource, isWebhookResource, } from '../types.js';
|
|
5
5
|
import { formatDateTime, formatDuration } from './dates.js';
|
|
6
6
|
import { capitalize, niceId, renderSection } from './presenters.js';
|
|
7
|
-
import { arrayifyCors, arrayifyDataset, arrayifyFunction, arrayifyRobot, arrayifyRole, arrayifyWebhook, } from './resources-formatting.js';
|
|
7
|
+
import { arrayifyCors, arrayifyDataset, arrayifyFunction, arrayifyRobot, arrayifyRole, arrayifyStudio, arrayifyWebhook, } from './resources-formatting.js';
|
|
8
8
|
const functionCategory = {
|
|
9
9
|
label: 'Functions',
|
|
10
10
|
displayNameAttribute: 'displayName',
|
|
@@ -58,6 +58,13 @@ const RESOURCE_CATEGORIES = {
|
|
|
58
58
|
return isWebhookResource(res) ? arrayifyWebhook(res) : [];
|
|
59
59
|
},
|
|
60
60
|
},
|
|
61
|
+
[SANITY_STUDIO]: {
|
|
62
|
+
label: 'Studios',
|
|
63
|
+
displayNameAttribute: 'title',
|
|
64
|
+
formatDetails(res) {
|
|
65
|
+
return isStudioResource(res) ? arrayifyStudio(res) : [];
|
|
66
|
+
},
|
|
67
|
+
},
|
|
61
68
|
};
|
|
62
69
|
const categoryByLabel = Object.values(RESOURCE_CATEGORIES).reduce((acc, curr) => {
|
|
63
70
|
acc[curr.label] = curr;
|
|
@@ -76,9 +83,11 @@ function resourceName(res, displayNameAttribute) {
|
|
|
76
83
|
}
|
|
77
84
|
function deployedResourceName(res, displayNameAttribute, verbose = false) {
|
|
78
85
|
const nameParts = [styleText(['bold', 'green'], res.name)];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
res.parameters[displayNameAttribute]
|
|
86
|
+
// deployed state: prefer the resolved value, fall back to the authored one
|
|
87
|
+
const nameValue = displayNameAttribute
|
|
88
|
+
? (res.resolvedParameters?.[displayNameAttribute] ?? res.parameters[displayNameAttribute])
|
|
89
|
+
: undefined;
|
|
90
|
+
const displayName = typeof nameValue === 'string' && nameValue;
|
|
82
91
|
if (displayName && displayName !== res.name)
|
|
83
92
|
nameParts.push(styleText('green', `"${displayName}"`));
|
|
84
93
|
if (verbose)
|
|
@@ -151,7 +160,9 @@ function buildOutputTree(resources, createName, mapToResource, verbose = false)
|
|
|
151
160
|
export function formatDeployedResourceTree(resources, verbose = false) {
|
|
152
161
|
if (!resources || resources.length === 0)
|
|
153
162
|
return ' Zero deployed resources';
|
|
154
|
-
const output = buildOutputTree(resources, (category, res, v) => deployedResourceName(res, category.displayNameAttribute, v),
|
|
163
|
+
const output = buildOutputTree(resources, (category, res, v) => deployedResourceName(res, category.displayNameAttribute, v),
|
|
164
|
+
// deployed state: prefer resolved values, fall back to authored ones
|
|
165
|
+
(res) => ({ name: res.name, type: res.type, ...(res.resolvedParameters ?? res.parameters) }), verbose);
|
|
155
166
|
return `${treeify(output)}\n`;
|
|
156
167
|
}
|
|
157
168
|
export function formatResourceTree(resources, verbose = false) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { BlueprintCorsOriginResource, BlueprintDatasetResource, BlueprintDocumentWebhookResource, BlueprintResource, BlueprintRobotResource, BlueprintRoleResource } from '@sanity/blueprints';
|
|
1
|
+
import type { BlueprintCorsOriginResource, BlueprintDatasetResource, BlueprintDocumentWebhookResource, BlueprintResource, BlueprintRobotResource, BlueprintRoleResource, BlueprintStudioResource } from '@sanity/blueprints';
|
|
2
2
|
import type { TreeInput } from 'array-treeify';
|
|
3
|
-
export declare function arrayifyFunction(fn: BlueprintResource): TreeInput;
|
|
4
3
|
export declare function arrayifyCors(resource: BlueprintCorsOriginResource): TreeInput;
|
|
5
4
|
export declare function arrayifyDataset(resource: BlueprintDatasetResource): TreeInput;
|
|
5
|
+
export declare function arrayifyFunction(fn: BlueprintResource): TreeInput;
|
|
6
6
|
export declare function arrayifyRobot(resource: BlueprintRobotResource): TreeInput;
|
|
7
7
|
export declare function arrayifyRole(resource: BlueprintRoleResource): TreeInput;
|
|
8
|
+
export declare function arrayifyStudio(resource: BlueprintStudioResource): TreeInput;
|
|
8
9
|
export declare function arrayifyWebhook(resource: BlueprintDocumentWebhookResource): TreeInput;
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { hasEventSource, isLocalFunctionResource, isScheduleEvent, } from '../../utils/types.js';
|
|
2
2
|
import { styleText } from '../style-text.js';
|
|
3
|
+
import { niceId } from './presenters.js';
|
|
3
4
|
function formatLabel(label) {
|
|
4
5
|
return styleText('dim', `${label}:`);
|
|
5
6
|
}
|
|
6
7
|
function formatLabeledValue(label, value) {
|
|
7
8
|
return `${styleText('dim', `${label}:`)} ${value}`;
|
|
8
9
|
}
|
|
10
|
+
export function arrayifyCors(resource) {
|
|
11
|
+
const details = [formatLabeledValue('origin', resource.origin)];
|
|
12
|
+
if (resource.allowCredentials !== undefined) {
|
|
13
|
+
details.push(formatLabeledValue('allowCredentials', resource.allowCredentials));
|
|
14
|
+
}
|
|
15
|
+
return details;
|
|
16
|
+
}
|
|
17
|
+
export function arrayifyDataset(resource) {
|
|
18
|
+
const details = [formatLabeledValue('title', resource.datasetName)];
|
|
19
|
+
if (resource.aclMode)
|
|
20
|
+
details.push(formatLabeledValue('visibility', resource.aclMode));
|
|
21
|
+
if (resource.project)
|
|
22
|
+
details.push(formatLabeledValue('project', niceId(resource.project)));
|
|
23
|
+
return details;
|
|
24
|
+
}
|
|
9
25
|
function arrayifyEvent(event) {
|
|
10
26
|
if (!event)
|
|
11
27
|
return undefined;
|
|
@@ -55,19 +71,8 @@ export function arrayifyFunction(fn) {
|
|
|
55
71
|
}
|
|
56
72
|
return details;
|
|
57
73
|
}
|
|
58
|
-
export function arrayifyCors(resource) {
|
|
59
|
-
return [formatLabeledValue('origin', resource.origin)];
|
|
60
|
-
}
|
|
61
|
-
export function arrayifyDataset(resource) {
|
|
62
|
-
const details = [formatLabeledValue('title', resource.datasetName)];
|
|
63
|
-
if (resource.aclMode)
|
|
64
|
-
details.push(formatLabeledValue('visibility', resource.aclMode));
|
|
65
|
-
if (resource.project)
|
|
66
|
-
details.push(formatLabeledValue('project', resource.project));
|
|
67
|
-
return details;
|
|
68
|
-
}
|
|
69
74
|
export function arrayifyRobot(resource) {
|
|
70
|
-
const details = [
|
|
75
|
+
const details = [];
|
|
71
76
|
if (resource.memberships.length > 0) {
|
|
72
77
|
details.push(formatLabel('memberships'));
|
|
73
78
|
const memberships = [];
|
|
@@ -115,8 +120,16 @@ export function arrayifyRole(resource) {
|
|
|
115
120
|
}
|
|
116
121
|
return details;
|
|
117
122
|
}
|
|
123
|
+
export function arrayifyStudio(resource) {
|
|
124
|
+
const details = [formatLabeledValue('appHost', resource.slug)];
|
|
125
|
+
if (resource.project)
|
|
126
|
+
details.push(formatLabeledValue('project', niceId(resource.project)));
|
|
127
|
+
return details;
|
|
128
|
+
}
|
|
118
129
|
export function arrayifyWebhook(resource) {
|
|
119
130
|
const details = [];
|
|
131
|
+
if (resource.displayName)
|
|
132
|
+
details.push(formatLabeledValue('displayName', resource.displayName));
|
|
120
133
|
if (resource.description)
|
|
121
134
|
details.push(formatLabeledValue('description', resource.description));
|
|
122
135
|
details.push(formatLabeledValue('url', resource.url));
|
|
@@ -131,6 +144,8 @@ export function arrayifyWebhook(resource) {
|
|
|
131
144
|
details.push(formatLabeledValue('httpMethod', resource.httpMethod));
|
|
132
145
|
if (resource.dataset)
|
|
133
146
|
details.push(formatLabeledValue('dataset', resource.dataset));
|
|
147
|
+
if (resource.project)
|
|
148
|
+
details.push(formatLabeledValue('project', niceId(resource.project)));
|
|
134
149
|
// not included: headers, includeDrafts, includeAllVersions, secret, apiVersion
|
|
135
150
|
return details;
|
|
136
151
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { ORGANIZATION_SCOPED_FUNCTION_TYPES, PROJECT_SCOPED_FUNCTION_TYPES } from '../../constants.js';
|
|
2
|
+
const REFERENCE_PREFIX = '$.resources.';
|
|
3
|
+
/**
|
|
4
|
+
* A scope ID the API can use: a literal, never an unresolved Blueprint reference.
|
|
5
|
+
* Overly defensive and checks resource.parameters as fallback.
|
|
6
|
+
*/
|
|
7
|
+
function literalScopeId(resource, key) {
|
|
8
|
+
const value = resource.resolvedParameters?.[key] ?? resource.parameters[key];
|
|
9
|
+
if (typeof value !== 'string' || value.startsWith(REFERENCE_PREFIX))
|
|
10
|
+
return undefined;
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
2
13
|
/**
|
|
3
14
|
* Resolves the correct auth scope for a function API request.
|
|
4
15
|
*
|
|
@@ -8,11 +19,13 @@ import { ORGANIZATION_SCOPED_FUNCTION_TYPES, PROJECT_SCOPED_FUNCTION_TYPES } fro
|
|
|
8
19
|
*/
|
|
9
20
|
export function resolveFunctionAuth(auth, deployedStack, resource) {
|
|
10
21
|
// 1. explicit resource-level scope takes highest priority
|
|
11
|
-
|
|
12
|
-
|
|
22
|
+
const project = literalScopeId(resource, 'project');
|
|
23
|
+
if (project) {
|
|
24
|
+
return { ...auth, scopeType: 'project', scopeId: project };
|
|
13
25
|
}
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
const organization = literalScopeId(resource, 'organization');
|
|
27
|
+
if (organization) {
|
|
28
|
+
return { ...auth, scopeType: 'organization', scopeId: organization };
|
|
16
29
|
}
|
|
17
30
|
// 2. project-scoped function types: resolve a project ID or fail
|
|
18
31
|
if (PROJECT_SCOPED_FUNCTION_TYPES.has(resource.type)) {
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -33,7 +33,10 @@ export interface AuthParams {
|
|
|
33
33
|
export interface BlueprintResourceRecord extends BlueprintResource {
|
|
34
34
|
id: string;
|
|
35
35
|
externalId?: string | null;
|
|
36
|
+
/** Authored values; a value can be an unresolved `$.resources.<name>` reference */
|
|
36
37
|
parameters: Record<string, unknown>;
|
|
38
|
+
/** Values deployment used, with references resolved */
|
|
39
|
+
resolvedParameters?: Record<string, unknown>;
|
|
37
40
|
}
|
|
38
41
|
/** The deployed resource; complete with external ID */
|
|
39
42
|
export interface DeployedResource extends BlueprintResourceRecord {
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,134 @@
|
|
|
1
1
|
{
|
|
2
2
|
"commands": {
|
|
3
|
+
"init": {
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"args": {},
|
|
6
|
+
"description": "Scaffolds a Blueprint, Studio, and starter function around an existing Sanity project.\n\nThis hidden command is an experiment; its interface and generated files are not stable.",
|
|
7
|
+
"examples": [
|
|
8
|
+
"<%= config.bin %> <%= command.id %>",
|
|
9
|
+
"<%= config.bin %> <%= command.id %> --yes",
|
|
10
|
+
"<%= config.bin %> <%= command.id %> --project-id <id> --dataset <name> --yes"
|
|
11
|
+
],
|
|
12
|
+
"flags": {
|
|
13
|
+
"json": {
|
|
14
|
+
"description": "Format output as json",
|
|
15
|
+
"name": "json",
|
|
16
|
+
"allowNo": false,
|
|
17
|
+
"type": "boolean"
|
|
18
|
+
},
|
|
19
|
+
"path": {
|
|
20
|
+
"aliases": [
|
|
21
|
+
"blueprint-path"
|
|
22
|
+
],
|
|
23
|
+
"char": "p",
|
|
24
|
+
"description": "Path to a Blueprint file or directory containing one",
|
|
25
|
+
"env": "SANITY_BLUEPRINT_PATH",
|
|
26
|
+
"hidden": true,
|
|
27
|
+
"name": "path",
|
|
28
|
+
"hasDynamicHelp": false,
|
|
29
|
+
"multiple": false,
|
|
30
|
+
"type": "option"
|
|
31
|
+
},
|
|
32
|
+
"trace": {
|
|
33
|
+
"description": "Trace output",
|
|
34
|
+
"hidden": true,
|
|
35
|
+
"name": "trace",
|
|
36
|
+
"allowNo": false,
|
|
37
|
+
"type": "boolean"
|
|
38
|
+
},
|
|
39
|
+
"validate-resources": {
|
|
40
|
+
"description": "Validate resources",
|
|
41
|
+
"hidden": true,
|
|
42
|
+
"name": "validate-resources",
|
|
43
|
+
"allowNo": true,
|
|
44
|
+
"type": "boolean"
|
|
45
|
+
},
|
|
46
|
+
"verbose": {
|
|
47
|
+
"description": "Verbose output",
|
|
48
|
+
"hidden": true,
|
|
49
|
+
"name": "verbose",
|
|
50
|
+
"allowNo": false,
|
|
51
|
+
"type": "boolean"
|
|
52
|
+
},
|
|
53
|
+
"llms": {
|
|
54
|
+
"aliases": [
|
|
55
|
+
"skill"
|
|
56
|
+
],
|
|
57
|
+
"description": "Show agent-oriented guidance for this command",
|
|
58
|
+
"hidden": true,
|
|
59
|
+
"name": "llms",
|
|
60
|
+
"allowNo": false,
|
|
61
|
+
"type": "boolean"
|
|
62
|
+
},
|
|
63
|
+
"yes": {
|
|
64
|
+
"char": "y",
|
|
65
|
+
"description": "Skip confirmation prompts",
|
|
66
|
+
"name": "yes",
|
|
67
|
+
"allowNo": false,
|
|
68
|
+
"type": "boolean"
|
|
69
|
+
},
|
|
70
|
+
"organization-id": {
|
|
71
|
+
"aliases": [
|
|
72
|
+
"organization",
|
|
73
|
+
"organizationId",
|
|
74
|
+
"org"
|
|
75
|
+
],
|
|
76
|
+
"description": "Organization to use when the account has several",
|
|
77
|
+
"name": "organization-id",
|
|
78
|
+
"hasDynamicHelp": false,
|
|
79
|
+
"multiple": false,
|
|
80
|
+
"type": "option"
|
|
81
|
+
},
|
|
82
|
+
"project-id": {
|
|
83
|
+
"aliases": [
|
|
84
|
+
"project",
|
|
85
|
+
"projectId"
|
|
86
|
+
],
|
|
87
|
+
"description": "Project to use when the organization has several",
|
|
88
|
+
"name": "project-id",
|
|
89
|
+
"hasDynamicHelp": false,
|
|
90
|
+
"multiple": false,
|
|
91
|
+
"type": "option"
|
|
92
|
+
},
|
|
93
|
+
"dataset": {
|
|
94
|
+
"description": "Dataset to attach",
|
|
95
|
+
"name": "dataset",
|
|
96
|
+
"hasDynamicHelp": false,
|
|
97
|
+
"multiple": false,
|
|
98
|
+
"type": "option"
|
|
99
|
+
},
|
|
100
|
+
"stack-name": {
|
|
101
|
+
"description": "Name for the new organization-scoped Stack",
|
|
102
|
+
"name": "stack-name",
|
|
103
|
+
"hasDynamicHelp": false,
|
|
104
|
+
"multiple": false,
|
|
105
|
+
"type": "option"
|
|
106
|
+
},
|
|
107
|
+
"studio-name": {
|
|
108
|
+
"description": "Name and hosted slug for the Studio resource",
|
|
109
|
+
"name": "studio-name",
|
|
110
|
+
"hasDynamicHelp": false,
|
|
111
|
+
"multiple": false,
|
|
112
|
+
"type": "option"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"hasDynamicHelp": false,
|
|
116
|
+
"hidden": true,
|
|
117
|
+
"hiddenAliases": [],
|
|
118
|
+
"id": "init",
|
|
119
|
+
"pluginAlias": "@sanity/runtime-cli",
|
|
120
|
+
"pluginName": "@sanity/runtime-cli",
|
|
121
|
+
"pluginType": "core",
|
|
122
|
+
"strict": true,
|
|
123
|
+
"summary": "Experimental blueprints-first project init",
|
|
124
|
+
"enableJsonFlag": true,
|
|
125
|
+
"isESM": true,
|
|
126
|
+
"relativePath": [
|
|
127
|
+
"dist",
|
|
128
|
+
"commands",
|
|
129
|
+
"init.js"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
3
132
|
"blueprints:add": {
|
|
4
133
|
"aliases": [],
|
|
5
134
|
"args": {
|
|
@@ -3127,5 +3256,5 @@
|
|
|
3127
3256
|
]
|
|
3128
3257
|
}
|
|
3129
3258
|
},
|
|
3130
|
-
"version": "17.
|
|
3259
|
+
"version": "17.7.0-blueprinit.ga49bda6"
|
|
3131
3260
|
}
|
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.7.0-blueprinit.ga49bda6",
|
|
5
5
|
"author": "Sanity Runtime Team",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -65,20 +65,20 @@
|
|
|
65
65
|
"@architect/hydrate": "~6.0.2",
|
|
66
66
|
"@architect/inventory": "~6.1.0",
|
|
67
67
|
"@inquirer/prompts": "^8.5.2",
|
|
68
|
-
"@oclif/core": "^4.13.
|
|
69
|
-
"@oclif/plugin-help": "^6.2.
|
|
68
|
+
"@oclif/core": "^4.13.4",
|
|
69
|
+
"@oclif/plugin-help": "^6.2.58",
|
|
70
70
|
"@sanity-labs/design-tokens": "^0.0.2-alpha.2",
|
|
71
71
|
"@sanity-labs/oclif-plugin-skills-flag": "^0.2.1",
|
|
72
|
-
"@sanity/blueprints": "^0.23.
|
|
73
|
-
"@sanity/blueprints-parser": "^0.
|
|
74
|
-
"@sanity/cli-build": "^5.
|
|
75
|
-
"@sanity/cli-core": "^
|
|
76
|
-
"@sanity/client": "^
|
|
72
|
+
"@sanity/blueprints": "^0.23.6",
|
|
73
|
+
"@sanity/blueprints-parser": "^0.5.0",
|
|
74
|
+
"@sanity/cli-build": "^5.2.0",
|
|
75
|
+
"@sanity/cli-core": "^3.0.0",
|
|
76
|
+
"@sanity/client": "^8.0.0",
|
|
77
77
|
"adm-zip": "^0.6.0",
|
|
78
|
-
"array-treeify": "^0.
|
|
78
|
+
"array-treeify": "^0.2.0",
|
|
79
79
|
"cardinal": "^2.1.1",
|
|
80
80
|
"empathic": "^2.0.1",
|
|
81
|
-
"eventsource": "^
|
|
81
|
+
"eventsource": "^5.1.0",
|
|
82
82
|
"groq-js": "^2.0.0",
|
|
83
83
|
"jiti": "^2.7.0",
|
|
84
84
|
"mime-types": "^3.0.2",
|
|
@@ -92,15 +92,15 @@
|
|
|
92
92
|
"xdg-basedir": "^5.1.0"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@biomejs/biome": "2.5.
|
|
95
|
+
"@biomejs/biome": "2.5.8",
|
|
96
96
|
"@codemirror/lang-json": "^6.0.2",
|
|
97
97
|
"@codemirror/state": "^6.7.1",
|
|
98
98
|
"@enhance/store": "^1.0.2",
|
|
99
99
|
"@lezer/highlight": "^1.2.3",
|
|
100
|
-
"@oclif/test": "^4.1.
|
|
100
|
+
"@oclif/test": "^4.1.22",
|
|
101
101
|
"@playwright/test": "^1.62.1",
|
|
102
102
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
103
|
-
"@sanity/functions": "^1.6.
|
|
103
|
+
"@sanity/functions": "^1.6.6",
|
|
104
104
|
"@types/adm-zip": "^0.5.8",
|
|
105
105
|
"@types/cardinal": "^2.1.1",
|
|
106
106
|
"@types/mime-types": "^3.0.1",
|