@sanity/runtime-cli 17.1.0 → 17.2.0-blueprinit.g3a96975

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.
Files changed (109) hide show
  1. package/README.md +38 -28
  2. package/SKILL.md +21 -0
  3. package/dist/actions/blueprinit/manifest.d.ts +13 -0
  4. package/dist/actions/blueprinit/manifest.js +57 -0
  5. package/dist/actions/blueprinit/studio.d.ts +6 -0
  6. package/dist/actions/blueprinit/studio.js +43 -0
  7. package/dist/actions/blueprinit/templates.d.ts +34 -0
  8. package/dist/actions/blueprinit/templates.js +83 -0
  9. package/dist/actions/blueprinit/workspace.d.ts +15 -0
  10. package/dist/actions/blueprinit/workspace.js +142 -0
  11. package/dist/actions/blueprints/assets.d.ts +2 -1
  12. package/dist/actions/blueprints/assets.js +17 -26
  13. package/dist/actions/blueprints/blueprint.d.ts +1 -1
  14. package/dist/actions/blueprints/pre-deploy.d.ts +29 -0
  15. package/dist/actions/blueprints/pre-deploy.js +164 -0
  16. package/dist/actions/blueprints/wait-for-operation.js +4 -0
  17. package/dist/actions/sanity/datasets.d.ts +15 -0
  18. package/dist/actions/sanity/datasets.js +26 -0
  19. package/dist/actions/sanity/examples.d.ts +4 -4
  20. package/dist/baseCommands.d.ts +11 -4
  21. package/dist/baseCommands.js +21 -0
  22. package/dist/commands/blueprinit.d.ts +14 -0
  23. package/dist/commands/blueprinit.js +45 -0
  24. package/dist/commands/blueprints/add.d.ts +1 -1
  25. package/dist/commands/blueprints/config.d.ts +1 -1
  26. package/dist/commands/blueprints/deploy.d.ts +1 -1
  27. package/dist/commands/blueprints/destroy.d.ts +1 -1
  28. package/dist/commands/blueprints/doctor.d.ts +0 -1
  29. package/dist/commands/blueprints/doctor.js +3 -7
  30. package/dist/commands/blueprints/info.d.ts +1 -1
  31. package/dist/commands/blueprints/logs.d.ts +1 -1
  32. package/dist/commands/blueprints/mint-deploy-token.d.ts +1 -1
  33. package/dist/commands/blueprints/plan.d.ts +1 -1
  34. package/dist/commands/blueprints/promote.d.ts +1 -1
  35. package/dist/commands/blueprints/stacks.d.ts +1 -1
  36. package/dist/commands/functions/add.d.ts +1 -1
  37. package/dist/commands/functions/build.d.ts +1 -1
  38. package/dist/commands/functions/dev.d.ts +1 -1
  39. package/dist/commands/functions/env/add.d.ts +4 -1
  40. package/dist/commands/functions/env/add.js +6 -2
  41. package/dist/commands/functions/env/list.d.ts +4 -1
  42. package/dist/commands/functions/env/list.js +9 -3
  43. package/dist/commands/functions/env/remove.d.ts +4 -1
  44. package/dist/commands/functions/env/remove.js +9 -3
  45. package/dist/commands/functions/logs.d.ts +1 -1
  46. package/dist/commands/functions/test.d.ts +1 -1
  47. package/dist/constants.d.ts +1 -0
  48. package/dist/constants.js +1 -0
  49. package/dist/cores/blueprinit/adopt.d.ts +6 -0
  50. package/dist/cores/blueprinit/adopt.js +90 -0
  51. package/dist/cores/blueprinit/finish.d.ts +14 -0
  52. package/dist/cores/blueprinit/finish.js +36 -0
  53. package/dist/cores/blueprinit/fresh.d.ts +3 -0
  54. package/dist/cores/blueprinit/fresh.js +88 -0
  55. package/dist/cores/blueprinit/prompts.d.ts +4 -0
  56. package/dist/cores/blueprinit/prompts.js +14 -0
  57. package/dist/cores/blueprinit/selection.d.ts +15 -0
  58. package/dist/cores/blueprinit/selection.js +63 -0
  59. package/dist/cores/blueprinit/types.d.ts +13 -0
  60. package/dist/cores/blueprinit/types.js +1 -0
  61. package/dist/cores/blueprinit.d.ts +7 -0
  62. package/dist/cores/blueprinit.js +39 -0
  63. package/dist/cores/blueprints/deploy.js +18 -65
  64. package/dist/cores/blueprints/doctor.js +15 -12
  65. package/dist/cores/functions/build.js +3 -2
  66. package/dist/cores/functions/test.js +4 -2
  67. package/dist/server/app.js +8 -2
  68. package/dist/server/static/favicon-dark.svg +1 -0
  69. package/dist/server/static/favicon.svg +1 -0
  70. package/dist/server/static/index.html +1 -1
  71. package/dist/server/static/vendor/vendor.bundle.js +5 -0
  72. package/dist/utils/command-skills.d.ts +2 -0
  73. package/dist/utils/command-skills.js +17 -0
  74. package/dist/utils/functions/child-process-wrapper.js +13 -171
  75. package/dist/utils/functions/child-runtime/console.d.ts +1 -0
  76. package/dist/utils/functions/child-runtime/console.js +50 -0
  77. package/dist/utils/functions/child-runtime/invoke.d.ts +4 -0
  78. package/dist/utils/functions/child-runtime/invoke.js +47 -0
  79. package/dist/utils/functions/child-runtime/resources.d.ts +4 -0
  80. package/dist/utils/functions/child-runtime/resources.js +59 -0
  81. package/dist/utils/functions/find-entry-point.d.ts +1 -1
  82. package/dist/utils/functions/find-entry-point.js +10 -12
  83. package/dist/utils/functions/invoke/local.js +1 -1
  84. package/dist/utils/functions/invoke/prepare.d.ts +1 -1
  85. package/dist/utils/functions/invoke/prepare.js +19 -8
  86. package/dist/utils/functions/package-json.d.ts +1 -2
  87. package/dist/utils/functions/package-json.js +4 -6
  88. package/dist/utils/functions/prepare-asset.d.ts +2 -2
  89. package/dist/utils/functions/prepare-asset.js +18 -7
  90. package/dist/utils/functions/resolve-dependencies.d.ts +4 -1
  91. package/dist/utils/functions/resolve-dependencies.js +5 -6
  92. package/dist/utils/functions/resource-to-arc.d.ts +1 -1
  93. package/dist/utils/functions/resource-to-arc.js +4 -5
  94. package/dist/utils/functions/should-transpile.d.ts +7 -1
  95. package/dist/utils/functions/should-transpile.js +10 -10
  96. package/dist/utils/functions/transpile/function.d.ts +4 -1
  97. package/dist/utils/functions/transpile/function.js +9 -14
  98. package/dist/utils/functions/transpile/verify-handler.js +1 -1
  99. package/dist/utils/logger.d.ts +7 -5
  100. package/dist/utils/logger.js +33 -1
  101. package/dist/utils/progress.d.ts +5 -0
  102. package/dist/utils/progress.js +40 -0
  103. package/dist/utils/studios/prepare-asset.d.ts +6 -0
  104. package/dist/utils/studios/prepare-asset.js +139 -0
  105. package/dist/utils/types.d.ts +9 -8
  106. package/dist/utils/types.js +2 -3
  107. package/oclif.manifest.json +1237 -930
  108. package/package.json +33 -24
  109. package/skills/blueprinit.md +137 -0
