@nebutra/design-sync 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +160 -0
- package/dist/detect.d.ts +21 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +79 -0
- package/dist/factory.d.ts +42 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +89 -0
- package/dist/figma-config/index.d.ts +37 -0
- package/dist/figma-config/index.d.ts.map +1 -0
- package/dist/figma-config/index.js +12 -0
- package/dist/figma-config/tokens-studio.config.json +34 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/io.d.ts +26 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +119 -0
- package/dist/providers/figma.d.ts +21 -0
- package/dist/providers/figma.d.ts.map +1 -0
- package/dist/providers/figma.js +179 -0
- package/dist/providers/git-only.d.ts +11 -0
- package/dist/providers/git-only.d.ts.map +1 -0
- package/dist/providers/git-only.js +104 -0
- package/dist/providers/memory.d.ts +17 -0
- package/dist/providers/memory.d.ts.map +1 -0
- package/dist/providers/memory.js +65 -0
- package/dist/providers/penpot.d.ts +21 -0
- package/dist/providers/penpot.d.ts.map +1 -0
- package/dist/providers/penpot.js +137 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/package.json +3 -3
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { logger } from "@nebutra/logger";
|
|
2
|
+
import { defaultTokensDir, defaultTokensStudioDir, readTokenSets, validateDtcgTree } from "../io";
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Penpot Provider — China-friendly + self-hostable Figma alternative
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// Penpot speaks DTCG natively (one of its differentiators) and exposes a
|
|
7
|
+
// public REST API. The provider is wired with full surface area so customers
|
|
8
|
+
// can swap providers without changing application code, but real network
|
|
9
|
+
// calls stay behind a `dryRun || !credsReady` guard until the operator
|
|
10
|
+
// explicitly provisions PENPOT_TOKEN.
|
|
11
|
+
//
|
|
12
|
+
// Why this matters:
|
|
13
|
+
// - Penpot can be self-hosted, sidesteps the Figma block in mainland China.
|
|
14
|
+
// - DTCG-native means we do not need a translation step like with Figma.
|
|
15
|
+
// - Tokens Studio plugin also targets Penpot — designers keep the same UX.
|
|
16
|
+
// =============================================================================
|
|
17
|
+
const DEFAULT_PENPOT_API = "https://design.penpot.app/api";
|
|
18
|
+
export class PenpotProvider {
|
|
19
|
+
name = "penpot";
|
|
20
|
+
tokensDir;
|
|
21
|
+
tokensStudioDir;
|
|
22
|
+
apiUrl;
|
|
23
|
+
token;
|
|
24
|
+
fileId;
|
|
25
|
+
teamId;
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.tokensDir = config.tokensDir ?? defaultTokensDir();
|
|
28
|
+
this.tokensStudioDir = config.tokensStudioDir ?? defaultTokensStudioDir();
|
|
29
|
+
this.apiUrl = config.apiUrl ?? process.env.PENPOT_API_URL ?? DEFAULT_PENPOT_API;
|
|
30
|
+
this.token = config.token ?? process.env.PENPOT_TOKEN ?? undefined;
|
|
31
|
+
this.fileId = config.fileId ?? process.env.PENPOT_FILE_ID ?? undefined;
|
|
32
|
+
this.teamId = config.teamId ?? process.env.PENPOT_TEAM_ID ?? undefined;
|
|
33
|
+
logger.info("[design-sync:penpot] Provider initialised", {
|
|
34
|
+
apiUrl: this.apiUrl,
|
|
35
|
+
hasToken: Boolean(this.token),
|
|
36
|
+
hasFileId: Boolean(this.fileId),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async pull(options = {}) {
|
|
40
|
+
if (!this.credsReady()) {
|
|
41
|
+
// No credentials → fall through to local DTCG, mirroring git-only.
|
|
42
|
+
const sets = await readTokenSets(this.tokensDir);
|
|
43
|
+
const filtered = filterSets(sets, options.themes);
|
|
44
|
+
logger.warn("[design-sync:penpot] pull falling back to local DTCG (no PENPOT_TOKEN)");
|
|
45
|
+
return {
|
|
46
|
+
sets: filtered,
|
|
47
|
+
written: false,
|
|
48
|
+
provider: "penpot",
|
|
49
|
+
pulledAt: new Date().toISOString(),
|
|
50
|
+
summary: `penpot: PENPOT_TOKEN missing — returned ${filtered.length} local DTCG set(s)`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Real pull placeholder — when wired up, this calls:
|
|
54
|
+
// GET {apiUrl}/rpc/command/get-file?id={fileId}
|
|
55
|
+
// Authorization: Token {token}
|
|
56
|
+
// and projects the design-tokens collection back into DTCG sets.
|
|
57
|
+
// See https://design.penpot.app/api/docs for the full RPC catalogue.
|
|
58
|
+
throw new Error("[design-sync:penpot] live pull is not yet implemented. " +
|
|
59
|
+
"Unset PENPOT_TOKEN to fall back to local DTCG, or open packages/design/design-sync/DESIGN.md for the rollout plan.");
|
|
60
|
+
}
|
|
61
|
+
async push(options = {}) {
|
|
62
|
+
const all = await readTokenSets(this.tokensDir);
|
|
63
|
+
const sets = filterSets(all, options.themes);
|
|
64
|
+
for (const set of sets) {
|
|
65
|
+
const errors = validateDtcgTree(set.tokens);
|
|
66
|
+
if (errors.length > 0) {
|
|
67
|
+
throw new Error(`[design-sync:penpot] DTCG validation failed for ${set.relativePath}:\n - ${errors.join("\n - ")}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const credsReady = this.credsReady();
|
|
71
|
+
const explicitDryRun = options.dryRun ?? false;
|
|
72
|
+
const dryRun = explicitDryRun || !credsReady;
|
|
73
|
+
if (dryRun) {
|
|
74
|
+
logger.warn("[design-sync:penpot] push skipped (dry-run scaffold)", {
|
|
75
|
+
reason: credsReady ? "explicit dryRun" : "missing credentials",
|
|
76
|
+
sets: sets.length,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
pushed: false,
|
|
80
|
+
sets: sets.map((s) => s.relativePath),
|
|
81
|
+
provider: "penpot",
|
|
82
|
+
pushedAt: new Date().toISOString(),
|
|
83
|
+
summary: credsReady
|
|
84
|
+
? `penpot: dry-run — would POST ${sets.length} DTCG set(s) to ${this.apiUrl}/rpc/command/update-file-design-tokens`
|
|
85
|
+
: "penpot: dry-run — PENPOT_TOKEN or PENPOT_FILE_ID missing",
|
|
86
|
+
dryRun: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Real push placeholder — when wired up, this calls:
|
|
90
|
+
// POST {apiUrl}/rpc/command/update-file-design-tokens
|
|
91
|
+
// Authorization: Token {token}
|
|
92
|
+
// body: { fileId, tokens: dtcgTree }
|
|
93
|
+
throw new Error("[design-sync:penpot] live push is not yet implemented. " +
|
|
94
|
+
"Use { dryRun: true } until the Penpot RPC integration is wired up.");
|
|
95
|
+
}
|
|
96
|
+
async healthcheck() {
|
|
97
|
+
const detected = [];
|
|
98
|
+
const missing = [];
|
|
99
|
+
if (this.token)
|
|
100
|
+
detected.push("PENPOT_TOKEN");
|
|
101
|
+
else
|
|
102
|
+
missing.push("PENPOT_TOKEN");
|
|
103
|
+
if (this.fileId)
|
|
104
|
+
detected.push("PENPOT_FILE_ID");
|
|
105
|
+
else
|
|
106
|
+
missing.push("PENPOT_FILE_ID");
|
|
107
|
+
if (this.teamId)
|
|
108
|
+
detected.push("PENPOT_TEAM_ID");
|
|
109
|
+
detected.push(`PENPOT_API_URL=${this.apiUrl}`);
|
|
110
|
+
const ok = missing.length === 0;
|
|
111
|
+
return {
|
|
112
|
+
ok,
|
|
113
|
+
provider: "penpot",
|
|
114
|
+
message: ok
|
|
115
|
+
? `penpot: credentials present (api=${this.apiUrl})`
|
|
116
|
+
: `penpot: not ready — missing ${missing.join(", ")}`,
|
|
117
|
+
detectedEnv: detected,
|
|
118
|
+
missingEnv: missing,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Reserved for future use — exposes the configured tokens-studio directory
|
|
123
|
+
* so consumers (e.g. CI workflows) can attach Penpot-side metadata mirrors.
|
|
124
|
+
*/
|
|
125
|
+
getTokensStudioDir() {
|
|
126
|
+
return this.tokensStudioDir;
|
|
127
|
+
}
|
|
128
|
+
credsReady() {
|
|
129
|
+
return Boolean(this.token && this.fileId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function filterSets(sets, themes) {
|
|
133
|
+
if (!themes || themes.length === 0)
|
|
134
|
+
return sets;
|
|
135
|
+
const wanted = new Set(themes);
|
|
136
|
+
return sets.filter((s) => wanted.has(s.name) || wanted.has(s.relativePath));
|
|
137
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Supported design-sync backend providers.
|
|
4
|
+
*
|
|
5
|
+
* - `figma` — Figma + Tokens Studio plugin (DTCG via GitHub provider sync)
|
|
6
|
+
* - `penpot` — Penpot REST API (self-hostable, China-friendly)
|
|
7
|
+
* - `git-only` — No design tool; reads/writes local DTCG files directly
|
|
8
|
+
* - `memory` — In-memory test fixture (CI / unit tests only)
|
|
9
|
+
*/
|
|
10
|
+
export type DesignSyncProviderType = "figma" | "penpot" | "git-only" | "memory";
|
|
11
|
+
/**
|
|
12
|
+
* A W3C Design Tokens Community Group (DTCG) leaf token.
|
|
13
|
+
* Every leaf MUST carry both `$value` and `$type`.
|
|
14
|
+
*
|
|
15
|
+
* Spec: https://design-tokens.github.io/community-group/format/
|
|
16
|
+
*/
|
|
17
|
+
export declare const DesignTokenLeafSchema: z.ZodObject<{
|
|
18
|
+
$value: z.ZodUnknown;
|
|
19
|
+
$type: z.ZodString;
|
|
20
|
+
$description: z.ZodOptional<z.ZodString>;
|
|
21
|
+
$extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
22
|
+
}, z.core.$loose>;
|
|
23
|
+
export type DesignTokenLeaf = z.infer<typeof DesignTokenLeafSchema>;
|
|
24
|
+
/**
|
|
25
|
+
* A DTCG token tree is a recursive map of named groups and leaves.
|
|
26
|
+
* Groups are plain objects; leaves carry `$value` + `$type`.
|
|
27
|
+
*/
|
|
28
|
+
export type DesignTokenTree = {
|
|
29
|
+
[key: string]: DesignTokenTree | DesignTokenLeaf;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* A single DTCG file = one token set (e.g. `core.json`, `themes/light.json`).
|
|
33
|
+
*/
|
|
34
|
+
export interface DesignTokenSet {
|
|
35
|
+
/** Token-set name (matches file basename without extension, e.g. "core") */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Path relative to the tokens directory (e.g. "themes/light.json") */
|
|
38
|
+
relativePath: string;
|
|
39
|
+
/** Parsed DTCG tree */
|
|
40
|
+
tokens: DesignTokenTree;
|
|
41
|
+
}
|
|
42
|
+
export interface PullOptions {
|
|
43
|
+
/**
|
|
44
|
+
* Optional theme/token-set filter. When omitted, all sets are pulled.
|
|
45
|
+
* Provider-specific naming applies (e.g. Figma collection IDs).
|
|
46
|
+
*/
|
|
47
|
+
themes?: string[];
|
|
48
|
+
/**
|
|
49
|
+
* If true, the provider should validate but NOT write to the local repo.
|
|
50
|
+
* Used by CI to verify a remote state without producing diffs.
|
|
51
|
+
*/
|
|
52
|
+
dryRun?: boolean;
|
|
53
|
+
/** Tenant scoping for multi-workspace SaaS deployments */
|
|
54
|
+
tenantId?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface PushOptions {
|
|
57
|
+
/** Restrict the push to specific token sets */
|
|
58
|
+
themes?: string[];
|
|
59
|
+
/**
|
|
60
|
+
* If true, the provider should compute the diff but NOT call the remote API.
|
|
61
|
+
* `figma.push({ dryRun: true })` is the default until the user opts in.
|
|
62
|
+
*/
|
|
63
|
+
dryRun?: boolean;
|
|
64
|
+
/** Tenant scoping */
|
|
65
|
+
tenantId?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface PullResult {
|
|
68
|
+
/** Token sets that were retrieved */
|
|
69
|
+
sets: DesignTokenSet[];
|
|
70
|
+
/** Whether the local repo was modified */
|
|
71
|
+
written: boolean;
|
|
72
|
+
/** Provider that produced the result */
|
|
73
|
+
provider: DesignSyncProviderType;
|
|
74
|
+
/** ISO-8601 timestamp */
|
|
75
|
+
pulledAt: string;
|
|
76
|
+
/** Human-readable summary line for CLI output */
|
|
77
|
+
summary: string;
|
|
78
|
+
}
|
|
79
|
+
export interface PushResult {
|
|
80
|
+
/** Whether the remote design tool was modified */
|
|
81
|
+
pushed: boolean;
|
|
82
|
+
/** Token sets that were sent (or would have been sent in a dry-run) */
|
|
83
|
+
sets: string[];
|
|
84
|
+
/** Provider name */
|
|
85
|
+
provider: DesignSyncProviderType;
|
|
86
|
+
/** ISO-8601 timestamp */
|
|
87
|
+
pushedAt: string;
|
|
88
|
+
/** Human-readable summary */
|
|
89
|
+
summary: string;
|
|
90
|
+
/** True when the provider intentionally skipped the call (no creds, dry-run) */
|
|
91
|
+
dryRun: boolean;
|
|
92
|
+
}
|
|
93
|
+
export interface HealthStatus {
|
|
94
|
+
/** Is the provider configured + reachable? */
|
|
95
|
+
ok: boolean;
|
|
96
|
+
/** Provider name */
|
|
97
|
+
provider: DesignSyncProviderType;
|
|
98
|
+
/** Free-form diagnostic */
|
|
99
|
+
message: string;
|
|
100
|
+
/** Detected env var names that are present (not their values) */
|
|
101
|
+
detectedEnv: string[];
|
|
102
|
+
/** Detected env var names that are missing */
|
|
103
|
+
missingEnv: string[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Every design-sync backend implements this interface.
|
|
107
|
+
* The factory (`createDesignSync`) returns a `DesignSyncProvider`.
|
|
108
|
+
*/
|
|
109
|
+
export interface DesignSyncProvider {
|
|
110
|
+
readonly name: DesignSyncProviderType;
|
|
111
|
+
/**
|
|
112
|
+
* Pull: design-tool → repo (DTCG JSON).
|
|
113
|
+
* For `git-only` this is a no-op read of local files.
|
|
114
|
+
*/
|
|
115
|
+
pull(options?: PullOptions): Promise<PullResult>;
|
|
116
|
+
/**
|
|
117
|
+
* Push: repo (DTCG JSON) → design-tool.
|
|
118
|
+
* For `git-only` this is a no-op write/format of local files.
|
|
119
|
+
* Real providers default to dry-run unless explicit credentials exist.
|
|
120
|
+
*/
|
|
121
|
+
push(options?: PushOptions): Promise<PushResult>;
|
|
122
|
+
/**
|
|
123
|
+
* Confirm the provider has the env vars / file access it needs.
|
|
124
|
+
*/
|
|
125
|
+
healthcheck(): Promise<HealthStatus>;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Shared options every provider accepts. The tokens directory is the
|
|
129
|
+
* filesystem source of truth (DTCG JSON), independent of which design tool
|
|
130
|
+
* we sync with.
|
|
131
|
+
*/
|
|
132
|
+
export interface BaseProviderConfig {
|
|
133
|
+
/**
|
|
134
|
+
* Absolute path to the DTCG tokens directory.
|
|
135
|
+
* Defaults to `<cwd>/packages/design/design-tokens/tokens`.
|
|
136
|
+
*/
|
|
137
|
+
tokensDir?: string;
|
|
138
|
+
/**
|
|
139
|
+
* Absolute path to the `.tokens-studio` metadata directory (if used).
|
|
140
|
+
* Defaults to `<cwd>/.tokens-studio`.
|
|
141
|
+
*/
|
|
142
|
+
tokensStudioDir?: string;
|
|
143
|
+
}
|
|
144
|
+
export interface FigmaProviderConfig extends BaseProviderConfig {
|
|
145
|
+
provider: "figma";
|
|
146
|
+
/** Figma personal access token. Defaults to `process.env.FIGMA_PERSONAL_ACCESS_TOKEN`. */
|
|
147
|
+
personalAccessToken?: string;
|
|
148
|
+
/** Figma file ID (the `:file_key` segment in the URL). */
|
|
149
|
+
fileId?: string;
|
|
150
|
+
/** GitHub repo (owner/name) used by the Tokens Studio plugin sync. */
|
|
151
|
+
githubRepo?: string;
|
|
152
|
+
/** GitHub branch the plugin pushes to. Defaults to `main`. */
|
|
153
|
+
githubBranch?: string;
|
|
154
|
+
}
|
|
155
|
+
export interface PenpotProviderConfig extends BaseProviderConfig {
|
|
156
|
+
provider: "penpot";
|
|
157
|
+
/** Penpot API URL — public cloud or self-hosted. */
|
|
158
|
+
apiUrl?: string;
|
|
159
|
+
/** Penpot personal access token. */
|
|
160
|
+
token?: string;
|
|
161
|
+
/** Penpot file ID. */
|
|
162
|
+
fileId?: string;
|
|
163
|
+
/** Penpot team / workspace ID. */
|
|
164
|
+
teamId?: string;
|
|
165
|
+
}
|
|
166
|
+
export interface GitOnlyProviderConfig extends BaseProviderConfig {
|
|
167
|
+
provider: "git-only";
|
|
168
|
+
}
|
|
169
|
+
export interface MemoryProviderConfig extends BaseProviderConfig {
|
|
170
|
+
provider: "memory";
|
|
171
|
+
/** Optional initial in-memory token sets (used in tests). */
|
|
172
|
+
initialSets?: DesignTokenSet[];
|
|
173
|
+
}
|
|
174
|
+
export type DesignSyncConfig = FigmaProviderConfig | PenpotProviderConfig | GitOnlyProviderConfig | MemoryProviderConfig;
|
|
175
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ── DTCG Token Schema ───────────────────────────────────────────────────────
|
|
3
|
+
/**
|
|
4
|
+
* A W3C Design Tokens Community Group (DTCG) leaf token.
|
|
5
|
+
* Every leaf MUST carry both `$value` and `$type`.
|
|
6
|
+
*
|
|
7
|
+
* Spec: https://design-tokens.github.io/community-group/format/
|
|
8
|
+
*/
|
|
9
|
+
export const DesignTokenLeafSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
$value: z.unknown(),
|
|
12
|
+
$type: z.string(),
|
|
13
|
+
$description: z.string().optional(),
|
|
14
|
+
$extensions: z.record(z.string(), z.unknown()).optional(),
|
|
15
|
+
})
|
|
16
|
+
.passthrough();
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebutra/design-sync",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Provider-agnostic design-tool sync. Figma + Tokens Studio | Penpot | git-only | memory.",
|
|
5
5
|
"private": false,
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"nebutra": {
|
|
9
9
|
"status": "foundation",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
],
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"zod": "^4.3.6",
|
|
62
|
-
"@nebutra/logger": "0.1.
|
|
62
|
+
"@nebutra/logger": "0.1.1"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/node": "^22.19.15",
|