@sanity/cli 8.0.0 → 8.0.2
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/dist/actions/backup/downloadAsset.js +3 -24
- package/dist/actions/backup/downloadAsset.js.map +1 -1
- package/dist/actions/backup/downloadDocument.js +11 -22
- package/dist/actions/backup/downloadDocument.js.map +1 -1
- package/dist/actions/backup/downloadStream.js +83 -0
- package/dist/actions/backup/downloadStream.js.map +1 -0
- package/dist/actions/documents/validate.js +0 -3
- package/dist/actions/documents/validate.js.map +1 -1
- package/dist/actions/documents/validateDocuments.worker.js +4 -1
- package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
- package/dist/actions/init/sdkAppDependencies.js +1 -1
- package/dist/actions/init/sdkAppDependencies.js.map +1 -1
- package/dist/actions/init/studioDependencies.js +1 -1
- package/dist/actions/init/studioDependencies.js.map +1 -1
- package/dist/actions/schema/uploadSchemaToLexicon.js +3 -0
- package/dist/actions/schema/uploadSchemaToLexicon.js.map +1 -1
- package/dist/actions/telemetry/telemetryDebug.js +2 -2
- package/dist/actions/telemetry/telemetryDebug.js.map +1 -1
- package/dist/commands/assets/upload.js +35 -1
- package/dist/commands/assets/upload.js.map +1 -1
- package/dist/commands/datasets/import.js +7 -10
- package/dist/commands/datasets/import.js.map +1 -1
- package/dist/exports/_internal.d.ts +50 -82
- package/dist/exports/index.d.ts +48 -78
- package/dist/exports/invokeSanityCli/index.d.ts +108 -18
- package/dist/exports/invokeSanityCli/index.js +2 -1
- package/dist/exports/invokeSanityCli/index.js.map +1 -1
- package/dist/exports/runtime.d.ts +3 -65
- package/dist/services/api.js +23 -15
- package/dist/services/api.js.map +1 -1
- package/dist/services/auth.js +4 -4
- package/dist/services/auth.js.map +1 -1
- package/dist/services/backup.js +3 -3
- package/dist/services/backup.js.map +1 -1
- package/dist/services/cors.js +3 -3
- package/dist/services/cors.js.map +1 -1
- package/dist/services/datasetAliases.js +5 -5
- package/dist/services/datasetAliases.js.map +1 -1
- package/dist/services/datasets.js +3 -3
- package/dist/services/datasets.js.map +1 -1
- package/dist/services/documents.js +1 -1
- package/dist/services/documents.js.map +1 -1
- package/dist/services/getProjectFeatures.js +1 -1
- package/dist/services/getProjectFeatures.js.map +1 -1
- package/dist/services/getUrlHeaders.js +3 -9
- package/dist/services/getUrlHeaders.js.map +1 -1
- package/dist/services/grants.js +1 -1
- package/dist/services/grants.js.map +1 -1
- package/dist/services/graphql.js +4 -3
- package/dist/services/graphql.js.map +1 -1
- package/dist/services/hooks.js +6 -6
- package/dist/services/hooks.js.map +1 -1
- package/dist/services/mcp.js +4 -4
- package/dist/services/mcp.js.map +1 -1
- package/dist/services/mediaLibraries.js +3 -3
- package/dist/services/mediaLibraries.js.map +1 -1
- package/dist/services/mintProject.js +6 -11
- package/dist/services/mintProject.js.map +1 -1
- package/dist/services/organizations.js +6 -6
- package/dist/services/organizations.js.map +1 -1
- package/dist/services/plans.js +2 -2
- package/dist/services/plans.js.map +1 -1
- package/dist/services/projects.js +7 -7
- package/dist/services/projects.js.map +1 -1
- package/dist/services/schemas.js +2 -2
- package/dist/services/schemas.js.map +1 -1
- package/dist/services/telemetry.js +2 -2
- package/dist/services/telemetry.js.map +1 -1
- package/dist/services/tokens.js +5 -5
- package/dist/services/tokens.js.map +1 -1
- package/dist/services/user.js +1 -1
- package/dist/services/user.js.map +1 -1
- package/dist/services/userApplications.js +18 -18
- package/dist/services/userApplications.js.map +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/exports/invokeSanityCli/index.ts"],"sourcesContent":["/**\n * Programmatic (in-process) invocation of CLI commands, e.g. from an MCP\n * server. The invokable surface is governed by a per-source command policy\n * (see ./commandPolicies): every CLI command is explicitly allowed, denied,\n * or allowed conditionally on the parsed invocation.\n *\n * {@link invokeSanityCli} handles arg parsing, policy enforcement, command\n * dispatch, per-invocation auth, and output capture.\n * ```ts\n * import {invokeSanityCli} from '@sanity/cli/invokeSanityCli'\n *\n * const {exitCode, output} = await invokeSanityCli({\n * args: 'cors list --project-id abc123',\n * source: 'mcp',\n * token: extra.authInfo.token,\n * })\n * ```\n *\n * Help works like the regular CLI, scoped to the source's policy: `--help`\n * (or `help`) renders root help listing the invokable topics, and a subject\n * (`cors --help`, `cors list --help`) renders topic or command help.\n */\nimport {Command, Config, Parser, settings} from '@oclif/core'\nimport {getHelpFlagAdditions, normalizeArgv} from '@oclif/core/help'\nimport {exitCodes} from '@sanity/cli-core'\nimport {runWithCliExecutionContext, type SanityEnvironment} from '@sanity/cli-core/executionContext'\nimport {type SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {parseArgsStringToArgv} from 'string-argv'\n\nimport {resolveTopicAliasInArgv} from '../../topicAliases.js'\nimport {commandPolicies} from './commandPolicies/index.js'\nimport {\n type CommandPolicySet,\n deny,\n type InvocationSource,\n isConditionalInvocationPolicy,\n} from './commandPolicies/policy.js'\nimport {isHelpRequest, renderInvokableHelp} from './help.js'\nimport {prettyPrintError} from './prettyPrintError.js'\n\ntype InvokableCommand = Pick<SanityCommand<typeof Command>, 'runInExecutionContext'>\n\n/**\n * Instantiate a policy-approved command for isolated execution.\n *\n * Every invokable command extends `SanityCommand`, whose\n * `runInExecutionContext()` runs the instance without oclif's static\n * `Command.run()` — the static runner re-enters `Config.load()` (filesystem\n * reads and a process-global config cache write) on every call. The manifest\n * types command classes as the abstract oclif `Command`, hence the\n * constructor cast. The method is probed rather than checked with\n * `instanceof`, because command modules may load from the compiled build\n * while this module runs from source, giving `SanityCommand` two identities.\n */\nfunction instantiateCommand(\n CommandClass: Command.Class,\n argv: string[],\n config: Config,\n): InvokableCommand {\n const ConcreteCommand = CommandClass as unknown as new (argv: string[], config: Config) => Command\n const command = new ConcreteCommand(argv, config) as Command & Partial<InvokableCommand>\n if (typeof command.runInExecutionContext !== 'function') {\n throw new TypeError(`Command \"${CommandClass.id}\" does not support isolated execution`)\n }\n return command as InvokableCommand\n}\n\n/**\n * Load the oclif `Config` for this package, needed to resolve, load, and run\n * commands. Loading it once and reusing it across invocations avoids\n * re-reading the command manifest per call. It only reads this package's own\n * installed files — process-lifetime initialization, not per-invocation host\n * state — so it happens outside any execution context.\n */\nfunction loadCliCommandConfig(): Promise<Config> {\n return Config.load(import.meta.url)\n}\n\nlet cachedConfig: Promise<Config> | undefined\n\nfunction unknownCommandResult(argv: string[], policySet: CommandPolicySet): InvokeSanityCliResult {\n const available = Object.entries(policySet)\n .filter(([, policy]) => policy.kind !== 'deny')\n .map(([id]) => id.replaceAll(':', ' '))\n .toSorted()\n return {\n exitCode: exitCodes.USAGE_ERROR,\n output: [\n `Unknown or unsupported command: ${argv.slice(0, 2).join(' ') || '(none)'}`,\n `Available commands: ${available.join(', ')}`,\n ].join('\\n'),\n }\n}\n\n/**\n * @internal\n */\nexport interface InvokeSanityCliOptions {\n /**\n * Arguments after `sanity` (a leading `sanity` token is tolerated), either\n * as a single string — shell-style quoting is supported, but no shell is\n * ever executed — or as a pre-split argv array.\n */\n args: string | string[]\n\n /**\n * Where this invocation originates. Selects the command policy to enforce:\n * which commands are invokable and which invocations of them are permitted.\n */\n source: InvocationSource\n\n /**\n * Auth token for this invocation. Scoped to this call via the CLI execution\n * context: it never touches process env or the process-wide token cache, so\n * concurrent invocations with different tokens are fully isolated.\n */\n token: string\n\n /**\n * Optional oclif config override (mainly for tests). Defaults to this\n * package's config, loaded once and cached across invocations.\n */\n config?: Config\n\n /**\n * Sanity deployment environment for this invocation. Scoped to this call\n * via the CLI execution context and defaults to production. The embedding\n * process's `SANITY_INTERNAL_ENV` is never consulted.\n */\n sanityEnv?: SanityEnvironment\n}\n\n/**\n * @internal\n */\nexport interface InvokeSanityCliResult {\n /** `0` on success, the command's exit code otherwise. */\n exitCode: number\n\n /** Combined stdout and stderr output, in emission order. */\n output: string\n\n /**\n * Canonical oclif command id when the invocation resolved to a command\n * exposed by the selected policy (for example, `datasets:create`).\n */\n commandId?: string\n}\n\n/**\n * Unlike a shell, string-argv keeps quotes that are glued to unquoted text:\n * `--name=\"my project\"` tokenizes with the quotes intact. Strip a matching\n * wrapping quote pair from the value side of `--flag=`-shaped tokens so the\n * common shell-style form yields the value the caller intended.\n */\nfunction stripFlagQuotes(rawToken: string): string {\n const match = /^(-{1,2}[^\\s=]+=)(['\"])([\\s\\S]*)\\2$/.exec(rawToken)\n return match ? match[1] + match[3] : rawToken\n}\n\n/**\n * Run a policy-permitted CLI command in-process and capture its result.\n *\n * Command-level failures (unknown command, bad flags, API errors) are\n * reported through `exitCode`/`output` rather than thrown, so callers can\n * relay them verbatim.\n *\n * @internal\n */\nexport async function invokeSanityCli(\n options: InvokeSanityCliOptions,\n): Promise<InvokeSanityCliResult> {\n // Always load compiled command modules. Oclif's dev-mode source resolution\n // otherwise probes tsconfigs (reading the filesystem and process.cwd) on\n // every command load, and may register ts-node process-wide.\n settings.enableAutoTranspile = false\n\n const resolvedConfig = options.config ?? (await (cachedConfig ??= loadCliCommandConfig()))\n const output: string[] = []\n const sink = (line: string) => output.push(line)\n const {sanityEnv, token} = options\n\n // Establish the isolation boundary before rendering help, loading command\n // modules, parsing, or executing. Any code reached by an external\n // invocation can therefore fail closed on context.\n return runWithCliExecutionContext({sanityEnv, stderr: sink, stdout: sink, token}, () =>\n invokeSanityCliInContext(options, resolvedConfig, output),\n )\n}\n\nasync function invokeSanityCliInContext(\n {args, source}: InvokeSanityCliOptions,\n resolvedConfig: Config,\n output: string[],\n): Promise<InvokeSanityCliResult> {\n const policySet = commandPolicies[source]\n\n // Pre-split argv arrays are taken verbatim; only string input goes through\n // shell-style tokenization and quote normalization.\n let argv =\n typeof args === 'string'\n ? parseArgsStringToArgv(args).map((t) => stripFlagQuotes(t))\n : [...args]\n if (argv[0] === 'sanity') argv = argv.slice(1)\n argv = resolveTopicAliasInArgv(argv)\n\n // Help requests are routed through oclif's help system, scoped to the\n // source's policy: root help for a bare request, topic/command help when a\n // subject is given. Denied subjects get the standard unknown-command\n // response (identical to a truly unknown command, so hosts can't probe the\n // full CLI surface through help), and a help request never executes a\n // command.\n if (isHelpRequest(argv, resolvedConfig)) {\n try {\n // Drop a leading `help` so the rest is the subject, mirroring how\n // oclif's dispatch consumes the token before the help command sees argv\n const helpArgv = argv[0] === 'help' ? argv.slice(1) : argv\n const result = await renderInvokableHelp(resolvedConfig, helpArgv, policySet)\n if (result) return {...result, exitCode: exitCodes.SUCCESS}\n const helpFlags = getHelpFlagAdditions(resolvedConfig)\n return unknownCommandResult(\n helpArgv.filter((token) => !helpFlags.includes(token)),\n policySet,\n )\n } catch (err) {\n return {\n exitCode: exitCodes.RUNTIME_ERROR,\n output: err instanceof Error ? err.message : String(err),\n }\n }\n }\n\n // Resolve the command id the same way oclif's dispatch would (collating\n // space-separated topics, accepting colon-separated ids as-is), then apply\n // the policy. Denied and uncategorized ids fail closed, indistinguishable\n // from commands that don't exist.\n const [commandId = '', ...commandArgv] = normalizeArgv(resolvedConfig, argv)\n const policy = policySet[commandId] ?? deny\n const commandDefinition =\n policy.kind === 'deny' ? undefined : resolvedConfig.findCommand(commandId)\n if (!commandDefinition) return unknownCommandResult(argv, policySet)\n\n const CommandClass = await commandDefinition.load()\n\n // Parse with the command's real definitions (without executing anything) so\n // conditional policies are evaluated against typed args/flags, not tokens.\n let invocation: {args: Record<string, unknown>; flags: Record<string, unknown>}\n try {\n const parsed = await Parser.parse(commandArgv, {\n args: CommandClass.args,\n baseFlags: CommandClass.baseFlags,\n enableJsonFlag: CommandClass.enableJsonFlag,\n flags: CommandClass.flags,\n strict: CommandClass.strict,\n })\n invocation = {\n args: parsed.args as Record<string, unknown>,\n flags: parsed.flags as Record<string, unknown>,\n }\n } catch (err) {\n return {\n commandId,\n exitCode: exitCodes.USAGE_ERROR,\n output: err instanceof Error ? err.message : String(err),\n }\n }\n\n if (!policy.validate(invocation)) {\n const displayId = commandId.replaceAll(':', ' ')\n let output = `This invocation of \\`${displayId}\\` is not supported here`\n\n if (isConditionalInvocationPolicy(policy)) {\n const usedDeniedFlags = policy.deniedFlags.filter(\n (name) => invocation.flags[name] !== undefined && invocation.flags[name] !== false,\n )\n if (usedDeniedFlags.length > 0) {\n output = `\\nThe ${usedDeniedFlags.map((name) => `--${name}`).join(', ')} flag is not supported here for \\`${displayId}\\``\n }\n }\n\n return {\n commandId,\n exitCode: exitCodes.USAGE_ERROR,\n output,\n }\n }\n\n try {\n const command = instantiateCommand(CommandClass, commandArgv, resolvedConfig)\n await command.runInExecutionContext()\n return {commandId, exitCode: exitCodes.SUCCESS, output: output.join('\\n')}\n } catch (err) {\n const exit = err.oclif?.exit\n\n // `this.exit(0)` throws an ExitError but is a successful outcome\n if (exit === exitCodes.SUCCESS) {\n return {commandId, exitCode: exitCodes.SUCCESS, output: output.join('\\n')}\n }\n\n const message = prettyPrintError(err) || String(err)\n if (message) output.push(message)\n return {\n commandId,\n exitCode: typeof exit === 'number' ? exit : exitCodes.RUNTIME_ERROR,\n output: output.join('\\n'),\n }\n }\n}\n"],"names":["Config","Parser","settings","getHelpFlagAdditions","normalizeArgv","exitCodes","runWithCliExecutionContext","parseArgsStringToArgv","resolveTopicAliasInArgv","commandPolicies","deny","isConditionalInvocationPolicy","isHelpRequest","renderInvokableHelp","prettyPrintError","instantiateCommand","CommandClass","argv","config","ConcreteCommand","command","runInExecutionContext","TypeError","id","loadCliCommandConfig","load","url","cachedConfig","unknownCommandResult","policySet","available","Object","entries","filter","policy","kind","map","replaceAll","toSorted","exitCode","USAGE_ERROR","output","slice","join","stripFlagQuotes","rawToken","match","exec","invokeSanityCli","options","enableAutoTranspile","resolvedConfig","sink","line","push","sanityEnv","token","stderr","stdout","invokeSanityCliInContext","args","source","t","helpArgv","result","SUCCESS","helpFlags","includes","err","RUNTIME_ERROR","Error","message","String","commandId","commandArgv","commandDefinition","undefined","findCommand","invocation","parsed","parse","baseFlags","enableJsonFlag","flags","strict","validate","displayId","usedDeniedFlags","deniedFlags","name","length","exit","oclif"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/exports/invokeSanityCli/index.ts"],"sourcesContent":["/**\n * Programmatic (in-process) invocation of CLI commands, e.g. from an MCP\n * server. The invokable surface is governed by a per-source command policy\n * (see ./commandPolicies): every CLI command is explicitly allowed, denied,\n * or allowed conditionally on the parsed invocation.\n *\n * {@link invokeSanityCli} handles arg parsing, policy enforcement, command\n * dispatch, per-invocation auth, and output capture.\n * ```ts\n * import {invokeSanityCli} from '@sanity/cli/invokeSanityCli'\n *\n * const {exitCode, output} = await invokeSanityCli({\n * args: 'cors list --project-id abc123',\n * source: 'mcp',\n * token: extra.authInfo.token,\n * })\n * ```\n *\n * Help works like the regular CLI, scoped to the source's policy: `--help`\n * (or `help`) renders root help listing the invokable topics, and a subject\n * (`cors --help`, `cors list --help`) renders topic or command help.\n */\nimport {Command, Config, Parser, settings} from '@oclif/core'\nimport {getHelpFlagAdditions, normalizeArgv} from '@oclif/core/help'\nimport {exitCodes} from '@sanity/cli-core'\nimport {runWithCliExecutionContext, type SanityEnvironment} from '@sanity/cli-core/executionContext'\nimport {type SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {type FetchFunction} from 'get-it'\nimport {parseArgsStringToArgv} from 'string-argv'\n\nimport {resolveTopicAliasInArgv} from '../../topicAliases.js'\nimport {commandPolicies} from './commandPolicies/index.js'\nimport {\n type CommandPolicySet,\n deny,\n type InvocationSource,\n isConditionalInvocationPolicy,\n} from './commandPolicies/policy.js'\nimport {isHelpRequest, renderInvokableHelp} from './help.js'\nimport {prettyPrintError} from './prettyPrintError.js'\n\ntype InvokableCommand = Pick<SanityCommand<typeof Command>, 'runInExecutionContext'>\n\n/**\n * Instantiate a policy-approved command for isolated execution.\n *\n * Every invokable command extends `SanityCommand`, whose\n * `runInExecutionContext()` runs the instance without oclif's static\n * `Command.run()` — the static runner re-enters `Config.load()` (filesystem\n * reads and a process-global config cache write) on every call. The manifest\n * types command classes as the abstract oclif `Command`, hence the\n * constructor cast. The method is probed rather than checked with\n * `instanceof`, because command modules may load from the compiled build\n * while this module runs from source, giving `SanityCommand` two identities.\n */\nfunction instantiateCommand(\n CommandClass: Command.Class,\n argv: string[],\n config: Config,\n): InvokableCommand {\n const ConcreteCommand = CommandClass as unknown as new (argv: string[], config: Config) => Command\n const command = new ConcreteCommand(argv, config) as Command & Partial<InvokableCommand>\n if (typeof command.runInExecutionContext !== 'function') {\n throw new TypeError(`Command \"${CommandClass.id}\" does not support isolated execution`)\n }\n return command as InvokableCommand\n}\n\n/**\n * Load the oclif `Config` for this package, needed to resolve, load, and run\n * commands. Loading it once and reusing it across invocations avoids\n * re-reading the command manifest per call. It only reads this package's own\n * installed files — process-lifetime initialization, not per-invocation host\n * state — so it happens outside any execution context.\n */\nfunction loadCliCommandConfig(): Promise<Config> {\n return Config.load(import.meta.url)\n}\n\nlet cachedConfig: Promise<Config> | undefined\n\nfunction unknownCommandResult(argv: string[], policySet: CommandPolicySet): InvokeSanityCliResult {\n const available = Object.entries(policySet)\n .filter(([, policy]) => policy.kind !== 'deny')\n .map(([id]) => id.replaceAll(':', ' '))\n .toSorted()\n return {\n exitCode: exitCodes.USAGE_ERROR,\n output: [\n `Unknown or unsupported command: ${argv.slice(0, 2).join(' ') || '(none)'}`,\n `Available commands: ${available.join(', ')}`,\n ].join('\\n'),\n }\n}\n\n/**\n * @internal\n */\nexport interface InvokeSanityCliOptions {\n /**\n * Arguments after `sanity` (a leading `sanity` token is tolerated), either\n * as a single string — shell-style quoting is supported, but no shell is\n * ever executed — or as a pre-split argv array.\n */\n args: string | string[]\n\n /**\n * Where this invocation originates. Selects the command policy to enforce:\n * which commands are invokable and which invocations of them are permitted.\n */\n source: InvocationSource\n\n /**\n * Auth token for this invocation. Scoped to this call via the CLI execution\n * context: it never touches process env or the process-wide token cache, so\n * concurrent invocations with different tokens are fully isolated.\n */\n token: string\n\n /**\n * Optional oclif config override (mainly for tests). Defaults to this\n * package's config, loaded once and cached across invocations.\n */\n config?: Config\n\n /**\n * Optional fetch implementation for API requests made by this invocation.\n * Scoped to this call via the CLI execution context; defaults to the CLI's\n * own transport. The execution context's transport hygiene (such as\n * stripping the embedding process's lineage header) is applied on top.\n */\n fetch?: FetchFunction\n\n /**\n * Sanity deployment environment for this invocation. Scoped to this call\n * via the CLI execution context and defaults to production. The embedding\n * process's `SANITY_INTERNAL_ENV` is never consulted.\n */\n sanityEnv?: SanityEnvironment\n}\n\n/**\n * @internal\n */\nexport interface InvokeSanityCliResult {\n /** `0` on success, the command's exit code otherwise. */\n exitCode: number\n\n /** Combined stdout and stderr output, in emission order. */\n output: string\n\n /**\n * Canonical oclif command id when the invocation resolved to a command\n * exposed by the selected policy (for example, `datasets:create`).\n */\n commandId?: string\n}\n\n/**\n * Unlike a shell, string-argv keeps quotes that are glued to unquoted text:\n * `--name=\"my project\"` tokenizes with the quotes intact. Strip a matching\n * wrapping quote pair from the value side of `--flag=`-shaped tokens so the\n * common shell-style form yields the value the caller intended.\n */\nfunction stripFlagQuotes(rawToken: string): string {\n const match = /^(-{1,2}[^\\s=]+=)(['\"])([\\s\\S]*)\\2$/.exec(rawToken)\n return match ? match[1] + match[3] : rawToken\n}\n\n/**\n * Run a policy-permitted CLI command in-process and capture its result.\n *\n * Command-level failures (unknown command, bad flags, API errors) are\n * reported through `exitCode`/`output` rather than thrown, so callers can\n * relay them verbatim.\n *\n * @internal\n */\nexport async function invokeSanityCli(\n options: InvokeSanityCliOptions,\n): Promise<InvokeSanityCliResult> {\n // Always load compiled command modules. Oclif's dev-mode source resolution\n // otherwise probes tsconfigs (reading the filesystem and process.cwd) on\n // every command load, and may register ts-node process-wide.\n settings.enableAutoTranspile = false\n\n const resolvedConfig = options.config ?? (await (cachedConfig ??= loadCliCommandConfig()))\n const output: string[] = []\n const sink = (line: string) => output.push(line)\n const {fetch, sanityEnv, token} = options\n\n // Establish the isolation boundary before rendering help, loading command\n // modules, parsing, or executing. Any code reached by an external\n // invocation can therefore fail closed on context.\n return runWithCliExecutionContext({fetch, sanityEnv, stderr: sink, stdout: sink, token}, () =>\n invokeSanityCliInContext(options, resolvedConfig, output),\n )\n}\n\nasync function invokeSanityCliInContext(\n {args, source}: InvokeSanityCliOptions,\n resolvedConfig: Config,\n output: string[],\n): Promise<InvokeSanityCliResult> {\n const policySet = commandPolicies[source]\n\n // Pre-split argv arrays are taken verbatim; only string input goes through\n // shell-style tokenization and quote normalization.\n let argv =\n typeof args === 'string'\n ? parseArgsStringToArgv(args).map((t) => stripFlagQuotes(t))\n : [...args]\n if (argv[0] === 'sanity') argv = argv.slice(1)\n argv = resolveTopicAliasInArgv(argv)\n\n // Help requests are routed through oclif's help system, scoped to the\n // source's policy: root help for a bare request, topic/command help when a\n // subject is given. Denied subjects get the standard unknown-command\n // response (identical to a truly unknown command, so hosts can't probe the\n // full CLI surface through help), and a help request never executes a\n // command.\n if (isHelpRequest(argv, resolvedConfig)) {\n try {\n // Drop a leading `help` so the rest is the subject, mirroring how\n // oclif's dispatch consumes the token before the help command sees argv\n const helpArgv = argv[0] === 'help' ? argv.slice(1) : argv\n const result = await renderInvokableHelp(resolvedConfig, helpArgv, policySet)\n if (result) return {...result, exitCode: exitCodes.SUCCESS}\n const helpFlags = getHelpFlagAdditions(resolvedConfig)\n return unknownCommandResult(\n helpArgv.filter((token) => !helpFlags.includes(token)),\n policySet,\n )\n } catch (err) {\n return {\n exitCode: exitCodes.RUNTIME_ERROR,\n output: err instanceof Error ? err.message : String(err),\n }\n }\n }\n\n // Resolve the command id the same way oclif's dispatch would (collating\n // space-separated topics, accepting colon-separated ids as-is), then apply\n // the policy. Denied and uncategorized ids fail closed, indistinguishable\n // from commands that don't exist.\n const [commandId = '', ...commandArgv] = normalizeArgv(resolvedConfig, argv)\n const policy = policySet[commandId] ?? deny\n const commandDefinition =\n policy.kind === 'deny' ? undefined : resolvedConfig.findCommand(commandId)\n if (!commandDefinition) return unknownCommandResult(argv, policySet)\n\n const CommandClass = await commandDefinition.load()\n\n // Parse with the command's real definitions (without executing anything) so\n // conditional policies are evaluated against typed args/flags, not tokens.\n let invocation: {args: Record<string, unknown>; flags: Record<string, unknown>}\n try {\n const parsed = await Parser.parse(commandArgv, {\n args: CommandClass.args,\n baseFlags: CommandClass.baseFlags,\n enableJsonFlag: CommandClass.enableJsonFlag,\n flags: CommandClass.flags,\n strict: CommandClass.strict,\n })\n invocation = {\n args: parsed.args as Record<string, unknown>,\n flags: parsed.flags as Record<string, unknown>,\n }\n } catch (err) {\n return {\n commandId,\n exitCode: exitCodes.USAGE_ERROR,\n output: err instanceof Error ? err.message : String(err),\n }\n }\n\n if (!policy.validate(invocation)) {\n const displayId = commandId.replaceAll(':', ' ')\n let output = `This invocation of \\`${displayId}\\` is not supported here`\n\n if (isConditionalInvocationPolicy(policy)) {\n const usedDeniedFlags = policy.deniedFlags.filter(\n (name) => invocation.flags[name] !== undefined && invocation.flags[name] !== false,\n )\n if (usedDeniedFlags.length > 0) {\n output = `\\nThe ${usedDeniedFlags.map((name) => `--${name}`).join(', ')} flag is not supported here for \\`${displayId}\\``\n }\n }\n\n return {\n commandId,\n exitCode: exitCodes.USAGE_ERROR,\n output,\n }\n }\n\n try {\n const command = instantiateCommand(CommandClass, commandArgv, resolvedConfig)\n await command.runInExecutionContext()\n return {commandId, exitCode: exitCodes.SUCCESS, output: output.join('\\n')}\n } catch (err) {\n const exit = err.oclif?.exit\n\n // `this.exit(0)` throws an ExitError but is a successful outcome\n if (exit === exitCodes.SUCCESS) {\n return {commandId, exitCode: exitCodes.SUCCESS, output: output.join('\\n')}\n }\n\n const message = prettyPrintError(err) || String(err)\n if (message) output.push(message)\n return {\n commandId,\n exitCode: typeof exit === 'number' ? exit : exitCodes.RUNTIME_ERROR,\n output: output.join('\\n'),\n }\n }\n}\n"],"names":["Config","Parser","settings","getHelpFlagAdditions","normalizeArgv","exitCodes","runWithCliExecutionContext","parseArgsStringToArgv","resolveTopicAliasInArgv","commandPolicies","deny","isConditionalInvocationPolicy","isHelpRequest","renderInvokableHelp","prettyPrintError","instantiateCommand","CommandClass","argv","config","ConcreteCommand","command","runInExecutionContext","TypeError","id","loadCliCommandConfig","load","url","cachedConfig","unknownCommandResult","policySet","available","Object","entries","filter","policy","kind","map","replaceAll","toSorted","exitCode","USAGE_ERROR","output","slice","join","stripFlagQuotes","rawToken","match","exec","invokeSanityCli","options","enableAutoTranspile","resolvedConfig","sink","line","push","fetch","sanityEnv","token","stderr","stdout","invokeSanityCliInContext","args","source","t","helpArgv","result","SUCCESS","helpFlags","includes","err","RUNTIME_ERROR","Error","message","String","commandId","commandArgv","commandDefinition","undefined","findCommand","invocation","parsed","parse","baseFlags","enableJsonFlag","flags","strict","validate","displayId","usedDeniedFlags","deniedFlags","name","length","exit","oclif"],"mappings":"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"}
|
|
@@ -1,65 +1,3 @@
|
|
|
1
|
-
import { AssetSource } from "@sanity/types";
|
|
2
|
-
import { AssetSourceComponent } from "@sanity/workbench-cli";
|
|
3
|
-
|
|
4
|
-
import { AssetSourceViewComponents } from "@sanity/workbench-cli";
|
|
5
|
-
import { DefinedService } from "@sanity/workbench-cli";
|
|
6
|
-
import { DefinedView } from "@sanity/workbench-cli";
|
|
7
|
-
import { InterfaceType } from "@sanity/workbench-cli";
|
|
8
|
-
import { PanelComponent } from "@sanity/workbench-cli";
|
|
9
|
-
import { PanelViewComponents } from "@sanity/workbench-cli";
|
|
10
|
-
import { PanelViewProps } from "@sanity/workbench-cli";
|
|
11
|
-
import { ServiceCallback } from "@sanity/workbench-cli";
|
|
12
|
-
import { ServiceContext } from "@sanity/workbench-cli";
|
|
13
|
-
import { ServiceInfo } from "@sanity/workbench-cli";
|
|
14
|
-
import { ServiceType } from "@sanity/workbench-cli";
|
|
15
|
-
import { TileComponent } from "@sanity/workbench-cli";
|
|
16
|
-
import { TileSize } from "@sanity/workbench-cli";
|
|
17
|
-
import { TileViewComponents } from "@sanity/workbench-cli";
|
|
18
|
-
import { TileViewProps } from "@sanity/workbench-cli";
|
|
19
|
-
import { unstable_defineService } from "@sanity/workbench-cli";
|
|
20
|
-
import { unstable_defineView } from "@sanity/workbench-cli";
|
|
21
|
-
import { ViewComponentsByType } from "@sanity/workbench-cli";
|
|
22
|
-
|
|
23
|
-
export { AssetSource };
|
|
24
|
-
|
|
25
|
-
export { AssetSourceComponent };
|
|
26
|
-
|
|
27
|
-
export { AssetSourceComponentProps };
|
|
28
|
-
|
|
29
|
-
export { AssetSourceViewComponents };
|
|
30
|
-
|
|
31
|
-
export { DefinedService };
|
|
32
|
-
|
|
33
|
-
export { DefinedView };
|
|
34
|
-
|
|
35
|
-
export { InterfaceType };
|
|
36
|
-
|
|
37
|
-
export { PanelComponent };
|
|
38
|
-
|
|
39
|
-
export { PanelViewComponents };
|
|
40
|
-
|
|
41
|
-
export { PanelViewProps };
|
|
42
|
-
|
|
43
|
-
export { ServiceCallback };
|
|
44
|
-
|
|
45
|
-
export { ServiceContext };
|
|
46
|
-
|
|
47
|
-
export { ServiceInfo };
|
|
48
|
-
|
|
49
|
-
export { ServiceType };
|
|
50
|
-
|
|
51
|
-
export { TileComponent };
|
|
52
|
-
|
|
53
|
-
export { TileSize };
|
|
54
|
-
|
|
55
|
-
export { TileViewComponents };
|
|
56
|
-
|
|
57
|
-
export { TileViewProps };
|
|
58
|
-
|
|
59
|
-
export { unstable_defineService };
|
|
60
|
-
|
|
61
|
-
export { unstable_defineView };
|
|
62
|
-
|
|
63
|
-
export { ViewComponentsByType };
|
|
64
|
-
|
|
65
|
-
export {};
|
|
1
|
+
import { AssetSource, AssetSourceComponentProps } from "@sanity/types";
|
|
2
|
+
import { AssetSourceComponent, AssetSourceViewComponents, DefinedService, DefinedView, InterfaceType, PanelComponent, PanelViewComponents, PanelViewProps, ServiceCallback, ServiceContext, ServiceInfo, ServiceType, TileComponent, TileSize, TileViewComponents, TileViewProps, ViewComponentsByType, unstable_defineService, unstable_defineView } from "@sanity/workbench-cli";
|
|
3
|
+
export { type AssetSource, type AssetSourceComponent, type AssetSourceComponentProps, type AssetSourceViewComponents, type DefinedService, type DefinedView, type InterfaceType, type PanelComponent, type PanelViewComponents, type PanelViewProps, type ServiceCallback, type ServiceContext, type ServiceInfo, type ServiceType, type TileComponent, type TileSize, type TileViewComponents, type TileViewProps, type ViewComponentsByType, unstable_defineService, unstable_defineView };
|
package/dist/services/api.js
CHANGED
|
@@ -28,38 +28,46 @@ const API_REQUEST_TAG = 'sanity.cli.api';
|
|
|
28
28
|
requestHeaders[key.toLowerCase()] = value;
|
|
29
29
|
}
|
|
30
30
|
const request = createRequester({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
}
|
|
31
|
+
httpErrors: false,
|
|
32
|
+
// Raw API passthrough: request duration is caller-controlled (eg long
|
|
33
|
+
// exports), so no default deadline is imposed.
|
|
34
|
+
timeout: false
|
|
37
35
|
});
|
|
38
36
|
const mergedQuery = {
|
|
39
37
|
...resolved.query,
|
|
40
38
|
...query
|
|
41
39
|
};
|
|
40
|
+
// Built as URLSearchParams so repeated field values (eg `-f tag=a -f tag=b`)
|
|
41
|
+
// become repeated query parameters.
|
|
42
|
+
const searchParams = new URLSearchParams({
|
|
43
|
+
tag: API_REQUEST_TAG
|
|
44
|
+
});
|
|
45
|
+
for (const [key, value] of Object.entries(mergedQuery)){
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
for (const item of value)searchParams.append(key, item);
|
|
48
|
+
} else {
|
|
49
|
+
searchParams.set(key, value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
42
52
|
const response = await request({
|
|
43
53
|
...requestBody === undefined ? {} : {
|
|
44
54
|
body: requestBody
|
|
45
55
|
},
|
|
56
|
+
as: 'text',
|
|
46
57
|
headers: requestHeaders,
|
|
47
58
|
method,
|
|
48
|
-
query:
|
|
49
|
-
tag: API_REQUEST_TAG,
|
|
50
|
-
...mergedQuery
|
|
51
|
-
},
|
|
59
|
+
query: searchParams,
|
|
52
60
|
url
|
|
53
61
|
});
|
|
54
|
-
const rawBody =
|
|
55
|
-
const parsed = parseBody(rawBody, response.headers
|
|
62
|
+
const rawBody = response.body;
|
|
63
|
+
const parsed = parseBody(rawBody, response.headers.get('content-type') ?? undefined);
|
|
56
64
|
return {
|
|
57
65
|
body: parsed.body,
|
|
58
|
-
headers: response.headers,
|
|
66
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
59
67
|
jsonBody: parsed.jsonBody,
|
|
60
68
|
rawBody,
|
|
61
|
-
statusCode: response.
|
|
62
|
-
statusMessage: response.
|
|
69
|
+
statusCode: response.status,
|
|
70
|
+
statusMessage: response.statusText,
|
|
63
71
|
url: response.url
|
|
64
72
|
};
|
|
65
73
|
}
|
package/dist/services/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/api.ts"],"sourcesContent":["import {getCliToken, getGlobalCliClient, getProjectCliClient} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\n\nimport {type ResolvedEndpoint} from '../actions/api/resolveEndpoint.js'\n\nconst API_REQUEST_TAG = 'sanity.cli.api'\n\n/**\n * Options for {@link performApiRequest}.\n */\nexport interface PerformApiRequestOptions {\n /** HTTP method (upper case). */\n method: string\n\n /** The resolved request target. */\n resolved: ResolvedEndpoint\n\n /** Request body: objects are JSON-serialized; strings and raw byte buffers are sent verbatim. */\n body?: Buffer | string | unknown\n\n /** Extra request headers. A user-provided `Authorization` header wins over the CLI token. */\n headers?: Record<string, string>\n\n /** Extra query parameters, merged with those from the endpoint argument. */\n query?: Record<string, string | string[]>\n\n /** Explicit API token, used instead of the logged-in user's token. */\n token?: string\n\n /** Send the request without an authorization token. */\n unauthenticated?: boolean\n}\n\n/**\n * The full HTTP response of an API request. Non-2xx responses are returned,\n * not thrown - the command decides how to surface them.\n */\nexport interface ApiResponse {\n /** Parsed JSON body for JSON responses, raw text otherwise. */\n body: unknown\n\n headers: Record<string, string>\n\n /** Whether `body` was parsed from a JSON response. */\n jsonBody: boolean\n\n /** The raw response body text. */\n rawBody: string\n\n statusCode: number\n\n url: string\n\n statusMessage?: string\n}\n\n/**\n * Perform an authenticated raw HTTP request against a Sanity API.\n *\n * URL construction and token resolution reuse the standard CLI client\n * factories; the request itself uses a bare requester so the response\n * (status, headers, non-JSON bodies) can be passed through unfiltered.\n */\nexport async function performApiRequest(options: PerformApiRequestOptions): Promise<ApiResponse> {\n const {\n body,\n headers = {},\n method,\n query = {},\n resolved,\n token: providedToken,\n unauthenticated = false,\n } = options\n\n const {token, url} = await resolveRequestTarget(resolved, unauthenticated, providedToken)\n\n // Header names are case-insensitive - keyed lowercase so a user-provided\n // header (eg `-H 'authorization: ...'`) replaces the default regardless of\n // how either side is cased.\n const requestHeaders: Record<string, string> = {}\n if (token) requestHeaders.authorization = `Bearer ${token}`\n\n let requestBody: Buffer | string | undefined\n if (typeof body === 'string' || Buffer.isBuffer(body)) {\n // Raw bodies (--input) pass through without a default Content-Type - the\n // caller knows the media type, we don't (gh api behaves the same way)\n requestBody = body\n } else if (body !== undefined) {\n requestBody = JSON.stringify(body)\n requestHeaders['content-type'] = 'application/json'\n }\n\n for (const [key, value] of Object.entries(headers)) {\n requestHeaders[key.toLowerCase()] = value\n }\n\n const request = createRequester({\n
|
|
1
|
+
{"version":3,"sources":["../../src/services/api.ts"],"sourcesContent":["import {getCliToken, getGlobalCliClient, getProjectCliClient} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\n\nimport {type ResolvedEndpoint} from '../actions/api/resolveEndpoint.js'\n\nconst API_REQUEST_TAG = 'sanity.cli.api'\n\n/**\n * Options for {@link performApiRequest}.\n */\nexport interface PerformApiRequestOptions {\n /** HTTP method (upper case). */\n method: string\n\n /** The resolved request target. */\n resolved: ResolvedEndpoint\n\n /** Request body: objects are JSON-serialized; strings and raw byte buffers are sent verbatim. */\n body?: Buffer | string | unknown\n\n /** Extra request headers. A user-provided `Authorization` header wins over the CLI token. */\n headers?: Record<string, string>\n\n /** Extra query parameters, merged with those from the endpoint argument. */\n query?: Record<string, string | string[]>\n\n /** Explicit API token, used instead of the logged-in user's token. */\n token?: string\n\n /** Send the request without an authorization token. */\n unauthenticated?: boolean\n}\n\n/**\n * The full HTTP response of an API request. Non-2xx responses are returned,\n * not thrown - the command decides how to surface them.\n */\nexport interface ApiResponse {\n /** Parsed JSON body for JSON responses, raw text otherwise. */\n body: unknown\n\n headers: Record<string, string>\n\n /** Whether `body` was parsed from a JSON response. */\n jsonBody: boolean\n\n /** The raw response body text. */\n rawBody: string\n\n statusCode: number\n\n /**\n * The final response URL, including merged query parameters and redirects.\n */\n url: string\n\n statusMessage?: string\n}\n\n/**\n * Perform an authenticated raw HTTP request against a Sanity API.\n *\n * URL construction and token resolution reuse the standard CLI client\n * factories; the request itself uses a bare requester so the response\n * (status, headers, non-JSON bodies) can be passed through unfiltered.\n */\nexport async function performApiRequest(options: PerformApiRequestOptions): Promise<ApiResponse> {\n const {\n body,\n headers = {},\n method,\n query = {},\n resolved,\n token: providedToken,\n unauthenticated = false,\n } = options\n\n const {token, url} = await resolveRequestTarget(resolved, unauthenticated, providedToken)\n\n // Header names are case-insensitive - keyed lowercase so a user-provided\n // header (eg `-H 'authorization: ...'`) replaces the default regardless of\n // how either side is cased.\n const requestHeaders: Record<string, string> = {}\n if (token) requestHeaders.authorization = `Bearer ${token}`\n\n let requestBody: Buffer | string | undefined\n if (typeof body === 'string' || Buffer.isBuffer(body)) {\n // Raw bodies (--input) pass through without a default Content-Type - the\n // caller knows the media type, we don't (gh api behaves the same way)\n requestBody = body\n } else if (body !== undefined) {\n requestBody = JSON.stringify(body)\n requestHeaders['content-type'] = 'application/json'\n }\n\n for (const [key, value] of Object.entries(headers)) {\n requestHeaders[key.toLowerCase()] = value\n }\n\n const request = createRequester({\n httpErrors: false,\n // Raw API passthrough: request duration is caller-controlled (eg long\n // exports), so no default deadline is imposed.\n timeout: false,\n })\n\n const mergedQuery = {...resolved.query, ...query}\n\n // Built as URLSearchParams so repeated field values (eg `-f tag=a -f tag=b`)\n // become repeated query parameters.\n const searchParams = new URLSearchParams({tag: API_REQUEST_TAG})\n for (const [key, value] of Object.entries(mergedQuery)) {\n if (Array.isArray(value)) {\n for (const item of value) searchParams.append(key, item)\n } else {\n searchParams.set(key, value)\n }\n }\n\n const response = await request({\n ...(requestBody === undefined ? {} : {body: requestBody}),\n as: 'text',\n headers: requestHeaders,\n method,\n query: searchParams,\n url,\n })\n\n const rawBody = response.body\n const parsed = parseBody(rawBody, response.headers.get('content-type') ?? undefined)\n\n return {\n body: parsed.body,\n headers: Object.fromEntries(response.headers.entries()),\n jsonBody: parsed.jsonBody,\n rawBody,\n statusCode: response.status,\n statusMessage: response.statusText,\n url: response.url,\n }\n}\n\nasync function resolveRequestTarget(\n resolved: ResolvedEndpoint,\n unauthenticated: boolean,\n providedToken?: string,\n): Promise<{token?: string; url: string}> {\n if (resolved.kind === 'url') {\n const token = unauthenticated ? undefined : providedToken || (await getCliToken())\n if (!token && !unauthenticated) {\n throw new Error('You must login first - run \"sanity login\"')\n }\n return {token, url: resolved.url}\n }\n\n // The client factories handle token resolution, staging/production API\n // hosts and the project subdomain - we only use them to build the URL.\n const client =\n resolved.host === 'project'\n ? await getProjectCliClient({\n apiVersion: resolved.apiVersion,\n projectId: resolved.projectId as string,\n requireUser: !unauthenticated,\n token: providedToken,\n })\n : await getGlobalCliClient({\n apiVersion: resolved.apiVersion,\n requireUser: !unauthenticated,\n token: providedToken,\n unauthenticated,\n })\n\n const token = unauthenticated ? undefined : (client.config().token ?? undefined)\n\n return {token, url: client.getUrl(resolved.path)}\n}\n\nfunction parseBody(\n rawBody: string,\n contentType: string | undefined,\n): {body: unknown; jsonBody: boolean} {\n if (rawBody === '' || !contentType || !/\\bjson\\b/.test(contentType)) {\n return {body: rawBody, jsonBody: false}\n }\n try {\n return {body: JSON.parse(rawBody), jsonBody: true}\n } catch {\n return {body: rawBody, jsonBody: false}\n }\n}\n"],"names":["getCliToken","getGlobalCliClient","getProjectCliClient","createRequester","API_REQUEST_TAG","performApiRequest","options","body","headers","method","query","resolved","token","providedToken","unauthenticated","url","resolveRequestTarget","requestHeaders","authorization","requestBody","Buffer","isBuffer","undefined","JSON","stringify","key","value","Object","entries","toLowerCase","request","httpErrors","timeout","mergedQuery","searchParams","URLSearchParams","tag","Array","isArray","item","append","set","response","as","rawBody","parsed","parseBody","get","fromEntries","jsonBody","statusCode","status","statusMessage","statusText","kind","Error","client","host","apiVersion","projectId","requireUser","config","getUrl","path","contentType","test","parse"],"mappings":"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"}
|
package/dist/services/auth.js
CHANGED
|
@@ -21,13 +21,13 @@ async function getUnauthenticatedClient() {
|
|
|
21
21
|
}
|
|
22
22
|
return client.request({
|
|
23
23
|
method: 'POST',
|
|
24
|
-
|
|
24
|
+
url: '/auth/logout'
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
export async function getProviders() {
|
|
28
28
|
const client = await getUnauthenticatedClient();
|
|
29
29
|
return client.request({
|
|
30
|
-
|
|
30
|
+
url: '/auth/providers'
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
export async function getVercelProviderUrl() {
|
|
@@ -39,13 +39,13 @@ export async function getVercelProviderUrl() {
|
|
|
39
39
|
export async function getSSOProviders(orgSlug) {
|
|
40
40
|
const client = await getUnauthenticatedClient();
|
|
41
41
|
return client.request({
|
|
42
|
-
|
|
42
|
+
url: `/auth/organizations/by-slug/${orgSlug}/providers`
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
export async function getTokenDetails(queryString) {
|
|
46
46
|
const client = await getUnauthenticatedClient();
|
|
47
47
|
return client.request({
|
|
48
|
-
|
|
48
|
+
url: `/auth/fetch${queryString}`
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/auth.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\n\nimport {\n type ProvidersResponse,\n type SamlLoginProvider,\n type TokenDetails,\n} from '../actions/auth/types.js'\n\nexport const AUTH_API_VERSION = 'v2025-09-23'\n\nasync function getUnauthenticatedClient() {\n return getGlobalCliClient({apiVersion: AUTH_API_VERSION, unauthenticated: true})\n}\n\n/**\n * Invalidate the current user session\n *\n * @param token - Optional token to invalidate.\n */\nexport async function logout(token?: string) {\n let client = await getGlobalCliClient({apiVersion: AUTH_API_VERSION})\n\n if (token) {\n client = client.withConfig({token})\n }\n\n return client.request({method: 'POST',
|
|
1
|
+
{"version":3,"sources":["../../src/services/auth.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\n\nimport {\n type ProvidersResponse,\n type SamlLoginProvider,\n type TokenDetails,\n} from '../actions/auth/types.js'\n\nexport const AUTH_API_VERSION = 'v2025-09-23'\n\nasync function getUnauthenticatedClient() {\n return getGlobalCliClient({apiVersion: AUTH_API_VERSION, unauthenticated: true})\n}\n\n/**\n * Invalidate the current user session\n *\n * @param token - Optional token to invalidate.\n */\nexport async function logout(token?: string) {\n let client = await getGlobalCliClient({apiVersion: AUTH_API_VERSION})\n\n if (token) {\n client = client.withConfig({token})\n }\n\n return client.request({method: 'POST', url: '/auth/logout'})\n}\n\nexport async function getProviders() {\n const client = await getUnauthenticatedClient()\n\n return client.request<ProvidersResponse>({url: '/auth/providers'})\n}\n\nexport async function getVercelProviderUrl() {\n const client = (await getUnauthenticatedClient()).withConfig({apiVersion: 'v1'})\n return client.getUrl('/auth/login/vercel')\n}\n\nexport async function getSSOProviders(orgSlug: string) {\n const client = await getUnauthenticatedClient()\n\n return client.request<SamlLoginProvider[]>({\n url: `/auth/organizations/by-slug/${orgSlug}/providers`,\n })\n}\n\nexport async function getTokenDetails(queryString: string) {\n const client = await getUnauthenticatedClient()\n\n return client.request<TokenDetails>({url: `/auth/fetch${queryString}`})\n}\n"],"names":["getGlobalCliClient","AUTH_API_VERSION","getUnauthenticatedClient","apiVersion","unauthenticated","logout","token","client","withConfig","request","method","url","getProviders","getVercelProviderUrl","getUrl","getSSOProviders","orgSlug","getTokenDetails","queryString"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,mBAAkB;AAQnD,OAAO,MAAMC,mBAAmB,cAAa;AAE7C,eAAeC;IACb,OAAOF,mBAAmB;QAACG,YAAYF;QAAkBG,iBAAiB;IAAI;AAChF;AAEA;;;;CAIC,GACD,OAAO,eAAeC,OAAOC,KAAc;IACzC,IAAIC,SAAS,MAAMP,mBAAmB;QAACG,YAAYF;IAAgB;IAEnE,IAAIK,OAAO;QACTC,SAASA,OAAOC,UAAU,CAAC;YAACF;QAAK;IACnC;IAEA,OAAOC,OAAOE,OAAO,CAAC;QAACC,QAAQ;QAAQC,KAAK;IAAc;AAC5D;AAEA,OAAO,eAAeC;IACpB,MAAML,SAAS,MAAML;IAErB,OAAOK,OAAOE,OAAO,CAAoB;QAACE,KAAK;IAAiB;AAClE;AAEA,OAAO,eAAeE;IACpB,MAAMN,SAAS,AAAC,CAAA,MAAML,0BAAyB,EAAGM,UAAU,CAAC;QAACL,YAAY;IAAI;IAC9E,OAAOI,OAAOO,MAAM,CAAC;AACvB;AAEA,OAAO,eAAeC,gBAAgBC,OAAe;IACnD,MAAMT,SAAS,MAAML;IAErB,OAAOK,OAAOE,OAAO,CAAsB;QACzCE,KAAK,CAAC,4BAA4B,EAAEK,QAAQ,UAAU,CAAC;IACzD;AACF;AAEA,OAAO,eAAeC,gBAAgBC,WAAmB;IACvD,MAAMX,SAAS,MAAML;IAErB,OAAOK,OAAOE,OAAO,CAAe;QAACE,KAAK,CAAC,WAAW,EAAEO,aAAa;IAAA;AACvE"}
|
package/dist/services/backup.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function listBackups(options) {
|
|
|
17
17
|
}
|
|
18
18
|
return client.request({
|
|
19
19
|
query,
|
|
20
|
-
|
|
20
|
+
url: `/projects/${options.projectId}/datasets/${options.datasetName}/backups`
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
export async function getBackupDetails(options) {
|
|
@@ -31,7 +31,7 @@ export async function getBackupDetails(options) {
|
|
|
31
31
|
}
|
|
32
32
|
return client.request({
|
|
33
33
|
query,
|
|
34
|
-
|
|
34
|
+
url: `/projects/${options.projectId}/datasets/${options.datasetName}/backups/${options.backupId}`
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
export async function setBackup({ dataset, projectId, status }) {
|
|
@@ -44,7 +44,7 @@ export async function setBackup({ dataset, projectId, status }) {
|
|
|
44
44
|
enabled: status
|
|
45
45
|
},
|
|
46
46
|
method: 'PUT',
|
|
47
|
-
|
|
47
|
+
url: `/projects/${projectId}/datasets/${dataset}/settings/backups`
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/backup.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\n\nimport {BACKUP_API_VERSION} from '../actions/backup/constants.js'\n\nexport interface BackupItem {\n createdAt: string\n id: string\n}\n\ninterface ListBackupsResponse {\n backups: BackupItem[]\n}\n\ninterface BackupDetailsResponse {\n createdAt: string\n files: Array<{\n name: string\n type: string\n url: string\n }>\n totalFiles: number\n\n nextCursor?: string\n}\n\nexport async function listBackups(options: {\n after?: string\n before?: string\n datasetName: string\n limit?: number\n projectId: string\n}): Promise<ListBackupsResponse> {\n const client = await getGlobalCliClient({\n apiVersion: BACKUP_API_VERSION,\n requireUser: true,\n })\n\n const query: Record<string, string> = {}\n if (options.limit) {\n query.limit = options.limit.toString()\n }\n\n if (options.after) {\n query.after = options.after\n }\n\n if (options.before) {\n query.before = options.before\n }\n\n return client.request({\n query,\n
|
|
1
|
+
{"version":3,"sources":["../../src/services/backup.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\n\nimport {BACKUP_API_VERSION} from '../actions/backup/constants.js'\n\nexport interface BackupItem {\n createdAt: string\n id: string\n}\n\ninterface ListBackupsResponse {\n backups: BackupItem[]\n}\n\ninterface BackupDetailsResponse {\n createdAt: string\n files: Array<{\n name: string\n type: string\n url: string\n }>\n totalFiles: number\n\n nextCursor?: string\n}\n\nexport async function listBackups(options: {\n after?: string\n before?: string\n datasetName: string\n limit?: number\n projectId: string\n}): Promise<ListBackupsResponse> {\n const client = await getGlobalCliClient({\n apiVersion: BACKUP_API_VERSION,\n requireUser: true,\n })\n\n const query: Record<string, string> = {}\n if (options.limit) {\n query.limit = options.limit.toString()\n }\n\n if (options.after) {\n query.after = options.after\n }\n\n if (options.before) {\n query.before = options.before\n }\n\n return client.request({\n query,\n url: `/projects/${options.projectId}/datasets/${options.datasetName}/backups`,\n })\n}\n\nexport async function getBackupDetails(options: {\n backupId: string\n datasetName: string\n nextCursor?: string\n projectId: string\n}): Promise<BackupDetailsResponse> {\n const client = await getGlobalCliClient({\n apiVersion: BACKUP_API_VERSION,\n requireUser: true,\n })\n\n const query: Record<string, string> = {}\n if (options.nextCursor) {\n query.nextCursor = options.nextCursor\n }\n\n return client.request({\n query,\n url: `/projects/${options.projectId}/datasets/${options.datasetName}/backups/${options.backupId}`,\n })\n}\n\ninterface SetBackupOptions {\n dataset: string\n projectId: string\n status: boolean\n}\n\nexport async function setBackup({dataset, projectId, status}: SetBackupOptions) {\n const client = await getGlobalCliClient({\n apiVersion: BACKUP_API_VERSION,\n requireUser: true,\n })\n\n return client.request({\n body: {\n enabled: status,\n },\n method: 'PUT',\n url: `/projects/${projectId}/datasets/${dataset}/settings/backups`,\n })\n}\n"],"names":["getGlobalCliClient","BACKUP_API_VERSION","listBackups","options","client","apiVersion","requireUser","query","limit","toString","after","before","request","url","projectId","datasetName","getBackupDetails","nextCursor","backupId","setBackup","dataset","status","body","enabled","method"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,mBAAkB;AAEnD,SAAQC,kBAAkB,QAAO,iCAAgC;AAuBjE,OAAO,eAAeC,YAAYC,OAMjC;IACC,MAAMC,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYJ;QACZK,aAAa;IACf;IAEA,MAAMC,QAAgC,CAAC;IACvC,IAAIJ,QAAQK,KAAK,EAAE;QACjBD,MAAMC,KAAK,GAAGL,QAAQK,KAAK,CAACC,QAAQ;IACtC;IAEA,IAAIN,QAAQO,KAAK,EAAE;QACjBH,MAAMG,KAAK,GAAGP,QAAQO,KAAK;IAC7B;IAEA,IAAIP,QAAQQ,MAAM,EAAE;QAClBJ,MAAMI,MAAM,GAAGR,QAAQQ,MAAM;IAC/B;IAEA,OAAOP,OAAOQ,OAAO,CAAC;QACpBL;QACAM,KAAK,CAAC,UAAU,EAAEV,QAAQW,SAAS,CAAC,UAAU,EAAEX,QAAQY,WAAW,CAAC,QAAQ,CAAC;IAC/E;AACF;AAEA,OAAO,eAAeC,iBAAiBb,OAKtC;IACC,MAAMC,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYJ;QACZK,aAAa;IACf;IAEA,MAAMC,QAAgC,CAAC;IACvC,IAAIJ,QAAQc,UAAU,EAAE;QACtBV,MAAMU,UAAU,GAAGd,QAAQc,UAAU;IACvC;IAEA,OAAOb,OAAOQ,OAAO,CAAC;QACpBL;QACAM,KAAK,CAAC,UAAU,EAAEV,QAAQW,SAAS,CAAC,UAAU,EAAEX,QAAQY,WAAW,CAAC,SAAS,EAAEZ,QAAQe,QAAQ,EAAE;IACnG;AACF;AAQA,OAAO,eAAeC,UAAU,EAACC,OAAO,EAAEN,SAAS,EAAEO,MAAM,EAAmB;IAC5E,MAAMjB,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYJ;QACZK,aAAa;IACf;IAEA,OAAOF,OAAOQ,OAAO,CAAC;QACpBU,MAAM;YACJC,SAASF;QACX;QACAG,QAAQ;QACRX,KAAK,CAAC,UAAU,EAAEC,UAAU,UAAU,EAAEM,QAAQ,iBAAiB,CAAC;IACpE;AACF"}
|
package/dist/services/cors.js
CHANGED
|
@@ -12,7 +12,7 @@ export async function createCorsOrigin({ allowCredentials, origin, projectId })
|
|
|
12
12
|
},
|
|
13
13
|
maxRedirects: 0,
|
|
14
14
|
method: 'POST',
|
|
15
|
-
|
|
15
|
+
url: `/projects/${projectId}/cors`
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
export async function deleteCorsOrigin({ originId, projectId }) {
|
|
@@ -22,7 +22,7 @@ export async function deleteCorsOrigin({ originId, projectId }) {
|
|
|
22
22
|
});
|
|
23
23
|
return client.request({
|
|
24
24
|
method: 'DELETE',
|
|
25
|
-
|
|
25
|
+
url: `/projects/${projectId}/cors/${originId}`
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
export async function listCorsOrigins(projectId) {
|
|
@@ -31,7 +31,7 @@ export async function listCorsOrigins(projectId) {
|
|
|
31
31
|
requireUser: true
|
|
32
32
|
});
|
|
33
33
|
return client.request({
|
|
34
|
-
|
|
34
|
+
url: `/projects/${projectId}/cors`
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/cors.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\n\nexport const CORS_API_VERSION = 'v2025-08-14'\n\ninterface CreateCorsOriginOptions {\n allowCredentials: boolean\n origin: string\n projectId: string\n}\n\nexport async function createCorsOrigin({\n allowCredentials,\n origin,\n projectId,\n}: CreateCorsOriginOptions) {\n const client = await getGlobalCliClient({\n apiVersion: CORS_API_VERSION,\n requireUser: true,\n })\n\n return client.request({\n body: {\n allowCredentials,\n origin,\n },\n maxRedirects: 0,\n method: 'POST',\n
|
|
1
|
+
{"version":3,"sources":["../../src/services/cors.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\n\nexport const CORS_API_VERSION = 'v2025-08-14'\n\ninterface CreateCorsOriginOptions {\n allowCredentials: boolean\n origin: string\n projectId: string\n}\n\nexport async function createCorsOrigin({\n allowCredentials,\n origin,\n projectId,\n}: CreateCorsOriginOptions) {\n const client = await getGlobalCliClient({\n apiVersion: CORS_API_VERSION,\n requireUser: true,\n })\n\n return client.request({\n body: {\n allowCredentials,\n origin,\n },\n maxRedirects: 0,\n method: 'POST',\n url: `/projects/${projectId}/cors`,\n })\n}\n\ninterface DeleteCorsOriginOptions {\n originId: number\n projectId: string\n}\n\nexport async function deleteCorsOrigin({originId, projectId}: DeleteCorsOriginOptions) {\n const client = await getGlobalCliClient({\n apiVersion: CORS_API_VERSION,\n requireUser: true,\n })\n\n return client.request({\n method: 'DELETE',\n url: `/projects/${projectId}/cors/${originId}`,\n })\n}\n\nexport interface CorsOrigin {\n allowCredentials: boolean\n createdAt: string\n deletedAt: string | null\n id: number\n origin: string\n projectId: string\n updatedAt: string | null\n}\n\nexport async function listCorsOrigins(projectId: string) {\n const client = await getGlobalCliClient({\n apiVersion: CORS_API_VERSION,\n requireUser: true,\n })\n\n return client.request<CorsOrigin[]>({url: `/projects/${projectId}/cors`})\n}\n"],"names":["getGlobalCliClient","CORS_API_VERSION","createCorsOrigin","allowCredentials","origin","projectId","client","apiVersion","requireUser","request","body","maxRedirects","method","url","deleteCorsOrigin","originId","listCorsOrigins"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,mBAAkB;AAEnD,OAAO,MAAMC,mBAAmB,cAAa;AAQ7C,OAAO,eAAeC,iBAAiB,EACrCC,gBAAgB,EAChBC,MAAM,EACNC,SAAS,EACe;IACxB,MAAMC,SAAS,MAAMN,mBAAmB;QACtCO,YAAYN;QACZO,aAAa;IACf;IAEA,OAAOF,OAAOG,OAAO,CAAC;QACpBC,MAAM;YACJP;YACAC;QACF;QACAO,cAAc;QACdC,QAAQ;QACRC,KAAK,CAAC,UAAU,EAAER,UAAU,KAAK,CAAC;IACpC;AACF;AAOA,OAAO,eAAeS,iBAAiB,EAACC,QAAQ,EAAEV,SAAS,EAA0B;IACnF,MAAMC,SAAS,MAAMN,mBAAmB;QACtCO,YAAYN;QACZO,aAAa;IACf;IAEA,OAAOF,OAAOG,OAAO,CAAC;QACpBG,QAAQ;QACRC,KAAK,CAAC,UAAU,EAAER,UAAU,MAAM,EAAEU,UAAU;IAChD;AACF;AAYA,OAAO,eAAeC,gBAAgBX,SAAiB;IACrD,MAAMC,SAAS,MAAMN,mBAAmB;QACtCO,YAAYN;QACZO,aAAa;IACf;IAEA,OAAOF,OAAOG,OAAO,CAAe;QAACI,KAAK,CAAC,UAAU,EAAER,UAAU,KAAK,CAAC;IAAA;AACzE"}
|
|
@@ -11,7 +11,7 @@ const getAliasClient = async (projectId)=>{
|
|
|
11
11
|
export async function listAliases(projectId) {
|
|
12
12
|
const client = await getAliasClient(projectId);
|
|
13
13
|
return client.request({
|
|
14
|
-
|
|
14
|
+
url: '/aliases'
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
export async function createAlias(projectId, aliasName, datasetName) {
|
|
@@ -21,7 +21,7 @@ export async function createAlias(projectId, aliasName, datasetName) {
|
|
|
21
21
|
datasetName
|
|
22
22
|
} : undefined,
|
|
23
23
|
method: 'PUT',
|
|
24
|
-
|
|
24
|
+
url: `/aliases/${aliasName}`
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
@@ -37,7 +37,7 @@ export async function createAlias(projectId, aliasName, datasetName) {
|
|
|
37
37
|
datasetName
|
|
38
38
|
},
|
|
39
39
|
method: 'PATCH',
|
|
40
|
-
|
|
40
|
+
url: `/aliases/${aliasName}`
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
@@ -50,14 +50,14 @@ export async function createAlias(projectId, aliasName, datasetName) {
|
|
|
50
50
|
return client.request({
|
|
51
51
|
body: {},
|
|
52
52
|
method: 'PATCH',
|
|
53
|
-
|
|
53
|
+
url: `/aliases/${aliasName}/unlink`
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
export async function removeAlias(projectId, aliasName) {
|
|
57
57
|
const client = await getAliasClient(projectId);
|
|
58
58
|
return client.request({
|
|
59
59
|
method: 'DELETE',
|
|
60
|
-
|
|
60
|
+
url: `/aliases/${aliasName}`
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/datasetAliases.ts"],"sourcesContent":["import {getProjectCliClient} from '@sanity/cli-core'\n\nexport const DATASET_ALIASES_API_VERSION = 'v2025-09-16'\nexport const ALIAS_PREFIX = '~'\n\ninterface DatasetAliasDefinition {\n datasetName: string | null\n name: string\n}\n\ninterface DatasetModificationResponse {\n aliasName: string\n datasetName: string | null\n}\n\nconst getAliasClient = async (projectId: string) => {\n return getProjectCliClient({\n apiVersion: DATASET_ALIASES_API_VERSION,\n projectId,\n requireUser: true,\n })\n}\n\nexport async function listAliases(projectId: string): Promise<DatasetAliasDefinition[]> {\n const client = await getAliasClient(projectId)\n return client.request<DatasetAliasDefinition[]>({
|
|
1
|
+
{"version":3,"sources":["../../src/services/datasetAliases.ts"],"sourcesContent":["import {getProjectCliClient} from '@sanity/cli-core'\n\nexport const DATASET_ALIASES_API_VERSION = 'v2025-09-16'\nexport const ALIAS_PREFIX = '~'\n\ninterface DatasetAliasDefinition {\n datasetName: string | null\n name: string\n}\n\ninterface DatasetModificationResponse {\n aliasName: string\n datasetName: string | null\n}\n\nconst getAliasClient = async (projectId: string) => {\n return getProjectCliClient({\n apiVersion: DATASET_ALIASES_API_VERSION,\n projectId,\n requireUser: true,\n })\n}\n\nexport async function listAliases(projectId: string): Promise<DatasetAliasDefinition[]> {\n const client = await getAliasClient(projectId)\n return client.request<DatasetAliasDefinition[]>({url: '/aliases'})\n}\n\nexport async function createAlias(\n projectId: string,\n aliasName: string,\n datasetName: string | null,\n): Promise<DatasetModificationResponse> {\n const client = await getAliasClient(projectId)\n return client.request({\n body: datasetName ? {datasetName} : undefined,\n method: 'PUT',\n url: `/aliases/${aliasName}`,\n })\n}\n\n/**\n * Updates an existing dataset alias to link to a different dataset\n * @param projectId - The project ID containing the alias\n * @param aliasName - The name of the alias to update (without ~ prefix)\n * @param datasetName - The name of the dataset to link the alias to\n * @returns Promise resolving to the updated alias information\n */\nexport async function updateAlias(\n projectId: string,\n aliasName: string,\n datasetName: string,\n): Promise<DatasetModificationResponse> {\n const client = await getAliasClient(projectId)\n return client.request<DatasetModificationResponse>({\n body: {datasetName},\n method: 'PATCH',\n url: `/aliases/${aliasName}`,\n })\n}\n\n/**\n * Unlinks an existing dataset alias from its dataset\n * @param projectId - The project ID containing the alias\n * @param aliasName - The name of the alias to unlink (without ~ prefix)\n * @returns Promise resolving to the unlink response with dataset name that was unlinked\n */\nexport async function unlinkAlias(\n projectId: string,\n aliasName: string,\n): Promise<DatasetModificationResponse> {\n const client = await getAliasClient(projectId)\n return client.request<DatasetModificationResponse>({\n body: {},\n method: 'PATCH',\n url: `/aliases/${aliasName}/unlink`,\n })\n}\n\nexport async function removeAlias(\n projectId: string,\n aliasName: string,\n): Promise<{deleted: boolean}> {\n const client = await getAliasClient(projectId)\n return client.request<{deleted: boolean}>({\n method: 'DELETE',\n url: `/aliases/${aliasName}`,\n })\n}\n"],"names":["getProjectCliClient","DATASET_ALIASES_API_VERSION","ALIAS_PREFIX","getAliasClient","projectId","apiVersion","requireUser","listAliases","client","request","url","createAlias","aliasName","datasetName","body","undefined","method","updateAlias","unlinkAlias","removeAlias"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,mBAAkB;AAEpD,OAAO,MAAMC,8BAA8B,cAAa;AACxD,OAAO,MAAMC,eAAe,IAAG;AAY/B,MAAMC,iBAAiB,OAAOC;IAC5B,OAAOJ,oBAAoB;QACzBK,YAAYJ;QACZG;QACAE,aAAa;IACf;AACF;AAEA,OAAO,eAAeC,YAAYH,SAAiB;IACjD,MAAMI,SAAS,MAAML,eAAeC;IACpC,OAAOI,OAAOC,OAAO,CAA2B;QAACC,KAAK;IAAU;AAClE;AAEA,OAAO,eAAeC,YACpBP,SAAiB,EACjBQ,SAAiB,EACjBC,WAA0B;IAE1B,MAAML,SAAS,MAAML,eAAeC;IACpC,OAAOI,OAAOC,OAAO,CAAC;QACpBK,MAAMD,cAAc;YAACA;QAAW,IAAIE;QACpCC,QAAQ;QACRN,KAAK,CAAC,SAAS,EAAEE,WAAW;IAC9B;AACF;AAEA;;;;;;CAMC,GACD,OAAO,eAAeK,YACpBb,SAAiB,EACjBQ,SAAiB,EACjBC,WAAmB;IAEnB,MAAML,SAAS,MAAML,eAAeC;IACpC,OAAOI,OAAOC,OAAO,CAA8B;QACjDK,MAAM;YAACD;QAAW;QAClBG,QAAQ;QACRN,KAAK,CAAC,SAAS,EAAEE,WAAW;IAC9B;AACF;AAEA;;;;;CAKC,GACD,OAAO,eAAeM,YACpBd,SAAiB,EACjBQ,SAAiB;IAEjB,MAAMJ,SAAS,MAAML,eAAeC;IACpC,OAAOI,OAAOC,OAAO,CAA8B;QACjDK,MAAM,CAAC;QACPE,QAAQ;QACRN,KAAK,CAAC,SAAS,EAAEE,UAAU,OAAO,CAAC;IACrC;AACF;AAEA,OAAO,eAAeO,YACpBf,SAAiB,EACjBQ,SAAiB;IAEjB,MAAMJ,SAAS,MAAML,eAAeC;IACpC,OAAOI,OAAOC,OAAO,CAAqB;QACxCO,QAAQ;QACRN,KAAK,CAAC,SAAS,EAAEE,WAAW;IAC9B;AACF"}
|
|
@@ -16,7 +16,7 @@ export async function listDatasets(projectId) {
|
|
|
16
16
|
export async function listDatasetAliases(projectId) {
|
|
17
17
|
const client = await getDatasetClient(projectId);
|
|
18
18
|
return client.request({
|
|
19
|
-
|
|
19
|
+
url: '/aliases'
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
export async function deleteDataset({ datasetName, projectId }) {
|
|
@@ -49,7 +49,7 @@ export async function copyDataset({ projectId, skipContentReleases, skipHistory,
|
|
|
49
49
|
targetDataset
|
|
50
50
|
},
|
|
51
51
|
method: 'PUT',
|
|
52
|
-
|
|
52
|
+
url: `/datasets/${sourceDataset}/copy`
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
export async function listDatasetCopyJobs({ limit, offset, projectId }) {
|
|
@@ -64,7 +64,7 @@ export async function listDatasetCopyJobs({ limit, offset, projectId }) {
|
|
|
64
64
|
return client.request({
|
|
65
65
|
method: 'GET',
|
|
66
66
|
query,
|
|
67
|
-
|
|
67
|
+
url: `/projects/${projectId}/datasets/copy`
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
async function getJobListenUrl(projectId, jobId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/datasets.ts"],"sourcesContent":["import {getProjectCliClient} from '@sanity/cli-core'\nimport {\n type DatasetCreateOptions as ClientCreateOptions,\n type DatasetAclMode,\n type EmbeddingsSettingsBody,\n} from '@sanity/client'\nimport {EventSource} from 'eventsource'\nimport {Observable} from 'rxjs'\n\nexport const DATASET_API_VERSION = 'v2025-09-16'\n\nfunction getDatasetClient(projectId: string) {\n return getProjectCliClient({\n apiVersion: DATASET_API_VERSION,\n projectId,\n requireUser: true,\n })\n}\n\nexport async function listDatasets(projectId: string) {\n const client = await getDatasetClient(projectId)\n return client.datasets.list()\n}\n\nexport interface DatasetAliasDefinition {\n datasetName: string | null\n name: string\n}\n\nexport async function listDatasetAliases(projectId: string): Promise<DatasetAliasDefinition[]> {\n const client = await getDatasetClient(projectId)\n return client.request<DatasetAliasDefinition[]>({uri: '/aliases'})\n}\n\ninterface DeleteDatasetOptions {\n datasetName: string\n projectId: string\n}\n\nexport async function deleteDataset({datasetName, projectId}: DeleteDatasetOptions) {\n const client = await getDatasetClient(projectId)\n return client.datasets.delete(datasetName)\n}\n\ninterface EditDatasetAclOptions {\n aclMode: 'private' | 'public'\n datasetName: string\n projectId: string\n}\n\nexport async function editDatasetAcl({aclMode, datasetName, projectId}: EditDatasetAclOptions) {\n const client = await getDatasetClient(projectId)\n return client.datasets.edit(datasetName, {aclMode})\n}\n\ninterface CreateDatasetOptions {\n datasetName: string\n projectId: string\n\n aclMode?: DatasetAclMode\n embeddings?: EmbeddingsSettingsBody\n}\n\nexport async function createDataset({\n aclMode,\n datasetName,\n embeddings,\n projectId,\n}: CreateDatasetOptions) {\n const client = await getDatasetClient(projectId)\n const options: ClientCreateOptions = {}\n\n if (aclMode) {\n options.aclMode = aclMode\n }\n if (embeddings) {\n options.embeddings = embeddings\n }\n\n return client.datasets.create(datasetName, options)\n}\n\ninterface CopyDatasetOptions {\n projectId: string\n skipHistory: boolean\n sourceDataset: string\n targetDataset: string\n\n skipContentReleases?: boolean\n}\n\ninterface CopyDatasetResponse {\n jobId: string\n}\n\nexport async function copyDataset({\n projectId,\n skipContentReleases,\n skipHistory,\n sourceDataset,\n targetDataset,\n}: CopyDatasetOptions): Promise<CopyDatasetResponse> {\n const client = await getDatasetClient(projectId)\n return client.request<CopyDatasetResponse>({\n body: {\n skipContentReleases,\n skipHistory,\n targetDataset,\n },\n method: 'PUT',\n uri: `/datasets/${sourceDataset}/copy`,\n })\n}\n\ninterface ListDatasetCopyJobsOptions {\n projectId: string\n\n limit?: number\n offset?: number\n}\n\nexport interface DatasetCopyJob {\n createdAt: string\n id: string\n sourceDataset: string\n state: string\n targetDataset: string\n updatedAt: string\n withHistory: boolean\n}\n\nexport async function listDatasetCopyJobs({\n limit,\n offset,\n projectId,\n}: ListDatasetCopyJobsOptions): Promise<DatasetCopyJob[]> {\n const client = await getDatasetClient(projectId)\n const query: {limit?: string; offset?: string} = {}\n\n if (offset !== undefined && offset >= 0) {\n query.offset = `${offset}`\n }\n if (limit !== undefined && limit > 0) {\n query.limit = `${limit}`\n }\n\n return client.request<DatasetCopyJob[]>({\n method: 'GET',\n query,\n uri: `/projects/${projectId}/datasets/copy`,\n })\n}\n\nexport interface CopyJobProgressEvent {\n type: 'reconnect' | string\n\n progress?: number\n state?: 'completed' | 'failed' | 'pending' | 'processing'\n}\n\ninterface FollowCopyJobProgressOptions {\n jobId: string\n projectId: string\n}\n\nasync function getJobListenUrl(projectId: string, jobId: string): Promise<string> {\n const client = await getDatasetClient(projectId)\n const baseUrl = client.config().url || 'https://api.sanity.io'\n return `${baseUrl}/jobs/${jobId}/listen`\n}\n\nexport function followCopyJobProgress({\n jobId,\n projectId,\n}: FollowCopyJobProgressOptions): Observable<CopyJobProgressEvent> {\n return new Observable<CopyJobProgressEvent>((observer) => {\n let progressSource: InstanceType<typeof EventSource> | null = null\n let stopped = false\n\n getJobListenUrl(projectId, jobId)\n .then((url) => {\n progressSource = new EventSource(url)\n\n function onError() {\n if (progressSource) {\n progressSource.close()\n progressSource = null\n }\n\n if (stopped) {\n return\n }\n\n observer.next({type: 'reconnect'})\n progressSource = new EventSource(url)\n attachListeners()\n }\n\n function onChannelError(error: MessageEvent) {\n stopped = true\n if (progressSource) {\n progressSource.close()\n progressSource = null\n }\n const errorMessage = error.data\n ? `Copy job failed: ${error.data}`\n : 'Copy job failed: Connection to server lost. Please check the job status using --list and retry if needed.'\n observer.error(new Error(errorMessage))\n }\n\n function onMessage(event: MessageEvent) {\n let data\n try {\n data = JSON.parse(event.data)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error'\n observer.error(new Error(`Invalid JSON received from server: ${message}`))\n return\n }\n\n if (data.state === 'failed') {\n const failureReason = data.message || data.error || 'Unknown reason'\n observer.error(new Error(`Copy job failed: ${failureReason}`))\n } else if (data.state === 'completed') {\n onComplete()\n } else {\n observer.next(data)\n }\n }\n\n function onComplete() {\n if (progressSource) {\n progressSource.removeEventListener('error', onError)\n progressSource.removeEventListener('channel_error', onChannelError)\n progressSource.removeEventListener('job', onMessage)\n progressSource.removeEventListener('done', onComplete)\n progressSource.close()\n progressSource = null\n }\n observer.complete()\n }\n\n function attachListeners() {\n if (progressSource) {\n progressSource.addEventListener('error', onError)\n progressSource.addEventListener('channel_error', onChannelError)\n progressSource.addEventListener('job', onMessage)\n progressSource.addEventListener('done', onComplete)\n }\n }\n\n attachListeners()\n })\n .catch((error) => {\n observer.error(error)\n })\n\n return () => {\n if (stopped) return\n stopped = true\n if (progressSource) {\n progressSource.close()\n progressSource = null\n }\n }\n })\n}\n"],"names":["getProjectCliClient","EventSource","Observable","DATASET_API_VERSION","getDatasetClient","projectId","apiVersion","requireUser","listDatasets","client","datasets","list","listDatasetAliases","request","uri","deleteDataset","datasetName","delete","editDatasetAcl","aclMode","edit","createDataset","embeddings","options","create","copyDataset","skipContentReleases","skipHistory","sourceDataset","targetDataset","body","method","listDatasetCopyJobs","limit","offset","query","undefined","getJobListenUrl","jobId","baseUrl","config","url","followCopyJobProgress","observer","progressSource","stopped","then","onError","close","next","type","attachListeners","onChannelError","error","errorMessage","data","Error","onMessage","event","JSON","parse","message","state","failureReason","onComplete","removeEventListener","complete","addEventListener","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/services/datasets.ts"],"sourcesContent":["import {getProjectCliClient} from '@sanity/cli-core'\nimport {\n type DatasetCreateOptions as ClientCreateOptions,\n type DatasetAclMode,\n type EmbeddingsSettingsBody,\n} from '@sanity/client'\nimport {EventSource} from 'eventsource'\nimport {Observable} from 'rxjs'\n\nexport const DATASET_API_VERSION = 'v2025-09-16'\n\nfunction getDatasetClient(projectId: string) {\n return getProjectCliClient({\n apiVersion: DATASET_API_VERSION,\n projectId,\n requireUser: true,\n })\n}\n\nexport async function listDatasets(projectId: string) {\n const client = await getDatasetClient(projectId)\n return client.datasets.list()\n}\n\nexport interface DatasetAliasDefinition {\n datasetName: string | null\n name: string\n}\n\nexport async function listDatasetAliases(projectId: string): Promise<DatasetAliasDefinition[]> {\n const client = await getDatasetClient(projectId)\n return client.request<DatasetAliasDefinition[]>({url: '/aliases'})\n}\n\ninterface DeleteDatasetOptions {\n datasetName: string\n projectId: string\n}\n\nexport async function deleteDataset({datasetName, projectId}: DeleteDatasetOptions) {\n const client = await getDatasetClient(projectId)\n return client.datasets.delete(datasetName)\n}\n\ninterface EditDatasetAclOptions {\n aclMode: 'private' | 'public'\n datasetName: string\n projectId: string\n}\n\nexport async function editDatasetAcl({aclMode, datasetName, projectId}: EditDatasetAclOptions) {\n const client = await getDatasetClient(projectId)\n return client.datasets.edit(datasetName, {aclMode})\n}\n\ninterface CreateDatasetOptions {\n datasetName: string\n projectId: string\n\n aclMode?: DatasetAclMode\n embeddings?: EmbeddingsSettingsBody\n}\n\nexport async function createDataset({\n aclMode,\n datasetName,\n embeddings,\n projectId,\n}: CreateDatasetOptions) {\n const client = await getDatasetClient(projectId)\n const options: ClientCreateOptions = {}\n\n if (aclMode) {\n options.aclMode = aclMode\n }\n if (embeddings) {\n options.embeddings = embeddings\n }\n\n return client.datasets.create(datasetName, options)\n}\n\ninterface CopyDatasetOptions {\n projectId: string\n skipHistory: boolean\n sourceDataset: string\n targetDataset: string\n\n skipContentReleases?: boolean\n}\n\ninterface CopyDatasetResponse {\n jobId: string\n}\n\nexport async function copyDataset({\n projectId,\n skipContentReleases,\n skipHistory,\n sourceDataset,\n targetDataset,\n}: CopyDatasetOptions): Promise<CopyDatasetResponse> {\n const client = await getDatasetClient(projectId)\n return client.request<CopyDatasetResponse>({\n body: {\n skipContentReleases,\n skipHistory,\n targetDataset,\n },\n method: 'PUT',\n url: `/datasets/${sourceDataset}/copy`,\n })\n}\n\ninterface ListDatasetCopyJobsOptions {\n projectId: string\n\n limit?: number\n offset?: number\n}\n\nexport interface DatasetCopyJob {\n createdAt: string\n id: string\n sourceDataset: string\n state: string\n targetDataset: string\n updatedAt: string\n withHistory: boolean\n}\n\nexport async function listDatasetCopyJobs({\n limit,\n offset,\n projectId,\n}: ListDatasetCopyJobsOptions): Promise<DatasetCopyJob[]> {\n const client = await getDatasetClient(projectId)\n const query: {limit?: string; offset?: string} = {}\n\n if (offset !== undefined && offset >= 0) {\n query.offset = `${offset}`\n }\n if (limit !== undefined && limit > 0) {\n query.limit = `${limit}`\n }\n\n return client.request<DatasetCopyJob[]>({\n method: 'GET',\n query,\n url: `/projects/${projectId}/datasets/copy`,\n })\n}\n\nexport interface CopyJobProgressEvent {\n type: 'reconnect' | string\n\n progress?: number\n state?: 'completed' | 'failed' | 'pending' | 'processing'\n}\n\ninterface FollowCopyJobProgressOptions {\n jobId: string\n projectId: string\n}\n\nasync function getJobListenUrl(projectId: string, jobId: string): Promise<string> {\n const client = await getDatasetClient(projectId)\n const baseUrl = client.config().url || 'https://api.sanity.io'\n return `${baseUrl}/jobs/${jobId}/listen`\n}\n\nexport function followCopyJobProgress({\n jobId,\n projectId,\n}: FollowCopyJobProgressOptions): Observable<CopyJobProgressEvent> {\n return new Observable<CopyJobProgressEvent>((observer) => {\n let progressSource: InstanceType<typeof EventSource> | null = null\n let stopped = false\n\n getJobListenUrl(projectId, jobId)\n .then((url) => {\n progressSource = new EventSource(url)\n\n function onError() {\n if (progressSource) {\n progressSource.close()\n progressSource = null\n }\n\n if (stopped) {\n return\n }\n\n observer.next({type: 'reconnect'})\n progressSource = new EventSource(url)\n attachListeners()\n }\n\n function onChannelError(error: MessageEvent) {\n stopped = true\n if (progressSource) {\n progressSource.close()\n progressSource = null\n }\n const errorMessage = error.data\n ? `Copy job failed: ${error.data}`\n : 'Copy job failed: Connection to server lost. Please check the job status using --list and retry if needed.'\n observer.error(new Error(errorMessage))\n }\n\n function onMessage(event: MessageEvent) {\n let data\n try {\n data = JSON.parse(event.data)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error'\n observer.error(new Error(`Invalid JSON received from server: ${message}`))\n return\n }\n\n if (data.state === 'failed') {\n const failureReason = data.message || data.error || 'Unknown reason'\n observer.error(new Error(`Copy job failed: ${failureReason}`))\n } else if (data.state === 'completed') {\n onComplete()\n } else {\n observer.next(data)\n }\n }\n\n function onComplete() {\n if (progressSource) {\n progressSource.removeEventListener('error', onError)\n progressSource.removeEventListener('channel_error', onChannelError)\n progressSource.removeEventListener('job', onMessage)\n progressSource.removeEventListener('done', onComplete)\n progressSource.close()\n progressSource = null\n }\n observer.complete()\n }\n\n function attachListeners() {\n if (progressSource) {\n progressSource.addEventListener('error', onError)\n progressSource.addEventListener('channel_error', onChannelError)\n progressSource.addEventListener('job', onMessage)\n progressSource.addEventListener('done', onComplete)\n }\n }\n\n attachListeners()\n })\n .catch((error) => {\n observer.error(error)\n })\n\n return () => {\n if (stopped) return\n stopped = true\n if (progressSource) {\n progressSource.close()\n progressSource = null\n }\n }\n })\n}\n"],"names":["getProjectCliClient","EventSource","Observable","DATASET_API_VERSION","getDatasetClient","projectId","apiVersion","requireUser","listDatasets","client","datasets","list","listDatasetAliases","request","url","deleteDataset","datasetName","delete","editDatasetAcl","aclMode","edit","createDataset","embeddings","options","create","copyDataset","skipContentReleases","skipHistory","sourceDataset","targetDataset","body","method","listDatasetCopyJobs","limit","offset","query","undefined","getJobListenUrl","jobId","baseUrl","config","followCopyJobProgress","observer","progressSource","stopped","then","onError","close","next","type","attachListeners","onChannelError","error","errorMessage","data","Error","onMessage","event","JSON","parse","message","state","failureReason","onComplete","removeEventListener","complete","addEventListener","catch"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/documents.ts"],"sourcesContent":["import {getProjectCliClient} from '@sanity/cli-core'\n\nexport const DOCUMENTS_API_VERSION = 'v2021-03-25'\n\n/**\n * Response from the document availability endpoint\n */\nexport interface AvailabilityResponse {\n omitted: {id: string; reason: 'existence' | 'permission'}[]\n}\n\ninterface DocumentsClientOptions {\n dataset: string\n projectId: string\n}\n\nfunction getDocumentsClient({dataset, projectId}: DocumentsClientOptions) {\n return getProjectCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n dataset,\n projectId,\n requireUser: true,\n })\n}\n\ninterface GetDocumentCountOptions {\n dataset: string\n projectId: string\n}\n\n/**\n * Get the total count of documents in the dataset\n */\nexport async function getDocumentCount({\n dataset,\n projectId,\n}: GetDocumentCountOptions): Promise<number> {\n const client = await getDocumentsClient({dataset, projectId})\n return client.fetch('length(*)')\n}\n\ninterface ExportDocumentsOptions {\n dataset: string\n projectId: string\n}\n\n/**\n * Export all documents from the dataset as a streaming response\n */\nexport async function exportDocuments({\n dataset,\n projectId,\n}: ExportDocumentsOptions): Promise<Response> {\n const client = await getDocumentsClient({dataset, projectId})\n const exportUrl = new URL(client.getUrl(`/data/export/${dataset}`, false))\n\n const {token} = client.config()\n const response = await fetch(exportUrl, {\n headers: new Headers({...(token && {Authorization: `Bearer ${token}`})}),\n })\n\n return response\n}\n\ninterface CheckDocumentAvailabilityOptions {\n dataset: string\n documentIds: string[]\n projectId: string\n}\n\n/**\n * Check the availability/existence of documents by their IDs\n */\nexport async function checkDocumentAvailability({\n dataset,\n documentIds,\n projectId,\n}: CheckDocumentAvailabilityOptions): Promise<AvailabilityResponse> {\n const client = await getDocumentsClient({dataset, projectId})\n return client.request<AvailabilityResponse>({\n json: true,\n query: {excludeContent: 'true'},\n tag: 'documents-availability',\n
|
|
1
|
+
{"version":3,"sources":["../../src/services/documents.ts"],"sourcesContent":["import {getProjectCliClient} from '@sanity/cli-core'\n\nexport const DOCUMENTS_API_VERSION = 'v2021-03-25'\n\n/**\n * Response from the document availability endpoint\n */\nexport interface AvailabilityResponse {\n omitted: {id: string; reason: 'existence' | 'permission'}[]\n}\n\ninterface DocumentsClientOptions {\n dataset: string\n projectId: string\n}\n\nfunction getDocumentsClient({dataset, projectId}: DocumentsClientOptions) {\n return getProjectCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n dataset,\n projectId,\n requireUser: true,\n })\n}\n\ninterface GetDocumentCountOptions {\n dataset: string\n projectId: string\n}\n\n/**\n * Get the total count of documents in the dataset\n */\nexport async function getDocumentCount({\n dataset,\n projectId,\n}: GetDocumentCountOptions): Promise<number> {\n const client = await getDocumentsClient({dataset, projectId})\n return client.fetch('length(*)')\n}\n\ninterface ExportDocumentsOptions {\n dataset: string\n projectId: string\n}\n\n/**\n * Export all documents from the dataset as a streaming response\n */\nexport async function exportDocuments({\n dataset,\n projectId,\n}: ExportDocumentsOptions): Promise<Response> {\n const client = await getDocumentsClient({dataset, projectId})\n const exportUrl = new URL(client.getUrl(`/data/export/${dataset}`, false))\n\n const {token} = client.config()\n const response = await fetch(exportUrl, {\n headers: new Headers({...(token && {Authorization: `Bearer ${token}`})}),\n })\n\n return response\n}\n\ninterface CheckDocumentAvailabilityOptions {\n dataset: string\n documentIds: string[]\n projectId: string\n}\n\n/**\n * Check the availability/existence of documents by their IDs\n */\nexport async function checkDocumentAvailability({\n dataset,\n documentIds,\n projectId,\n}: CheckDocumentAvailabilityOptions): Promise<AvailabilityResponse> {\n const client = await getDocumentsClient({dataset, projectId})\n return client.request<AvailabilityResponse>({\n json: true,\n query: {excludeContent: 'true'},\n tag: 'documents-availability',\n url: client.getDataUrl('doc', documentIds.join(',')),\n })\n}\n"],"names":["getProjectCliClient","DOCUMENTS_API_VERSION","getDocumentsClient","dataset","projectId","apiVersion","requireUser","getDocumentCount","client","fetch","exportDocuments","exportUrl","URL","getUrl","token","config","response","headers","Headers","Authorization","checkDocumentAvailability","documentIds","request","json","query","excludeContent","tag","url","getDataUrl","join"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,mBAAkB;AAEpD,OAAO,MAAMC,wBAAwB,cAAa;AAclD,SAASC,mBAAmB,EAACC,OAAO,EAAEC,SAAS,EAAyB;IACtE,OAAOJ,oBAAoB;QACzBK,YAAYJ;QACZE;QACAC;QACAE,aAAa;IACf;AACF;AAOA;;CAEC,GACD,OAAO,eAAeC,iBAAiB,EACrCJ,OAAO,EACPC,SAAS,EACe;IACxB,MAAMI,SAAS,MAAMN,mBAAmB;QAACC;QAASC;IAAS;IAC3D,OAAOI,OAAOC,KAAK,CAAC;AACtB;AAOA;;CAEC,GACD,OAAO,eAAeC,gBAAgB,EACpCP,OAAO,EACPC,SAAS,EACc;IACvB,MAAMI,SAAS,MAAMN,mBAAmB;QAACC;QAASC;IAAS;IAC3D,MAAMO,YAAY,IAAIC,IAAIJ,OAAOK,MAAM,CAAC,CAAC,aAAa,EAAEV,SAAS,EAAE;IAEnE,MAAM,EAACW,KAAK,EAAC,GAAGN,OAAOO,MAAM;IAC7B,MAAMC,WAAW,MAAMP,MAAME,WAAW;QACtCM,SAAS,IAAIC,QAAQ;YAAC,GAAIJ,SAAS;gBAACK,eAAe,CAAC,OAAO,EAAEL,OAAO;YAAA,CAAC;QAAC;IACxE;IAEA,OAAOE;AACT;AAQA;;CAEC,GACD,OAAO,eAAeI,0BAA0B,EAC9CjB,OAAO,EACPkB,WAAW,EACXjB,SAAS,EACwB;IACjC,MAAMI,SAAS,MAAMN,mBAAmB;QAACC;QAASC;IAAS;IAC3D,OAAOI,OAAOc,OAAO,CAAuB;QAC1CC,MAAM;QACNC,OAAO;YAACC,gBAAgB;QAAM;QAC9BC,KAAK;QACLC,KAAKnB,OAAOoB,UAAU,CAAC,OAAOP,YAAYQ,IAAI,CAAC;IACjD;AACF"}
|