@zeroxsolutions/zaku 0.0.3 → 0.0.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/rules.js +1 -1
- package/dist/zaku.mjs +1274 -209
- package/package.json +1 -1
package/dist/zaku.mjs
CHANGED
|
@@ -12066,7 +12066,7 @@ var require_websocket = __commonJS({
|
|
|
12066
12066
|
var http = __require("http");
|
|
12067
12067
|
var net = __require("net");
|
|
12068
12068
|
var tls = __require("tls");
|
|
12069
|
-
var { randomBytes, createHash:
|
|
12069
|
+
var { randomBytes, createHash: createHash3 } = __require("crypto");
|
|
12070
12070
|
var { Duplex, Readable } = __require("stream");
|
|
12071
12071
|
var { URL: URL2 } = __require("url");
|
|
12072
12072
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -12747,7 +12747,7 @@ var require_websocket = __commonJS({
|
|
|
12747
12747
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
12748
12748
|
return;
|
|
12749
12749
|
}
|
|
12750
|
-
const digest =
|
|
12750
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
12751
12751
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
12752
12752
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
12753
12753
|
return;
|
|
@@ -13116,7 +13116,7 @@ var require_websocket_server = __commonJS({
|
|
|
13116
13116
|
var EventEmitter2 = __require("events");
|
|
13117
13117
|
var http = __require("http");
|
|
13118
13118
|
var { Duplex } = __require("stream");
|
|
13119
|
-
var { createHash:
|
|
13119
|
+
var { createHash: createHash3 } = __require("crypto");
|
|
13120
13120
|
var extension2 = require_extension();
|
|
13121
13121
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
13122
13122
|
var subprotocol2 = require_subprotocol();
|
|
@@ -13423,7 +13423,7 @@ var require_websocket_server = __commonJS({
|
|
|
13423
13423
|
);
|
|
13424
13424
|
}
|
|
13425
13425
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
13426
|
-
const digest =
|
|
13426
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
13427
13427
|
const headers = [
|
|
13428
13428
|
"HTTP/1.1 101 Switching Protocols",
|
|
13429
13429
|
"Upgrade: websocket",
|
|
@@ -17351,49 +17351,49 @@ var require_fast_uri = __commonJS({
|
|
|
17351
17351
|
schemelessOptions.skipEscape = true;
|
|
17352
17352
|
return serialize(resolved, schemelessOptions);
|
|
17353
17353
|
}
|
|
17354
|
-
function resolveComponent(base,
|
|
17354
|
+
function resolveComponent(base, relative3, options, skipNormalization) {
|
|
17355
17355
|
const target = {};
|
|
17356
17356
|
if (!skipNormalization) {
|
|
17357
17357
|
base = parse4(serialize(base, options), options);
|
|
17358
|
-
|
|
17358
|
+
relative3 = parse4(serialize(relative3, options), options);
|
|
17359
17359
|
}
|
|
17360
17360
|
options = options || {};
|
|
17361
|
-
if (!options.tolerant &&
|
|
17362
|
-
target.scheme =
|
|
17363
|
-
target.userinfo =
|
|
17364
|
-
target.host =
|
|
17365
|
-
target.port =
|
|
17366
|
-
target.path = removeDotSegments(
|
|
17367
|
-
target.query =
|
|
17361
|
+
if (!options.tolerant && relative3.scheme) {
|
|
17362
|
+
target.scheme = relative3.scheme;
|
|
17363
|
+
target.userinfo = relative3.userinfo;
|
|
17364
|
+
target.host = relative3.host;
|
|
17365
|
+
target.port = relative3.port;
|
|
17366
|
+
target.path = removeDotSegments(relative3.path || "");
|
|
17367
|
+
target.query = relative3.query;
|
|
17368
17368
|
} else {
|
|
17369
|
-
if (
|
|
17370
|
-
target.userinfo =
|
|
17371
|
-
target.host =
|
|
17372
|
-
target.port =
|
|
17373
|
-
target.path = removeDotSegments(
|
|
17374
|
-
target.query =
|
|
17369
|
+
if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
|
|
17370
|
+
target.userinfo = relative3.userinfo;
|
|
17371
|
+
target.host = relative3.host;
|
|
17372
|
+
target.port = relative3.port;
|
|
17373
|
+
target.path = removeDotSegments(relative3.path || "");
|
|
17374
|
+
target.query = relative3.query;
|
|
17375
17375
|
} else {
|
|
17376
|
-
if (!
|
|
17376
|
+
if (!relative3.path) {
|
|
17377
17377
|
target.path = base.path;
|
|
17378
|
-
if (
|
|
17379
|
-
target.query =
|
|
17378
|
+
if (relative3.query !== void 0) {
|
|
17379
|
+
target.query = relative3.query;
|
|
17380
17380
|
} else {
|
|
17381
17381
|
target.query = base.query;
|
|
17382
17382
|
}
|
|
17383
17383
|
} else {
|
|
17384
|
-
if (
|
|
17385
|
-
target.path = removeDotSegments(
|
|
17384
|
+
if (relative3.path[0] === "/") {
|
|
17385
|
+
target.path = removeDotSegments(relative3.path);
|
|
17386
17386
|
} else {
|
|
17387
17387
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
17388
|
-
target.path = "/" +
|
|
17388
|
+
target.path = "/" + relative3.path;
|
|
17389
17389
|
} else if (!base.path) {
|
|
17390
|
-
target.path =
|
|
17390
|
+
target.path = relative3.path;
|
|
17391
17391
|
} else {
|
|
17392
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
17392
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
|
|
17393
17393
|
}
|
|
17394
17394
|
target.path = removeDotSegments(target.path);
|
|
17395
17395
|
}
|
|
17396
|
-
target.query =
|
|
17396
|
+
target.query = relative3.query;
|
|
17397
17397
|
}
|
|
17398
17398
|
target.userinfo = base.userinfo;
|
|
17399
17399
|
target.host = base.host;
|
|
@@ -17401,7 +17401,7 @@ var require_fast_uri = __commonJS({
|
|
|
17401
17401
|
}
|
|
17402
17402
|
target.scheme = base.scheme;
|
|
17403
17403
|
}
|
|
17404
|
-
target.fragment =
|
|
17404
|
+
target.fragment = relative3.fragment;
|
|
17405
17405
|
return target;
|
|
17406
17406
|
}
|
|
17407
17407
|
function equal(uriA, uriB, options) {
|
|
@@ -20681,7 +20681,7 @@ var import_reflect_metadata3 = __toESM(require_Reflect(), 1);
|
|
|
20681
20681
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
20682
20682
|
import { createRequire } from "node:module";
|
|
20683
20683
|
import { homedir as homedir2 } from "node:os";
|
|
20684
|
-
import { dirname as dirname4, join as
|
|
20684
|
+
import { dirname as dirname4, join as join12, resolve as resolve2, sep } from "node:path";
|
|
20685
20685
|
import { fileURLToPath } from "node:url";
|
|
20686
20686
|
|
|
20687
20687
|
// node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
|
|
@@ -24178,11 +24178,15 @@ var WriteRecipe = class extends DomainCommand {
|
|
|
24178
24178
|
// packages/zaku/dist/lib/commands/save-library.js
|
|
24179
24179
|
var SaveLibrary = class extends DomainCommand {
|
|
24180
24180
|
root;
|
|
24181
|
+
key;
|
|
24181
24182
|
part;
|
|
24182
24183
|
constructor(input2) {
|
|
24183
24184
|
super();
|
|
24184
24185
|
this.root = input2.root;
|
|
24185
|
-
|
|
24186
|
+
if (input2.key !== void 0)
|
|
24187
|
+
this.key = input2.key;
|
|
24188
|
+
if (input2.part !== void 0)
|
|
24189
|
+
this.part = input2.part;
|
|
24186
24190
|
}
|
|
24187
24191
|
};
|
|
24188
24192
|
|
|
@@ -44393,6 +44397,18 @@ var FigmaTokenMissing = class extends Error {
|
|
|
44393
44397
|
}
|
|
44394
44398
|
};
|
|
44395
44399
|
|
|
44400
|
+
// packages/zaku/dist/lib/domain/errors/library-key-missing.js
|
|
44401
|
+
var LibraryKeyMissing = class extends Error {
|
|
44402
|
+
keys;
|
|
44403
|
+
given;
|
|
44404
|
+
constructor(keys, given) {
|
|
44405
|
+
super(given === void 0 ? `zaku.yaml lists several libraries and kits; name one with --key: ${keys.join(", ")}` : `${given} is not a library or kit zaku.yaml lists; name one with --key: ${keys.join(", ")}`);
|
|
44406
|
+
this.keys = keys;
|
|
44407
|
+
this.given = given;
|
|
44408
|
+
this.name = "LibraryKeyMissing";
|
|
44409
|
+
}
|
|
44410
|
+
};
|
|
44411
|
+
|
|
44396
44412
|
// packages/zaku/dist/lib/domain/errors/playwright-missing.js
|
|
44397
44413
|
var PlaywrightMissing = class extends Error {
|
|
44398
44414
|
constructor() {
|
|
@@ -44611,12 +44627,106 @@ WriteRecipeHandler = __decorate2([
|
|
|
44611
44627
|
|
|
44612
44628
|
// packages/zaku/dist/lib/handlers/save-library.js
|
|
44613
44629
|
var import_tsyringe3 = __toESM(require_cjs(), 1);
|
|
44630
|
+
import { relative as relative2 } from "node:path";
|
|
44614
44631
|
|
|
44615
44632
|
// packages/zaku/dist/lib/domain/copy-defaults.js
|
|
44616
44633
|
var DEFAULT_COPY = { locales: ["en"], currencies: [] };
|
|
44617
44634
|
|
|
44635
|
+
// packages/zaku/dist/lib/domain/design-graph.js
|
|
44636
|
+
var DESKTOP_FAMILIES = /* @__PURE__ */ new Set(["macos", "windows", "gnome", "kde"]);
|
|
44637
|
+
function defaultBranch(family) {
|
|
44638
|
+
if (family === "web")
|
|
44639
|
+
return "ui";
|
|
44640
|
+
return DESKTOP_FAMILIES.has(family) ? void 0 : "native";
|
|
44641
|
+
}
|
|
44642
|
+
function defaultPlatform(family) {
|
|
44643
|
+
if (family === "web")
|
|
44644
|
+
return "web-app";
|
|
44645
|
+
return DESKTOP_FAMILIES.has(family) ? "desktop" : "mobile";
|
|
44646
|
+
}
|
|
44647
|
+
var branchOf = (target) => target.branch ?? defaultBranch(target.family);
|
|
44648
|
+
var platformOf = (target) => target.platform ?? defaultPlatform(target.family);
|
|
44649
|
+
var unique = (values) => [...new Set(values)];
|
|
44650
|
+
function legacyFiles(config2) {
|
|
44651
|
+
const branches = unique(config2.targets.flatMap((target) => branchOf(target) ?? []));
|
|
44652
|
+
const platforms = unique(config2.targets.map(platformOf));
|
|
44653
|
+
const { library, product } = config2.figma;
|
|
44654
|
+
return {
|
|
44655
|
+
libraries: library === void 0 ? [] : [{ key: library, layer: "foundations", branches: branches.length > 0 ? branches : ["ui"], extends: [] }],
|
|
44656
|
+
products: product === void 0 ? [] : platforms.map((platform) => ({ key: product, platform }))
|
|
44657
|
+
};
|
|
44658
|
+
}
|
|
44659
|
+
function designGraph(config2) {
|
|
44660
|
+
const { figma } = config2;
|
|
44661
|
+
const legacy = figma.library !== void 0 || figma.product !== void 0;
|
|
44662
|
+
const { libraries, products } = legacy ? legacyFiles(config2) : { libraries: figma.libraries ?? [], products: figma.products ?? [] };
|
|
44663
|
+
const kits = figma.kits ?? [];
|
|
44664
|
+
const prototypes = figma.prototypes ?? [];
|
|
44665
|
+
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
44666
|
+
const closure = (key) => {
|
|
44667
|
+
const out = [];
|
|
44668
|
+
const visit2 = (next) => {
|
|
44669
|
+
if (out.includes(next))
|
|
44670
|
+
return;
|
|
44671
|
+
out.push(next);
|
|
44672
|
+
for (const base of byKey.get(next)?.extends ?? [])
|
|
44673
|
+
visit2(base);
|
|
44674
|
+
};
|
|
44675
|
+
visit2(key);
|
|
44676
|
+
return out;
|
|
44677
|
+
};
|
|
44678
|
+
return {
|
|
44679
|
+
libraries,
|
|
44680
|
+
kits,
|
|
44681
|
+
products,
|
|
44682
|
+
prototypes,
|
|
44683
|
+
legacy,
|
|
44684
|
+
branchOf,
|
|
44685
|
+
platformOf,
|
|
44686
|
+
librariesFor: (target) => {
|
|
44687
|
+
if (legacy)
|
|
44688
|
+
return libraries;
|
|
44689
|
+
const branch = branchOf(target);
|
|
44690
|
+
return libraries.filter((library) => branch !== void 0 && library.branches.includes(branch));
|
|
44691
|
+
},
|
|
44692
|
+
kitsFor: (target) => kits.filter((kit) => kit.family === target.family),
|
|
44693
|
+
closure,
|
|
44694
|
+
multiBranch: (key) => (byKey.get(key)?.branches.length ?? 0) > 1,
|
|
44695
|
+
productOf: (prototypeKey) => {
|
|
44696
|
+
const prototype2 = prototypes.find((candidate) => candidate.key === prototypeKey);
|
|
44697
|
+
return prototype2?.product ?? (products.length === 1 ? products[0]?.key : void 0);
|
|
44698
|
+
}
|
|
44699
|
+
};
|
|
44700
|
+
}
|
|
44701
|
+
function snapshotsFor(input2, target) {
|
|
44702
|
+
const graph = designGraph(input2.config);
|
|
44703
|
+
const branch = target ? graph.branchOf(target) : void 0;
|
|
44704
|
+
const missing = [];
|
|
44705
|
+
const libraries = (target ? graph.librariesFor(target) : graph.libraries).flatMap((library) => {
|
|
44706
|
+
const snapshot = input2.libraries[library.key];
|
|
44707
|
+
if (!snapshot) {
|
|
44708
|
+
missing.push(library.key);
|
|
44709
|
+
return [];
|
|
44710
|
+
}
|
|
44711
|
+
if (!target || !graph.multiBranch(library.key))
|
|
44712
|
+
return [snapshot];
|
|
44713
|
+
const components = snapshot.components.filter((component2) => component2.branch === void 0 || component2.branch === branch);
|
|
44714
|
+
return [{ ...snapshot, components }];
|
|
44715
|
+
});
|
|
44716
|
+
const kits = (target ? graph.kitsFor(target) : graph.kits).flatMap((kit) => {
|
|
44717
|
+
const snapshot = input2.kits[kit.key];
|
|
44718
|
+
if (!snapshot)
|
|
44719
|
+
missing.push(kit.key);
|
|
44720
|
+
return snapshot ? [snapshot] : [];
|
|
44721
|
+
});
|
|
44722
|
+
return { libraries, kits, missing };
|
|
44723
|
+
}
|
|
44724
|
+
|
|
44618
44725
|
// packages/zaku/dist/lib/schema/zaku-config.js
|
|
44619
44726
|
var PLATFORM_FAMILIES = ["web", "ios", "android", "macos", "windows", "gnome", "kde"];
|
|
44727
|
+
var LAYERS = ["foundations", "components"];
|
|
44728
|
+
var BRANCHES = ["ui", "native"];
|
|
44729
|
+
var PLATFORMS = ["web-app", "mobile", "desktop"];
|
|
44620
44730
|
var DEFAULT_INTERACTIVE = [
|
|
44621
44731
|
"Button",
|
|
44622
44732
|
"Button Group",
|
|
@@ -44643,7 +44753,11 @@ var targetSchema = external_exports.object({
|
|
|
44643
44753
|
family: external_exports.enum(PLATFORM_FAMILIES),
|
|
44644
44754
|
name: external_exports.string().regex(/^\S(.*\S)?$/, "a name has no leading or trailing space").refine((name) => !name.includes("/"), "a name has no slash, which separates the parts of a frame name"),
|
|
44645
44755
|
/** The frame size every frame of this target is drawn at; the frame check compares it. */
|
|
44646
|
-
size: external_exports.object({ width: external_exports.number().positive(), height: external_exports.number().positive() }).strict().optional()
|
|
44756
|
+
size: external_exports.object({ width: external_exports.number().positive(), height: external_exports.number().positive() }).strict().optional(),
|
|
44757
|
+
/** The renderer whose libraries its frames draw from; `defaultBranch` in the design graph gives it when left out. */
|
|
44758
|
+
branch: external_exports.enum(BRANCHES).optional(),
|
|
44759
|
+
/** What its frames serve; `defaultPlatform` in the design graph gives it when left out. */
|
|
44760
|
+
platform: external_exports.enum(PLATFORMS).optional()
|
|
44647
44761
|
}).strict();
|
|
44648
44762
|
var DEFAULT_SYSTEM_BARS = {
|
|
44649
44763
|
web: [],
|
|
@@ -44663,7 +44777,33 @@ var budgetSchema = external_exports.object({
|
|
|
44663
44777
|
mcpPerRun: external_exports.number().int().positive().default(30),
|
|
44664
44778
|
reserve: external_exports.number().min(0).max(1).default(0.2)
|
|
44665
44779
|
}).strict();
|
|
44666
|
-
var
|
|
44780
|
+
var fileKey = external_exports.string().min(1);
|
|
44781
|
+
var kitSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
44782
|
+
var librarySchema = external_exports.object({
|
|
44783
|
+
key: fileKey,
|
|
44784
|
+
layer: external_exports.enum(LAYERS),
|
|
44785
|
+
branches: external_exports.array(external_exports.enum(BRANCHES)).min(1),
|
|
44786
|
+
/** The libraries and kits this one is built on, by key. */
|
|
44787
|
+
extends: external_exports.array(fileKey).default([])
|
|
44788
|
+
}).strict();
|
|
44789
|
+
var productSchema = external_exports.object({ key: fileKey, platform: external_exports.enum(PLATFORMS) }).strict();
|
|
44790
|
+
var prototypeSchema = external_exports.object({
|
|
44791
|
+
key: fileKey,
|
|
44792
|
+
platform: external_exports.enum(PLATFORMS),
|
|
44793
|
+
/** The product file its frames are copied from; required when there are several. */
|
|
44794
|
+
product: fileKey.optional()
|
|
44795
|
+
}).strict();
|
|
44796
|
+
var files = external_exports.object({
|
|
44797
|
+
library: fileKey.optional(),
|
|
44798
|
+
product: fileKey.optional(),
|
|
44799
|
+
kits: external_exports.array(kitSchema).optional(),
|
|
44800
|
+
libraries: external_exports.array(librarySchema).optional(),
|
|
44801
|
+
products: external_exports.array(productSchema).optional(),
|
|
44802
|
+
prototypes: external_exports.array(prototypeSchema).optional()
|
|
44803
|
+
}).strict();
|
|
44804
|
+
function byRole(figma) {
|
|
44805
|
+
return [figma.kits, figma.libraries, figma.products, figma.prototypes].some((list) => list !== void 0);
|
|
44806
|
+
}
|
|
44667
44807
|
var shadcnSystem = external_exports.object({ preset: external_exports.string().min(1) }).strict();
|
|
44668
44808
|
var tokenFiles = external_exports.array(external_exports.string().min(1)).min(1);
|
|
44669
44809
|
var resolverInputs = external_exports.record(external_exports.string(), external_exports.string());
|
|
@@ -44715,7 +44855,7 @@ var copySchema = external_exports.object({
|
|
|
44715
44855
|
locales: external_exports.array(external_exports.string().refine(writtenInAScript, "a BCP 47 language tag, such as en or vi")).min(1).default(["en"]),
|
|
44716
44856
|
currencies: external_exports.array(external_exports.string().refine((code) => Intl.supportedValuesOf("currency").includes(code), "an ISO 4217 code, such as VND or USD")).default([])
|
|
44717
44857
|
}).strict();
|
|
44718
|
-
var
|
|
44858
|
+
var configShape = external_exports.object({
|
|
44719
44859
|
product: external_exports.string().min(1),
|
|
44720
44860
|
designSystem: designSystemSchema,
|
|
44721
44861
|
figma: files.default({}),
|
|
@@ -44727,7 +44867,8 @@ var zakuConfigSchema = external_exports.object({
|
|
|
44727
44867
|
budget: budgetSchema.default({ mcpPerDay: 200, mcpPerRun: 30, reserve: 0.2 }),
|
|
44728
44868
|
recipe: recipeSchema.optional(),
|
|
44729
44869
|
copy: copySchema.default(DEFAULT_COPY)
|
|
44730
|
-
}).strict()
|
|
44870
|
+
}).strict();
|
|
44871
|
+
var zakuConfigSchema = configShape.superRefine((config2, ctx) => {
|
|
44731
44872
|
for (const key of ["id", "name"]) {
|
|
44732
44873
|
const seen = /* @__PURE__ */ new Set();
|
|
44733
44874
|
config2.targets.forEach((target, index) => {
|
|
@@ -44741,7 +44882,112 @@ var zakuConfigSchema = external_exports.object({
|
|
|
44741
44882
|
seen.add(target[key]);
|
|
44742
44883
|
});
|
|
44743
44884
|
}
|
|
44885
|
+
if (byRole(config2.figma))
|
|
44886
|
+
refineFilesByRole(config2, ctx);
|
|
44744
44887
|
});
|
|
44888
|
+
function refineFilesByRole(config2, ctx) {
|
|
44889
|
+
const { figma } = config2;
|
|
44890
|
+
if (figma.library !== void 0 || figma.product !== void 0) {
|
|
44891
|
+
ctx.addIssue({
|
|
44892
|
+
code: "custom",
|
|
44893
|
+
path: ["figma"],
|
|
44894
|
+
message: "figma.library and figma.product describe one library and one product; list files by role instead"
|
|
44895
|
+
});
|
|
44896
|
+
}
|
|
44897
|
+
const kits = figma.kits ?? [];
|
|
44898
|
+
const libraries = figma.libraries ?? [];
|
|
44899
|
+
const products = figma.products ?? [];
|
|
44900
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44901
|
+
const lists = [
|
|
44902
|
+
["kits", kits],
|
|
44903
|
+
["libraries", libraries],
|
|
44904
|
+
["products", products],
|
|
44905
|
+
["prototypes", figma.prototypes ?? []]
|
|
44906
|
+
];
|
|
44907
|
+
for (const [list, entries] of lists) {
|
|
44908
|
+
entries.forEach((entry, index) => {
|
|
44909
|
+
if (seen.has(entry.key))
|
|
44910
|
+
ctx.addIssue({
|
|
44911
|
+
code: "custom",
|
|
44912
|
+
path: ["figma", list, index, "key"],
|
|
44913
|
+
message: `a second file with key ${entry.key}`
|
|
44914
|
+
});
|
|
44915
|
+
seen.add(entry.key);
|
|
44916
|
+
});
|
|
44917
|
+
}
|
|
44918
|
+
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
44919
|
+
const kitKeys = new Set(kits.map((kit) => kit.key));
|
|
44920
|
+
libraries.forEach((library, index) => {
|
|
44921
|
+
const path2 = ["figma", "libraries", index, "extends"];
|
|
44922
|
+
for (const key of library.extends) {
|
|
44923
|
+
const base = byKey.get(key);
|
|
44924
|
+
if (!base && !kitKeys.has(key)) {
|
|
44925
|
+
ctx.addIssue({
|
|
44926
|
+
code: "custom",
|
|
44927
|
+
path: path2,
|
|
44928
|
+
message: `${library.key} extends ${key}, which is no library or kit listed`
|
|
44929
|
+
});
|
|
44930
|
+
} else if (base?.layer === "components" && library.layer === "foundations") {
|
|
44931
|
+
ctx.addIssue({ code: "custom", path: path2, message: `foundations ${library.key} extends components ${key}` });
|
|
44932
|
+
} else if (base && !base.branches.some((branch) => library.branches.includes(branch))) {
|
|
44933
|
+
ctx.addIssue({
|
|
44934
|
+
code: "custom",
|
|
44935
|
+
path: path2,
|
|
44936
|
+
message: `${library.key} extends ${key}, which holds none of its branches`
|
|
44937
|
+
});
|
|
44938
|
+
}
|
|
44939
|
+
}
|
|
44940
|
+
});
|
|
44941
|
+
const cycle = findCycle(libraries);
|
|
44942
|
+
if (cycle)
|
|
44943
|
+
ctx.addIssue({ code: "custom", path: ["figma", "libraries"], message: `extends comes back: ${cycle}` });
|
|
44944
|
+
(figma.prototypes ?? []).forEach((prototype2, index) => {
|
|
44945
|
+
const path2 = ["figma", "prototypes", index];
|
|
44946
|
+
if (prototype2.product === void 0) {
|
|
44947
|
+
if (products.length > 1)
|
|
44948
|
+
ctx.addIssue({ code: "custom", path: [...path2, "product"], message: "name the product its frames come from" });
|
|
44949
|
+
return;
|
|
44950
|
+
}
|
|
44951
|
+
const product = products.find((candidate) => candidate.key === prototype2.product);
|
|
44952
|
+
if (!product) {
|
|
44953
|
+
ctx.addIssue({ code: "custom", path: [...path2, "product"], message: `no product with key ${prototype2.product}` });
|
|
44954
|
+
} else if (product.platform !== prototype2.platform) {
|
|
44955
|
+
ctx.addIssue({
|
|
44956
|
+
code: "custom",
|
|
44957
|
+
path: [...path2, "platform"],
|
|
44958
|
+
message: `${prototype2.platform}, and its product serves ${product.platform}`
|
|
44959
|
+
});
|
|
44960
|
+
}
|
|
44961
|
+
});
|
|
44962
|
+
config2.targets.forEach((target, index) => {
|
|
44963
|
+
const branch = target.branch ?? defaultBranch(target.family);
|
|
44964
|
+
const path2 = ["targets", index, "branch"];
|
|
44965
|
+
if (branch === void 0) {
|
|
44966
|
+
ctx.addIssue({ code: "custom", path: path2, message: `a ${target.family} target names its branch, ui or native` });
|
|
44967
|
+
} else if (libraries.length > 0 && !libraries.some((library) => library.branches.includes(branch))) {
|
|
44968
|
+
ctx.addIssue({ code: "custom", path: path2, message: `no library holds the ${branch} branch` });
|
|
44969
|
+
}
|
|
44970
|
+
});
|
|
44971
|
+
}
|
|
44972
|
+
function findCycle(libraries) {
|
|
44973
|
+
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
44974
|
+
const visit2 = (key, path2) => {
|
|
44975
|
+
if (path2.includes(key))
|
|
44976
|
+
return [...path2.slice(path2.indexOf(key)), key].join(" -> ");
|
|
44977
|
+
for (const next of byKey.get(key)?.extends ?? []) {
|
|
44978
|
+
const found = visit2(next, [...path2, key]);
|
|
44979
|
+
if (found)
|
|
44980
|
+
return found;
|
|
44981
|
+
}
|
|
44982
|
+
return void 0;
|
|
44983
|
+
};
|
|
44984
|
+
for (const library of libraries) {
|
|
44985
|
+
const found = visit2(library.key, []);
|
|
44986
|
+
if (found)
|
|
44987
|
+
return found;
|
|
44988
|
+
}
|
|
44989
|
+
return void 0;
|
|
44990
|
+
}
|
|
44745
44991
|
|
|
44746
44992
|
// packages/zaku/dist/lib/repositories/design-file.js
|
|
44747
44993
|
var import_yaml = __toESM(require_dist(), 1);
|
|
@@ -44782,6 +45028,12 @@ async function writeDesignFile(path2, value) {
|
|
|
44782
45028
|
|
|
44783
45029
|
// packages/zaku/dist/lib/repositories/design-paths.js
|
|
44784
45030
|
import { join as join2 } from "node:path";
|
|
45031
|
+
function librarySnapshotDir(paths, key) {
|
|
45032
|
+
if (key === null)
|
|
45033
|
+
return paths;
|
|
45034
|
+
const library = join2(paths.library, key);
|
|
45035
|
+
return { root: paths.root, library, libraryIndex: join2(library, "index.json"), legacyLibrary: null };
|
|
45036
|
+
}
|
|
44785
45037
|
function designPaths(root) {
|
|
44786
45038
|
return {
|
|
44787
45039
|
root,
|
|
@@ -44825,8 +45077,13 @@ var libraryItemSchema = external_exports.object({
|
|
|
44825
45077
|
fontFamily: external_exports.string().nullable(),
|
|
44826
45078
|
textStyleKey: external_exports.string().nullable(),
|
|
44827
45079
|
componentKey: external_exports.string().nullable(),
|
|
44828
|
-
bindings: external_exports.record(external_exports.string(), external_exports.string().nullable())
|
|
45080
|
+
bindings: external_exports.record(external_exports.string(), external_exports.string().nullable()),
|
|
45081
|
+
/** Every variable the layer's own properties are bound to, by id without its `VariableID:` prefix. */
|
|
45082
|
+
variableIds: external_exports.array(external_exports.string()).optional(),
|
|
45083
|
+
effectStyleKey: external_exports.string().optional()
|
|
44829
45084
|
}).strict();
|
|
45085
|
+
var variableKeySchema = external_exports.object({ key: external_exports.string(), local: external_exports.boolean() }).strict();
|
|
45086
|
+
var effectStyleSchema = external_exports.object({ key: external_exports.string(), name: external_exports.string() }).strict();
|
|
44830
45087
|
var libraryVariantSchema = external_exports.object({
|
|
44831
45088
|
key: external_exports.string(),
|
|
44832
45089
|
name: external_exports.string(),
|
|
@@ -44837,6 +45094,8 @@ var libraryComponentSchema = external_exports.object({
|
|
|
44837
45094
|
name: external_exports.string(),
|
|
44838
45095
|
key: external_exports.string(),
|
|
44839
45096
|
page: external_exports.string(),
|
|
45097
|
+
/** The branch of the view that holds it, in a file that holds several; none where it serves every branch. */
|
|
45098
|
+
branch: external_exports.string().optional(),
|
|
44840
45099
|
codePath: external_exports.string().nullable(),
|
|
44841
45100
|
map: external_exports.object({ props: external_exports.record(external_exports.string(), external_exports.string()), parts: external_exports.record(external_exports.string(), external_exports.string()) }).strict().nullable(),
|
|
44842
45101
|
variants: external_exports.array(libraryVariantSchema).min(1)
|
|
@@ -44856,12 +45115,22 @@ var libraryPartSchema = external_exports.object({
|
|
|
44856
45115
|
exportedAt: external_exports.string(),
|
|
44857
45116
|
components: external_exports.array(libraryComponentSchema),
|
|
44858
45117
|
textStyles: external_exports.array(textStyleSchema),
|
|
44859
|
-
tokens: external_exports.array(tokenSnapshotSchema)
|
|
45118
|
+
tokens: external_exports.array(tokenSnapshotSchema),
|
|
45119
|
+
/**
|
|
45120
|
+
* What the items' references resolve against, absent from a snapshot saved before they were recorded: each
|
|
45121
|
+
* variable id's key, the file's effect styles, and the keys of the components the file holds unpublished.
|
|
45122
|
+
*/
|
|
45123
|
+
variableKeys: external_exports.record(external_exports.string(), variableKeySchema).optional(),
|
|
45124
|
+
effectStyles: external_exports.array(effectStyleSchema).optional(),
|
|
45125
|
+
localComponents: external_exports.array(external_exports.string()).optional()
|
|
44860
45126
|
}).strict();
|
|
44861
45127
|
var variablePartSchema = external_exports.object({
|
|
44862
45128
|
exportedAt: external_exports.string(),
|
|
44863
45129
|
variables: external_exports.record(external_exports.string(), external_exports.string()),
|
|
44864
45130
|
textStyles: external_exports.array(textStyleSchema),
|
|
45131
|
+
/** Each variable's key, keyed like `variables`. */
|
|
45132
|
+
variableKeys: external_exports.record(external_exports.string(), variableKeySchema).optional(),
|
|
45133
|
+
effectStyles: external_exports.array(effectStyleSchema).optional(),
|
|
44865
45134
|
tokens: external_exports.array(external_exports.object({
|
|
44866
45135
|
combo: external_exports.record(external_exports.string(), external_exports.string()),
|
|
44867
45136
|
values: external_exports.record(external_exports.string(), external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]))
|
|
@@ -44872,10 +45141,17 @@ var variablePartSchema = external_exports.object({
|
|
|
44872
45141
|
key: external_exports.string(),
|
|
44873
45142
|
name: external_exports.string(),
|
|
44874
45143
|
page: external_exports.string(),
|
|
45144
|
+
/** The view that holds it: the frame directly on its page, where it sits in one. */
|
|
45145
|
+
frame: external_exports.string().optional(),
|
|
44875
45146
|
description: external_exports.string(),
|
|
44876
45147
|
set: external_exports.boolean()
|
|
44877
45148
|
}).strict()).optional()
|
|
44878
45149
|
}).strict();
|
|
45150
|
+
var kitSnapshotSchema = external_exports.object({
|
|
45151
|
+
key: external_exports.string(),
|
|
45152
|
+
family: external_exports.string(),
|
|
45153
|
+
components: external_exports.array(external_exports.object({ key: external_exports.string(), name: external_exports.string() }).strict())
|
|
45154
|
+
}).strict();
|
|
44879
45155
|
var librarySnapshotSchema = libraryPartSchema.extend({ source: external_exports.string(), version: external_exports.string() }).strict();
|
|
44880
45156
|
|
|
44881
45157
|
// packages/zaku/dist/lib/domain/library-files.js
|
|
@@ -44944,7 +45220,9 @@ function expandItem(stored, values) {
|
|
|
44944
45220
|
fontFamily: stored.fontFamily ?? null,
|
|
44945
45221
|
textStyleKey: stored.textStyleKey ?? null,
|
|
44946
45222
|
componentKey: stored.componentKey ?? null,
|
|
44947
|
-
bindings
|
|
45223
|
+
bindings,
|
|
45224
|
+
...stored.variableIds ? { variableIds: stored.variableIds } : {},
|
|
45225
|
+
...stored.effectStyleKey ? { effectStyleKey: stored.effectStyleKey } : {}
|
|
44948
45226
|
};
|
|
44949
45227
|
}
|
|
44950
45228
|
function compactItem(item, values) {
|
|
@@ -44960,6 +45238,10 @@ function compactItem(item, values) {
|
|
|
44960
45238
|
stored[field] = item[field];
|
|
44961
45239
|
if (item.glyph)
|
|
44962
45240
|
stored["glyph"] = item.glyph;
|
|
45241
|
+
if (item.variableIds)
|
|
45242
|
+
stored["variableIds"] = item.variableIds;
|
|
45243
|
+
if (item.effectStyleKey)
|
|
45244
|
+
stored["effectStyleKey"] = item.effectStyleKey;
|
|
44963
45245
|
const bindings = Object.fromEntries(Object.entries(item.bindings).filter(([name, value]) => value !== null || name === "glyph"));
|
|
44964
45246
|
if (Object.keys(bindings).length > 0)
|
|
44965
45247
|
stored["bindings"] = bindings;
|
|
@@ -45077,7 +45359,7 @@ async function writeText(path2, text) {
|
|
|
45077
45359
|
async function readLibrarySnapshot(paths) {
|
|
45078
45360
|
const index = await readOptionalDesignFile(paths.libraryIndex, libraryIndexSchema);
|
|
45079
45361
|
if (!index)
|
|
45080
|
-
return readOptionalDesignFile(paths.legacyLibrary, librarySnapshotSchema);
|
|
45362
|
+
return paths.legacyLibrary ? readOptionalDesignFile(paths.legacyLibrary, librarySnapshotSchema) : null;
|
|
45081
45363
|
const files2 = /* @__PURE__ */ new Map();
|
|
45082
45364
|
for (const component2 of index.components) {
|
|
45083
45365
|
const path2 = join3(paths.library, component2.file);
|
|
@@ -45118,12 +45400,49 @@ async function writeLibrarySnapshot(paths, snapshot) {
|
|
|
45118
45400
|
removed.push(file2);
|
|
45119
45401
|
}
|
|
45120
45402
|
await writeText(paths.libraryIndex, formatLibraryFile(index));
|
|
45121
|
-
if (await readText(paths.legacyLibrary) !== null) {
|
|
45403
|
+
if (paths.legacyLibrary && await readText(paths.legacyLibrary) !== null) {
|
|
45122
45404
|
await rm(paths.legacyLibrary);
|
|
45123
45405
|
removed.push(relative(paths.root, paths.legacyLibrary));
|
|
45124
45406
|
}
|
|
45125
45407
|
return { written, unchanged, removed };
|
|
45126
45408
|
}
|
|
45409
|
+
async function writeKitSnapshot(paths, kit) {
|
|
45410
|
+
await mkdir(paths.library, { recursive: true });
|
|
45411
|
+
const path2 = join3(paths.library, "kit.json");
|
|
45412
|
+
await writeText(path2, formatLibraryFile(kit));
|
|
45413
|
+
return path2;
|
|
45414
|
+
}
|
|
45415
|
+
async function readDesignSnapshots(paths, config2) {
|
|
45416
|
+
const graph = designGraph(config2);
|
|
45417
|
+
const libraries = {};
|
|
45418
|
+
const kits = {};
|
|
45419
|
+
const errors = [];
|
|
45420
|
+
const attempt = async (read) => {
|
|
45421
|
+
try {
|
|
45422
|
+
await read();
|
|
45423
|
+
} catch (error62) {
|
|
45424
|
+
if (!(error62 instanceof DesignFileInvalid))
|
|
45425
|
+
throw error62;
|
|
45426
|
+
errors.push(error62);
|
|
45427
|
+
}
|
|
45428
|
+
};
|
|
45429
|
+
for (const library of graph.libraries) {
|
|
45430
|
+
await attempt(async () => {
|
|
45431
|
+
const snapshot = await readLibrarySnapshot(librarySnapshotDir(paths, graph.legacy ? null : library.key));
|
|
45432
|
+
if (snapshot)
|
|
45433
|
+
libraries[library.key] = snapshot;
|
|
45434
|
+
});
|
|
45435
|
+
}
|
|
45436
|
+
for (const kit of graph.kits) {
|
|
45437
|
+
await attempt(async () => {
|
|
45438
|
+
const path2 = join3(librarySnapshotDir(paths, kit.key).library, "kit.json");
|
|
45439
|
+
const snapshot = await readOptionalDesignFile(path2, kitSnapshotSchema);
|
|
45440
|
+
if (snapshot)
|
|
45441
|
+
kits[kit.key] = snapshot;
|
|
45442
|
+
});
|
|
45443
|
+
}
|
|
45444
|
+
return { libraries, kits, errors };
|
|
45445
|
+
}
|
|
45127
45446
|
|
|
45128
45447
|
// packages/zaku/dist/lib/adapters/figma-rest-library.js
|
|
45129
45448
|
var DOCUMENTATION_PREFIXES = ["DS/"];
|
|
@@ -45197,6 +45516,23 @@ function strokeWeightsOf(node2) {
|
|
|
45197
45516
|
const weight = node2.strokeWeight ?? 0;
|
|
45198
45517
|
return [weight, weight, weight, weight];
|
|
45199
45518
|
}
|
|
45519
|
+
function aliasIds(node2) {
|
|
45520
|
+
const out = [];
|
|
45521
|
+
const visit2 = (value) => {
|
|
45522
|
+
if (Array.isArray(value))
|
|
45523
|
+
value.forEach(visit2);
|
|
45524
|
+
else if (value && typeof value === "object") {
|
|
45525
|
+
if ("id" in value && typeof value.id === "string")
|
|
45526
|
+
out.push(value.id.replace(/^VariableID:/, ""));
|
|
45527
|
+
else
|
|
45528
|
+
Object.values(value).forEach(visit2);
|
|
45529
|
+
}
|
|
45530
|
+
};
|
|
45531
|
+
visit2(node2.boundVariables);
|
|
45532
|
+
for (const paint of [...node2.fills ?? [], ...node2.strokes ?? []])
|
|
45533
|
+
visit2(paint.boundVariables);
|
|
45534
|
+
return [...new Set(out)];
|
|
45535
|
+
}
|
|
45200
45536
|
var GLYPH_TYPES = /* @__PURE__ */ new Set(["VECTOR", "BOOLEAN_OPERATION", "LINE", "ELLIPSE", "POLYGON", "STAR"]);
|
|
45201
45537
|
function glyphOf(instance, at) {
|
|
45202
45538
|
let text = false;
|
|
@@ -45236,6 +45572,9 @@ function itemsOf(root, at) {
|
|
|
45236
45572
|
const textStyle = node2.styles?.["text"];
|
|
45237
45573
|
const glyph = path2 !== "" && node2.type === "INSTANCE" ? glyphOf(node2, at) : null;
|
|
45238
45574
|
const componentId = node2.type === "INSTANCE" ? node2.componentId : path2 === "" ? node2.id : void 0;
|
|
45575
|
+
const variableIds = aliasIds(node2);
|
|
45576
|
+
const effectStyle = node2.styles?.["effect"];
|
|
45577
|
+
const effectStyleKey = effectStyle ? at.entry.styles[effectStyle]?.key : void 0;
|
|
45239
45578
|
out.push({
|
|
45240
45579
|
nodeId: node2.id,
|
|
45241
45580
|
path: path2,
|
|
@@ -45260,7 +45599,9 @@ function itemsOf(root, at) {
|
|
|
45260
45599
|
textColor: isText ? fill.binding : null,
|
|
45261
45600
|
radius: radiusName,
|
|
45262
45601
|
...glyph?.value ? { glyph: glyph.binding } : {}
|
|
45263
|
-
}
|
|
45602
|
+
},
|
|
45603
|
+
...variableIds.length > 0 ? { variableIds } : {},
|
|
45604
|
+
...effectStyleKey ? { effectStyleKey } : {}
|
|
45264
45605
|
});
|
|
45265
45606
|
if (path2 === "" || node2.type !== "INSTANCE") {
|
|
45266
45607
|
for (const child of node2.children ?? [])
|
|
@@ -45279,28 +45620,55 @@ function asPublished(component2) {
|
|
|
45279
45620
|
containing_frame: { pageName: component2.page }
|
|
45280
45621
|
};
|
|
45281
45622
|
}
|
|
45623
|
+
function viewBranch(view, branches) {
|
|
45624
|
+
const prefix = view?.split(" / ")[0];
|
|
45625
|
+
return view?.includes(" / ") && prefix !== void 0 && branches.includes(prefix) ? prefix : void 0;
|
|
45626
|
+
}
|
|
45627
|
+
function viewsByPage(document) {
|
|
45628
|
+
return new Map((document.children ?? []).map((page) => [
|
|
45629
|
+
page.name,
|
|
45630
|
+
(page.children ?? []).flatMap((view) => view.absoluteBoundingBox ? [{ name: view.name, box: view.absoluteBoundingBox }] : [])
|
|
45631
|
+
]));
|
|
45632
|
+
}
|
|
45633
|
+
function viewHolding(views, box) {
|
|
45634
|
+
if (!box)
|
|
45635
|
+
return void 0;
|
|
45636
|
+
return views.find(({ box: view }) => box.x >= view.x && box.y >= view.y && box.x < view.x + view.width && box.y < view.y + view.height)?.name;
|
|
45637
|
+
}
|
|
45282
45638
|
async function readLibrary(options) {
|
|
45283
|
-
const { rest, fileKey:
|
|
45639
|
+
const { rest, fileKey: fileKey3, part } = options;
|
|
45640
|
+
const branches = options.branches ?? [];
|
|
45641
|
+
const multiBranch = branches.length > 1;
|
|
45642
|
+
const exported = new Map((part.components ?? []).map((component2) => [component2.id, component2.frame]));
|
|
45284
45643
|
const listed = part.components ? {
|
|
45285
45644
|
sets: part.components.filter((component2) => component2.set).map(asPublished),
|
|
45286
45645
|
components: part.components.filter((component2) => !component2.set).map(asPublished)
|
|
45287
|
-
} : await rest.published(
|
|
45646
|
+
} : await rest.published(fileKey3);
|
|
45288
45647
|
const published = [
|
|
45289
45648
|
...listed.sets,
|
|
45290
45649
|
...listed.components.filter((component2) => !component2.containing_frame?.containingComponentSet)
|
|
45291
45650
|
].filter((meta3) => !DOCUMENTATION_PREFIXES.some((prefix) => meta3.name.startsWith(prefix)));
|
|
45292
|
-
const file2 = await rest.file(
|
|
45293
|
-
const
|
|
45651
|
+
const file2 = await rest.file(fileKey3, multiBranch ? 2 : 1);
|
|
45652
|
+
const views = multiBranch ? viewsByPage(file2.document) : /* @__PURE__ */ new Map();
|
|
45653
|
+
const response = published.length > 0 ? await rest.nodes(fileKey3, published.map((meta3) => meta3.node_id)) : { version: file2.version, nodes: {} };
|
|
45294
45654
|
const components = [];
|
|
45655
|
+
const localComponents = /* @__PURE__ */ new Set();
|
|
45656
|
+
for (const entry of Object.values(response.nodes))
|
|
45657
|
+
for (const meta3 of Object.values(entry?.components ?? {}))
|
|
45658
|
+
if (meta3.remote === false)
|
|
45659
|
+
localComponents.add(meta3.key);
|
|
45295
45660
|
for (const meta3 of published) {
|
|
45296
45661
|
const entry = response.nodes[meta3.node_id];
|
|
45297
45662
|
if (!entry)
|
|
45298
45663
|
continue;
|
|
45299
45664
|
const variantNodes = entry.document.type === "COMPONENT_SET" ? (entry.document.children ?? []).filter((child) => child.type === "COMPONENT") : [entry.document];
|
|
45665
|
+
const view = exported.has(meta3.node_id) ? exported.get(meta3.node_id) : viewHolding(views.get(meta3.containing_frame?.pageName ?? "") ?? [], entry.document.absoluteBoundingBox);
|
|
45666
|
+
const branch = multiBranch ? viewBranch(view, branches) : void 0;
|
|
45300
45667
|
components.push({
|
|
45301
45668
|
name: meta3.name,
|
|
45302
45669
|
key: meta3.key,
|
|
45303
45670
|
page: (meta3.containing_frame?.pageName ?? "").replace(/^\W+\s*/, ""),
|
|
45671
|
+
...branch ? { branch } : {},
|
|
45304
45672
|
...descriptionMap(meta3.description),
|
|
45305
45673
|
variants: variantNodes.map((variant) => ({
|
|
45306
45674
|
key: entry.components[variant.id]?.key ?? "",
|
|
@@ -45314,11 +45682,16 @@ async function readLibrary(options) {
|
|
|
45314
45682
|
});
|
|
45315
45683
|
}
|
|
45316
45684
|
return {
|
|
45317
|
-
source:
|
|
45685
|
+
source: fileKey3,
|
|
45318
45686
|
version: file2.version,
|
|
45319
45687
|
exportedAt: part.exportedAt,
|
|
45320
45688
|
components,
|
|
45321
45689
|
textStyles: part.textStyles,
|
|
45690
|
+
...part.variableKeys ? {
|
|
45691
|
+
variableKeys: part.variableKeys,
|
|
45692
|
+
effectStyles: part.effectStyles ?? [],
|
|
45693
|
+
localComponents: [...localComponents].sort()
|
|
45694
|
+
} : {},
|
|
45322
45695
|
tokens: part.tokens.map((token) => ({
|
|
45323
45696
|
combo: token.combo,
|
|
45324
45697
|
values: Object.fromEntries(Object.entries(token.values).map(([name, value]) => [
|
|
@@ -45328,16 +45701,57 @@ async function readLibrary(options) {
|
|
|
45328
45701
|
}))
|
|
45329
45702
|
};
|
|
45330
45703
|
}
|
|
45704
|
+
async function readKit(options) {
|
|
45705
|
+
const components = await options.rest.components(options.key);
|
|
45706
|
+
return {
|
|
45707
|
+
key: options.key,
|
|
45708
|
+
family: options.family,
|
|
45709
|
+
components: components.map((component2) => ({ key: component2.key, name: component2.name }))
|
|
45710
|
+
};
|
|
45711
|
+
}
|
|
45331
45712
|
|
|
45332
45713
|
// packages/zaku/dist/lib/handlers/save-library.js
|
|
45714
|
+
function librarySaveTarget(config2, key) {
|
|
45715
|
+
const graph = designGraph(config2);
|
|
45716
|
+
const keys = [...graph.libraries, ...graph.kits].map((file2) => file2.key);
|
|
45717
|
+
if (keys.length === 0) {
|
|
45718
|
+
const byRole2 = config2.figma.libraries !== void 0 || config2.figma.kits !== void 0;
|
|
45719
|
+
throw new FigmaFileKeyMissing(byRole2 ? "figma.libraries" : "figma.library");
|
|
45720
|
+
}
|
|
45721
|
+
const library = key === void 0 ? graph.libraries.length === 1 ? graph.libraries[0] : void 0 : void 0;
|
|
45722
|
+
if (library)
|
|
45723
|
+
return { kind: "library", library, legacy: graph.legacy };
|
|
45724
|
+
if (key === void 0)
|
|
45725
|
+
throw new LibraryKeyMissing(keys);
|
|
45726
|
+
const named = graph.libraries.find((candidate) => candidate.key === key);
|
|
45727
|
+
if (named)
|
|
45728
|
+
return { kind: "library", library: named, legacy: graph.legacy };
|
|
45729
|
+
const kit = graph.kits.find((candidate) => candidate.key === key);
|
|
45730
|
+
if (kit)
|
|
45731
|
+
return { kind: "kit", kit };
|
|
45732
|
+
throw new LibraryKeyMissing(keys, key);
|
|
45733
|
+
}
|
|
45333
45734
|
async function saveLibrary(options) {
|
|
45334
45735
|
const paths = designPaths(options.root);
|
|
45335
45736
|
const config2 = await readDesignFile(paths.config, zakuConfigSchema);
|
|
45336
|
-
const
|
|
45337
|
-
if (
|
|
45338
|
-
|
|
45339
|
-
|
|
45340
|
-
|
|
45737
|
+
const target = librarySaveTarget(config2, options.key);
|
|
45738
|
+
if (target.kind === "kit") {
|
|
45739
|
+
const at2 = librarySnapshotDir(paths, target.kit.key);
|
|
45740
|
+
const kit = await readKit({ rest: options.rest, key: target.kit.key, family: target.kit.family });
|
|
45741
|
+
await writeKitSnapshot(at2, kit);
|
|
45742
|
+
return { kind: "kit", dir: relative2(paths.root, at2.library), kit };
|
|
45743
|
+
}
|
|
45744
|
+
if (!options.part)
|
|
45745
|
+
throw new TypeError(`saving library ${target.library.key} needs the variables export`);
|
|
45746
|
+
const { key, branches } = target.library;
|
|
45747
|
+
const at = librarySnapshotDir(paths, target.legacy ? null : key);
|
|
45748
|
+
const snapshot = librarySnapshotSchema.parse(await readLibrary({ rest: options.rest, fileKey: key, part: options.part, branches }));
|
|
45749
|
+
return {
|
|
45750
|
+
kind: "library",
|
|
45751
|
+
dir: relative2(paths.root, at.library),
|
|
45752
|
+
snapshot,
|
|
45753
|
+
...await writeLibrarySnapshot(at, snapshot)
|
|
45754
|
+
};
|
|
45341
45755
|
}
|
|
45342
45756
|
var SaveLibraryHandler = class SaveLibraryHandler2 {
|
|
45343
45757
|
rest;
|
|
@@ -45346,7 +45760,12 @@ var SaveLibraryHandler = class SaveLibraryHandler2 {
|
|
|
45346
45760
|
this.rest = rest;
|
|
45347
45761
|
}
|
|
45348
45762
|
handle(command) {
|
|
45349
|
-
return saveLibrary({
|
|
45763
|
+
return saveLibrary({
|
|
45764
|
+
root: command.root,
|
|
45765
|
+
rest: this.rest,
|
|
45766
|
+
...command.key !== void 0 ? { key: command.key } : {},
|
|
45767
|
+
...command.part !== void 0 ? { part: command.part } : {}
|
|
45768
|
+
});
|
|
45350
45769
|
}
|
|
45351
45770
|
};
|
|
45352
45771
|
SaveLibraryHandler = __decorate2([
|
|
@@ -45356,9 +45775,10 @@ SaveLibraryHandler = __decorate2([
|
|
|
45356
45775
|
|
|
45357
45776
|
// packages/zaku/dist/lib/handlers/write-outline.js
|
|
45358
45777
|
var import_tsyringe4 = __toESM(require_cjs(), 1);
|
|
45778
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
45359
45779
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
45360
45780
|
import { mkdir as mkdir2, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
45361
|
-
import { dirname as dirname2 } from "node:path";
|
|
45781
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
45362
45782
|
|
|
45363
45783
|
// packages/zaku/dist/lib/domain/documentation-measures.js
|
|
45364
45784
|
var COVER = {
|
|
@@ -45866,6 +46286,9 @@ function indexTitles(maps) {
|
|
|
45866
46286
|
return { titles, duplicates };
|
|
45867
46287
|
}
|
|
45868
46288
|
|
|
46289
|
+
// packages/zaku/dist/lib/adapters/figma-rest-outline.js
|
|
46290
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
46291
|
+
|
|
45869
46292
|
// packages/zaku/dist/lib/domain/layer-names.js
|
|
45870
46293
|
var DEFAULT_NAMES = {
|
|
45871
46294
|
FRAME: ["Frame"],
|
|
@@ -45934,7 +46357,7 @@ function outlineFrame(frame, where, ctx) {
|
|
|
45934
46357
|
const images2 = [];
|
|
45935
46358
|
const defaultNames = [];
|
|
45936
46359
|
const links = [];
|
|
45937
|
-
const
|
|
46360
|
+
const relative3 = (node2) => {
|
|
45938
46361
|
const box = node2.absoluteBoundingBox;
|
|
45939
46362
|
return box ? { x: box.x - origin.x, y: box.y - origin.y, width: box.width, height: box.height } : null;
|
|
45940
46363
|
};
|
|
@@ -45963,7 +46386,7 @@ function outlineFrame(frame, where, ctx) {
|
|
|
45963
46386
|
componentKey: ctx.components[child.componentId ?? ""]?.key ?? "",
|
|
45964
46387
|
component: component2,
|
|
45965
46388
|
interactive: ctx.interactive.has(component2),
|
|
45966
|
-
bounds:
|
|
46389
|
+
bounds: relative3(child)
|
|
45967
46390
|
});
|
|
45968
46391
|
} else if (child.type === "TEXT") {
|
|
45969
46392
|
instance.texts.push({
|
|
@@ -46004,7 +46427,7 @@ function outlineFrame(frame, where, ctx) {
|
|
|
46004
46427
|
texts: [],
|
|
46005
46428
|
interactive: ctx.interactive.has(component2),
|
|
46006
46429
|
local: meta3?.remote === false,
|
|
46007
|
-
bounds:
|
|
46430
|
+
bounds: relative3(node2),
|
|
46008
46431
|
sizing: {
|
|
46009
46432
|
horizontal: node2.layoutSizingHorizontal ?? "FIXED",
|
|
46010
46433
|
vertical: node2.layoutSizingVertical ?? "FIXED"
|
|
@@ -46053,6 +46476,17 @@ function outlineFrame(frame, where, ctx) {
|
|
|
46053
46476
|
links.push(...linksOf(frame));
|
|
46054
46477
|
for (const child of shown(frame))
|
|
46055
46478
|
walk(child);
|
|
46479
|
+
const drawn = {
|
|
46480
|
+
size: [origin.width, origin.height],
|
|
46481
|
+
instances: instances.map((instance) => [
|
|
46482
|
+
instance.componentKey,
|
|
46483
|
+
instance.variant,
|
|
46484
|
+
instance.properties,
|
|
46485
|
+
instance.texts.map((text) => text.characters),
|
|
46486
|
+
instance.bounds
|
|
46487
|
+
]),
|
|
46488
|
+
texts: texts.map((text) => text.characters)
|
|
46489
|
+
};
|
|
46056
46490
|
return {
|
|
46057
46491
|
nodeId: frame.id,
|
|
46058
46492
|
name: frame.name,
|
|
@@ -46066,7 +46500,8 @@ function outlineFrame(frame, where, ctx) {
|
|
|
46066
46500
|
raw,
|
|
46067
46501
|
images: images2,
|
|
46068
46502
|
defaultNames,
|
|
46069
|
-
links
|
|
46503
|
+
links,
|
|
46504
|
+
digest: createHash2("sha256").update(JSON.stringify(drawn)).digest("hex").slice(0, 16)
|
|
46070
46505
|
};
|
|
46071
46506
|
}
|
|
46072
46507
|
|
|
@@ -46132,36 +46567,78 @@ var frameOutlineSchema = external_exports.object({
|
|
|
46132
46567
|
raw: external_exports.array(rawOutlineSchema),
|
|
46133
46568
|
images: external_exports.array(imageOutlineSchema),
|
|
46134
46569
|
defaultNames: external_exports.array(external_exports.object({ nodeId: external_exports.string(), name: external_exports.string() }).strict()),
|
|
46135
|
-
links: external_exports.array(linkOutlineSchema)
|
|
46570
|
+
links: external_exports.array(linkOutlineSchema),
|
|
46571
|
+
/** In a product file of one page per screen: the page the frame is on, and the product file it is in. */
|
|
46572
|
+
page: external_exports.string().optional(),
|
|
46573
|
+
source: external_exports.string().optional(),
|
|
46574
|
+
/** What the frame draws, without its node ids, so a copy and its source digest alike. */
|
|
46575
|
+
digest: external_exports.string().optional()
|
|
46576
|
+
}).strict();
|
|
46577
|
+
var flowOutlineSchema = external_exports.object({
|
|
46578
|
+
/** The Figma file key the page is in. */
|
|
46579
|
+
source: external_exports.string(),
|
|
46580
|
+
page: external_exports.string(),
|
|
46581
|
+
fileVersion: external_exports.string(),
|
|
46582
|
+
frames: external_exports.array(external_exports.object({
|
|
46583
|
+
nodeId: external_exports.string(),
|
|
46584
|
+
name: external_exports.string(),
|
|
46585
|
+
screen: external_exports.string().nullable(),
|
|
46586
|
+
target: external_exports.string(),
|
|
46587
|
+
state: external_exports.string(),
|
|
46588
|
+
start: external_exports.boolean(),
|
|
46589
|
+
links: external_exports.array(linkOutlineSchema),
|
|
46590
|
+
digest: external_exports.string()
|
|
46591
|
+
}).strict())
|
|
46136
46592
|
}).strict();
|
|
46137
|
-
var
|
|
46593
|
+
var LEGACY_LIBRARY_VERSION = "figma.library";
|
|
46594
|
+
function legacyVersion(value) {
|
|
46595
|
+
if (value === null || typeof value !== "object" || !("libraryVersion" in value))
|
|
46596
|
+
return value;
|
|
46597
|
+
const { libraryVersion, ...rest } = value;
|
|
46598
|
+
return {
|
|
46599
|
+
...rest,
|
|
46600
|
+
libraryVersions: typeof libraryVersion === "string" ? { [LEGACY_LIBRARY_VERSION]: libraryVersion } : {}
|
|
46601
|
+
};
|
|
46602
|
+
}
|
|
46603
|
+
var screenOutlineSchema = external_exports.preprocess(legacyVersion, external_exports.object({
|
|
46138
46604
|
feature: external_exports.string(),
|
|
46139
46605
|
screen: external_exports.string(),
|
|
46140
46606
|
/** The Figma file key the frames were read from. */
|
|
46141
46607
|
source: external_exports.string(),
|
|
46142
46608
|
fileVersion: external_exports.string(),
|
|
46143
46609
|
mapDigest: external_exports.string(),
|
|
46144
|
-
|
|
46610
|
+
/** The version of each library snapshot the frames were read against, by key. */
|
|
46611
|
+
libraryVersions: external_exports.record(external_exports.string(), external_exports.string()),
|
|
46612
|
+
/** The version of every product file zaku.yaml lists, when it lists them by platform. */
|
|
46613
|
+
fileVersions: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
46145
46614
|
frames: external_exports.array(frameOutlineSchema)
|
|
46146
|
-
}).strict();
|
|
46615
|
+
}).strict());
|
|
46147
46616
|
var unmappedSchema = external_exports.object({
|
|
46148
46617
|
fileVersion: external_exports.string(),
|
|
46149
|
-
frames: external_exports.array(external_exports.object({ nodeId: external_exports.string(), name: external_exports.string() }).strict())
|
|
46618
|
+
frames: external_exports.array(external_exports.object({ nodeId: external_exports.string(), name: external_exports.string() }).strict()),
|
|
46619
|
+
/** A component drawn on a product page, which belongs in a Components library. */
|
|
46620
|
+
components: external_exports.array(external_exports.object({ nodeId: external_exports.string(), name: external_exports.string(), page: external_exports.string(), source: external_exports.string() }).strict()).optional()
|
|
46150
46621
|
}).strict();
|
|
46151
46622
|
|
|
46152
46623
|
// packages/zaku/dist/lib/repositories/outlines.js
|
|
46624
|
+
var FLOWS_DIR = "flows";
|
|
46625
|
+
function flowOutlinePath(dir, source, page) {
|
|
46626
|
+
const slug2 = page.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "page";
|
|
46627
|
+
return join5(dir, FLOWS_DIR, source, `${slug2}.yaml`);
|
|
46628
|
+
}
|
|
46153
46629
|
function outlinePath(dir, feature, screen) {
|
|
46154
46630
|
return join5(dir, feature, `${screen}.yaml`);
|
|
46155
46631
|
}
|
|
46156
46632
|
async function loadOutlines(dir) {
|
|
46157
46633
|
const outlines = [];
|
|
46634
|
+
const flows = [];
|
|
46158
46635
|
const errors = [];
|
|
46159
46636
|
let features;
|
|
46160
46637
|
try {
|
|
46161
|
-
features = (await readdir3(dir, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
46638
|
+
features = (await readdir3(dir, { withFileTypes: true })).filter((entry) => entry.isDirectory() && entry.name !== FLOWS_DIR).map((entry) => entry.name).sort();
|
|
46162
46639
|
} catch (error62) {
|
|
46163
46640
|
if (error62.code === "ENOENT")
|
|
46164
|
-
return { outlines, unmapped: null, errors };
|
|
46641
|
+
return { outlines, flows, unmapped: null, errors };
|
|
46165
46642
|
throw error62;
|
|
46166
46643
|
}
|
|
46167
46644
|
for (const feature of features) {
|
|
@@ -46177,6 +46654,24 @@ async function loadOutlines(dir) {
|
|
|
46177
46654
|
}
|
|
46178
46655
|
}
|
|
46179
46656
|
}
|
|
46657
|
+
const sources = await readdir3(join5(dir, FLOWS_DIR)).catch((error62) => {
|
|
46658
|
+
if (error62.code === "ENOENT")
|
|
46659
|
+
return [];
|
|
46660
|
+
throw error62;
|
|
46661
|
+
});
|
|
46662
|
+
for (const source of sources.sort()) {
|
|
46663
|
+
const files2 = (await readdir3(join5(dir, FLOWS_DIR, source))).filter((name) => name.endsWith(".yaml")).sort();
|
|
46664
|
+
for (const file2 of files2) {
|
|
46665
|
+
try {
|
|
46666
|
+
flows.push(await readDesignFile(join5(dir, FLOWS_DIR, source, file2), flowOutlineSchema));
|
|
46667
|
+
} catch (error62) {
|
|
46668
|
+
if (error62 instanceof DesignFileInvalid)
|
|
46669
|
+
errors.push(error62);
|
|
46670
|
+
else
|
|
46671
|
+
throw error62;
|
|
46672
|
+
}
|
|
46673
|
+
}
|
|
46674
|
+
}
|
|
46180
46675
|
let unmapped = null;
|
|
46181
46676
|
try {
|
|
46182
46677
|
unmapped = await readOptionalDesignFile(join5(dir, "unmapped.yaml"), unmappedSchema);
|
|
@@ -46186,7 +46681,7 @@ async function loadOutlines(dir) {
|
|
|
46186
46681
|
else
|
|
46187
46682
|
throw error62;
|
|
46188
46683
|
}
|
|
46189
|
-
return { outlines, unmapped, errors };
|
|
46684
|
+
return { outlines, flows, unmapped, errors };
|
|
46190
46685
|
}
|
|
46191
46686
|
|
|
46192
46687
|
// packages/zaku/dist/lib/handlers/write-outline.js
|
|
@@ -46223,95 +46718,202 @@ function resolveFrame(frame, parsed, maps) {
|
|
|
46223
46718
|
return candidates.find((ref) => ref.feature === pageFeature);
|
|
46224
46719
|
return candidates.length === 1 ? candidates[0] : void 0;
|
|
46225
46720
|
}
|
|
46721
|
+
function resolveTitle(parsed, maps) {
|
|
46722
|
+
const candidates = [...indexScreens(maps).values()].filter((ref) => ref.screen.title === parsed.title);
|
|
46723
|
+
return candidates.length === 1 ? candidates[0] : void 0;
|
|
46724
|
+
}
|
|
46226
46725
|
function looksLikeScreenFrame(name) {
|
|
46227
46726
|
return name.includes("/");
|
|
46228
46727
|
}
|
|
46229
|
-
function holdsScreens(page) {
|
|
46728
|
+
function holdsScreens(page, prototypes = /* @__PURE__ */ new Set()) {
|
|
46230
46729
|
if (page === COVER.page || page === DOCUMENTATION_COMPONENTS_PAGE || page === DIRECTIONS_PAGE)
|
|
46231
46730
|
return false;
|
|
46731
|
+
if (prototypes.has(page))
|
|
46732
|
+
return false;
|
|
46232
46733
|
return !page.startsWith("\u2756 ") && !page.includes(" / ") && !/^-+$/.test(page);
|
|
46233
46734
|
}
|
|
46735
|
+
function listComponents(document, source) {
|
|
46736
|
+
const out = [];
|
|
46737
|
+
for (const page of document.children ?? []) {
|
|
46738
|
+
if (page.type !== "CANVAS" || !holdsScreens(page.name))
|
|
46739
|
+
continue;
|
|
46740
|
+
const walk = (node2) => {
|
|
46741
|
+
for (const child of node2.children ?? []) {
|
|
46742
|
+
if (child.type === "COMPONENT" || child.type === "COMPONENT_SET")
|
|
46743
|
+
out.push({ nodeId: child.id, name: child.name, page: page.name, source });
|
|
46744
|
+
else if (child.type === "SECTION")
|
|
46745
|
+
walk(child);
|
|
46746
|
+
}
|
|
46747
|
+
};
|
|
46748
|
+
walk(page);
|
|
46749
|
+
}
|
|
46750
|
+
return out;
|
|
46751
|
+
}
|
|
46752
|
+
function productFiles(config2) {
|
|
46753
|
+
const graph = designGraph(config2);
|
|
46754
|
+
if (graph.legacy)
|
|
46755
|
+
return config2.figma.product === void 0 ? [] : [{ key: config2.figma.product, targets: config2.targets }];
|
|
46756
|
+
return graph.products.map((product) => ({
|
|
46757
|
+
key: product.key,
|
|
46758
|
+
targets: config2.targets.filter((target) => graph.platformOf(target) === product.platform)
|
|
46759
|
+
}));
|
|
46760
|
+
}
|
|
46234
46761
|
async function runOutline(options) {
|
|
46235
46762
|
const paths = designPaths(options.root);
|
|
46236
46763
|
const config2 = await readDesignFile(paths.config, zakuConfigSchema);
|
|
46237
|
-
const
|
|
46238
|
-
|
|
46239
|
-
|
|
46764
|
+
const { libraries: listed, kits, products: byPlatform, prototypes: flows } = config2.figma;
|
|
46765
|
+
const legacy = [listed, kits, byPlatform, flows].every((files2) => files2 === void 0);
|
|
46766
|
+
const products = productFiles(config2);
|
|
46767
|
+
if (products.length === 0)
|
|
46768
|
+
throw new FigmaFileKeyMissing(legacy ? "figma.product" : "figma.products");
|
|
46240
46769
|
const { maps, errors } = await loadMaps(paths.maps);
|
|
46241
46770
|
if (errors[0])
|
|
46242
46771
|
throw errors[0];
|
|
46243
46772
|
const digests = new Map(maps.map((loaded) => [loaded.map.feature, loaded.digest]));
|
|
46244
|
-
const
|
|
46773
|
+
const { libraries } = await readDesignSnapshots(paths, config2);
|
|
46774
|
+
const libraryVersions = Object.fromEntries(Object.entries(libraries).map(([key, library]) => [key, library.version]));
|
|
46245
46775
|
const existing = await loadOutlines(paths.outline);
|
|
46246
|
-
const
|
|
46247
|
-
const
|
|
46776
|
+
const prototypes = new Set(legacy ? config2.targets.map((target) => `${target.name} prototype`) : []);
|
|
46777
|
+
const versions = {};
|
|
46778
|
+
const flowPages = /* @__PURE__ */ new Map();
|
|
46779
|
+
const flowFrame = (source, frame, targets) => {
|
|
46780
|
+
const parsed = parseFrameName(frame.name, targets);
|
|
46781
|
+
if (!parsed)
|
|
46782
|
+
return;
|
|
46783
|
+
const key = `${source}
|
|
46784
|
+
${frame.page}`;
|
|
46785
|
+
const page = flowPages.get(key) ?? { source, page: frame.page, frames: [] };
|
|
46786
|
+
page.frames.push({ frame, parsed });
|
|
46787
|
+
flowPages.set(key, page);
|
|
46788
|
+
};
|
|
46248
46789
|
const resolved = /* @__PURE__ */ new Map();
|
|
46249
|
-
const unmapped = { fileVersion:
|
|
46250
|
-
|
|
46251
|
-
|
|
46252
|
-
|
|
46253
|
-
|
|
46790
|
+
const unmapped = { fileVersion: "", frames: [] };
|
|
46791
|
+
const components = [];
|
|
46792
|
+
for (const product of products) {
|
|
46793
|
+
const file2 = await options.rest.file(product.key, INDEX_DEPTH);
|
|
46794
|
+
versions[product.key] = file2.version;
|
|
46795
|
+
const listed2 = listFrames(file2.document);
|
|
46796
|
+
for (const frame of listed2.filter((candidate) => prototypes.has(candidate.page)))
|
|
46797
|
+
flowFrame(product.key, frame, product.targets);
|
|
46798
|
+
for (const frame of listed2.filter((candidate) => holdsScreens(candidate.page, prototypes))) {
|
|
46799
|
+
const parsed = parseFrameName(frame.name, product.targets);
|
|
46800
|
+
if (!parsed) {
|
|
46801
|
+
if (looksLikeScreenFrame(frame.name))
|
|
46802
|
+
unmapped.frames.push({ nodeId: frame.id, name: frame.name });
|
|
46803
|
+
continue;
|
|
46804
|
+
}
|
|
46805
|
+
const ref = legacy ? resolveFrame(frame, parsed, maps) : resolveTitle(parsed, maps);
|
|
46806
|
+
if (ref)
|
|
46807
|
+
resolved.set(frame.id, { frame, parsed, ref, source: product.key });
|
|
46808
|
+
else
|
|
46254
46809
|
unmapped.frames.push({ nodeId: frame.id, name: frame.name });
|
|
46255
|
-
continue;
|
|
46256
46810
|
}
|
|
46257
|
-
|
|
46258
|
-
|
|
46259
|
-
|
|
46260
|
-
|
|
46261
|
-
|
|
46811
|
+
if (!legacy)
|
|
46812
|
+
components.push(...listComponents(file2.document, product.key));
|
|
46813
|
+
}
|
|
46814
|
+
const graph = designGraph(config2);
|
|
46815
|
+
for (const file2 of legacy ? [] : graph.prototypes) {
|
|
46816
|
+
const read = await options.rest.file(file2.key, INDEX_DEPTH);
|
|
46817
|
+
versions[file2.key] = read.version;
|
|
46818
|
+
const targets = config2.targets.filter((target) => graph.platformOf(target) === file2.platform);
|
|
46819
|
+
for (const frame of listFrames(read.document).filter((candidate) => holdsScreens(candidate.page)))
|
|
46820
|
+
flowFrame(file2.key, frame, targets);
|
|
46262
46821
|
}
|
|
46822
|
+
unmapped.fileVersion = Object.values(versions).join(",");
|
|
46823
|
+
if (!legacy)
|
|
46824
|
+
unmapped.components = components;
|
|
46263
46825
|
const outlined = new Set(existing.outlines.flatMap((outline) => outline.frames.map((frame) => frame.nodeId)));
|
|
46264
46826
|
const drawnScreens = new Set([...resolved.values()].map(({ ref }) => `${ref.feature}/${ref.id}`));
|
|
46265
|
-
const current = existing.outlines.every((outline) => outline.fileVersion ===
|
|
46827
|
+
const current = existing.outlines.every((outline) => (legacy ? outline.fileVersion === versions[outline.source] : isDeepStrictEqual2(outline.fileVersions, versions)) && outline.mapDigest === digests.get(outline.feature) && isDeepStrictEqual2(outline.libraryVersions, libraryVersions)) && [...resolved.keys()].every((id2) => outlined.has(id2)) && existing.flows.length === flowPages.size && existing.flows.every((flow) => flow.fileVersion === versions[flow.source]) && existing.outlines.every((outline) => drawnScreens.has(`${outline.feature}/${outline.screen}`));
|
|
46266
46828
|
if (options.frames === null && existing.outlines.length > 0 && current) {
|
|
46267
46829
|
return { skipped: true, read: 0, written: [], unmapped: unmapped.frames.length };
|
|
46268
46830
|
}
|
|
46269
46831
|
const ids = options.frames ?? [...resolved.keys()];
|
|
46270
|
-
const response = ids.length > 0 ? await options.rest.nodes(fileKey2, ids) : { version: file2.version, nodes: {} };
|
|
46271
46832
|
const byScreen = /* @__PURE__ */ new Map();
|
|
46272
46833
|
if (options.frames !== null) {
|
|
46273
46834
|
for (const outline of existing.outlines)
|
|
46274
46835
|
byScreen.set(`${outline.feature}/${outline.screen}`, outline);
|
|
46275
46836
|
}
|
|
46276
46837
|
const interactive = new Set(config2.interactive);
|
|
46277
|
-
|
|
46278
|
-
|
|
46279
|
-
|
|
46280
|
-
const read = await options.rest.nodes(fileKey2, [...resized]);
|
|
46281
|
-
for (const [id2, entry] of Object.entries(read.nodes)) {
|
|
46282
|
-
const box = entry?.document.absoluteBoundingBox;
|
|
46283
|
-
if (box)
|
|
46284
|
-
sizes.set(id2, { width: box.width, height: box.height });
|
|
46285
|
-
}
|
|
46286
|
-
}
|
|
46287
|
-
for (const [id2, entry] of Object.entries(response.nodes)) {
|
|
46288
|
-
const found = resolved.get(id2);
|
|
46289
|
-
if (!entry || !found)
|
|
46838
|
+
for (const product of products) {
|
|
46839
|
+
const own2 = ids.filter((id2) => resolved.has(id2) ? resolved.get(id2)?.source === product.key : product === products[0]);
|
|
46840
|
+
if (own2.length === 0)
|
|
46290
46841
|
continue;
|
|
46291
|
-
const
|
|
46292
|
-
const
|
|
46293
|
-
const
|
|
46294
|
-
|
|
46295
|
-
|
|
46296
|
-
|
|
46297
|
-
|
|
46298
|
-
|
|
46299
|
-
|
|
46300
|
-
|
|
46301
|
-
}
|
|
46302
|
-
const
|
|
46303
|
-
|
|
46304
|
-
|
|
46305
|
-
|
|
46306
|
-
|
|
46307
|
-
|
|
46308
|
-
|
|
46309
|
-
|
|
46310
|
-
|
|
46311
|
-
|
|
46312
|
-
|
|
46842
|
+
const response = await options.rest.nodes(product.key, own2);
|
|
46843
|
+
const resized = new Set(Object.values(response.nodes).flatMap((entry) => entry ? resizedLocalComponents(entry.document, entry.components) : []));
|
|
46844
|
+
const sizes = /* @__PURE__ */ new Map();
|
|
46845
|
+
if (resized.size > 0) {
|
|
46846
|
+
const read = await options.rest.nodes(product.key, [...resized]);
|
|
46847
|
+
for (const [id2, entry] of Object.entries(read.nodes)) {
|
|
46848
|
+
const box = entry?.document.absoluteBoundingBox;
|
|
46849
|
+
if (box)
|
|
46850
|
+
sizes.set(id2, { width: box.width, height: box.height });
|
|
46851
|
+
}
|
|
46852
|
+
}
|
|
46853
|
+
for (const [id2, entry] of Object.entries(response.nodes)) {
|
|
46854
|
+
const found = resolved.get(id2);
|
|
46855
|
+
if (!entry || !found)
|
|
46856
|
+
continue;
|
|
46857
|
+
const { frame: place, parsed, ref } = found;
|
|
46858
|
+
const key = `${ref.feature}/${ref.id}`;
|
|
46859
|
+
const outline = byScreen.get(key) ?? {
|
|
46860
|
+
feature: ref.feature,
|
|
46861
|
+
screen: ref.id,
|
|
46862
|
+
source: product.key,
|
|
46863
|
+
fileVersion: versions[product.key] ?? "",
|
|
46864
|
+
mapDigest: "",
|
|
46865
|
+
libraryVersions: {},
|
|
46866
|
+
frames: []
|
|
46867
|
+
};
|
|
46868
|
+
const frame = outlineFrame(entry.document, {
|
|
46869
|
+
target: parsed.target.id,
|
|
46870
|
+
state: parsed.state,
|
|
46871
|
+
containers: place.containers,
|
|
46872
|
+
start: place.start
|
|
46873
|
+
}, { ...entry, interactive, sizes });
|
|
46874
|
+
if (!legacy)
|
|
46875
|
+
Object.assign(frame, { page: place.page, source: product.key });
|
|
46876
|
+
outline.frames = [...outline.frames.filter((kept) => kept.nodeId !== id2), frame].sort((a, b) => a.name.localeCompare(b.name));
|
|
46877
|
+
outline.mapDigest = digests.get(ref.feature) ?? "";
|
|
46878
|
+
outline.libraryVersions = libraryVersions;
|
|
46879
|
+
if (legacy)
|
|
46880
|
+
outline.fileVersion = versions[product.key] ?? "";
|
|
46881
|
+
else
|
|
46882
|
+
outline.fileVersions = versions;
|
|
46883
|
+
byScreen.set(key, outline);
|
|
46884
|
+
}
|
|
46313
46885
|
}
|
|
46314
46886
|
if (options.frames === null) {
|
|
46887
|
+
await rm2(join6(paths.outline, FLOWS_DIR), { recursive: true, force: true });
|
|
46888
|
+
for (const page of flowPages.values()) {
|
|
46889
|
+
const response = await options.rest.nodes(page.source, page.frames.map(({ frame }) => frame.id));
|
|
46890
|
+
const flow = {
|
|
46891
|
+
source: page.source,
|
|
46892
|
+
page: page.page,
|
|
46893
|
+
fileVersion: versions[page.source] ?? "",
|
|
46894
|
+
frames: []
|
|
46895
|
+
};
|
|
46896
|
+
for (const { frame, parsed } of page.frames) {
|
|
46897
|
+
const entry = response.nodes[frame.id];
|
|
46898
|
+
if (!entry)
|
|
46899
|
+
continue;
|
|
46900
|
+
const read = outlineFrame(entry.document, { target: parsed.target.id, state: parsed.state, containers: frame.containers, start: frame.start }, { ...entry, interactive, sizes: /* @__PURE__ */ new Map() });
|
|
46901
|
+
const ref = resolveTitle(parsed, maps);
|
|
46902
|
+
flow.frames.push({
|
|
46903
|
+
nodeId: frame.id,
|
|
46904
|
+
name: frame.name,
|
|
46905
|
+
screen: ref ? `${ref.feature}/${ref.id}` : null,
|
|
46906
|
+
target: parsed.target.id,
|
|
46907
|
+
state: parsed.state,
|
|
46908
|
+
start: frame.start,
|
|
46909
|
+
links: read.links,
|
|
46910
|
+
digest: read.digest ?? ""
|
|
46911
|
+
});
|
|
46912
|
+
}
|
|
46913
|
+
const path2 = flowOutlinePath(paths.outline, page.source, page.page);
|
|
46914
|
+
await mkdir2(dirname2(path2), { recursive: true });
|
|
46915
|
+
await writeFile3(path2, (0, import_yaml2.stringify)(flow));
|
|
46916
|
+
}
|
|
46315
46917
|
for (const outline of existing.outlines) {
|
|
46316
46918
|
if (!byScreen.has(`${outline.feature}/${outline.screen}`))
|
|
46317
46919
|
await rm2(outlinePath(paths.outline, outline.feature, outline.screen), { force: true });
|
|
@@ -46441,13 +47043,13 @@ RecipeRepository = __decorate2([
|
|
|
46441
47043
|
// packages/zaku/dist/lib/repositories/json-schema-files.js
|
|
46442
47044
|
var import_tsyringe10 = __toESM(require_cjs(), 1);
|
|
46443
47045
|
import { mkdir as mkdir3 } from "node:fs/promises";
|
|
46444
|
-
import { join as
|
|
47046
|
+
import { join as join7 } from "node:path";
|
|
46445
47047
|
var JsonSchemaFiles = class JsonSchemaFiles2 {
|
|
46446
47048
|
async write(dir, schemas) {
|
|
46447
47049
|
await mkdir3(dir, { recursive: true });
|
|
46448
47050
|
const written = [];
|
|
46449
47051
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
46450
|
-
const path2 =
|
|
47052
|
+
const path2 = join7(dir, name);
|
|
46451
47053
|
await writeDesignFile(path2, schema);
|
|
46452
47054
|
written.push(path2);
|
|
46453
47055
|
}
|
|
@@ -46475,10 +47077,10 @@ SourceFiles = __decorate2([
|
|
|
46475
47077
|
|
|
46476
47078
|
// packages/zaku/dist/lib/repositories/budget-ledger.js
|
|
46477
47079
|
import { mkdir as mkdir4, readFile as readFile5, rename as rename3, writeFile as writeFile4 } from "node:fs/promises";
|
|
46478
|
-
import { dirname as dirname3, join as
|
|
47080
|
+
import { dirname as dirname3, join as join8 } from "node:path";
|
|
46479
47081
|
function ledgerPath(env, platform, home) {
|
|
46480
|
-
const cache = env["XDG_CACHE_HOME"] ?? (platform === "darwin" ?
|
|
46481
|
-
return
|
|
47082
|
+
const cache = env["XDG_CACHE_HOME"] ?? (platform === "darwin" ? join8(home, "Library", "Caches") : join8(home, ".cache"));
|
|
47083
|
+
return join8(cache, "zaku", "ledger.json");
|
|
46482
47084
|
}
|
|
46483
47085
|
function today(now) {
|
|
46484
47086
|
return now.toISOString().slice(0, 10);
|
|
@@ -46547,6 +47149,30 @@ var pairingSchema = external_exports.object({
|
|
|
46547
47149
|
}).strict();
|
|
46548
47150
|
var pairingsFileSchema = external_exports.object({ pairings: external_exports.array(pairingSchema.extend({ hash: external_exports.string() }).strict()) }).strict();
|
|
46549
47151
|
|
|
47152
|
+
// packages/zaku/dist/lib/domain/print-graph.js
|
|
47153
|
+
function printGraph(config2, snapshots) {
|
|
47154
|
+
const graph = designGraph(config2);
|
|
47155
|
+
const lines = ["targets"];
|
|
47156
|
+
for (const target of config2.targets) {
|
|
47157
|
+
const files2 = [
|
|
47158
|
+
...graph.librariesFor(target).map((library) => `${library.key} ${library.layer}`),
|
|
47159
|
+
...graph.kitsFor(target).map((kit) => `${kit.key} ${kit.family} kit`)
|
|
47160
|
+
];
|
|
47161
|
+
const branch = graph.branchOf(target);
|
|
47162
|
+
lines.push(` ${target.name} (${target.id}, ${branch ? `branch ${branch}` : "no branch"}, ${graph.platformOf(target)}): ${files2.join(", ") || "nothing"}`);
|
|
47163
|
+
}
|
|
47164
|
+
lines.push("files");
|
|
47165
|
+
const extendedBy = (key) => graph.libraries.filter((library) => library.extends.includes(key)).map((library) => library.key).join(", ") || "nothing";
|
|
47166
|
+
const saved = (key, present) => present ? "" : ` (no snapshot; run zaku library save --key ${key})`;
|
|
47167
|
+
for (const library of graph.libraries) {
|
|
47168
|
+
lines.push(` ${library.key} ${library.layer} [${library.branches.join(", ")}]: extends ${library.extends.join(", ") || "nothing"}; extended by ${extendedBy(library.key)}${saved(library.key, snapshots.libraries[library.key] !== void 0)}`);
|
|
47169
|
+
}
|
|
47170
|
+
for (const kit of graph.kits) {
|
|
47171
|
+
lines.push(` ${kit.key} ${kit.family} kit: extended by ${extendedBy(kit.key)}${saved(kit.key, snapshots.kits[kit.key] !== void 0)}`);
|
|
47172
|
+
}
|
|
47173
|
+
return lines;
|
|
47174
|
+
}
|
|
47175
|
+
|
|
46550
47176
|
// packages/zaku/dist/lib/adapters/figma-rest.js
|
|
46551
47177
|
var FigmaRateLimited = class extends Error {
|
|
46552
47178
|
url;
|
|
@@ -46591,26 +47217,30 @@ function createFigmaRest(options) {
|
|
|
46591
47217
|
throw new FigmaRateLimited(url2);
|
|
46592
47218
|
}
|
|
46593
47219
|
const chunks = (ids) => Array.from({ length: Math.ceil(ids.length / BATCH) }, (_, index) => ids.slice(index * BATCH, (index + 1) * BATCH));
|
|
47220
|
+
async function components(fileKey3) {
|
|
47221
|
+
const listed = await call(`${BASE}/files/${fileKey3}/components`);
|
|
47222
|
+
return listed.meta.components;
|
|
47223
|
+
}
|
|
46594
47224
|
return {
|
|
46595
|
-
file: (
|
|
46596
|
-
async nodes(
|
|
47225
|
+
file: (fileKey3, depth) => call(`${BASE}/files/${fileKey3}?depth=${depth}`),
|
|
47226
|
+
async nodes(fileKey3, ids) {
|
|
46597
47227
|
const merged = { version: "", nodes: {} };
|
|
46598
47228
|
for (const chunk of chunks(ids)) {
|
|
46599
|
-
const part = await call(`${BASE}/files/${
|
|
47229
|
+
const part = await call(`${BASE}/files/${fileKey3}/nodes?ids=${encodeURIComponent(chunk.join(","))}`);
|
|
46600
47230
|
merged.version = part.version;
|
|
46601
47231
|
Object.assign(merged.nodes, part.nodes);
|
|
46602
47232
|
}
|
|
46603
47233
|
return merged;
|
|
46604
47234
|
},
|
|
46605
|
-
async published(
|
|
46606
|
-
const sets = await call(`${BASE}/files/${
|
|
46607
|
-
|
|
46608
|
-
return { sets: sets.meta.component_sets, components: components.meta.components };
|
|
47235
|
+
async published(fileKey3) {
|
|
47236
|
+
const sets = await call(`${BASE}/files/${fileKey3}/component_sets`);
|
|
47237
|
+
return { sets: sets.meta.component_sets, components: await components(fileKey3) };
|
|
46609
47238
|
},
|
|
46610
|
-
|
|
47239
|
+
components,
|
|
47240
|
+
async images(fileKey3, ids) {
|
|
46611
47241
|
const merged = {};
|
|
46612
47242
|
for (const chunk of chunks(ids)) {
|
|
46613
|
-
const part = await call(`${BASE}/images/${
|
|
47243
|
+
const part = await call(`${BASE}/images/${fileKey3}?ids=${encodeURIComponent(chunk.join(","))}&format=png&scale=1`);
|
|
46614
47244
|
Object.assign(merged, part.images);
|
|
46615
47245
|
}
|
|
46616
47246
|
return merged;
|
|
@@ -46620,17 +47250,40 @@ function createFigmaRest(options) {
|
|
|
46620
47250
|
|
|
46621
47251
|
// packages/zaku/dist/lib/adapters/figma-variables-script.js
|
|
46622
47252
|
async function exportVariables(figma, options) {
|
|
46623
|
-
const collections = await figma.variables.getLocalVariableCollectionsAsync();
|
|
47253
|
+
const collections = [...await figma.variables.getLocalVariableCollectionsAsync()];
|
|
47254
|
+
if (!collections.some((collection) => collection.name === "semantic")) {
|
|
47255
|
+
const available = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
|
|
47256
|
+
const bases = [
|
|
47257
|
+
...new Set(available.filter((entry) => entry.name === "semantic").map((entry) => entry.libraryName))
|
|
47258
|
+
];
|
|
47259
|
+
if (bases.length === 0)
|
|
47260
|
+
throw new Error("the file has no semantic collection and no enabled library has one");
|
|
47261
|
+
if (bases.length > 1)
|
|
47262
|
+
throw new Error(`several enabled libraries hold a semantic collection: ${bases.join(", ")}; enable only the one this library extends`);
|
|
47263
|
+
const imported = /* @__PURE__ */ new Map();
|
|
47264
|
+
for (const entry of available.filter((candidate) => candidate.libraryName === bases[0])) {
|
|
47265
|
+
for (const listed of await figma.teamLibrary.getVariablesInLibraryCollectionAsync(entry.key)) {
|
|
47266
|
+
const variable = await figma.variables.importVariableByKeyAsync(listed.key);
|
|
47267
|
+
if (!imported.has(variable.variableCollectionId))
|
|
47268
|
+
imported.set(variable.variableCollectionId, await figma.variables.getVariableCollectionByIdAsync(variable.variableCollectionId));
|
|
47269
|
+
}
|
|
47270
|
+
}
|
|
47271
|
+
collections.push(...[...imported.values()].filter(Boolean));
|
|
47272
|
+
}
|
|
46624
47273
|
const semantic = collections.find((collection) => collection.name === "semantic");
|
|
46625
47274
|
if (!semantic)
|
|
46626
47275
|
throw new Error("the library has no semantic variable collection");
|
|
46627
47276
|
const hex3 = (value) => Math.round(Math.min(1, Math.max(0, value)) * 255).toString(16).padStart(2, "0");
|
|
46628
47277
|
const variables = {};
|
|
47278
|
+
const variableKeys = {};
|
|
46629
47279
|
for (const collection of collections) {
|
|
46630
47280
|
for (const id2 of collection.variableIds) {
|
|
46631
47281
|
const variable = await figma.variables.getVariableByIdAsync(id2);
|
|
46632
|
-
if (variable)
|
|
46633
|
-
|
|
47282
|
+
if (!variable)
|
|
47283
|
+
continue;
|
|
47284
|
+
const short = String(id2).replace(/^VariableID:/, "");
|
|
47285
|
+
variables[short] = variable.name;
|
|
47286
|
+
variableKeys[short] = { key: variable.key, local: variable.remote !== true };
|
|
46634
47287
|
}
|
|
46635
47288
|
}
|
|
46636
47289
|
const holder = figma.createFrame();
|
|
@@ -46652,6 +47305,8 @@ async function exportVariables(figma, options) {
|
|
|
46652
47305
|
const values = {};
|
|
46653
47306
|
for (const id2 of semantic.variableIds) {
|
|
46654
47307
|
const variable = await figma.variables.getVariableByIdAsync(id2);
|
|
47308
|
+
if (!variable)
|
|
47309
|
+
continue;
|
|
46655
47310
|
const resolved = variable.resolveForConsumer(holder).value;
|
|
46656
47311
|
values[variable.name] = typeof resolved === "object" && resolved !== null ? `#${hex3(resolved.r)}${hex3(resolved.g)}${hex3(resolved.b)}${hex3(resolved.a ?? 1)}` : resolved;
|
|
46657
47312
|
}
|
|
@@ -46671,21 +47326,31 @@ async function exportVariables(figma, options) {
|
|
|
46671
47326
|
for (const node2 of page.findAllWithCriteria({ types: ["COMPONENT_SET", "COMPONENT"] })) {
|
|
46672
47327
|
if (node2.type === "COMPONENT" && node2.parent?.type === "COMPONENT_SET")
|
|
46673
47328
|
continue;
|
|
47329
|
+
let view = node2;
|
|
47330
|
+
while (view.parent && view.parent.type !== "PAGE")
|
|
47331
|
+
view = view.parent;
|
|
46674
47332
|
components.push({
|
|
46675
47333
|
id: node2.id,
|
|
46676
47334
|
key: node2.key,
|
|
46677
47335
|
name: node2.name,
|
|
46678
47336
|
page: page.name,
|
|
47337
|
+
...view !== node2 && view.parent ? { frame: view.name } : {},
|
|
46679
47338
|
description: node2.description ?? "",
|
|
46680
47339
|
set: node2.type === "COMPONENT_SET"
|
|
46681
47340
|
});
|
|
46682
47341
|
}
|
|
46683
47342
|
}
|
|
46684
47343
|
}
|
|
47344
|
+
const effectStyles = (await figma.getLocalEffectStylesAsync()).map((style) => ({
|
|
47345
|
+
key: style.key,
|
|
47346
|
+
name: style.name
|
|
47347
|
+
}));
|
|
46685
47348
|
return {
|
|
46686
47349
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
46687
47350
|
variables,
|
|
47351
|
+
variableKeys,
|
|
46688
47352
|
textStyles,
|
|
47353
|
+
effectStyles,
|
|
46689
47354
|
tokens,
|
|
46690
47355
|
...options.local ? { components } : {}
|
|
46691
47356
|
};
|
|
@@ -47277,15 +47942,15 @@ async function startPluginBridge(options = {}) {
|
|
|
47277
47942
|
});
|
|
47278
47943
|
});
|
|
47279
47944
|
});
|
|
47280
|
-
function request(
|
|
47945
|
+
function request(fileKey3, message, timeoutMs) {
|
|
47281
47946
|
if (port === null)
|
|
47282
47947
|
return Promise.resolve({
|
|
47283
47948
|
ok: false,
|
|
47284
47949
|
error: `no port from ${ports[0]} to ${ports[ports.length - 1]} was free, so zaku mcp could not listen for the plugin`
|
|
47285
47950
|
});
|
|
47286
|
-
const socket = holderOf(
|
|
47951
|
+
const socket = holderOf(fileKey3);
|
|
47287
47952
|
if (!socket)
|
|
47288
|
-
return Promise.resolve({ ok: false, error: `file ${
|
|
47953
|
+
return Promise.resolve({ ok: false, error: `file ${fileKey3} is not open in Figma with the zaku plugin` });
|
|
47289
47954
|
const id2 = `c${++next}`;
|
|
47290
47955
|
return new Promise((resolve3) => {
|
|
47291
47956
|
const timer = setTimeout(() => settle2(id2, { ok: false, error: `no answer from the zaku panel in ${timeoutMs / 1e3} s; ${PARTIAL}` }), timeoutMs);
|
|
@@ -47295,8 +47960,8 @@ async function startPluginBridge(options = {}) {
|
|
|
47295
47960
|
}
|
|
47296
47961
|
return {
|
|
47297
47962
|
port,
|
|
47298
|
-
run: (
|
|
47299
|
-
screenshot: (
|
|
47963
|
+
run: (fileKey3, call, timeoutMs) => request(fileKey3, { type: "run", ...call }, timeoutMs),
|
|
47964
|
+
screenshot: (fileKey3, call, timeoutMs) => request(fileKey3, { type: "screenshot", ...call }, timeoutMs),
|
|
47300
47965
|
close: () => new Promise((done) => {
|
|
47301
47966
|
if (!server || !bound)
|
|
47302
47967
|
return done();
|
|
@@ -47307,12 +47972,66 @@ async function startPluginBridge(options = {}) {
|
|
|
47307
47972
|
};
|
|
47308
47973
|
}
|
|
47309
47974
|
|
|
47975
|
+
// packages/zaku/dist/lib/domain/checks/libraries.js
|
|
47976
|
+
var comboKey2 = (combo) => JSON.stringify(Object.entries(combo).sort(([a], [b]) => a.localeCompare(b)));
|
|
47977
|
+
function joinLibraries(snapshots) {
|
|
47978
|
+
if (snapshots.length === 1 && snapshots[0])
|
|
47979
|
+
return snapshots[0];
|
|
47980
|
+
const tokens = /* @__PURE__ */ new Map();
|
|
47981
|
+
for (const snapshot of snapshots) {
|
|
47982
|
+
for (const token of snapshot.tokens) {
|
|
47983
|
+
const key = comboKey2(token.combo);
|
|
47984
|
+
tokens.set(key, { combo: token.combo, values: { ...tokens.get(key)?.values, ...token.values } });
|
|
47985
|
+
}
|
|
47986
|
+
}
|
|
47987
|
+
return {
|
|
47988
|
+
source: snapshots.map((snapshot) => snapshot.source).join(","),
|
|
47989
|
+
version: snapshots.map((snapshot) => snapshot.version).join(","),
|
|
47990
|
+
exportedAt: snapshots.map((snapshot) => snapshot.exportedAt).sort().at(-1) ?? "",
|
|
47991
|
+
components: snapshots.flatMap((snapshot) => snapshot.components),
|
|
47992
|
+
textStyles: snapshots.flatMap((snapshot) => snapshot.textStyles),
|
|
47993
|
+
tokens: [...tokens.values()]
|
|
47994
|
+
};
|
|
47995
|
+
}
|
|
47996
|
+
function missingSnapshots(graph, keys) {
|
|
47997
|
+
const paths = keys.map((key) => graph.legacy ? "library/index.json" : `library/${key}/index.json`);
|
|
47998
|
+
return `${paths.join(", ")} ${paths.length === 1 ? "is" : "are"} missing`;
|
|
47999
|
+
}
|
|
48000
|
+
function checkLibraries(input2) {
|
|
48001
|
+
const graph = designGraph(input2.config);
|
|
48002
|
+
const { libraries, missing } = snapshotsFor(input2);
|
|
48003
|
+
const kits = new Set(graph.kits.map((kit) => kit.key));
|
|
48004
|
+
const absent = missing.filter((key) => !kits.has(key));
|
|
48005
|
+
if (absent.length > 0)
|
|
48006
|
+
return { notRun: missingSnapshots(graph, absent) };
|
|
48007
|
+
if (libraries.length === 0)
|
|
48008
|
+
return { notRun: "library/index.json is missing" };
|
|
48009
|
+
const all = joinLibraries(libraries);
|
|
48010
|
+
const joined = /* @__PURE__ */ new Map();
|
|
48011
|
+
return {
|
|
48012
|
+
all,
|
|
48013
|
+
forTarget(targetId) {
|
|
48014
|
+
const target = input2.config.targets.find((candidate) => candidate.id === targetId);
|
|
48015
|
+
if (!target)
|
|
48016
|
+
return all;
|
|
48017
|
+
const cached2 = joined.get(targetId);
|
|
48018
|
+
if (cached2)
|
|
48019
|
+
return cached2;
|
|
48020
|
+
const own2 = joinLibraries(snapshotsFor(input2, target).libraries);
|
|
48021
|
+
joined.set(targetId, own2);
|
|
48022
|
+
return own2;
|
|
48023
|
+
}
|
|
48024
|
+
};
|
|
48025
|
+
}
|
|
48026
|
+
|
|
47310
48027
|
// packages/zaku/dist/lib/domain/checks/binding.js
|
|
47311
48028
|
var PAINTS = ["fill", "stroke", "textColor", "glyph"];
|
|
47312
48029
|
var SEMANTIC = /^(color|mode|radius)\//;
|
|
47313
|
-
var binding = (
|
|
47314
|
-
|
|
47315
|
-
|
|
48030
|
+
var binding = (input2) => {
|
|
48031
|
+
const libraries = checkLibraries(input2);
|
|
48032
|
+
if ("notRun" in libraries)
|
|
48033
|
+
return libraries;
|
|
48034
|
+
const library = libraries.all;
|
|
47316
48035
|
const findings = [];
|
|
47317
48036
|
for (const component2 of library.components) {
|
|
47318
48037
|
for (const variant of component2.variants) {
|
|
@@ -47678,8 +48397,9 @@ var frameCheck = ({ config: config2, outlines }) => {
|
|
|
47678
48397
|
}
|
|
47679
48398
|
return { findings };
|
|
47680
48399
|
};
|
|
47681
|
-
var systemBars = ({ config: config2, outlines }) => {
|
|
48400
|
+
var systemBars = ({ config: config2, outlines, kits }) => {
|
|
47682
48401
|
const families2 = new Map(config2.targets.map((target) => [target.id, target.family]));
|
|
48402
|
+
const graph = designGraph(config2);
|
|
47683
48403
|
const bars = { ...DEFAULT_SYSTEM_BARS, ...config2.systemBars };
|
|
47684
48404
|
const findings = [];
|
|
47685
48405
|
for (const outline of outlines) {
|
|
@@ -47687,7 +48407,10 @@ var systemBars = ({ config: config2, outlines }) => {
|
|
|
47687
48407
|
const family = families2.get(frame.target);
|
|
47688
48408
|
if (!family)
|
|
47689
48409
|
continue;
|
|
47690
|
-
const
|
|
48410
|
+
const own2 = graph.kits.filter((kit) => kit.family === family && kits[kit.key]);
|
|
48411
|
+
const kitKeys = new Set(own2.flatMap((kit) => kits[kit.key]?.components.map((component2) => component2.key) ?? []));
|
|
48412
|
+
const from = own2.length > 0 ? ` from ${own2.map((kit) => kit.key).join(" or ")}` : "";
|
|
48413
|
+
const held = new Set(frame.instances.filter((instance) => own2.length === 0 || kitKeys.has(instance.componentKey)).map((instance) => instance.component));
|
|
47691
48414
|
for (const names of bars[family]) {
|
|
47692
48415
|
if (!names.some((name) => held.has(name))) {
|
|
47693
48416
|
findings.push({
|
|
@@ -47696,7 +48419,7 @@ var systemBars = ({ config: config2, outlines }) => {
|
|
|
47696
48419
|
screen: outline.screen,
|
|
47697
48420
|
frame: frame.name,
|
|
47698
48421
|
nodeId: frame.nodeId,
|
|
47699
|
-
message: `no ${names.join(" or ")} instance on a ${family} frame`
|
|
48422
|
+
message: `no ${names.join(" or ")} instance${from} on a ${family} frame`
|
|
47700
48423
|
});
|
|
47701
48424
|
}
|
|
47702
48425
|
}
|
|
@@ -47710,6 +48433,18 @@ var placement = ({ maps, outlines }) => {
|
|
|
47710
48433
|
for (const outline of outlines) {
|
|
47711
48434
|
const title = titles.get(`${outline.feature}/${outline.screen}`);
|
|
47712
48435
|
for (const frame of outline.frames) {
|
|
48436
|
+
if (frame.page !== void 0) {
|
|
48437
|
+
if (title !== void 0 && frame.page !== title)
|
|
48438
|
+
findings.push({
|
|
48439
|
+
check: "placement",
|
|
48440
|
+
feature: outline.feature,
|
|
48441
|
+
screen: outline.screen,
|
|
48442
|
+
frame: frame.name,
|
|
48443
|
+
nodeId: frame.nodeId,
|
|
48444
|
+
message: `sits on the page ${frame.page}, and its screen is drawn on the page ${title}`
|
|
48445
|
+
});
|
|
48446
|
+
continue;
|
|
48447
|
+
}
|
|
47713
48448
|
const expected = [title, frame.state];
|
|
47714
48449
|
if (frame.containers.length !== 2 || frame.containers[0] !== expected[0] || frame.containers[1] !== expected[1]) {
|
|
47715
48450
|
findings.push({
|
|
@@ -47743,8 +48478,19 @@ var naming = ({ outlines }) => {
|
|
|
47743
48478
|
}
|
|
47744
48479
|
return { findings };
|
|
47745
48480
|
};
|
|
47746
|
-
var component = ({ outlines }) => {
|
|
48481
|
+
var component = ({ config: config2, outlines, productComponents }) => {
|
|
47747
48482
|
const findings = [];
|
|
48483
|
+
const graph = designGraph(config2);
|
|
48484
|
+
for (const drawn of productComponents) {
|
|
48485
|
+
const platform = graph.products.find((product) => product.key === drawn.source)?.platform;
|
|
48486
|
+
const branches = new Set(config2.targets.filter((target) => graph.platformOf(target) === platform).flatMap((target) => graph.branchOf(target) ?? []));
|
|
48487
|
+
const homes = graph.libraries.filter((library) => library.layer === "components" && library.branches.some((branch) => branches.has(branch))).map((library) => library.key);
|
|
48488
|
+
findings.push({
|
|
48489
|
+
check: "component",
|
|
48490
|
+
nodeId: drawn.nodeId,
|
|
48491
|
+
message: `${drawn.name} is a component on the product page ${drawn.page}; a product file draws screens only, so draw it in ${homes.length > 0 ? homes.join(" or ") : `a Components library of the ${[...branches].join(" or ")} branch`}`
|
|
48492
|
+
});
|
|
48493
|
+
}
|
|
47748
48494
|
for (const outline of outlines) {
|
|
47749
48495
|
const seen = /* @__PURE__ */ new Map();
|
|
47750
48496
|
for (const frame of outline.frames) {
|
|
@@ -47776,13 +48522,16 @@ var component = ({ outlines }) => {
|
|
|
47776
48522
|
};
|
|
47777
48523
|
|
|
47778
48524
|
// packages/zaku/dist/lib/domain/checks/font.js
|
|
47779
|
-
var font = (
|
|
47780
|
-
|
|
47781
|
-
|
|
47782
|
-
|
|
48525
|
+
var font = (input2) => {
|
|
48526
|
+
const libraries = checkLibraries(input2);
|
|
48527
|
+
if ("notRun" in libraries)
|
|
48528
|
+
return libraries;
|
|
48529
|
+
const keys = /* @__PURE__ */ new Map();
|
|
47783
48530
|
const findings = [];
|
|
47784
|
-
for (const outline of outlines) {
|
|
48531
|
+
for (const outline of input2.outlines) {
|
|
47785
48532
|
for (const frame of outline.frames) {
|
|
48533
|
+
const styles = keys.get(frame.target) ?? new Set(libraries.forTarget(frame.target).textStyles.map((style) => style.key));
|
|
48534
|
+
keys.set(frame.target, styles);
|
|
47786
48535
|
const where = { feature: outline.feature, screen: outline.screen, frame: frame.name };
|
|
47787
48536
|
for (const text of frame.texts) {
|
|
47788
48537
|
if (text.styleKey === null) {
|
|
@@ -47792,7 +48541,7 @@ var font = ({ outlines, library }) => {
|
|
|
47792
48541
|
nodeId: text.nodeId,
|
|
47793
48542
|
message: "text outside a component uses no library text style"
|
|
47794
48543
|
});
|
|
47795
|
-
} else if (!
|
|
48544
|
+
} else if (!styles.has(text.styleKey)) {
|
|
47796
48545
|
findings.push({
|
|
47797
48546
|
check: "font",
|
|
47798
48547
|
...where,
|
|
@@ -47807,8 +48556,9 @@ var font = ({ outlines, library }) => {
|
|
|
47807
48556
|
};
|
|
47808
48557
|
|
|
47809
48558
|
// packages/zaku/dist/lib/domain/checks/freshness.js
|
|
47810
|
-
var freshness = ({ maps, outlines,
|
|
48559
|
+
var freshness = ({ config: config2, maps, outlines, flows, libraries }) => {
|
|
47811
48560
|
const digests = new Map(maps.map((loaded) => [loaded.map.feature, loaded.digest]));
|
|
48561
|
+
const graph = designGraph(config2);
|
|
47812
48562
|
const findings = [];
|
|
47813
48563
|
for (const outline of outlines) {
|
|
47814
48564
|
const where = { feature: outline.feature, screen: outline.screen };
|
|
@@ -47820,11 +48570,35 @@ var freshness = ({ maps, outlines, library }) => {
|
|
|
47820
48570
|
message: "the map changed after this outline was read; run zaku outline"
|
|
47821
48571
|
});
|
|
47822
48572
|
}
|
|
47823
|
-
|
|
48573
|
+
for (const [key, library] of Object.entries(libraries)) {
|
|
48574
|
+
const read = outline.libraryVersions[key] ?? (graph.legacy ? outline.libraryVersions[LEGACY_LIBRARY_VERSION] : void 0);
|
|
48575
|
+
if (read === library.version)
|
|
48576
|
+
continue;
|
|
47824
48577
|
findings.push({
|
|
47825
48578
|
check: "freshness",
|
|
47826
48579
|
...where,
|
|
47827
|
-
message: "the library changed after this outline was read; run zaku outline"
|
|
48580
|
+
message: graph.legacy ? "the library changed after this outline was read; run zaku outline" : `library ${key} changed after this outline was read; run zaku outline`
|
|
48581
|
+
});
|
|
48582
|
+
}
|
|
48583
|
+
}
|
|
48584
|
+
const drawn = new Map(outlines.flatMap((outline) => outline.frames.map((frame) => [`${outline.feature}/${outline.screen}
|
|
48585
|
+
${frame.name}`, frame])));
|
|
48586
|
+
for (const page of flows) {
|
|
48587
|
+
for (const copy2 of page.frames) {
|
|
48588
|
+
if (copy2.screen === null)
|
|
48589
|
+
continue;
|
|
48590
|
+
const source = drawn.get(`${copy2.screen}
|
|
48591
|
+
${copy2.name}`);
|
|
48592
|
+
if (source?.digest === void 0 || source.digest === copy2.digest)
|
|
48593
|
+
continue;
|
|
48594
|
+
const [feature = "", screen = ""] = copy2.screen.split("/");
|
|
48595
|
+
findings.push({
|
|
48596
|
+
check: "freshness",
|
|
48597
|
+
feature,
|
|
48598
|
+
screen,
|
|
48599
|
+
frame: copy2.name,
|
|
48600
|
+
nodeId: copy2.nodeId,
|
|
48601
|
+
message: `the copy on the flow page ${page.page} differs from the frame it copies; copy it again`
|
|
47828
48602
|
});
|
|
47829
48603
|
}
|
|
47830
48604
|
}
|
|
@@ -47832,13 +48606,43 @@ var freshness = ({ maps, outlines, library }) => {
|
|
|
47832
48606
|
};
|
|
47833
48607
|
|
|
47834
48608
|
// packages/zaku/dist/lib/domain/checks/library.js
|
|
47835
|
-
|
|
47836
|
-
|
|
47837
|
-
|
|
48609
|
+
function frameFindings(input2) {
|
|
48610
|
+
const libraries = checkLibraries(input2);
|
|
48611
|
+
if ("notRun" in libraries)
|
|
48612
|
+
return libraries;
|
|
48613
|
+
const { config: config2, maps, outlines } = input2;
|
|
48614
|
+
const library = libraries.all;
|
|
47838
48615
|
const bars = systemBarNames(config2);
|
|
47839
48616
|
const owned = outlines.flatMap((outline) => outline.frames.flatMap((frame) => frame.instances.filter((instance) => instance.local).map((instance) => instance.component)));
|
|
47840
48617
|
const names = /* @__PURE__ */ new Set([...library.components.map((component2) => component2.name), ...owned]);
|
|
47841
48618
|
const keys = new Set(library.components.flatMap((component2) => component2.variants.map((variant) => variant.key)));
|
|
48619
|
+
const graph = designGraph(config2);
|
|
48620
|
+
const owners = /* @__PURE__ */ new Map();
|
|
48621
|
+
for (const [key, snapshot] of Object.entries(input2.libraries)) {
|
|
48622
|
+
const holds = graph.libraries.find((candidate) => candidate.key === key)?.branches ?? [];
|
|
48623
|
+
for (const component2 of snapshot.components) {
|
|
48624
|
+
const branches = component2.branch ? [component2.branch] : holds;
|
|
48625
|
+
for (const variant of component2.variants)
|
|
48626
|
+
owners.set(variant.key, `${key}, a ${branches.join(" and ")} library`);
|
|
48627
|
+
}
|
|
48628
|
+
}
|
|
48629
|
+
for (const [key, kit] of Object.entries(input2.kits)) {
|
|
48630
|
+
for (const component2 of kit.components)
|
|
48631
|
+
owners.set(component2.key, `${key}, an ${kit.family} kit`);
|
|
48632
|
+
}
|
|
48633
|
+
const allowed2 = /* @__PURE__ */ new Map();
|
|
48634
|
+
const allowedFor = (target) => {
|
|
48635
|
+
const cached2 = allowed2.get(target.id);
|
|
48636
|
+
if (cached2)
|
|
48637
|
+
return cached2;
|
|
48638
|
+
const { libraries: own2, kits } = snapshotsFor(input2, target);
|
|
48639
|
+
const set2 = /* @__PURE__ */ new Set([
|
|
48640
|
+
...own2.flatMap((snapshot) => snapshot.components.flatMap((component2) => component2.variants.map((v) => v.key))),
|
|
48641
|
+
...kits.flatMap((kit) => kit.components.map((component2) => component2.key))
|
|
48642
|
+
]);
|
|
48643
|
+
allowed2.set(target.id, set2);
|
|
48644
|
+
return set2;
|
|
48645
|
+
};
|
|
47842
48646
|
const findings = [];
|
|
47843
48647
|
for (const { map: map2 } of maps) {
|
|
47844
48648
|
for (const [id2, screen] of Object.entries(map2.screens)) {
|
|
@@ -47858,8 +48662,22 @@ var libraryCheck = ({ config: config2, maps, outlines, library }) => {
|
|
|
47858
48662
|
for (const outline of outlines) {
|
|
47859
48663
|
for (const frame of outline.frames) {
|
|
47860
48664
|
const where = { feature: outline.feature, screen: outline.screen, frame: frame.name };
|
|
48665
|
+
const target = config2.targets.find((candidate) => candidate.id === frame.target);
|
|
47861
48666
|
for (const instance of frame.instances) {
|
|
47862
|
-
if (
|
|
48667
|
+
if (instance.local)
|
|
48668
|
+
continue;
|
|
48669
|
+
const owner = owners.get(instance.componentKey);
|
|
48670
|
+
if (target && owner && !allowedFor(target).has(instance.componentKey)) {
|
|
48671
|
+
const draws = owner.endsWith(" kit") ? `${target.family} kits` : graph.branchOf(target) ?? "no branch";
|
|
48672
|
+
findings.push({
|
|
48673
|
+
check: "library",
|
|
48674
|
+
...where,
|
|
48675
|
+
nodeId: instance.nodeId,
|
|
48676
|
+
message: `an instance of ${instance.component} comes from ${owner}; a ${target.name} frame draws from ${draws}`
|
|
48677
|
+
});
|
|
48678
|
+
continue;
|
|
48679
|
+
}
|
|
48680
|
+
if (!bars.has(instance.component) && !keys.has(instance.componentKey) && !owner) {
|
|
47863
48681
|
findings.push({
|
|
47864
48682
|
check: "library",
|
|
47865
48683
|
...where,
|
|
@@ -47879,6 +48697,82 @@ var libraryCheck = ({ config: config2, maps, outlines, library }) => {
|
|
|
47879
48697
|
}
|
|
47880
48698
|
}
|
|
47881
48699
|
return { findings };
|
|
48700
|
+
}
|
|
48701
|
+
function referable(snapshot) {
|
|
48702
|
+
return {
|
|
48703
|
+
variable: Object.values(snapshot.variableKeys ?? {}).flatMap((variable) => variable.local ? [variable.key] : []),
|
|
48704
|
+
"text style": snapshot.textStyles.map((style) => style.key),
|
|
48705
|
+
"effect style": (snapshot.effectStyles ?? []).map((style) => style.key),
|
|
48706
|
+
instance: snapshot.components.flatMap((component2) => [
|
|
48707
|
+
component2.key,
|
|
48708
|
+
...component2.variants.map((variant) => variant.key)
|
|
48709
|
+
])
|
|
48710
|
+
};
|
|
48711
|
+
}
|
|
48712
|
+
function referenceFindings(input2) {
|
|
48713
|
+
const graph = designGraph(input2.config);
|
|
48714
|
+
const findings = [];
|
|
48715
|
+
for (const [key, snapshot] of Object.entries(input2.libraries)) {
|
|
48716
|
+
if (!snapshot.variableKeys)
|
|
48717
|
+
continue;
|
|
48718
|
+
const bases = graph.closure(key).slice(1);
|
|
48719
|
+
const missing = bases.filter((base) => !input2.libraries[base] && !input2.kits[base]);
|
|
48720
|
+
if (missing.length > 0) {
|
|
48721
|
+
const paths = missing.map((base) => graph.kits.some((kit) => kit.key === base) ? `library/${base}/kit.json` : `library/${base}/index.json`);
|
|
48722
|
+
return { notRun: `${paths.join(", ")} ${paths.length === 1 ? "is" : "are"} missing` };
|
|
48723
|
+
}
|
|
48724
|
+
const allowed2 = {
|
|
48725
|
+
variable: /* @__PURE__ */ new Set(),
|
|
48726
|
+
"text style": /* @__PURE__ */ new Set(),
|
|
48727
|
+
"effect style": /* @__PURE__ */ new Set(),
|
|
48728
|
+
instance: new Set(snapshot.localComponents ?? [])
|
|
48729
|
+
};
|
|
48730
|
+
for (const from of [key, ...bases]) {
|
|
48731
|
+
const library = input2.libraries[from];
|
|
48732
|
+
if (library)
|
|
48733
|
+
for (const [kind, keys] of Object.entries(referable(library)))
|
|
48734
|
+
for (const ref of keys)
|
|
48735
|
+
allowed2[kind].add(ref);
|
|
48736
|
+
for (const component2 of input2.kits[from]?.components ?? [])
|
|
48737
|
+
allowed2.instance.add(component2.key);
|
|
48738
|
+
}
|
|
48739
|
+
const extended2 = bases.length > 0 ? `from ${bases.join(", ")}` : "from a library it extends, and it extends none";
|
|
48740
|
+
for (const component2 of snapshot.components) {
|
|
48741
|
+
for (const variant of component2.variants) {
|
|
48742
|
+
for (const item of variant.modes[0]?.items ?? []) {
|
|
48743
|
+
const refs = [
|
|
48744
|
+
...(item.variableIds ?? []).map((id2) => [
|
|
48745
|
+
"variable",
|
|
48746
|
+
snapshot.variableKeys?.[id2]?.key ?? id2
|
|
48747
|
+
]),
|
|
48748
|
+
...item.textStyleKey ? [["text style", item.textStyleKey]] : [],
|
|
48749
|
+
...item.effectStyleKey ? [["effect style", item.effectStyleKey]] : [],
|
|
48750
|
+
...item.componentKey ? [["instance", item.componentKey]] : []
|
|
48751
|
+
];
|
|
48752
|
+
for (const [kind, ref] of refs) {
|
|
48753
|
+
if (allowed2[kind].has(ref))
|
|
48754
|
+
continue;
|
|
48755
|
+
findings.push({
|
|
48756
|
+
check: "library",
|
|
48757
|
+
nodeId: item.nodeId,
|
|
48758
|
+
field: "references",
|
|
48759
|
+
message: `${key}: ${component2.name} ${variant.name} ${item.path || "(root)"}: ${kind} ${ref} is neither the library's own nor ${extended2}`
|
|
48760
|
+
});
|
|
48761
|
+
}
|
|
48762
|
+
}
|
|
48763
|
+
}
|
|
48764
|
+
}
|
|
48765
|
+
}
|
|
48766
|
+
return { findings };
|
|
48767
|
+
}
|
|
48768
|
+
var libraryCheck = (input2) => {
|
|
48769
|
+
const frames = frameFindings(input2);
|
|
48770
|
+
if ("notRun" in frames)
|
|
48771
|
+
return frames;
|
|
48772
|
+
const references = referenceFindings(input2);
|
|
48773
|
+
if ("notRun" in references)
|
|
48774
|
+
return references;
|
|
48775
|
+
return { findings: [...frames.findings, ...references.findings] };
|
|
47882
48776
|
};
|
|
47883
48777
|
|
|
47884
48778
|
// packages/zaku/dist/lib/domain/checks/navigation.js
|
|
@@ -47949,7 +48843,11 @@ var ALLOWED_OVERRIDES = /* @__PURE__ */ new Set([
|
|
|
47949
48843
|
"name",
|
|
47950
48844
|
"componentProperties",
|
|
47951
48845
|
"componentPropertyReferences",
|
|
47952
|
-
"exposedInstances"
|
|
48846
|
+
"exposedInstances",
|
|
48847
|
+
"reactions",
|
|
48848
|
+
"transitionNodeID",
|
|
48849
|
+
"transitionDuration",
|
|
48850
|
+
"transitionEasing"
|
|
47953
48851
|
]);
|
|
47954
48852
|
var SIZING_MODES = /* @__PURE__ */ new Set(["primaryAxisSizingMode", "counterAxisSizingMode"]);
|
|
47955
48853
|
function componentSized(field, size2, main2) {
|
|
@@ -47963,9 +48861,12 @@ function stretches(sizing) {
|
|
|
47963
48861
|
function insideSwap(instance, nodeId) {
|
|
47964
48862
|
return instance.nested.some((nested) => nodeId.startsWith(`${nested.nodeId};`) && instance.swaps.includes(nested.componentKey));
|
|
47965
48863
|
}
|
|
47966
|
-
var overrides = (
|
|
47967
|
-
|
|
47968
|
-
|
|
48864
|
+
var overrides = (input2) => {
|
|
48865
|
+
const libraries = checkLibraries(input2);
|
|
48866
|
+
if ("notRun" in libraries)
|
|
48867
|
+
return libraries;
|
|
48868
|
+
const { outlines } = input2;
|
|
48869
|
+
const library = libraries.all;
|
|
47969
48870
|
const nestedOf = /* @__PURE__ */ new Map();
|
|
47970
48871
|
const componentOf = /* @__PURE__ */ new Map();
|
|
47971
48872
|
for (const component2 of library.components) {
|
|
@@ -48026,18 +48927,58 @@ var overrides = ({ outlines, library }) => {
|
|
|
48026
48927
|
return { findings };
|
|
48027
48928
|
};
|
|
48028
48929
|
|
|
48930
|
+
// packages/zaku/dist/lib/domain/flows.js
|
|
48931
|
+
function flowsOf(maps) {
|
|
48932
|
+
const index = indexScreens(maps);
|
|
48933
|
+
const flows = [];
|
|
48934
|
+
for (const root of index.values()) {
|
|
48935
|
+
if (!root.screen.root)
|
|
48936
|
+
continue;
|
|
48937
|
+
const screens = [root];
|
|
48938
|
+
for (let at = 0; at < screens.length; at += 1) {
|
|
48939
|
+
const from = screens[at];
|
|
48940
|
+
if (!from)
|
|
48941
|
+
continue;
|
|
48942
|
+
for (const exit of from.screen.exits) {
|
|
48943
|
+
const next = index.get(qualify(exit.to, from.feature));
|
|
48944
|
+
if (next && !screens.includes(next))
|
|
48945
|
+
screens.push(next);
|
|
48946
|
+
}
|
|
48947
|
+
}
|
|
48948
|
+
flows.push({ root, screens });
|
|
48949
|
+
}
|
|
48950
|
+
return flows;
|
|
48951
|
+
}
|
|
48952
|
+
|
|
48029
48953
|
// packages/zaku/dist/lib/domain/checks/prototype.js
|
|
48030
|
-
|
|
48031
|
-
if (
|
|
48032
|
-
return
|
|
48954
|
+
function legacyScreens(input2) {
|
|
48955
|
+
if (input2.flows.length === 0)
|
|
48956
|
+
return input2.outlines;
|
|
48957
|
+
const byScreen = /* @__PURE__ */ new Map();
|
|
48958
|
+
for (const page of input2.flows) {
|
|
48959
|
+
for (const frame of page.frames) {
|
|
48960
|
+
if (frame.screen === null)
|
|
48961
|
+
continue;
|
|
48962
|
+
const [feature = "", screen = ""] = frame.screen.split("/");
|
|
48963
|
+
const entry = byScreen.get(frame.screen) ?? { feature, screen, frames: [] };
|
|
48964
|
+
entry.frames.push(frame);
|
|
48965
|
+
byScreen.set(frame.screen, entry);
|
|
48966
|
+
}
|
|
48967
|
+
}
|
|
48968
|
+
return [...byScreen.values()];
|
|
48969
|
+
}
|
|
48970
|
+
function legacyFindings(input2) {
|
|
48971
|
+
const screens = legacyScreens(input2);
|
|
48972
|
+
if (screens.length === 0)
|
|
48973
|
+
return [];
|
|
48033
48974
|
const screenOfFrame = /* @__PURE__ */ new Map();
|
|
48034
|
-
const outlineOf = new Map(
|
|
48035
|
-
for (const outline of
|
|
48975
|
+
const outlineOf = new Map(screens.map((outline) => [`${outline.feature}/${outline.screen}`, outline]));
|
|
48976
|
+
for (const outline of screens) {
|
|
48036
48977
|
for (const frame of outline.frames)
|
|
48037
48978
|
screenOfFrame.set(frame.nodeId, `${outline.feature}/${outline.screen}`);
|
|
48038
48979
|
}
|
|
48039
48980
|
const findings = [];
|
|
48040
|
-
for (const { map: map2 } of maps) {
|
|
48981
|
+
for (const { map: map2 } of input2.maps) {
|
|
48041
48982
|
for (const [id2, screen] of Object.entries(map2.screens)) {
|
|
48042
48983
|
const outline = outlineOf.get(`${map2.feature}/${id2}`);
|
|
48043
48984
|
if (!outline)
|
|
@@ -48074,8 +49015,64 @@ var prototype = ({ maps, outlines }) => {
|
|
|
48074
49015
|
}
|
|
48075
49016
|
}
|
|
48076
49017
|
}
|
|
48077
|
-
return
|
|
48078
|
-
}
|
|
49018
|
+
return findings;
|
|
49019
|
+
}
|
|
49020
|
+
function flowFindings(input2) {
|
|
49021
|
+
const prototypes = new Set(designGraph(input2.config).prototypes.map((file2) => file2.key));
|
|
49022
|
+
const findings = [];
|
|
49023
|
+
for (const flow of flowsOf(input2.maps)) {
|
|
49024
|
+
const { root } = flow;
|
|
49025
|
+
const title = root.screen.title;
|
|
49026
|
+
const keyOf = (ref) => `${ref.feature}/${ref.id}`;
|
|
49027
|
+
const pages = input2.flows.filter((page) => page.page === title && prototypes.has(page.source));
|
|
49028
|
+
if (pages.length === 0) {
|
|
49029
|
+
findings.push({
|
|
49030
|
+
check: "prototype",
|
|
49031
|
+
feature: root.feature,
|
|
49032
|
+
screen: root.id,
|
|
49033
|
+
message: `no flow page is named ${title}`
|
|
49034
|
+
});
|
|
49035
|
+
continue;
|
|
49036
|
+
}
|
|
49037
|
+
const inFlow = new Set(flow.screens.map(keyOf));
|
|
49038
|
+
for (const page of pages) {
|
|
49039
|
+
const screenOf = new Map(page.frames.map((frame) => [frame.nodeId, frame.screen]));
|
|
49040
|
+
const first = root.screen.states[0];
|
|
49041
|
+
if (!page.frames.some((frame) => frame.screen === keyOf(root) && frame.state === first && frame.start))
|
|
49042
|
+
findings.push({
|
|
49043
|
+
check: "prototype",
|
|
49044
|
+
feature: root.feature,
|
|
49045
|
+
screen: root.id,
|
|
49046
|
+
message: `the flow page ${title} does not start on ${title}'s first state`
|
|
49047
|
+
});
|
|
49048
|
+
for (const ref of flow.screens) {
|
|
49049
|
+
const where = { check: "prototype", feature: ref.feature, screen: ref.id };
|
|
49050
|
+
const copies = page.frames.filter((frame) => frame.screen === keyOf(ref));
|
|
49051
|
+
for (const exit of ref.screen.exits) {
|
|
49052
|
+
const target = qualify(exit.to, ref.feature);
|
|
49053
|
+
if (!inFlow.has(target))
|
|
49054
|
+
continue;
|
|
49055
|
+
const connected = copies.some((frame) => frame.links.some((link) => link.to !== "back" && screenOf.get(link.to.nodeId) === target));
|
|
49056
|
+
if (!connected)
|
|
49057
|
+
findings.push({
|
|
49058
|
+
...where,
|
|
49059
|
+
field: "exits",
|
|
49060
|
+
message: `on the flow page ${title}, the exit to ${exit.to} (${exit.via}) has no connection`
|
|
49061
|
+
});
|
|
49062
|
+
}
|
|
49063
|
+
if (ref !== root && copies.length > 0 && !copies.some((frame) => frame.links.some((link) => link.to === "back")))
|
|
49064
|
+
findings.push({
|
|
49065
|
+
...where,
|
|
49066
|
+
message: `on the flow page ${title}, a screen that is not the root has no Back action`
|
|
49067
|
+
});
|
|
49068
|
+
}
|
|
49069
|
+
}
|
|
49070
|
+
}
|
|
49071
|
+
return findings;
|
|
49072
|
+
}
|
|
49073
|
+
var prototype = (input2) => ({
|
|
49074
|
+
findings: designGraph(input2.config).prototypes.length > 0 ? flowFindings(input2) : legacyFindings(input2)
|
|
49075
|
+
});
|
|
48079
49076
|
|
|
48080
49077
|
// packages/zaku/dist/lib/domain/checks/recipe.js
|
|
48081
49078
|
function propsLabel(props) {
|
|
@@ -48155,9 +49152,14 @@ function comparePart(at, part) {
|
|
|
48155
49152
|
});
|
|
48156
49153
|
}
|
|
48157
49154
|
}
|
|
48158
|
-
var recipe = (
|
|
48159
|
-
|
|
48160
|
-
|
|
49155
|
+
var recipe = (input2) => {
|
|
49156
|
+
const { config: config2, recipe: doc } = input2;
|
|
49157
|
+
const libraries = checkLibraries(input2);
|
|
49158
|
+
if ("notRun" in libraries)
|
|
49159
|
+
return doc ? libraries : { notRun: `recipe.json or ${libraries.notRun}` };
|
|
49160
|
+
if (!doc)
|
|
49161
|
+
return { notRun: "recipe.json is missing" };
|
|
49162
|
+
const library = libraries.all;
|
|
48161
49163
|
const findings = [];
|
|
48162
49164
|
for (const code of doc.components) {
|
|
48163
49165
|
const component2 = library.components.find((candidate) => candidate.name === code.name);
|
|
@@ -48248,9 +49250,12 @@ var MIN_TARGET = {
|
|
|
48248
49250
|
function controlsOf(frame) {
|
|
48249
49251
|
return frame.instances.flatMap((instance) => [instance, ...instance.nested].flatMap((control) => control.interactive && control.bounds ? [{ nodeId: control.nodeId, componentKey: control.componentKey, bounds: control.bounds }] : []));
|
|
48250
49252
|
}
|
|
48251
|
-
var targetSize = (
|
|
48252
|
-
|
|
48253
|
-
|
|
49253
|
+
var targetSize = (input2) => {
|
|
49254
|
+
const libraries = checkLibraries(input2);
|
|
49255
|
+
if ("notRun" in libraries)
|
|
49256
|
+
return libraries;
|
|
49257
|
+
const { config: config2, outlines } = input2;
|
|
49258
|
+
const library = libraries.all;
|
|
48254
49259
|
const presetHeight = /* @__PURE__ */ new Map();
|
|
48255
49260
|
for (const component2 of library.components) {
|
|
48256
49261
|
for (const variant of component2.variants) {
|
|
@@ -48332,9 +49337,14 @@ function rgbaOf(token) {
|
|
|
48332
49337
|
const [r, g, b] = token.$value.components;
|
|
48333
49338
|
return { r, g, b, a: token.$value.alpha };
|
|
48334
49339
|
}
|
|
48335
|
-
var tokensCheck = (
|
|
48336
|
-
|
|
48337
|
-
|
|
49340
|
+
var tokensCheck = (input2) => {
|
|
49341
|
+
const { config: config2, tokens } = input2;
|
|
49342
|
+
const libraries = checkLibraries(input2);
|
|
49343
|
+
if ("notRun" in libraries)
|
|
49344
|
+
return libraries;
|
|
49345
|
+
if (!tokens)
|
|
49346
|
+
return { notRun: "tokens.json is missing" };
|
|
49347
|
+
const library = libraries.all;
|
|
48338
49348
|
const sets = tokenSets(tokens);
|
|
48339
49349
|
const findings = [];
|
|
48340
49350
|
for (const [scheme, set2] of [
|
|
@@ -48638,13 +49648,25 @@ async function loadDesign(root) {
|
|
|
48638
49648
|
message: `two screens share the title ${title}; a frame name could not tell them apart`
|
|
48639
49649
|
});
|
|
48640
49650
|
}
|
|
48641
|
-
const { outlines, unmapped, errors: outlineErrors } = await loadOutlines(paths.outline);
|
|
49651
|
+
const { outlines, flows, unmapped, errors: outlineErrors } = await loadOutlines(paths.outline);
|
|
48642
49652
|
findings.push(...outlineErrors.map(schemaFinding));
|
|
48643
|
-
const
|
|
49653
|
+
const { libraries, kits, errors: snapshotErrors } = await readDesignSnapshots(paths, config2);
|
|
49654
|
+
findings.push(...snapshotErrors.map(schemaFinding));
|
|
48644
49655
|
const tokens = await optional3(() => readOptionalDesignFile(paths.tokens, tokenDocumentSchema), findings);
|
|
48645
49656
|
const recipe2 = await optional3(() => readOptionalDesignFile(paths.recipe, recipeDocumentSchema), findings);
|
|
48646
49657
|
return {
|
|
48647
|
-
input: {
|
|
49658
|
+
input: {
|
|
49659
|
+
config: config2,
|
|
49660
|
+
maps,
|
|
49661
|
+
outlines,
|
|
49662
|
+
flows,
|
|
49663
|
+
unmapped: unmapped?.frames ?? [],
|
|
49664
|
+
productComponents: unmapped?.components ?? [],
|
|
49665
|
+
libraries,
|
|
49666
|
+
kits,
|
|
49667
|
+
tokens,
|
|
49668
|
+
recipe: recipe2
|
|
49669
|
+
},
|
|
48648
49670
|
findings
|
|
48649
49671
|
};
|
|
48650
49672
|
}
|
|
@@ -48679,6 +49701,7 @@ function refusalOf(error62) {
|
|
|
48679
49701
|
}
|
|
48680
49702
|
if (error62 instanceof FigmaFileKeyMissing) return { code: 3, line: error62.message };
|
|
48681
49703
|
if (error62 instanceof FigmaTokenMissing) return { code: 3, line: error62.message };
|
|
49704
|
+
if (error62 instanceof LibraryKeyMissing) return { code: 3, line: error62.message };
|
|
48682
49705
|
if (error62 instanceof RecipePageFailed) return { code: 2, line: `zaku recipe: ${error62.message}` };
|
|
48683
49706
|
return null;
|
|
48684
49707
|
}
|
|
@@ -58368,11 +59391,11 @@ var StdioServerTransport = class {
|
|
|
58368
59391
|
// apps/zaku-cli/src/mcp/server.ts
|
|
58369
59392
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
58370
59393
|
import { tmpdir } from "node:os";
|
|
58371
|
-
import { join as
|
|
59394
|
+
import { join as join11 } from "node:path";
|
|
58372
59395
|
|
|
58373
59396
|
// apps/zaku-cli/src/mcp/screenshots.ts
|
|
58374
59397
|
import { readdir as readdir4, rm as rm3, stat } from "node:fs/promises";
|
|
58375
|
-
import { join as
|
|
59398
|
+
import { join as join9 } from "node:path";
|
|
58376
59399
|
var KEPT_MS = 24 * 60 * 60 * 1e3;
|
|
58377
59400
|
async function pruneScreenshots(dir, now) {
|
|
58378
59401
|
let names;
|
|
@@ -58382,7 +59405,7 @@ async function pruneScreenshots(dir, now) {
|
|
|
58382
59405
|
return;
|
|
58383
59406
|
}
|
|
58384
59407
|
for (const name of names.filter((entry) => entry.endsWith(".png"))) {
|
|
58385
|
-
const path2 =
|
|
59408
|
+
const path2 = join9(dir, name);
|
|
58386
59409
|
const written = await stat(path2).then(
|
|
58387
59410
|
(stats) => stats.mtimeMs,
|
|
58388
59411
|
() => now
|
|
@@ -58393,8 +59416,8 @@ async function pruneScreenshots(dir, now) {
|
|
|
58393
59416
|
|
|
58394
59417
|
// apps/zaku-cli/src/mcp/tools.ts
|
|
58395
59418
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
58396
|
-
import { join as
|
|
58397
|
-
var
|
|
59419
|
+
import { join as join10 } from "node:path";
|
|
59420
|
+
var fileKey2 = external_exports.string().min(1).regex(/^[0-9a-zA-Z]{22,128}$/).describe(
|
|
58398
59421
|
"The key of the Figma file to use. If the URL is provided, extract the file key from the URL: https://figma.com/design/:fileKey/:fileName."
|
|
58399
59422
|
);
|
|
58400
59423
|
var FALLBACK = "zaku's fallback for Figma's MCP server: the same tool and input, run in the file through the zaku plugin, which the person has open in that file with its key given.";
|
|
@@ -58406,7 +59429,7 @@ function registerFigmaTools(server, bridge, options) {
|
|
|
58406
59429
|
inputSchema: external_exports.object({
|
|
58407
59430
|
code: external_exports.string().max(5e4).describe("JavaScript code to execute. Has access to the `figma` global (Figma Plugin API)"),
|
|
58408
59431
|
description: external_exports.string().max(2e3).describe("A concise description of what the code aims to do"),
|
|
58409
|
-
fileKey,
|
|
59432
|
+
fileKey: fileKey2,
|
|
58410
59433
|
skillNames: external_exports.string().optional().describe("A comma-separated list of Figma skill names being followed, if any.")
|
|
58411
59434
|
}).strict()
|
|
58412
59435
|
},
|
|
@@ -58424,7 +59447,7 @@ function registerFigmaTools(server, bridge, options) {
|
|
|
58424
59447
|
inputSchema: external_exports.object({
|
|
58425
59448
|
contentsOnly: external_exports.boolean().optional().describe("When true, renders the node in isolation. Defaults to false."),
|
|
58426
59449
|
enableBase64Response: external_exports.boolean().default(false).describe("When true, the response also includes the screenshot inline as a base64-encoded image entry."),
|
|
58427
|
-
fileKey,
|
|
59450
|
+
fileKey: fileKey2,
|
|
58428
59451
|
maxDimension: external_exports.number().int().max(65536).default(1024).describe("Maximum pixel size of the longer edge of the rendered screenshot. Defaults to 1024."),
|
|
58429
59452
|
nodeId: external_exports.string().min(1).regex(/^\d+[:-]\d+$/).describe('The ID of the node in the Figma document, eg. "123:456" or "123-456".')
|
|
58430
59453
|
}).strict()
|
|
@@ -58437,7 +59460,7 @@ function registerFigmaTools(server, bridge, options) {
|
|
|
58437
59460
|
options.timeoutMs
|
|
58438
59461
|
);
|
|
58439
59462
|
if (!answer.ok) return { isError: true, content: [{ type: "text", text: answer.error }] };
|
|
58440
|
-
const path2 =
|
|
59463
|
+
const path2 = join10(options.imageDir, `${id2.replace(":", "-")}-${Date.now()}.png`);
|
|
58441
59464
|
await writeFile5(path2, Buffer.from(answer.png, "base64"));
|
|
58442
59465
|
const text = JSON.stringify({
|
|
58443
59466
|
path: path2,
|
|
@@ -58463,7 +59486,7 @@ async function serveMcp(log) {
|
|
|
58463
59486
|
log(
|
|
58464
59487
|
bridge.port === null ? "zaku mcp: no port from 7337 to 7346 was free; every call will say so" : `zaku mcp: listening for the zaku plugin on localhost:${bridge.port}`
|
|
58465
59488
|
);
|
|
58466
|
-
const imageDir =
|
|
59489
|
+
const imageDir = join11(tmpdir(), "zaku-screenshots");
|
|
58467
59490
|
await mkdir5(imageDir, { recursive: true });
|
|
58468
59491
|
await pruneScreenshots(imageDir, Date.now());
|
|
58469
59492
|
const server = new McpServer({ name: "zaku", version: "1" });
|
|
@@ -58480,7 +59503,7 @@ async function serveMcp(log) {
|
|
|
58480
59503
|
|
|
58481
59504
|
// apps/zaku-cli/src/cli.ts
|
|
58482
59505
|
var USE_FIGMA_CODE_LIMIT = 5e4;
|
|
58483
|
-
var USAGE = "usage: zaku <check|outline|tokens|recipe|library|rules|budget|schema|mcp> [--root docs/design]";
|
|
59506
|
+
var USAGE = "usage: zaku <check|outline|tokens|recipe|library|libraries|rules|budget|schema|mcp> [--root docs/design]";
|
|
58484
59507
|
async function sendOrRefuse(cli, io, finish, command) {
|
|
58485
59508
|
try {
|
|
58486
59509
|
return await cli.bus.send(command);
|
|
@@ -58498,6 +59521,14 @@ async function recordRestCalls(cli, io) {
|
|
|
58498
59521
|
const { seat, run } = seatAndRun(io.env);
|
|
58499
59522
|
await cli.bus.send(new RecordBudgetCalls({ day: today(clock.now()), seat, run, kind: "rest", count }));
|
|
58500
59523
|
}
|
|
59524
|
+
var librariesCommand = (program2, io, finish) => {
|
|
59525
|
+
program2.command("libraries").description("print the design graph: what each target draws from, and what each file extends and is extended by").option("--root <dir>", "the design directory", "docs/design").action(async (options) => {
|
|
59526
|
+
const paths = designPaths(resolve2(io.cwd, options.root));
|
|
59527
|
+
const config2 = await readDesignFile(paths.config, zakuConfigSchema);
|
|
59528
|
+
for (const line of printGraph(config2, await readDesignSnapshots(paths, config2))) io.out(line);
|
|
59529
|
+
finish(0);
|
|
59530
|
+
});
|
|
59531
|
+
};
|
|
58501
59532
|
var schemaCommand = (program2, io, finish, cli) => {
|
|
58502
59533
|
program2.command("schema").description("write the JSON Schemas an editor reads for the design files").option("--out <dir>", "where to write them", "docs/design").action(async (options) => {
|
|
58503
59534
|
const written = await cli.bus.send(new WriteSchemas({ out: resolve2(io.cwd, options.out) }));
|
|
@@ -58524,7 +59555,7 @@ var checkCommand = (program2, io, finish) => {
|
|
|
58524
59555
|
});
|
|
58525
59556
|
};
|
|
58526
59557
|
async function productPlaywright(cwd) {
|
|
58527
|
-
const require2 = createRequire(
|
|
59558
|
+
const require2 = createRequire(join12(cwd, "package.json"));
|
|
58528
59559
|
let resolved;
|
|
58529
59560
|
try {
|
|
58530
59561
|
resolved = require2.resolve("playwright");
|
|
@@ -58536,7 +59567,7 @@ async function productPlaywright(cwd) {
|
|
|
58536
59567
|
}
|
|
58537
59568
|
function fromProductTree(cwd, resolved) {
|
|
58538
59569
|
for (let dir = resolve2(cwd); ; dir = dirname4(dir)) {
|
|
58539
|
-
if (resolved.startsWith(
|
|
59570
|
+
if (resolved.startsWith(join12(dir, "node_modules") + sep)) return true;
|
|
58540
59571
|
if (dirname4(dir) === dir) return false;
|
|
58541
59572
|
}
|
|
58542
59573
|
}
|
|
@@ -58661,13 +59692,26 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
58661
59692
|
finish(0);
|
|
58662
59693
|
}
|
|
58663
59694
|
);
|
|
58664
|
-
library.command("save").description(
|
|
59695
|
+
library.command("save").description(
|
|
59696
|
+
"write a library's snapshot from its components over Figma REST, joined to the variables export, or a kit's published components"
|
|
59697
|
+
).option("--root <dir>", "the design directory", "docs/design").option("--key <key>", "the library or kit to save, as zaku.yaml lists it; needed when it lists several").option(
|
|
58665
59698
|
"--input <variables.json>",
|
|
58666
59699
|
"what use_figma returned for zaku library script; once per page export for a library in the product file",
|
|
58667
59700
|
(value, previous = []) => [...previous, value]
|
|
58668
59701
|
).action(async (options) => {
|
|
58669
59702
|
const root = resolve2(io.cwd, options.root);
|
|
58670
|
-
|
|
59703
|
+
const config2 = await readDesignFile(designPaths(root).config, zakuConfigSchema);
|
|
59704
|
+
let target;
|
|
59705
|
+
try {
|
|
59706
|
+
target = librarySaveTarget(config2, options.key);
|
|
59707
|
+
} catch (error62) {
|
|
59708
|
+
const refusal = refusalOf(error62);
|
|
59709
|
+
if (!refusal) throw error62;
|
|
59710
|
+
io.err(refusal.line);
|
|
59711
|
+
finish(refusal.code);
|
|
59712
|
+
return;
|
|
59713
|
+
}
|
|
59714
|
+
if (target.kind === "library" && (!options.input || options.input.length === 0)) {
|
|
58671
59715
|
io.err("zaku library save needs --input, the variables use_figma returned for zaku library script");
|
|
58672
59716
|
finish(3);
|
|
58673
59717
|
return;
|
|
@@ -58677,26 +59721,36 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
58677
59721
|
finish(3);
|
|
58678
59722
|
return;
|
|
58679
59723
|
}
|
|
58680
|
-
const part = mergeParts(
|
|
59724
|
+
const part = target.kind === "library" ? mergeParts(
|
|
58681
59725
|
await Promise.all(
|
|
58682
|
-
options.input.map(
|
|
59726
|
+
(options.input ?? []).map(
|
|
58683
59727
|
async (input2) => parseDesignFile(input2, await readFile6(resolve2(io.cwd, input2), "utf8"), variablePartSchema)
|
|
58684
59728
|
)
|
|
58685
59729
|
)
|
|
58686
|
-
);
|
|
59730
|
+
) : void 0;
|
|
58687
59731
|
try {
|
|
58688
|
-
const
|
|
58689
|
-
new SaveLibrary({
|
|
59732
|
+
const saved = await cli.bus.send(
|
|
59733
|
+
new SaveLibrary({
|
|
59734
|
+
root,
|
|
59735
|
+
...options.key !== void 0 ? { key: options.key } : {},
|
|
59736
|
+
...part ? { part } : {}
|
|
59737
|
+
})
|
|
58690
59738
|
);
|
|
59739
|
+
if (saved.kind === "kit") {
|
|
59740
|
+
io.out(`wrote ${saved.dir}/kit.json: ${saved.kit.components.length} components`);
|
|
59741
|
+
finish(0);
|
|
59742
|
+
return;
|
|
59743
|
+
}
|
|
59744
|
+
const { snapshot, written, unchanged, removed } = saved;
|
|
58691
59745
|
if (snapshot.components.length === 0) {
|
|
58692
59746
|
io.err(
|
|
58693
|
-
|
|
59747
|
+
`${saved.dir}/ holds no components: the file publishes none and the export listed none; for a library in the product file, run zaku library script --local`
|
|
58694
59748
|
);
|
|
58695
59749
|
finish(1);
|
|
58696
59750
|
return;
|
|
58697
59751
|
}
|
|
58698
59752
|
io.out(
|
|
58699
|
-
`wrote
|
|
59753
|
+
`wrote ${saved.dir}/: ${snapshot.components.length} components at version ${snapshot.version}; ${written.length} component files written, ${unchanged} unchanged, ${removed.length} removed`
|
|
58700
59754
|
);
|
|
58701
59755
|
finish(0);
|
|
58702
59756
|
} finally {
|
|
@@ -58706,7 +59760,7 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
58706
59760
|
};
|
|
58707
59761
|
var rulesCommand = (program2, io, finish) => {
|
|
58708
59762
|
const rules = program2.command("rules").description("zaku's rule checks, for a run that reaches Figma through use_figma");
|
|
58709
|
-
rules.command("script").description("print the Plugin API code that runs the rules over a page or a node, for use_figma").option("--root <dir>", "the design directory", "docs/design").option("--page <page>", "the page to check, by id or name").option("--node <id>", "the node to check, with everything inside it").option("--after <write.js>", "run this use_figma write first, then the rules, and answer both").action(async (options) => {
|
|
59763
|
+
rules.command("script").description("print the Plugin API code that runs the rules over a page or a node, for use_figma").option("--root <dir>", "the design directory", "docs/design").option("--page <page>", "the page to check, by id or name").option("--node <id>", "the node to check, with everything inside it").option("--after <write.js>", "run this use_figma write first, then the rules, and answer both").option("--key <key>", "the library file the page is in, so its views are held to the branches it holds").action(async (options) => {
|
|
58710
59764
|
if (options.page === void 0 === (options.node === void 0)) {
|
|
58711
59765
|
io.err("zaku rules script needs --page or --node, one of them");
|
|
58712
59766
|
finish(3);
|
|
@@ -58714,7 +59768,17 @@ var rulesCommand = (program2, io, finish) => {
|
|
|
58714
59768
|
}
|
|
58715
59769
|
const config2 = await readDesignFile(designPaths(resolve2(io.cwd, options.root)).config, zakuConfigSchema);
|
|
58716
59770
|
const scope = options.node !== void 0 ? { nodeId: options.node } : { page: options.page };
|
|
58717
|
-
const
|
|
59771
|
+
const graph = designGraph(config2);
|
|
59772
|
+
const file2 = options.key === void 0 ? graph.libraries.length === 1 ? graph.libraries[0] : void 0 : graph.libraries.find((library2) => library2.key === options.key);
|
|
59773
|
+
if (options.key !== void 0 && !file2) {
|
|
59774
|
+
io.err(
|
|
59775
|
+
`zaku rules script: ${options.key} is not a library zaku.yaml lists; name one with --key: ${graph.libraries.map((library2) => library2.key).join(", ")}`
|
|
59776
|
+
);
|
|
59777
|
+
finish(3);
|
|
59778
|
+
return;
|
|
59779
|
+
}
|
|
59780
|
+
const branches = file2?.branches ?? [];
|
|
59781
|
+
const check2 = `await zakuRulesLib.zakuRules(figma, ${JSON.stringify({ scope, copy: resolveCopy(config2.copy), ...branches.length > 1 ? { branches } : {} })})`;
|
|
58718
59782
|
const library = await runners.rulesLibrary();
|
|
58719
59783
|
if (options.after === void 0) {
|
|
58720
59784
|
io.out(`${library}
|
|
@@ -58753,6 +59817,7 @@ var COMMANDS = [
|
|
|
58753
59817
|
recipeCommand,
|
|
58754
59818
|
budgetCommand,
|
|
58755
59819
|
schemaCommand,
|
|
59820
|
+
librariesCommand,
|
|
58756
59821
|
mcpCommand
|
|
58757
59822
|
];
|
|
58758
59823
|
async function main(argv, io) {
|