@@ -3,18 +3,17 @@ import { join } from 'node:path';
3
3
  import hydrate from '@architect/hydrate';
4
4
  import inventory from '@architect/inventory';
5
5
  import { convertResourceToArcFormat } from './resource-to-arc.js';
6
- export async function resolveResourceDependencies(resource, { transpiled, installer, }) {
7
- const rawArc = await convertResourceToArcFormat(resource, transpiled);
8
- const inv = await inventory({ rawArc });
9
- const cwd = inv.inv._project.cwd;
6
+ export async function resolveResourceDependencies({ resource, transpiled, blueprintFileDir, functionPath, installer, }) {
7
+ const rawArc = await convertResourceToArcFormat(resource, functionPath, transpiled);
8
+ const inv = await inventory({ rawArc, cwd: blueprintFileDir });
10
9
  let installType = 'npm';
11
10
  if (installer) {
12
11
  installType = installer;
13
12
  }
14
- else if (existsSync(join(cwd, 'pnpm-lock.yaml'))) {
13
+ else if (existsSync(join(blueprintFileDir, 'pnpm-lock.yaml'))) {
15
14
  installType = 'pnpm';
16
15
  }
17
- else if (existsSync(join(cwd, 'yarn.lock'))) {
16
+ else if (existsSync(join(blueprintFileDir, 'yarn.lock'))) {
18
17
  installType = 'yarn';
19
18
  }
20
19
  try {
@@ -1,2 +1,2 @@
1
1
  import type { FunctionResource } from '../types.js';
2
- export declare function convertResourceToArcFormat(resource: FunctionResource, transpiled: boolean): Promise<string>;
2
+ export declare function convertResourceToArcFormat(resource: FunctionResource, functionPath: string, transpiled: boolean): Promise<string>;
@@ -1,16 +1,15 @@
1
1
  import { stat } from 'node:fs/promises';
2
- import { resolve, sep } from 'node:path';
3
- import { cwd } from 'node:process';
4
- export async function convertResourceToArcFormat(resource, transpiled) {
2
+ import { sep } from 'node:path';
3
+ export async function convertResourceToArcFormat(resource, functionPath, transpiled) {
5
4
  if (!resource.src) {
6
5
  throw Error('Missing `resource.src` property');
7
6
  }
8
7
  // Get stats from file
9
- const stats = await stat(resolve(cwd(), resource.src));
8
+ const stats = await stat(functionPath);
10
9
  // Convert resource.src to arc file path format
11
10
  const srcPath = resource.src?.split(sep).join('/');
12
11
  const entryDir = stats.isFile() ? srcPath.substring(0, srcPath.lastIndexOf('/')) : srcPath;
13
- const functionPath = transpiled ? `${entryDir}/.build/function-${resource.name}` : entryDir;
12
+ functionPath = transpiled ? `${entryDir}/.build/function-${resource.name}` : entryDir;
14
13
  return `@app
15
14
  hydrate-function
16
15
 
@@ -1,2 +1,8 @@
1
1
  import type { FunctionResource } from '../types.js';
2
- export declare function shouldTranspileFunction(resource: FunctionResource): Promise<boolean>;
2
+ export type ShouldTranspileResult = {
3
+ transpile: true;
4
+ entryPoint: string;
5
+ } | {
6
+ transpile: false;
7
+ };
8
+ export declare function shouldTranspileFunction(resource: FunctionResource, functionPath: string): Promise<ShouldTranspileResult>;
@@ -1,22 +1,22 @@
1
1
  import { findFunctionEntryPoint } from './find-entry-point.js';
2
- export async function shouldTranspileFunction(resource) {
3
- if ('transpile' in resource && typeof resource.transpile === 'boolean') {
4
- return resource.transpile;
5
- }
6
- if (!resource.src) {
7
- // Cannot determine without a source path
8
- return false;
2
+ export async function shouldTranspileFunction(resource, functionPath) {
3
+ const hasTranspile = 'transpile' in resource && typeof resource.transpile === 'boolean';
4
+ if (!functionPath || (hasTranspile && resource.transpile === false)) {
5
+ return { transpile: false };
9
6
  }
10
7
  try {
11
8
  // 2. Find the actual entry point
12
- const entryPoint = await findFunctionEntryPoint(resource.src, resource.displayName ?? resource.name);
9
+ const entryPoint = await findFunctionEntryPoint(functionPath, resource.displayName ?? resource.name);
13
10
  // 3. Check if the resolved entry point is a TypeScript file
14
- return entryPoint.endsWith('.ts');
11
+ return {
12
+ entryPoint,
13
+ transpile: hasTranspile ? resource.transpile === true : entryPoint.endsWith('.ts'),
14
+ };
15
15
  }
16
16
  catch (err) {
17
17
  // If we cannot find the entry point, we cannot determine if it's TS.
18
18
  // Log a warning and default to false (don't bundle).
19
19
  console.warn(`[warn] Could not determine entry point for function "${resource.displayName ?? resource.name}" while checking if transpiling is needed: ${err instanceof Error ? err.message : err}`);
20
- return false;
20
+ return { transpile: false };
21
21
  }
22
22
  }
@@ -1,6 +1,9 @@
1
1
  import type { FunctionResource, InstallerType } from '../../types.js';
2
2
  export declare const resolveViteRoot: (entry: string) => string;
3
- export declare function transpileFunction(resource: FunctionResource, { installer }?: {
3
+ export declare function transpileFunction({ resource, functionPath, entryPoint, installer, }: {
4
+ resource: FunctionResource;
5
+ functionPath: string;
6
+ entryPoint: string;
4
7
  installer?: InstallerType;
5
8
  }): Promise<{
6
9
  type: string;
@@ -3,9 +3,9 @@ import path from 'node:path';
3
3
  import { performance } from 'node:perf_hooks';
4
4
  import { cwd } from 'node:process';
5
5
  import * as find from 'empathic/find';
6
+ import stripAnsi from 'strip-ansi';
6
7
  import { build as viteBuild } from 'vite';
7
8
  import { detectNativeModulesPlugin } from '../detect-native-modules.js';
8
- import { findFunctionEntryPoint } from '../find-entry-point.js';
9
9
  import { cleanupSourceMaps } from './cleanup-source-maps.js';
10
10
  import { createPnpmRequire } from './pnpm.js';
11
11
  import { verifyHandler } from './verify-handler.js';
@@ -13,23 +13,18 @@ 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, { installer } = {}) {
16
+ export async function transpileFunction({ resource, functionPath, entryPoint, installer, }) {
17
17
  if (!resource.src)
18
18
  throw new Error('Resource src is required');
19
19
  if (!resource.name)
20
20
  throw new Error('Resource name is required');
21
21
  const timings = {};
22
22
  const transpileStart = performance.now();
23
- const sourcePath = path.resolve(cwd(), resource.src);
24
- const stats = await stat(sourcePath);
25
- const fnDisplayName = resource.displayName ?? resource.name;
26
- const findEntryStart = performance.now();
27
- const entry = await findFunctionEntryPoint(sourcePath, fnDisplayName);
28
- timings['transpile:findEntry'] = performance.now() - findEntryStart;
29
- const entryDir = stats.isFile() ? path.dirname(sourcePath) : sourcePath;
23
+ const stats = await stat(functionPath);
24
+ const entryDir = stats.isFile() ? path.dirname(functionPath) : functionPath;
30
25
  const outputPathStart = performance.now();
31
26
  const outputDir = await getTranspileOutputPath(entryDir, resource.name);
32
- const outputFile = path.join(outputDir, getOutputFilename(entry));
27
+ const outputFile = path.join(outputDir, getOutputFilename(entryPoint));
33
28
  const fnRootDir = resolveViteRoot(entryDir);
34
29
  timings['transpile:setupOutput'] = performance.now() - outputPathStart;
35
30
  async function cleanupTmpDir() {
@@ -51,10 +46,10 @@ export async function transpileFunction(resource, { installer } = {}) {
51
46
  sourcemap: true,
52
47
  ssr: true,
53
48
  rolldownOptions: {
54
- input: entry,
49
+ input: entryPoint,
55
50
  output: {
56
51
  format: 'esm',
57
- entryFileNames: getOutputFilename(entry),
52
+ entryFileNames: getOutputFilename(entryPoint),
58
53
  ...(bundle
59
54
  ? {}
60
55
  : {
@@ -86,7 +81,7 @@ export async function transpileFunction(resource, { installer } = {}) {
86
81
  await writeTranspiledPackageJson(entryDir, outputFile);
87
82
  timings['transpile:writePackage'] = performance.now() - pkgStart;
88
83
  const cleanupStart = performance.now();
89
- await cleanupSourceMaps(sourcePath, outputDir);
84
+ await cleanupSourceMaps(functionPath, outputDir);
90
85
  timings['transpile:cleanupMaps'] = performance.now() - cleanupStart;
91
86
  timings.bundle = performance.now() - transpileStart;
92
87
  return {
@@ -100,7 +95,7 @@ export async function transpileFunction(resource, { installer } = {}) {
100
95
  }
101
96
  catch (err) {
102
97
  await cleanupTmpDir();
103
- throw new Error(`Transpiling of function failed: ${formatBuildError(err)}`, {
98
+ throw new Error(`Transpiling of function failed: ${stripAnsi(formatBuildError(err))}`, {
104
99
  cause: err,
105
100
  });
106
101
  }
@@ -4,7 +4,7 @@ export async function verifyHandler(result) {
4
4
  }
5
5
  const outputs = (Array.isArray(result) ? result : [result]).flatMap(({ output }) => output);
6
6
  const bundledIndex = outputs.find((output) => output.type === 'chunk' && output.isEntry && output.fileName === 'index.js');
7
- if (!bundledIndex || bundledIndex.type !== 'chunk') {
7
+ if (bundledIndex?.type !== 'chunk') {
8
8
  throw new Error('Unexpected build output, no bundled index found');
9
9
  }
10
10
  if (!bundledIndex.exports.includes('handler')) {
@@ -6,11 +6,13 @@ export declare function Logger(log: (msg: string) => void, flags?: {
6
6
  }): {
7
7
  (msg: string): void;
8
8
  isTraceEnabled: boolean;
9
- trace(formatter: unknown, ...args: unknown[]): false | void;
10
- verbose(formatter: unknown, ...args: unknown[]): false | void;
11
- info(formatter: unknown, ...args: unknown[]): false | void;
12
- warn(formatter: unknown, ...args: unknown[]): false | void;
13
- error(formatter: unknown, ...args: unknown[]): false | void;
9
+ trace: (formatter: unknown, ...args: unknown[]) => void | false;
10
+ verbose: (formatter: unknown, ...args: unknown[]) => void | false;
11
+ info: (formatter: unknown, ...args: unknown[]) => void | false;
12
+ warn: (formatter: unknown, ...args: unknown[]) => void | false;
13
+ error: (formatter: unknown, ...args: unknown[]) => void | false;
14
+ showProgress: (percent?: number) => void;
15
+ clearProgress: () => void;
14
16
  ora: typeof ora;
15
17
  };
16
18
  export type Logger = ReturnType<typeof Logger>;
@@ -1,5 +1,6 @@
1
1
  import { format } from 'node:util';
2
2
  import ora from 'ora';
3
+ import { clearProgress, showBusy, showError, showProgress } from './progress.js';
3
4
  var LogLevel;
4
5
  (function (LogLevel) {
5
6
  LogLevel[LogLevel["TRACE"] = 0] = "TRACE";
@@ -19,16 +20,47 @@ export function Logger(log, flags = {}) {
19
20
  logger.info = (formatter, ...args) => level <= LogLevel.INFO && logger(format(formatter, ...args));
20
21
  logger.warn = (formatter, ...args) => level <= LogLevel.WARN && logger(format(formatter, ...args));
21
22
  logger.error = (formatter, ...args) => level <= LogLevel.ERROR && logger(format(formatter, ...args));
23
+ logger.showProgress = (percent) => {
24
+ if (flags.json)
25
+ return;
26
+ if (percent === undefined)
27
+ showBusy();
28
+ else
29
+ showProgress(percent);
30
+ };
31
+ logger.clearProgress = () => {
32
+ if (flags.json)
33
+ return;
34
+ clearProgress();
35
+ };
22
36
  const oraWrapper = (opts) => {
23
37
  if (flags.json)
24
38
  return createOraLineLoggingWrapper(opts, logger);
25
39
  if (level >= LogLevel.INFO)
26
- return ora(opts);
40
+ return withTerminalProgress(ora(opts));
27
41
  return createOraLineLoggingWrapper(opts, logger);
28
42
  };
29
43
  logger.ora = oraWrapper;
30
44
  return logger;
31
45
  }
46
+ function withTerminalProgress(spinner) {
47
+ const wrap = (name, effect) => {
48
+ if (typeof spinner[name] !== 'function')
49
+ return;
50
+ const original = spinner[name].bind(spinner);
51
+ spinner[name] = (...args) => {
52
+ const result = original(...args);
53
+ effect();
54
+ return result;
55
+ };
56
+ };
57
+ wrap('start', showBusy);
58
+ wrap('fail', showError);
59
+ for (const name of ['stop', 'succeed', 'warn', 'info', 'stopAndPersist']) {
60
+ wrap(name, clearProgress);
61
+ }
62
+ return spinner;
63
+ }
32
64
  /**
33
65
  * An ora-like wrapper that uses standard line output logging instead of rendering a spinner; used in verbose and trace modes.
34
66
  */
@@ -0,0 +1,5 @@
1
+ export declare function showProgress(percent: number): void;
2
+ export declare function showBusy(): void;
3
+ export declare function showError(): void;
4
+ export declare function showPaused(percent: number): void;
5
+ export declare function clearProgress(): void;
@@ -0,0 +1,40 @@
1
+ import { stderr } from 'node:process';
2
+ import { onExit } from 'signal-exit';
3
+ const ST = '\x1b\\';
4
+ const STATES = {
5
+ clear: 0,
6
+ normal: 1,
7
+ error: 2,
8
+ paused: 4,
9
+ busy: 3,
10
+ };
11
+ let exitHookRegistered = false;
12
+ function write(state, value = 0) {
13
+ if (!stderr.isTTY)
14
+ return;
15
+ if (!exitHookRegistered) {
16
+ exitHookRegistered = true;
17
+ function clear() {
18
+ stderr.write(`\x1b]9;4;0;0${ST}`);
19
+ }
20
+ // arc/utils SIGINT handler clobbers our signal-exit; luckily it then calls process.exit()
21
+ process.once('exit', clear); // triggered by arc/utils SIGINT handler
22
+ onExit(clear); // triggered by all other exit paths
23
+ }
24
+ stderr.write(`\x1b]9;4;${STATES[state]};${Math.round(value)}${ST}`);
25
+ }
26
+ export function showProgress(percent) {
27
+ write('normal', Math.max(0, Math.min(100, percent)));
28
+ }
29
+ export function showBusy() {
30
+ write('busy');
31
+ }
32
+ export function showError() {
33
+ write('error', 100);
34
+ }
35
+ export function showPaused(percent) {
36
+ write('paused', Math.max(0, Math.min(100, percent)));
37
+ }
38
+ export function clearProgress() {
39
+ write('clear');
40
+ }
@@ -0,0 +1,6 @@
1
+ import type { BlueprintStudioResource } from '@sanity/blueprints';
2
+ import type { AssetPrepResult } from '../types.js';
3
+ export declare function prepareStudioAsset({ blueprintFileDir, resource, }: {
4
+ blueprintFileDir: string;
5
+ resource: BlueprintStudioResource;
6
+ }): Promise<AssetPrepResult>;
@@ -0,0 +1,139 @@
1
+ import { createWriteStream } from 'node:fs';
2
+ import { mkdtemp, rm, stat } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import path, { basename, dirname, join } from 'node:path';
5
+ import { pipeline } from 'node:stream/promises';
6
+ import { createGzip } from 'node:zlib';
7
+ import { buildStudio, compareDependencyVersions } from '@sanity/cli-build/_internal/build';
8
+ import { pack } from 'tar-fs';
9
+ export async function prepareStudioAsset({ blueprintFileDir, resource, }) {
10
+ // validate resource has an externalId
11
+ if (!('externalId' in resource) ||
12
+ typeof resource.externalId !== 'string' ||
13
+ !resource.externalId) {
14
+ return {
15
+ success: false,
16
+ async cleanup() {
17
+ // no op
18
+ },
19
+ error: `Unable to determine appId for sanity.studio resource '${resource.name}'`,
20
+ };
21
+ }
22
+ let cleanup = async () => {
23
+ // no op
24
+ };
25
+ const studioPath = path.resolve(blueprintFileDir, resource.src);
26
+ try {
27
+ const studioPathStat = await stat(studioPath);
28
+ if (!studioPathStat.isDirectory()) {
29
+ return {
30
+ success: false,
31
+ cleanup,
32
+ error: `Property 'src' on resource with type '${resource.type}' must be a directory`,
33
+ };
34
+ }
35
+ }
36
+ catch (error) {
37
+ const msg = error instanceof Error ? error.message : String(error);
38
+ return {
39
+ success: false,
40
+ cleanup,
41
+ error: `Unable to read given 'src' on resource with type '${resource.type}': ${msg}`,
42
+ };
43
+ }
44
+ try {
45
+ const outDir = await mkdtemp(join(tmpdir(), `studio-build-`));
46
+ const outFile = `${outDir}.tar.gz`;
47
+ cleanup = async () => {
48
+ await rm(outDir, { force: true, recursive: true });
49
+ await rm(outFile, { force: true });
50
+ };
51
+ const appId = resource.externalId;
52
+ try {
53
+ await buildStudio({
54
+ appId,
55
+ autoUpdatesEnabled: resource.autoUpdates.enabled,
56
+ checkAppId() { },
57
+ async compareDependencyVersions(packages) {
58
+ return compareDependencyVersions(packages, studioPath, { appId });
59
+ },
60
+ determineBasePath() {
61
+ return resource.basePath ?? '/';
62
+ },
63
+ isApp: false,
64
+ isWorkbenchApp: false,
65
+ minify: resource.minify ?? true,
66
+ outDir,
67
+ output: createSilentOutput(),
68
+ reactCompiler: resource.reactCompiler || false,
69
+ schemaExtraction: undefined,
70
+ sourceMap: resource.sourceMap ?? false,
71
+ stats: false,
72
+ unattendedMode: true,
73
+ // TODO pass in vite config from the studio resource
74
+ vite: undefined,
75
+ workDir: studioPath,
76
+ eventListener: {
77
+ onBuildFail({ message }) {
78
+ throw new Error(message);
79
+ },
80
+ onInvalidStyledComponentsVersionRange({ message }) {
81
+ throw new Error(message);
82
+ },
83
+ onNoDeclaredStyledComponentsVersion({ message }) {
84
+ throw new Error(message);
85
+ },
86
+ onNoInstalledSanityVersion({ message }) {
87
+ throw new Error(message);
88
+ },
89
+ onNoInstalledStyledComponentsVersion({ message }) {
90
+ throw new Error(message);
91
+ },
92
+ onPreReleaseInNonInteractiveAutoUpdate({ message }) {
93
+ throw new Error(message);
94
+ },
95
+ },
96
+ });
97
+ }
98
+ catch (error) {
99
+ const message = error instanceof Error ? error.message : String(error);
100
+ return {
101
+ success: false,
102
+ cleanup,
103
+ error: message,
104
+ };
105
+ }
106
+ // tar/gzip/write the built output
107
+ await pipeline(pack(dirname(outDir), { entries: [basename(outDir)] }), createGzip(), createWriteStream(outFile));
108
+ return {
109
+ success: true,
110
+ cleanup,
111
+ // studio must be pre built (e.g. with `npm run build`) and tarred/gzipped
112
+ outputPath: outFile,
113
+ };
114
+ }
115
+ catch (error) {
116
+ return {
117
+ success: false,
118
+ cleanup,
119
+ error: error instanceof Error ? error.message : String(error),
120
+ };
121
+ }
122
+ }
123
+ function createSilentOutput() {
124
+ return {
125
+ error(input, options) {
126
+ if (typeof options?.exit === 'number') {
127
+ if (input instanceof Error) {
128
+ throw input;
129
+ }
130
+ throw new Error(input);
131
+ }
132
+ return undefined;
133
+ },
134
+ log() { },
135
+ warn(input) {
136
+ return input;
137
+ },
138
+ };
139
+ }
@@ -1,4 +1,4 @@
1
- import { type BlueprintCorsOriginResource, type BlueprintDatasetResource, type BlueprintDocumentFunctionResource, type BlueprintDocumentWebhookResource, type BlueprintMediaLibraryAssetFunctionResource, type BlueprintProjectResource, type BlueprintResource, type BlueprintRobotResource, type BlueprintRoleResource, type BlueprintScheduledFunctionResource, type BlueprintSyncTagInvalidateFunctionResource } from '@sanity/blueprints';
1
+ import { type BlueprintCorsOriginResource, type BlueprintDatasetResource, type BlueprintDocumentFunctionResource, type BlueprintDocumentWebhookResource, type BlueprintMediaLibraryAssetFunctionResource, type BlueprintProjectResource, type BlueprintResource, type BlueprintRobotResource, type BlueprintRoleResource, type BlueprintScheduledFunctionResource, type BlueprintStudioResource, type BlueprintSyncTagInvalidateFunctionResource } from '@sanity/blueprints';
2
2
  export type ScopeType = 'organization' | 'project';
3
3
  /** Result utility type */
4
4
  export type Result<T, E = string> = {
@@ -16,12 +16,8 @@ export interface ActionResponse {
16
16
  /** @internal */
17
17
  export type FunctionGroqResource = BlueprintDocumentFunctionResource | BlueprintMediaLibraryAssetFunctionResource;
18
18
  export type FunctionResource = FunctionGroqResource | BlueprintScheduledFunctionResource | BlueprintSyncTagInvalidateFunctionResource;
19
- export interface StudioResource extends BlueprintResource {
20
- type: 'sanity.studio';
21
- src: string;
22
- }
23
19
  /** Resource types that carry a deployable asset (have src: string) */
24
- export type AssetResource = FunctionResource | StudioResource;
20
+ export type AssetResource = FunctionResource | BlueprintStudioResource;
25
21
  /** @internal */
26
22
  export interface AuthParams {
27
23
  token: string;
@@ -46,7 +42,7 @@ export declare function isProjectResource(r: unknown): r is BlueprintProjectReso
46
42
  export declare function isRobotResource(r: unknown): r is BlueprintRobotResource;
47
43
  export declare function isRoleResource(r: unknown): r is BlueprintRoleResource;
48
44
  export declare function isDatasetResource(r: unknown): r is BlueprintDatasetResource;
49
- export declare function isStudioResource(r: BlueprintResource): r is StudioResource;
45
+ export declare function isStudioResource(r: BlueprintResource): r is BlueprintStudioResource;
50
46
  export declare function isAssetResource(r: BlueprintResource): r is AssetResource;
51
47
  export declare function isWebhookResource(r: unknown): r is BlueprintDocumentWebhookResource;
52
48
  interface StackBase {
@@ -84,6 +80,7 @@ export interface StackMutation {
84
80
  resources?: BlueprintResource[];
85
81
  };
86
82
  userMessage?: string;
83
+ preDeploy?: boolean;
87
84
  }
88
85
  /** @internal */
89
86
  export interface BuildPayloadOptions {
@@ -126,6 +123,8 @@ export interface InvokeGroqContextOptions {
126
123
  functionResourceId: string;
127
124
  /** All resources declared by the blueprint, used to populate `context.resources` at invoke time. */
128
125
  resources?: BlueprintResource[];
126
+ /** The directory where the blueprint manifest is located. */
127
+ blueprintFileDir: string;
129
128
  }
130
129
  /** @internal */
131
130
  export interface InvokeScheduleContextOptions {
@@ -134,6 +133,8 @@ export interface InvokeScheduleContextOptions {
134
133
  };
135
134
  /** All resources declared by the blueprint, used to populate `context.resources` at invoke time. */
136
135
  resources?: BlueprintResource[];
136
+ /** The directory where the blueprint manifest is located. */
137
+ blueprintFileDir: string;
137
138
  }
138
139
  export type InvokeContextOptions = InvokeGroqContextOptions | InvokeScheduleContextOptions;
139
140
  export declare function isGroqContextOptions(context: InvokeContextOptions): context is InvokeGroqContextOptions;
@@ -265,7 +266,7 @@ export declare interface FetchConfig {
265
266
  apiHost?: string;
266
267
  apiVersion?: string;
267
268
  }
268
- export declare const INSTALLER_OPTIONS: readonly ["npm", "pnpm", "yarn"];
269
+ export declare const INSTALLER_OPTIONS: readonly ['npm', 'pnpm', 'yarn'];
269
270
  export type InstallerType = 'npm' | 'pnpm' | 'yarn';
270
271
  export type AssetPrepResult = {
271
272
  success: true;
@@ -1,5 +1,5 @@
1
1
  import { validateCorsOrigin, validateDataset, validateDocumentWebhook, validateProject, validateRobot, validateRole, } from '@sanity/blueprints';
2
- import { SANITY_FUNCTION_PREFIX } from '../constants.js';
2
+ import { SANITY_FUNCTION_PREFIX, SANITY_STUDIO } from '../constants.js';
3
3
  export function isLocalFunctionResource(r) {
4
4
  return r.type.startsWith(SANITY_FUNCTION_PREFIX);
5
5
  }
@@ -22,9 +22,8 @@ export function isRoleResource(r) {
22
22
  export function isDatasetResource(r) {
23
23
  return validateDataset(r).length === 0;
24
24
  }
25
- // TODO: update to use blueprints helpers once available
26
25
  export function isStudioResource(r) {
27
- return r.type === 'sanity.studio';
26
+ return r.type === SANITY_STUDIO;
28
27
  }
29
28
  export function isAssetResource(r) {
30
29
  return isLocalFunctionResource(r) || isStudioResource(r);