@payloadcms/figma 0.1.0-alpha.2 → 0.1.0-alpha.4
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/api/check-project-subdomain-availability.d.ts +12 -0
- package/dist/api/check-project-subdomain-availability.js +32 -0
- package/dist/api/control-plane-error.d.ts +6 -0
- package/dist/api/control-plane-error.js +8 -0
- package/dist/api/control-plane-fetch.d.ts +7 -0
- package/dist/api/control-plane-fetch.js +37 -0
- package/dist/api/control-plane.d.ts +1 -9
- package/dist/api/control-plane.js +2 -48
- package/dist/api/create-project.d.ts +18 -0
- package/dist/api/create-project.js +37 -0
- package/dist/api/list-project-workspaces.d.ts +8 -0
- package/dist/api/list-project-workspaces.js +28 -0
- package/dist/api/project-resource-type.d.ts +1 -0
- package/dist/api/project-resource-type.js +1 -0
- package/dist/auth/headless-oauth-flow.d.ts +23 -0
- package/dist/auth/headless-oauth-flow.js +69 -0
- package/dist/auth/oauth-flow.d.ts +2 -0
- package/dist/auth/oauth-flow.js +13 -8
- package/dist/auth/token-store.d.ts +4 -1
- package/dist/auth/token-store.js +14 -0
- package/dist/auth/types.d.ts +12 -0
- package/dist/cli.d.ts +39 -0
- package/dist/cli.js +71 -36
- package/dist/commands/bootstrap.js +2 -1
- package/dist/commands/deploy.d.ts +12 -0
- package/dist/commands/deploy.js +61 -23
- package/dist/commands/detect-project-resource-type.d.ts +3 -0
- package/dist/commands/detect-project-resource-type.js +28 -0
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.js +163 -78
- package/dist/commands/login.d.ts +11 -1
- package/dist/commands/login.js +66 -4
- package/dist/commands/prompt-to-create-project/format-project-subdomain.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/format-project-subdomain.js +3 -0
- package/dist/commands/prompt-to-create-project/format-unavailable-subdomain-reason.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/format-unavailable-subdomain-reason.js +7 -0
- package/dist/commands/prompt-to-create-project/get-default-project-name.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/get-default-project-name.js +13 -0
- package/dist/commands/prompt-to-create-project/prompt-for-available-subdomain.d.ts +7 -0
- package/dist/commands/prompt-to-create-project/prompt-for-available-subdomain.js +32 -0
- package/dist/commands/prompt-to-create-project/resolve-project-region.d.ts +8 -0
- package/dist/commands/prompt-to-create-project/resolve-project-region.js +27 -0
- package/dist/commands/prompt-to-create-project/resolve-project-subdomain.d.ts +9 -0
- package/dist/commands/prompt-to-create-project/resolve-project-subdomain.js +54 -0
- package/dist/commands/prompt-to-create-project/resolve-text-input.d.ts +9 -0
- package/dist/commands/prompt-to-create-project/resolve-text-input.js +23 -0
- package/dist/commands/prompt-to-create-project/resolve-workspace-plan-key.d.ts +12 -0
- package/dist/commands/prompt-to-create-project/resolve-workspace-plan-key.js +36 -0
- package/dist/commands/prompt-to-create-project/validate-subdomain.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/validate-subdomain.js +9 -0
- package/dist/commands/prompt-to-create-project.d.ts +24 -0
- package/dist/commands/prompt-to-create-project.js +69 -0
- package/dist/commands/setup-agent.d.ts +12 -0
- package/dist/commands/setup-agent.js +123 -0
- package/dist/commands/write-project-configuration.d.ts +12 -0
- package/dist/commands/write-project-configuration.js +16 -0
- package/dist/db-content-api/index.d.ts +1 -1
- package/dist/db-content-api/index.js +90 -55
- package/dist/db-content-api/utilities/data/injectGlobalType.d.ts +6 -0
- package/dist/db-content-api/utilities/data/injectGlobalType.js +11 -0
- package/dist/db-content-api/utilities/data/stringifyNumericIds.d.ts +1 -0
- package/dist/db-content-api/utilities/data/stringifyNumericIds.js +19 -0
- package/dist/db-content-api/utilities/isRecord.d.ts +9 -0
- package/dist/db-content-api/utilities/isRecord.js +19 -0
- package/dist/db-content-api/utilities/schema/getDocumentSchema.d.ts +3 -0
- package/dist/db-content-api/utilities/schema/getDocumentSchema.js +24 -0
- package/dist/db-content-api/utilities/where.js +6 -4
- package/dist/exports/client.d.ts +2 -0
- package/dist/exports/client.js +2 -0
- package/dist/lib/write-agent-config.d.ts +12 -0
- package/dist/lib/write-agent-config.js +52 -0
- package/dist/plugin/build-config.js +32 -3
- package/dist/plugin/cloud-limits/CloudLimitModal/index.d.ts +9 -0
- package/dist/plugin/cloud-limits/CloudLimitModal/index.js +78 -0
- package/dist/plugin/cloud-limits/CloudLimitModal/index.scss +51 -0
- package/dist/plugin/cloud-limits/CloudLimitProvider/index.d.ts +7 -0
- package/dist/plugin/cloud-limits/CloudLimitProvider/index.js +169 -0
- package/dist/plugin/cloud-limits/SlugRegistryContext/index.d.ts +2 -0
- package/dist/plugin/cloud-limits/SlugRegistryContext/index.js +3 -0
- package/dist/plugin/cloud-limits/SlugTracker/index.d.ts +9 -0
- package/dist/plugin/cloud-limits/SlugTracker/index.js +23 -0
- package/dist/plugin/cloud-limits/icons/ExternalLinkIcon.d.ts +2 -0
- package/dist/plugin/cloud-limits/icons/ExternalLinkIcon.js +30 -0
- package/dist/plugin/cloud-limits/shared.d.ts +10 -0
- package/dist/plugin/cloud-limits/shared.js +27 -0
- package/dist/skills/deploy-to-figma/SKILL.md +234 -0
- package/dist/skills/deploy-to-figma/references/cli-reference.md +146 -0
- package/dist/translations/ar.d.ts +12 -0
- package/dist/translations/ar.js +12 -0
- package/dist/translations/az.d.ts +12 -0
- package/dist/translations/az.js +12 -0
- package/dist/translations/bg.d.ts +12 -0
- package/dist/translations/bg.js +12 -0
- package/dist/translations/bnBd.d.ts +12 -0
- package/dist/translations/bnBd.js +12 -0
- package/dist/translations/bnIn.d.ts +12 -0
- package/dist/translations/bnIn.js +12 -0
- package/dist/translations/ca.d.ts +12 -0
- package/dist/translations/ca.js +12 -0
- package/dist/translations/cs.d.ts +12 -0
- package/dist/translations/cs.js +12 -0
- package/dist/translations/da.d.ts +12 -0
- package/dist/translations/da.js +12 -0
- package/dist/translations/de.d.ts +12 -0
- package/dist/translations/de.js +12 -0
- package/dist/translations/en.d.ts +12 -0
- package/dist/translations/en.js +12 -0
- package/dist/translations/es.d.ts +12 -0
- package/dist/translations/es.js +12 -0
- package/dist/translations/et.d.ts +12 -0
- package/dist/translations/et.js +12 -0
- package/dist/translations/fa.d.ts +12 -0
- package/dist/translations/fa.js +12 -0
- package/dist/translations/fr.d.ts +12 -0
- package/dist/translations/fr.js +12 -0
- package/dist/translations/he.d.ts +12 -0
- package/dist/translations/he.js +12 -0
- package/dist/translations/hr.d.ts +12 -0
- package/dist/translations/hr.js +12 -0
- package/dist/translations/hu.d.ts +12 -0
- package/dist/translations/hu.js +12 -0
- package/dist/translations/hy.d.ts +12 -0
- package/dist/translations/hy.js +12 -0
- package/dist/translations/id.d.ts +12 -0
- package/dist/translations/id.js +12 -0
- package/dist/translations/index.d.ts +533 -0
- package/dist/translations/index.js +90 -0
- package/dist/translations/is.d.ts +12 -0
- package/dist/translations/is.js +12 -0
- package/dist/translations/it.d.ts +12 -0
- package/dist/translations/it.js +12 -0
- package/dist/translations/ja.d.ts +12 -0
- package/dist/translations/ja.js +12 -0
- package/dist/translations/ko.d.ts +12 -0
- package/dist/translations/ko.js +12 -0
- package/dist/translations/lt.d.ts +12 -0
- package/dist/translations/lt.js +12 -0
- package/dist/translations/lv.d.ts +12 -0
- package/dist/translations/lv.js +12 -0
- package/dist/translations/my.d.ts +12 -0
- package/dist/translations/my.js +12 -0
- package/dist/translations/nb.d.ts +12 -0
- package/dist/translations/nb.js +12 -0
- package/dist/translations/nl.d.ts +12 -0
- package/dist/translations/nl.js +12 -0
- package/dist/translations/pl.d.ts +12 -0
- package/dist/translations/pl.js +12 -0
- package/dist/translations/pt.d.ts +12 -0
- package/dist/translations/pt.js +12 -0
- package/dist/translations/ro.d.ts +12 -0
- package/dist/translations/ro.js +12 -0
- package/dist/translations/rs.d.ts +12 -0
- package/dist/translations/rs.js +12 -0
- package/dist/translations/rsLatin.d.ts +12 -0
- package/dist/translations/rsLatin.js +12 -0
- package/dist/translations/ru.d.ts +12 -0
- package/dist/translations/ru.js +12 -0
- package/dist/translations/sk.d.ts +12 -0
- package/dist/translations/sk.js +12 -0
- package/dist/translations/sl.d.ts +12 -0
- package/dist/translations/sl.js +12 -0
- package/dist/translations/sv.d.ts +12 -0
- package/dist/translations/sv.js +12 -0
- package/dist/translations/ta.d.ts +12 -0
- package/dist/translations/ta.js +12 -0
- package/dist/translations/th.d.ts +12 -0
- package/dist/translations/th.js +12 -0
- package/dist/translations/tr.d.ts +12 -0
- package/dist/translations/tr.js +12 -0
- package/dist/translations/uk.d.ts +12 -0
- package/dist/translations/uk.js +12 -0
- package/dist/translations/vi.d.ts +12 -0
- package/dist/translations/vi.js +12 -0
- package/dist/translations/zh.d.ts +12 -0
- package/dist/translations/zh.js +12 -0
- package/dist/translations/zhTw.d.ts +12 -0
- package/dist/translations/zhTw.js +12 -0
- package/dist/types.d.ts +11 -0
- package/dist/utils/adapters/nextjs.d.ts +3 -3
- package/dist/utils/adapters/nextjs.js +9 -7
- package/dist/utils/adapters/nitro.d.ts +3 -3
- package/dist/utils/adapters/nitro.js +73 -77
- package/dist/utils/adapters/vite.d.ts +1 -1
- package/dist/utils/adapters/vite.js +8 -7
- package/dist/utils/assert-never.d.ts +1 -0
- package/dist/utils/assert-never.js +3 -0
- package/dist/utils/asset-collection.d.ts +2 -2
- package/dist/utils/asset-collection.js +10 -15
- package/dist/utils/build-detection.d.ts +6 -1
- package/dist/utils/build-detection.js +68 -89
- package/dist/utils/build-lambda-zip.d.ts +5 -6
- package/dist/utils/build-lambda-zip.js +31 -48
- package/dist/utils/deploy-adapter.d.ts +4 -4
- package/dist/utils/deploy-adapter.js +12 -8
- package/dist/utils/deploy-output/inspectNextjsOutput/getNextRelativeAppDir.d.ts +1 -0
- package/dist/utils/deploy-output/inspectNextjsOutput/getNextRelativeAppDir.js +15 -0
- package/dist/utils/deploy-output/inspectNextjsOutput.d.ts +12 -0
- package/dist/utils/deploy-output/inspectNextjsOutput.js +28 -0
- package/dist/utils/deploy-output/inspectNitroOutput.d.ts +9 -0
- package/dist/utils/deploy-output/inspectNitroOutput.js +13 -0
- package/dist/utils/deploy-output/isFile.d.ts +1 -0
- package/dist/utils/deploy-output/isFile.js +4 -0
- package/dist/utils/deploy-output/readJson.d.ts +1 -0
- package/dist/utils/deploy-output/readJson.js +9 -0
- package/dist/utils/deploy-output/resolveNitroOutputLayout.d.ts +8 -0
- package/dist/utils/deploy-output/resolveNitroOutputLayout.js +16 -0
- package/dist/utils/deploy-output/resolveOutputPath.d.ts +2 -0
- package/dist/utils/deploy-output/resolveOutputPath.js +9 -0
- package/dist/utils/deploy-output/resolveWithin.d.ts +1 -0
- package/dist/utils/deploy-output/resolveWithin.js +12 -0
- package/dist/utils/lambda-config.js +4 -14
- package/dist/utils/messages.js +24 -3
- package/dist/utils/payload-generate.d.ts +10 -0
- package/dist/utils/payload-generate.js +59 -0
- package/dist/utils/pnpm-builds.d.ts +14 -0
- package/dist/utils/pnpm-builds.js +125 -0
- package/package.json +6 -5
- package/dist/lib/download-skill.d.ts +0 -12
- package/dist/lib/download-skill.js +0 -77
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
export async function resolveTextInput({ fieldName, initialValue, message, nonInteractive, value }) {
|
|
3
|
+
if (value !== undefined) {
|
|
4
|
+
const trimmedValue = value.trim();
|
|
5
|
+
if (!trimmedValue) {
|
|
6
|
+
throw new Error(`${fieldName} is required`);
|
|
7
|
+
}
|
|
8
|
+
return trimmedValue;
|
|
9
|
+
}
|
|
10
|
+
if (nonInteractive) {
|
|
11
|
+
return initialValue;
|
|
12
|
+
}
|
|
13
|
+
const promptedValue = await p.text({
|
|
14
|
+
initialValue,
|
|
15
|
+
message,
|
|
16
|
+
validate: (candidate)=>candidate?.trim() ? undefined : `${fieldName} is required`
|
|
17
|
+
});
|
|
18
|
+
if (p.isCancel(promptedValue)) {
|
|
19
|
+
p.cancel('Operation cancelled');
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
return promptedValue.trim();
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface ProjectWorkspace {
|
|
2
|
+
isDefault: boolean;
|
|
3
|
+
name: string;
|
|
4
|
+
planKey: string;
|
|
5
|
+
}
|
|
6
|
+
interface ResolveWorkspacePlanKeyArgs {
|
|
7
|
+
nonInteractive?: boolean;
|
|
8
|
+
value?: string;
|
|
9
|
+
workspaces: ProjectWorkspace[];
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveWorkspacePlanKey({ nonInteractive, value, workspaces, }: ResolveWorkspacePlanKeyArgs): Promise<string>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
export async function resolveWorkspacePlanKey({ nonInteractive, value, workspaces }) {
|
|
3
|
+
if (value !== undefined) {
|
|
4
|
+
const planKey = value.trim();
|
|
5
|
+
const workspace = workspaces.find((candidate)=>candidate.planKey === planKey);
|
|
6
|
+
if (!workspace) {
|
|
7
|
+
throw new Error(`Workspace plan key "${planKey}" is not eligible. Available: ${formatWorkspaces(workspaces)}`);
|
|
8
|
+
}
|
|
9
|
+
return workspace.planKey;
|
|
10
|
+
}
|
|
11
|
+
if (workspaces.length === 1) {
|
|
12
|
+
return workspaces[0].planKey;
|
|
13
|
+
}
|
|
14
|
+
if (nonInteractive) {
|
|
15
|
+
const defaultWorkspace = workspaces.find((workspace)=>workspace.isDefault);
|
|
16
|
+
if (defaultWorkspace) {
|
|
17
|
+
return defaultWorkspace.planKey;
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`Multiple eligible Figma workspaces. Pass --workspace <plan-key>. Available: ${formatWorkspaces(workspaces)}`);
|
|
20
|
+
}
|
|
21
|
+
const selectedWorkspacePlanKey = await p.select({
|
|
22
|
+
message: 'Select a Figma workspace:',
|
|
23
|
+
options: workspaces.map((workspace)=>({
|
|
24
|
+
label: workspace.name,
|
|
25
|
+
value: workspace.planKey
|
|
26
|
+
}))
|
|
27
|
+
});
|
|
28
|
+
if (p.isCancel(selectedWorkspacePlanKey)) {
|
|
29
|
+
p.cancel('Operation cancelled');
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
return selectedWorkspacePlanKey;
|
|
33
|
+
}
|
|
34
|
+
function formatWorkspaces(workspaces) {
|
|
35
|
+
return workspaces.map((workspace)=>`${workspace.name} (${workspace.planKey})`).join(', ');
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function validateSubdomain(value: string | undefined): "Subdomain is required" | "Use 1–60 lowercase letters, numbers, or hyphens" | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ProjectResourceType } from '../api/project-resource-type.js';
|
|
2
|
+
import type { AuthCredential } from '../auth/credentials.js';
|
|
3
|
+
interface ProjectCreationInputs {
|
|
4
|
+
description?: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
region?: string;
|
|
7
|
+
subdomain?: string;
|
|
8
|
+
workspacePlanKey?: string;
|
|
9
|
+
}
|
|
10
|
+
interface PromptToCreateProjectArgs {
|
|
11
|
+
credential: AuthCredential;
|
|
12
|
+
inputs?: ProjectCreationInputs;
|
|
13
|
+
nonInteractive?: boolean;
|
|
14
|
+
projectPath: string;
|
|
15
|
+
resourceType: ProjectResourceType;
|
|
16
|
+
}
|
|
17
|
+
interface PromptToCreateProjectResponse {
|
|
18
|
+
domainName: string;
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
/** Prompt for required project fields and create a blank Figma CMS project. */
|
|
23
|
+
export declare function promptToCreateProject({ credential, inputs, nonInteractive, projectPath, resourceType, }: PromptToCreateProjectArgs): Promise<PromptToCreateProjectResponse>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
import { createProject } from '../api/create-project.js';
|
|
4
|
+
import { listProjectWorkspaces } from '../api/list-project-workspaces.js';
|
|
5
|
+
import { formatProjectSubdomain } from './prompt-to-create-project/format-project-subdomain.js';
|
|
6
|
+
import { getDefaultProjectName } from './prompt-to-create-project/get-default-project-name.js';
|
|
7
|
+
import { resolveProjectRegion } from './prompt-to-create-project/resolve-project-region.js';
|
|
8
|
+
import { resolveProjectSubdomain } from './prompt-to-create-project/resolve-project-subdomain.js';
|
|
9
|
+
import { resolveTextInput } from './prompt-to-create-project/resolve-text-input.js';
|
|
10
|
+
import { resolveWorkspacePlanKey } from './prompt-to-create-project/resolve-workspace-plan-key.js';
|
|
11
|
+
/** Prompt for required project fields and create a blank Figma CMS project. */ export async function promptToCreateProject({ credential, inputs, nonInteractive, projectPath, resourceType }) {
|
|
12
|
+
const workspaces = await listProjectWorkspaces(credential);
|
|
13
|
+
if (workspaces.length === 0) {
|
|
14
|
+
if (nonInteractive) {
|
|
15
|
+
throw new Error('No eligible Figma workspaces found.');
|
|
16
|
+
}
|
|
17
|
+
p.log.error(pc.red('No eligible Figma workspaces found.'));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const defaultProjectName = await getDefaultProjectName(projectPath);
|
|
21
|
+
const projectName = await resolveTextInput({
|
|
22
|
+
fieldName: 'Project name',
|
|
23
|
+
initialValue: defaultProjectName,
|
|
24
|
+
message: 'Project name:',
|
|
25
|
+
nonInteractive,
|
|
26
|
+
value: inputs?.name
|
|
27
|
+
});
|
|
28
|
+
const projectDescription = await resolveTextInput({
|
|
29
|
+
fieldName: 'Description',
|
|
30
|
+
initialValue: `${projectName} project`,
|
|
31
|
+
message: 'Project description:',
|
|
32
|
+
nonInteractive,
|
|
33
|
+
value: inputs?.description
|
|
34
|
+
});
|
|
35
|
+
const projectSubdomain = await resolveProjectSubdomain({
|
|
36
|
+
credential,
|
|
37
|
+
initialValue: formatProjectSubdomain(projectName),
|
|
38
|
+
nonInteractive,
|
|
39
|
+
value: inputs?.subdomain
|
|
40
|
+
});
|
|
41
|
+
const parentPlanKey = await resolveWorkspacePlanKey({
|
|
42
|
+
nonInteractive,
|
|
43
|
+
value: inputs?.workspacePlanKey,
|
|
44
|
+
workspaces
|
|
45
|
+
});
|
|
46
|
+
const region = await resolveProjectRegion({
|
|
47
|
+
nonInteractive,
|
|
48
|
+
resourceType,
|
|
49
|
+
value: inputs?.region
|
|
50
|
+
});
|
|
51
|
+
const spinner = p.spinner();
|
|
52
|
+
spinner.start('Creating Figma project...');
|
|
53
|
+
try {
|
|
54
|
+
const project = await createProject({
|
|
55
|
+
name: projectName,
|
|
56
|
+
credential,
|
|
57
|
+
description: projectDescription,
|
|
58
|
+
parentPlanKey,
|
|
59
|
+
region,
|
|
60
|
+
resourceType,
|
|
61
|
+
subdomain: projectSubdomain
|
|
62
|
+
});
|
|
63
|
+
spinner.stop(pc.green(`✓ Project created: ${project.domainName}`));
|
|
64
|
+
return project;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
spinner.stop(pc.red('✗ Failed to create project'));
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SetupAgentOptions {
|
|
2
|
+
global?: boolean;
|
|
3
|
+
project?: boolean;
|
|
4
|
+
yes?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/** Install or update the bundled deploy skill through the standard skills CLI. */
|
|
7
|
+
export declare function setupAgentCommand(options: SetupAgentOptions, dependencies?: {
|
|
8
|
+
homeDir?: string;
|
|
9
|
+
isTTY?: boolean;
|
|
10
|
+
projectDir?: string;
|
|
11
|
+
skillDir?: string;
|
|
12
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import spawn from 'cross-spawn';
|
|
3
|
+
import crypto from 'node:crypto';
|
|
4
|
+
import fs from 'node:fs/promises';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
const SKILL_NAME = 'deploy-to-figma';
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const SKILLS_CLI_PATH = require.resolve('skills/bin/cli.mjs');
|
|
11
|
+
/** Install or update the bundled deploy skill through the standard skills CLI. */ export async function setupAgentCommand(options, dependencies = {}) {
|
|
12
|
+
if (options.global && options.project) {
|
|
13
|
+
throw new Error('Use either --global or --project, not both.');
|
|
14
|
+
}
|
|
15
|
+
const isTTY = dependencies.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
16
|
+
const scope = await resolveScope(options, isTTY);
|
|
17
|
+
const projectDir = dependencies.projectDir ?? process.cwd();
|
|
18
|
+
const homeDir = dependencies.homeDir ?? os.homedir();
|
|
19
|
+
const skillDir = dependencies.skillDir ?? resolveBundledSkillDir();
|
|
20
|
+
const installedDir = path.join(scope === 'global' ? homeDir : projectDir, '.agents', 'skills', SKILL_NAME);
|
|
21
|
+
const [bundledHash, installedHash] = await Promise.all([
|
|
22
|
+
hashDirectory(skillDir),
|
|
23
|
+
hashDirectory(installedDir)
|
|
24
|
+
]);
|
|
25
|
+
if (!bundledHash) {
|
|
26
|
+
throw new Error(`Bundled ${SKILL_NAME} skill was not found at ${skillDir}.`);
|
|
27
|
+
}
|
|
28
|
+
if (bundledHash === installedHash) {
|
|
29
|
+
p.log.success(`✓ ${SKILL_NAME} skill is already up to date (${scope})`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
p.log.step(`${installedHash ? 'Updating' : 'Installing'} ${SKILL_NAME} skill (${scope})...`);
|
|
33
|
+
const args = [
|
|
34
|
+
'add',
|
|
35
|
+
skillDir,
|
|
36
|
+
'--skill',
|
|
37
|
+
SKILL_NAME,
|
|
38
|
+
'--copy',
|
|
39
|
+
...scope === 'global' ? [
|
|
40
|
+
'--global'
|
|
41
|
+
] : [],
|
|
42
|
+
...options.yes || !isTTY ? [
|
|
43
|
+
'--yes'
|
|
44
|
+
] : []
|
|
45
|
+
];
|
|
46
|
+
const exitCode = await run(process.execPath, [
|
|
47
|
+
SKILLS_CLI_PATH,
|
|
48
|
+
...args
|
|
49
|
+
], projectDir);
|
|
50
|
+
if (exitCode !== 0) {
|
|
51
|
+
throw new Error(`Skill installation failed with exit code ${exitCode}.`);
|
|
52
|
+
}
|
|
53
|
+
p.log.success(`✓ ${SKILL_NAME} skill ${installedHash ? 'updated' : 'installed'} (${scope})`);
|
|
54
|
+
}
|
|
55
|
+
async function resolveScope(options, isTTY) {
|
|
56
|
+
if (options.global) {
|
|
57
|
+
return 'global';
|
|
58
|
+
}
|
|
59
|
+
if (options.project) {
|
|
60
|
+
return 'project';
|
|
61
|
+
}
|
|
62
|
+
if (!isTTY) {
|
|
63
|
+
throw new Error('Non-interactive setup requires either --global or --project.');
|
|
64
|
+
}
|
|
65
|
+
const selected = await p.select({
|
|
66
|
+
initialValue: 'global',
|
|
67
|
+
message: 'Where should the Figma deploy skill be installed?',
|
|
68
|
+
options: [
|
|
69
|
+
{
|
|
70
|
+
label: 'Globally (recommended)',
|
|
71
|
+
value: 'global'
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: 'Current project only',
|
|
75
|
+
value: 'project'
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
if (p.isCancel(selected)) {
|
|
80
|
+
throw new Error('Skill installation cancelled.');
|
|
81
|
+
}
|
|
82
|
+
return selected;
|
|
83
|
+
}
|
|
84
|
+
function resolveBundledSkillDir() {
|
|
85
|
+
return path.resolve(import.meta.dirname, '..', 'skills', SKILL_NAME);
|
|
86
|
+
}
|
|
87
|
+
async function hashDirectory(directory) {
|
|
88
|
+
if (!await pathExists(directory)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const hash = crypto.createHash('sha256');
|
|
92
|
+
async function visit(currentDir, relativeDir = '') {
|
|
93
|
+
const entries = await fs.readdir(currentDir, {
|
|
94
|
+
withFileTypes: true
|
|
95
|
+
});
|
|
96
|
+
entries.sort((left, right)=>left.name.localeCompare(right.name));
|
|
97
|
+
for (const entry of entries){
|
|
98
|
+
const relativePath = path.join(relativeDir, entry.name);
|
|
99
|
+
const absolutePath = path.join(currentDir, entry.name);
|
|
100
|
+
if (entry.isDirectory()) {
|
|
101
|
+
await visit(absolutePath, relativePath);
|
|
102
|
+
} else if (entry.isFile()) {
|
|
103
|
+
hash.update(relativePath);
|
|
104
|
+
hash.update(await fs.readFile(absolutePath));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
await visit(directory);
|
|
109
|
+
return hash.digest('hex');
|
|
110
|
+
}
|
|
111
|
+
function run(command, args, cwd) {
|
|
112
|
+
return new Promise((resolve, reject)=>{
|
|
113
|
+
const child = spawn(command, args, {
|
|
114
|
+
cwd,
|
|
115
|
+
stdio: 'inherit'
|
|
116
|
+
});
|
|
117
|
+
child.once('error', reject);
|
|
118
|
+
child.once('close', (code)=>resolve(code ?? 1));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async function pathExists(filePath) {
|
|
122
|
+
return fs.access(filePath).then(()=>true).catch(()=>false);
|
|
123
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BootstrapInfo } from '../api/control-plane.js';
|
|
2
|
+
import type { TokenStore } from '../auth/token-store.js';
|
|
3
|
+
interface WriteProjectConfigurationArgs {
|
|
4
|
+
bootstrapInfo: BootstrapInfo | null;
|
|
5
|
+
environmentName: string;
|
|
6
|
+
projectDir: string;
|
|
7
|
+
projectId: string;
|
|
8
|
+
shouldWriteEnvironmentVariables?: boolean;
|
|
9
|
+
tokenStore: TokenStore;
|
|
10
|
+
}
|
|
11
|
+
export declare function writeProjectConfiguration({ bootstrapInfo, environmentName, projectDir, projectId, shouldWriteEnvironmentVariables, tokenStore, }: WriteProjectConfigurationArgs): Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getInfraEnvironment } from '../constants.js';
|
|
2
|
+
import { cacheAllEnvironments } from '../utils/cache-bootstrap.js';
|
|
3
|
+
import { addOrUpdateEnvVar } from '../utils/env-management.js';
|
|
4
|
+
export async function writeProjectConfiguration({ bootstrapInfo, environmentName, projectDir, projectId, shouldWriteEnvironmentVariables = true, tokenStore }) {
|
|
5
|
+
if (shouldWriteEnvironmentVariables) {
|
|
6
|
+
await addOrUpdateEnvVar(projectDir, 'FIGMA_PROJECT_ID', projectId);
|
|
7
|
+
await addOrUpdateEnvVar(projectDir, 'FIGMA_ENVIRONMENT_NAME', environmentName);
|
|
8
|
+
const infraEnvironment = getInfraEnvironment();
|
|
9
|
+
if (infraEnvironment !== 'production') {
|
|
10
|
+
await addOrUpdateEnvVar(projectDir, 'FIGMA_INFRA_ENV', infraEnvironment);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (bootstrapInfo) {
|
|
14
|
+
cacheAllEnvironments(tokenStore, projectId, bootstrapInfo);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -29,7 +29,7 @@ export type ContentAPIAdapter = {
|
|
|
29
29
|
client: ReturnType<typeof createClient<paths>>;
|
|
30
30
|
clientVersionHeaders: Record<string, string>;
|
|
31
31
|
contentSystemId: string;
|
|
32
|
-
documentSchema: DocumentSchemaWire;
|
|
32
|
+
documentSchema: () => DocumentSchemaWire;
|
|
33
33
|
environmentName?: string;
|
|
34
34
|
idType: 'uuid';
|
|
35
35
|
notifyLocalJobQueue: boolean;
|