@zeroxsolutions/zaku 0.1.0 → 0.2.0
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/README.md +9 -1
- package/dist/zaku.mjs +1056 -614
- package/package.json +1 -1
package/dist/zaku.mjs
CHANGED
|
@@ -1187,11 +1187,11 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
1187
1187
|
}
|
|
1188
1188
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1189
1189
|
function adopt(value) {
|
|
1190
|
-
return value instanceof P ? value : new P(function(
|
|
1191
|
-
|
|
1190
|
+
return value instanceof P ? value : new P(function(resolve4) {
|
|
1191
|
+
resolve4(value);
|
|
1192
1192
|
});
|
|
1193
1193
|
}
|
|
1194
|
-
return new (P || (P = Promise))(function(
|
|
1194
|
+
return new (P || (P = Promise))(function(resolve4, reject) {
|
|
1195
1195
|
function fulfilled(value) {
|
|
1196
1196
|
try {
|
|
1197
1197
|
step(generator.next(value));
|
|
@@ -1207,7 +1207,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
1207
1207
|
}
|
|
1208
1208
|
}
|
|
1209
1209
|
function step(result) {
|
|
1210
|
-
result.done ?
|
|
1210
|
+
result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
1211
1211
|
}
|
|
1212
1212
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1213
1213
|
});
|
|
@@ -1385,14 +1385,14 @@ function __asyncValues(o) {
|
|
|
1385
1385
|
}, i);
|
|
1386
1386
|
function verb(n) {
|
|
1387
1387
|
i[n] = o[n] && function(v) {
|
|
1388
|
-
return new Promise(function(
|
|
1389
|
-
v = o[n](v), settle2(
|
|
1388
|
+
return new Promise(function(resolve4, reject) {
|
|
1389
|
+
v = o[n](v), settle2(resolve4, reject, v.done, v.value);
|
|
1390
1390
|
});
|
|
1391
1391
|
};
|
|
1392
1392
|
}
|
|
1393
|
-
function settle2(
|
|
1393
|
+
function settle2(resolve4, reject, d, v) {
|
|
1394
1394
|
Promise.resolve(v).then(function(v2) {
|
|
1395
|
-
|
|
1395
|
+
resolve4({ value: v2, done: d });
|
|
1396
1396
|
}, reject);
|
|
1397
1397
|
}
|
|
1398
1398
|
}
|
|
@@ -2217,7 +2217,7 @@ var require_injectable = __commonJS({
|
|
|
2217
2217
|
var reflection_helpers_1 = require_reflection_helpers();
|
|
2218
2218
|
var dependency_container_1 = require_dependency_container();
|
|
2219
2219
|
var dependency_container_2 = require_dependency_container();
|
|
2220
|
-
function
|
|
2220
|
+
function injectable11(options) {
|
|
2221
2221
|
return function(target) {
|
|
2222
2222
|
dependency_container_1.typeInfo.set(target, reflection_helpers_1.getParamInfo(target));
|
|
2223
2223
|
if (options && options.token) {
|
|
@@ -2231,7 +2231,7 @@ var require_injectable = __commonJS({
|
|
|
2231
2231
|
}
|
|
2232
2232
|
};
|
|
2233
2233
|
}
|
|
2234
|
-
exports.default =
|
|
2234
|
+
exports.default = injectable11;
|
|
2235
2235
|
}
|
|
2236
2236
|
});
|
|
2237
2237
|
|
|
@@ -16461,7 +16461,7 @@ var require_compile = __commonJS({
|
|
|
16461
16461
|
const schOrFunc = root.refs[ref];
|
|
16462
16462
|
if (schOrFunc)
|
|
16463
16463
|
return schOrFunc;
|
|
16464
|
-
let _sch =
|
|
16464
|
+
let _sch = resolve4.call(this, root, ref);
|
|
16465
16465
|
if (_sch === void 0) {
|
|
16466
16466
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
16467
16467
|
const { schemaId } = this.opts;
|
|
@@ -16488,7 +16488,7 @@ var require_compile = __commonJS({
|
|
|
16488
16488
|
function sameSchemaEnv(s1, s2) {
|
|
16489
16489
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
16490
16490
|
}
|
|
16491
|
-
function
|
|
16491
|
+
function resolve4(root, ref) {
|
|
16492
16492
|
let sch;
|
|
16493
16493
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
16494
16494
|
ref = sch;
|
|
@@ -17318,7 +17318,7 @@ var require_fast_uri = __commonJS({
|
|
|
17318
17318
|
}
|
|
17319
17319
|
return uri;
|
|
17320
17320
|
}
|
|
17321
|
-
function
|
|
17321
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
17322
17322
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
17323
17323
|
const {
|
|
17324
17324
|
parsed: baseParsed,
|
|
@@ -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, relative4, options, skipNormalization) {
|
|
17355
17355
|
const target = {};
|
|
17356
17356
|
if (!skipNormalization) {
|
|
17357
17357
|
base = parse4(serialize(base, options), options);
|
|
17358
|
-
|
|
17358
|
+
relative4 = parse4(serialize(relative4, 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 && relative4.scheme) {
|
|
17362
|
+
target.scheme = relative4.scheme;
|
|
17363
|
+
target.userinfo = relative4.userinfo;
|
|
17364
|
+
target.host = relative4.host;
|
|
17365
|
+
target.port = relative4.port;
|
|
17366
|
+
target.path = removeDotSegments(relative4.path || "");
|
|
17367
|
+
target.query = relative4.query;
|
|
17368
17368
|
} else {
|
|
17369
|
-
if (
|
|
17370
|
-
target.userinfo =
|
|
17371
|
-
target.host =
|
|
17372
|
-
target.port =
|
|
17373
|
-
target.path = removeDotSegments(
|
|
17374
|
-
target.query =
|
|
17369
|
+
if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
|
|
17370
|
+
target.userinfo = relative4.userinfo;
|
|
17371
|
+
target.host = relative4.host;
|
|
17372
|
+
target.port = relative4.port;
|
|
17373
|
+
target.path = removeDotSegments(relative4.path || "");
|
|
17374
|
+
target.query = relative4.query;
|
|
17375
17375
|
} else {
|
|
17376
|
-
if (!
|
|
17376
|
+
if (!relative4.path) {
|
|
17377
17377
|
target.path = base.path;
|
|
17378
|
-
if (
|
|
17379
|
-
target.query =
|
|
17378
|
+
if (relative4.query !== void 0) {
|
|
17379
|
+
target.query = relative4.query;
|
|
17380
17380
|
} else {
|
|
17381
17381
|
target.query = base.query;
|
|
17382
17382
|
}
|
|
17383
17383
|
} else {
|
|
17384
|
-
if (
|
|
17385
|
-
target.path = removeDotSegments(
|
|
17384
|
+
if (relative4.path[0] === "/") {
|
|
17385
|
+
target.path = removeDotSegments(relative4.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 = "/" + relative4.path;
|
|
17389
17389
|
} else if (!base.path) {
|
|
17390
|
-
target.path =
|
|
17390
|
+
target.path = relative4.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) + relative4.path;
|
|
17393
17393
|
}
|
|
17394
17394
|
target.path = removeDotSegments(target.path);
|
|
17395
17395
|
}
|
|
17396
|
-
target.query =
|
|
17396
|
+
target.query = relative4.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 = relative4.fragment;
|
|
17405
17405
|
return target;
|
|
17406
17406
|
}
|
|
17407
17407
|
function equal(uriA, uriB, options) {
|
|
@@ -17687,7 +17687,7 @@ var require_fast_uri = __commonJS({
|
|
|
17687
17687
|
var fastUri = {
|
|
17688
17688
|
SCHEMES,
|
|
17689
17689
|
normalize,
|
|
17690
|
-
resolve:
|
|
17690
|
+
resolve: resolve4,
|
|
17691
17691
|
resolveComponent,
|
|
17692
17692
|
equal,
|
|
17693
17693
|
serialize,
|
|
@@ -20678,10 +20678,10 @@ var require_dist2 = __commonJS({
|
|
|
20678
20678
|
|
|
20679
20679
|
// apps/zaku-cli/src/cli.ts
|
|
20680
20680
|
var import_reflect_metadata3 = __toESM(require_Reflect(), 1);
|
|
20681
|
-
import { readFile as
|
|
20681
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
20682
20682
|
import { createRequire } from "node:module";
|
|
20683
20683
|
import { homedir as homedir2 } from "node:os";
|
|
20684
|
-
import { dirname as
|
|
20684
|
+
import { dirname as dirname5, join as join13, relative as relative3, resolve as resolve3, 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
|
|
@@ -24111,7 +24111,7 @@ function bootstrap(scope, tokens) {
|
|
|
24111
24111
|
}
|
|
24112
24112
|
|
|
24113
24113
|
// apps/zaku-cli/src/dependencies.ts
|
|
24114
|
-
var
|
|
24114
|
+
var import_tsyringe11 = __toESM(require_cjs(), 1);
|
|
24115
24115
|
import { homedir } from "node:os";
|
|
24116
24116
|
|
|
24117
24117
|
// packages/zaku/dist/index.js
|
|
@@ -24154,11 +24154,13 @@ async function decodePreset(code, run) {
|
|
|
24154
24154
|
// packages/zaku/dist/lib/commands/write-tokens.js
|
|
24155
24155
|
var WriteTokens = class extends DomainCommand {
|
|
24156
24156
|
root;
|
|
24157
|
+
config;
|
|
24157
24158
|
cwd;
|
|
24158
24159
|
css;
|
|
24159
24160
|
constructor(input2) {
|
|
24160
24161
|
super();
|
|
24161
24162
|
this.root = input2.root;
|
|
24163
|
+
this.config = input2.config;
|
|
24162
24164
|
this.cwd = input2.cwd;
|
|
24163
24165
|
this.css = input2.css;
|
|
24164
24166
|
}
|
|
@@ -24167,10 +24169,12 @@ var WriteTokens = class extends DomainCommand {
|
|
|
24167
24169
|
// packages/zaku/dist/lib/commands/write-recipe.js
|
|
24168
24170
|
var WriteRecipe = class extends DomainCommand {
|
|
24169
24171
|
root;
|
|
24172
|
+
config;
|
|
24170
24173
|
url;
|
|
24171
24174
|
constructor(input2) {
|
|
24172
24175
|
super();
|
|
24173
24176
|
this.root = input2.root;
|
|
24177
|
+
this.config = input2.config;
|
|
24174
24178
|
this.url = input2.url;
|
|
24175
24179
|
}
|
|
24176
24180
|
};
|
|
@@ -24178,11 +24182,13 @@ var WriteRecipe = class extends DomainCommand {
|
|
|
24178
24182
|
// packages/zaku/dist/lib/commands/save-library.js
|
|
24179
24183
|
var SaveLibrary = class extends DomainCommand {
|
|
24180
24184
|
root;
|
|
24185
|
+
config;
|
|
24181
24186
|
key;
|
|
24182
24187
|
part;
|
|
24183
24188
|
constructor(input2) {
|
|
24184
24189
|
super();
|
|
24185
24190
|
this.root = input2.root;
|
|
24191
|
+
this.config = input2.config;
|
|
24186
24192
|
if (input2.key !== void 0)
|
|
24187
24193
|
this.key = input2.key;
|
|
24188
24194
|
if (input2.part !== void 0)
|
|
@@ -24193,10 +24199,12 @@ var SaveLibrary = class extends DomainCommand {
|
|
|
24193
24199
|
// packages/zaku/dist/lib/commands/write-outline.js
|
|
24194
24200
|
var WriteOutline = class extends DomainCommand {
|
|
24195
24201
|
root;
|
|
24202
|
+
config;
|
|
24196
24203
|
frames;
|
|
24197
24204
|
constructor(input2) {
|
|
24198
24205
|
super();
|
|
24199
24206
|
this.root = input2.root;
|
|
24207
|
+
this.config = input2.config;
|
|
24200
24208
|
this.frames = input2.frames;
|
|
24201
24209
|
}
|
|
24202
24210
|
};
|
|
@@ -24236,7 +24244,6 @@ var TOKENS = {
|
|
|
24236
24244
|
RUN_COMMAND: "zaku.runCommand",
|
|
24237
24245
|
RECIPE_PAGE_READER: "zaku.recipePageReader",
|
|
24238
24246
|
BUDGET_LEDGER: "zaku.budgetLedger",
|
|
24239
|
-
DESIGN_CONFIG_REPOSITORY: "zaku.designConfigRepository",
|
|
24240
24247
|
TOKEN_DOCUMENT_REPOSITORY: "zaku.tokenDocumentRepository",
|
|
24241
24248
|
RECIPE_REPOSITORY: "zaku.recipeRepository",
|
|
24242
24249
|
JSON_SCHEMA_FILES: "zaku.jsonSchemaFiles",
|
|
@@ -29385,7 +29392,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
29385
29392
|
var NONE = 0;
|
|
29386
29393
|
var ASSUMED = 1;
|
|
29387
29394
|
var PROVEN = 2;
|
|
29388
|
-
function isRecursive(inst, stack,
|
|
29395
|
+
function isRecursive(inst, stack, resolve4) {
|
|
29389
29396
|
const cached2 = recursive.get(inst);
|
|
29390
29397
|
if (cached2 !== void 0)
|
|
29391
29398
|
return cached2 ? PROVEN : NONE;
|
|
@@ -29395,7 +29402,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
29395
29402
|
let result = NONE;
|
|
29396
29403
|
const check2 = (child) => {
|
|
29397
29404
|
if (result !== PROVEN && child?._zod) {
|
|
29398
|
-
const answer = isRecursive(child, stack,
|
|
29405
|
+
const answer = isRecursive(child, stack, resolve4);
|
|
29399
29406
|
if (answer > result)
|
|
29400
29407
|
result = answer;
|
|
29401
29408
|
}
|
|
@@ -29406,7 +29413,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
29406
29413
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
29407
29414
|
if (spread && !desc.enumerable)
|
|
29408
29415
|
continue;
|
|
29409
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
29416
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve4) : NONE;
|
|
29410
29417
|
if (child > answer)
|
|
29411
29418
|
answer = child;
|
|
29412
29419
|
}
|
|
@@ -29470,7 +29477,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
29470
29477
|
break;
|
|
29471
29478
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
29472
29479
|
case "lazy": {
|
|
29473
|
-
const inner = def._cachedInner ?? (
|
|
29480
|
+
const inner = def._cachedInner ?? (resolve4 ? inst._zod.innerType : void 0);
|
|
29474
29481
|
merge3(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
29475
29482
|
break;
|
|
29476
29483
|
}
|
|
@@ -44362,7 +44369,7 @@ function dtcgTokenDocument(system, schemes, name) {
|
|
|
44362
44369
|
// packages/zaku/dist/lib/domain/errors/css-required.js
|
|
44363
44370
|
var CssRequired = class extends Error {
|
|
44364
44371
|
constructor() {
|
|
44365
|
-
super("zaku tokens needs
|
|
44372
|
+
super("zaku tokens needs designSystem.shadcn.css, the stylesheet that declares :root and .dark, or --css when it runs on one product");
|
|
44366
44373
|
this.name = "CssRequired";
|
|
44367
44374
|
}
|
|
44368
44375
|
};
|
|
@@ -44417,6 +44424,34 @@ var PlaywrightMissing = class extends Error {
|
|
|
44417
44424
|
}
|
|
44418
44425
|
};
|
|
44419
44426
|
|
|
44427
|
+
// packages/zaku/dist/lib/domain/errors/product-config-missing.js
|
|
44428
|
+
var ProductConfigMissing = class extends Error {
|
|
44429
|
+
path;
|
|
44430
|
+
product;
|
|
44431
|
+
constructor(path2, product) {
|
|
44432
|
+
super(`no ${path2}, the zaku.yaml of the product ${product} the workspace config lists`);
|
|
44433
|
+
this.path = path2;
|
|
44434
|
+
this.product = product;
|
|
44435
|
+
this.name = "ProductConfigMissing";
|
|
44436
|
+
}
|
|
44437
|
+
};
|
|
44438
|
+
|
|
44439
|
+
// packages/zaku/dist/lib/domain/errors/product-required.js
|
|
44440
|
+
var ProductRequired = class extends Error {
|
|
44441
|
+
constructor(command, listed) {
|
|
44442
|
+
super(`${command} acts on one product; name one with --product: ${listed.join(", ")}`);
|
|
44443
|
+
this.name = "ProductRequired";
|
|
44444
|
+
}
|
|
44445
|
+
};
|
|
44446
|
+
|
|
44447
|
+
// packages/zaku/dist/lib/domain/errors/product-unknown.js
|
|
44448
|
+
var ProductUnknown = class extends Error {
|
|
44449
|
+
constructor(name, listed) {
|
|
44450
|
+
super(`no product ${name}; the config lists ${listed.join(", ")}`);
|
|
44451
|
+
this.name = "ProductUnknown";
|
|
44452
|
+
}
|
|
44453
|
+
};
|
|
44454
|
+
|
|
44420
44455
|
// packages/zaku/dist/lib/domain/errors/recipe-page-failed.js
|
|
44421
44456
|
var RecipePageFailed = class extends Error {
|
|
44422
44457
|
constructor(cause) {
|
|
@@ -44433,6 +44468,18 @@ var RecipeUrlRequired = class extends Error {
|
|
|
44433
44468
|
}
|
|
44434
44469
|
};
|
|
44435
44470
|
|
|
44471
|
+
// packages/zaku/dist/lib/domain/errors/workspace-config-missing.js
|
|
44472
|
+
var WorkspaceConfigMissing = class extends Error {
|
|
44473
|
+
path;
|
|
44474
|
+
legacy;
|
|
44475
|
+
constructor(path2, legacy) {
|
|
44476
|
+
super(legacy === null ? `no ${path2}` : `no ${path2}, and no ${legacy} to fall back on; run zaku where zaku.config.yaml is, or name it with --config`);
|
|
44477
|
+
this.path = path2;
|
|
44478
|
+
this.legacy = legacy;
|
|
44479
|
+
this.name = "WorkspaceConfigMissing";
|
|
44480
|
+
}
|
|
44481
|
+
};
|
|
44482
|
+
|
|
44436
44483
|
// packages/zaku/dist/lib/domain/theme-css.js
|
|
44437
44484
|
function declarations(css, selector) {
|
|
44438
44485
|
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -44452,19 +44499,17 @@ function parseThemeCss(css) {
|
|
|
44452
44499
|
|
|
44453
44500
|
// packages/zaku/dist/lib/handlers/write-tokens.js
|
|
44454
44501
|
var WriteTokensHandler = class WriteTokensHandler2 {
|
|
44455
|
-
configs;
|
|
44456
44502
|
documents;
|
|
44457
44503
|
files;
|
|
44458
44504
|
run;
|
|
44459
44505
|
command = WriteTokens;
|
|
44460
|
-
constructor(
|
|
44461
|
-
this.configs = configs;
|
|
44506
|
+
constructor(documents, files2, run) {
|
|
44462
44507
|
this.documents = documents;
|
|
44463
44508
|
this.files = files2;
|
|
44464
44509
|
this.run = run;
|
|
44465
44510
|
}
|
|
44466
44511
|
async handle(command) {
|
|
44467
|
-
const config2 =
|
|
44512
|
+
const { config: config2 } = command;
|
|
44468
44513
|
const system = config2.designSystem;
|
|
44469
44514
|
let doc;
|
|
44470
44515
|
let from;
|
|
@@ -44489,10 +44534,9 @@ var WriteTokensHandler = class WriteTokensHandler2 {
|
|
|
44489
44534
|
};
|
|
44490
44535
|
WriteTokensHandler = __decorate2([
|
|
44491
44536
|
(0, import_tsyringe.injectable)({ token: TOKENS.COMMAND_HANDLER }),
|
|
44492
|
-
__param2(0, (0, import_tsyringe.inject)(TOKENS.
|
|
44493
|
-
__param2(1, (0, import_tsyringe.inject)(TOKENS.
|
|
44494
|
-
__param2(2, (0, import_tsyringe.inject)(TOKENS.
|
|
44495
|
-
__param2(3, (0, import_tsyringe.inject)(TOKENS.RUN_COMMAND))
|
|
44537
|
+
__param2(0, (0, import_tsyringe.inject)(TOKENS.TOKEN_DOCUMENT_REPOSITORY)),
|
|
44538
|
+
__param2(1, (0, import_tsyringe.inject)(TOKENS.SOURCE_FILES)),
|
|
44539
|
+
__param2(2, (0, import_tsyringe.inject)(TOKENS.RUN_COMMAND))
|
|
44496
44540
|
], WriteTokensHandler);
|
|
44497
44541
|
|
|
44498
44542
|
// packages/zaku/dist/lib/handlers/write-recipe.js
|
|
@@ -44587,17 +44631,15 @@ ${JSON.stringify(Object.entries(props).sort(([a], [b]) => a.localeCompare(b)))}`
|
|
|
44587
44631
|
|
|
44588
44632
|
// packages/zaku/dist/lib/handlers/write-recipe.js
|
|
44589
44633
|
var WriteRecipeHandler = class WriteRecipeHandler2 {
|
|
44590
|
-
configs;
|
|
44591
44634
|
recipes;
|
|
44592
44635
|
readPage;
|
|
44593
44636
|
command = WriteRecipe;
|
|
44594
|
-
constructor(
|
|
44595
|
-
this.configs = configs;
|
|
44637
|
+
constructor(recipes, readPage) {
|
|
44596
44638
|
this.recipes = recipes;
|
|
44597
44639
|
this.readPage = readPage;
|
|
44598
44640
|
}
|
|
44599
44641
|
async handle(command) {
|
|
44600
|
-
const config2 =
|
|
44642
|
+
const { config: config2 } = command;
|
|
44601
44643
|
const url2 = command.url ?? config2.recipe?.url;
|
|
44602
44644
|
if (!url2)
|
|
44603
44645
|
throw new RecipeUrlRequired();
|
|
@@ -44620,17 +44662,41 @@ var WriteRecipeHandler = class WriteRecipeHandler2 {
|
|
|
44620
44662
|
};
|
|
44621
44663
|
WriteRecipeHandler = __decorate2([
|
|
44622
44664
|
(0, import_tsyringe2.injectable)({ token: TOKENS.COMMAND_HANDLER }),
|
|
44623
|
-
__param2(0, (0, import_tsyringe2.inject)(TOKENS.
|
|
44624
|
-
__param2(1, (0, import_tsyringe2.inject)(TOKENS.
|
|
44625
|
-
__param2(2, (0, import_tsyringe2.inject)(TOKENS.RECIPE_PAGE_READER))
|
|
44665
|
+
__param2(0, (0, import_tsyringe2.inject)(TOKENS.RECIPE_REPOSITORY)),
|
|
44666
|
+
__param2(1, (0, import_tsyringe2.inject)(TOKENS.RECIPE_PAGE_READER))
|
|
44626
44667
|
], WriteRecipeHandler);
|
|
44627
44668
|
|
|
44628
44669
|
// packages/zaku/dist/lib/handlers/save-library.js
|
|
44629
44670
|
var import_tsyringe3 = __toESM(require_cjs(), 1);
|
|
44630
44671
|
import { relative as relative2 } from "node:path";
|
|
44631
44672
|
|
|
44632
|
-
// packages/zaku/dist/lib/
|
|
44633
|
-
|
|
44673
|
+
// packages/zaku/dist/lib/repositories/design-paths.js
|
|
44674
|
+
import { join as join2 } from "node:path";
|
|
44675
|
+
function librarySnapshotDir(paths, key) {
|
|
44676
|
+
if (key === null)
|
|
44677
|
+
return paths;
|
|
44678
|
+
const library = join2(paths.library, key);
|
|
44679
|
+
return { root: paths.root, library, libraryIndex: join2(library, "index.json"), legacyLibrary: null };
|
|
44680
|
+
}
|
|
44681
|
+
function designPaths(root) {
|
|
44682
|
+
return {
|
|
44683
|
+
root,
|
|
44684
|
+
config: join2(root, "zaku.yaml"),
|
|
44685
|
+
maps: join2(root, "map"),
|
|
44686
|
+
outline: join2(root, "outline"),
|
|
44687
|
+
unmapped: join2(root, "outline", "unmapped.yaml"),
|
|
44688
|
+
files: join2(root, "outline", "files.yaml"),
|
|
44689
|
+
library: join2(root, "library"),
|
|
44690
|
+
libraryIndex: join2(root, "library", "index.json"),
|
|
44691
|
+
legacyLibrary: join2(root, "library.json"),
|
|
44692
|
+
tokens: join2(root, "tokens.json"),
|
|
44693
|
+
recipe: join2(root, "recipe.json")
|
|
44694
|
+
};
|
|
44695
|
+
}
|
|
44696
|
+
|
|
44697
|
+
// packages/zaku/dist/lib/repositories/library-snapshot.js
|
|
44698
|
+
import { mkdir, readdir, readFile as readFile2, rename as rename2, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
44699
|
+
import { join as join3, relative } from "node:path";
|
|
44634
44700
|
|
|
44635
44701
|
// packages/zaku/dist/lib/domain/design-graph.js
|
|
44636
44702
|
var DESKTOP_FAMILIES = /* @__PURE__ */ new Set(["macos", "windows", "gnome", "kde"]);
|
|
@@ -44716,334 +44782,6 @@ function snapshotsFor(input2, target) {
|
|
|
44716
44782
|
return { libraries, kits, missing };
|
|
44717
44783
|
}
|
|
44718
44784
|
|
|
44719
|
-
// packages/zaku/dist/lib/schema/zaku-config.js
|
|
44720
|
-
var PLATFORM_FAMILIES = ["web", "ios", "android", "macos", "windows", "gnome", "kde"];
|
|
44721
|
-
var LAYERS = ["foundations", "components"];
|
|
44722
|
-
var BRANCHES = ["ui", "native"];
|
|
44723
|
-
var DEFAULT_INTERACTIVE = [
|
|
44724
|
-
"Button",
|
|
44725
|
-
"Button Group",
|
|
44726
|
-
"Checkbox",
|
|
44727
|
-
"Combobox",
|
|
44728
|
-
"Dropdown Menu",
|
|
44729
|
-
"Input",
|
|
44730
|
-
"Input Group",
|
|
44731
|
-
"Input OTP",
|
|
44732
|
-
"Native Select",
|
|
44733
|
-
"Pagination",
|
|
44734
|
-
"Radio Group",
|
|
44735
|
-
"Select",
|
|
44736
|
-
"Slider",
|
|
44737
|
-
"Switch",
|
|
44738
|
-
"Tabs",
|
|
44739
|
-
"Textarea",
|
|
44740
|
-
"Toggle",
|
|
44741
|
-
"Toggle Group"
|
|
44742
|
-
];
|
|
44743
|
-
var id = external_exports.string().regex(/^[a-z][a-z0-9-]*$/, "lowercase letters, digits and dashes, starting with a letter");
|
|
44744
|
-
var targetSchema = external_exports.object({
|
|
44745
|
-
id,
|
|
44746
|
-
family: external_exports.enum(PLATFORM_FAMILIES),
|
|
44747
|
-
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"),
|
|
44748
|
-
/** The frame size every frame of this target is drawn at; the frame check compares it. */
|
|
44749
|
-
size: external_exports.object({ width: external_exports.number().positive(), height: external_exports.number().positive() }).strict().optional(),
|
|
44750
|
-
/** The renderer whose libraries its frames draw from; `defaultBranch` in the design graph gives it when left out. */
|
|
44751
|
-
branch: external_exports.enum(BRANCHES).optional()
|
|
44752
|
-
}).strict();
|
|
44753
|
-
var DEFAULT_SYSTEM_BARS = {
|
|
44754
|
-
web: [],
|
|
44755
|
-
ios: [["Status Bar"], ["Home Indicator"]],
|
|
44756
|
-
android: [["Status Bar"], ["Navigation Bar", "Gesture Handle"]],
|
|
44757
|
-
macos: [["Window Controls"]],
|
|
44758
|
-
windows: [["Title Bar"]],
|
|
44759
|
-
gnome: [["Header Bar"]],
|
|
44760
|
-
kde: [["Title Bar"]]
|
|
44761
|
-
};
|
|
44762
|
-
function systemBarNames(config2) {
|
|
44763
|
-
const bars = { ...DEFAULT_SYSTEM_BARS, ...config2.systemBars };
|
|
44764
|
-
return new Set(Object.values(bars).flat(2));
|
|
44765
|
-
}
|
|
44766
|
-
var budgetSchema = external_exports.object({
|
|
44767
|
-
mcpPerDay: external_exports.number().int().positive().default(200),
|
|
44768
|
-
mcpPerRun: external_exports.number().int().positive().default(30),
|
|
44769
|
-
reserve: external_exports.number().min(0).max(1).default(0.2)
|
|
44770
|
-
}).strict();
|
|
44771
|
-
var fileKey = external_exports.string().min(1);
|
|
44772
|
-
var kitSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
44773
|
-
var librarySchema = external_exports.object({
|
|
44774
|
-
key: fileKey,
|
|
44775
|
-
layer: external_exports.enum(LAYERS),
|
|
44776
|
-
branches: external_exports.array(external_exports.enum(BRANCHES)).min(1),
|
|
44777
|
-
/** The libraries and kits this one is built on, by key. */
|
|
44778
|
-
extends: external_exports.array(fileKey).default([])
|
|
44779
|
-
}).strict();
|
|
44780
|
-
var productSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
44781
|
-
var prototypeSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
44782
|
-
var files = external_exports.object({
|
|
44783
|
-
library: fileKey.optional(),
|
|
44784
|
-
product: fileKey.optional(),
|
|
44785
|
-
kits: external_exports.array(kitSchema).optional(),
|
|
44786
|
-
libraries: external_exports.array(librarySchema).optional(),
|
|
44787
|
-
products: external_exports.array(productSchema).optional(),
|
|
44788
|
-
prototypes: external_exports.array(prototypeSchema).optional()
|
|
44789
|
-
}).strict();
|
|
44790
|
-
function byRole(figma) {
|
|
44791
|
-
return [figma.kits, figma.libraries, figma.products, figma.prototypes].some((list) => list !== void 0);
|
|
44792
|
-
}
|
|
44793
|
-
var shadcnSystem = external_exports.object({ preset: external_exports.string().min(1) }).strict();
|
|
44794
|
-
var tokenFiles = external_exports.array(external_exports.string().min(1)).min(1);
|
|
44795
|
-
var resolverInputs = external_exports.record(external_exports.string(), external_exports.string());
|
|
44796
|
-
var dtcgSystem = external_exports.object({
|
|
44797
|
-
resolver: external_exports.string().min(1).optional(),
|
|
44798
|
-
light: external_exports.union([tokenFiles, resolverInputs]),
|
|
44799
|
-
dark: external_exports.union([tokenFiles, resolverInputs]),
|
|
44800
|
-
/** The group whose tokens are the colour roles, and the one whose tokens are the radius steps. */
|
|
44801
|
-
colors: external_exports.string().min(1).default("color"),
|
|
44802
|
-
radii: external_exports.string().min(1).default("radius"),
|
|
44803
|
-
/** Foreground and background token pairs a text is read in, each needing 4.5:1. */
|
|
44804
|
-
contrast: external_exports.array(external_exports.tuple([external_exports.string().min(1), external_exports.string().min(1)])).default([])
|
|
44805
|
-
}).strict().superRefine((dtcg, ctx) => {
|
|
44806
|
-
for (const scheme of ["light", "dark"]) {
|
|
44807
|
-
const files2 = Array.isArray(dtcg[scheme]);
|
|
44808
|
-
if (dtcg.resolver !== void 0 && files2) {
|
|
44809
|
-
ctx.addIssue({
|
|
44810
|
-
code: "custom",
|
|
44811
|
-
path: [scheme],
|
|
44812
|
-
message: "with a resolver, name the modifier contexts, not files"
|
|
44813
|
-
});
|
|
44814
|
-
}
|
|
44815
|
-
if (dtcg.resolver === void 0 && !files2) {
|
|
44816
|
-
ctx.addIssue({
|
|
44817
|
-
code: "custom",
|
|
44818
|
-
path: [scheme],
|
|
44819
|
-
message: "without a resolver, list the token files"
|
|
44820
|
-
});
|
|
44821
|
-
}
|
|
44822
|
-
}
|
|
44823
|
-
});
|
|
44824
|
-
var designSystemSchema = external_exports.union([
|
|
44825
|
-
external_exports.object({ shadcn: shadcnSystem }).strict(),
|
|
44826
|
-
external_exports.object({ dtcg: dtcgSystem }).strict()
|
|
44827
|
-
]);
|
|
44828
|
-
var recipeSchema = external_exports.object({
|
|
44829
|
-
url: external_exports.url().optional(),
|
|
44830
|
-
dark: external_exports.enum(["class", "media"]).default("class"),
|
|
44831
|
-
darkClass: external_exports.string().min(1).default("dark")
|
|
44832
|
-
}).strict();
|
|
44833
|
-
function writtenInAScript(tag) {
|
|
44834
|
-
try {
|
|
44835
|
-
return new Intl.Locale(tag).maximize().script !== void 0;
|
|
44836
|
-
} catch {
|
|
44837
|
-
return false;
|
|
44838
|
-
}
|
|
44839
|
-
}
|
|
44840
|
-
var copySchema = external_exports.object({
|
|
44841
|
-
locales: external_exports.array(external_exports.string().refine(writtenInAScript, "a BCP 47 language tag, such as en or vi")).min(1).default(["en"]),
|
|
44842
|
-
currencies: external_exports.array(external_exports.string().refine((code) => Intl.supportedValuesOf("currency").includes(code), "an ISO 4217 code, such as VND or USD")).default([])
|
|
44843
|
-
}).strict();
|
|
44844
|
-
var configShape = external_exports.object({
|
|
44845
|
-
product: external_exports.string().min(1),
|
|
44846
|
-
designSystem: designSystemSchema,
|
|
44847
|
-
figma: files.default({}),
|
|
44848
|
-
targets: external_exports.array(targetSchema).min(1),
|
|
44849
|
-
modes: external_exports.record(external_exports.string(), external_exports.string()).default({}),
|
|
44850
|
-
interactive: external_exports.array(external_exports.string().min(1)).default([...DEFAULT_INTERACTIVE]),
|
|
44851
|
-
/** The bars of the families whose kit names them its own way; every family left out keeps its default. */
|
|
44852
|
-
systemBars: external_exports.partialRecord(external_exports.enum(PLATFORM_FAMILIES), external_exports.array(external_exports.array(external_exports.string().min(1)).min(1))).optional(),
|
|
44853
|
-
budget: budgetSchema.default({ mcpPerDay: 200, mcpPerRun: 30, reserve: 0.2 }),
|
|
44854
|
-
recipe: recipeSchema.optional(),
|
|
44855
|
-
copy: copySchema.default(DEFAULT_COPY)
|
|
44856
|
-
}).strict();
|
|
44857
|
-
var zakuConfigSchema = configShape.superRefine((config2, ctx) => {
|
|
44858
|
-
for (const key of ["id", "name"]) {
|
|
44859
|
-
const seen = /* @__PURE__ */ new Set();
|
|
44860
|
-
config2.targets.forEach((target, index) => {
|
|
44861
|
-
if (seen.has(target[key])) {
|
|
44862
|
-
ctx.addIssue({
|
|
44863
|
-
code: "custom",
|
|
44864
|
-
path: ["targets", index, key],
|
|
44865
|
-
message: `a second target with ${key} ${target[key]}`
|
|
44866
|
-
});
|
|
44867
|
-
}
|
|
44868
|
-
seen.add(target[key]);
|
|
44869
|
-
});
|
|
44870
|
-
}
|
|
44871
|
-
if (byRole(config2.figma))
|
|
44872
|
-
refineFilesByRole(config2, ctx);
|
|
44873
|
-
});
|
|
44874
|
-
function refineFilesByRole(config2, ctx) {
|
|
44875
|
-
const { figma } = config2;
|
|
44876
|
-
if (figma.library !== void 0 || figma.product !== void 0) {
|
|
44877
|
-
ctx.addIssue({
|
|
44878
|
-
code: "custom",
|
|
44879
|
-
path: ["figma"],
|
|
44880
|
-
message: "figma.library and figma.product describe one library and one product; list files by role instead"
|
|
44881
|
-
});
|
|
44882
|
-
}
|
|
44883
|
-
const kits = figma.kits ?? [];
|
|
44884
|
-
const libraries = figma.libraries ?? [];
|
|
44885
|
-
const products = figma.products ?? [];
|
|
44886
|
-
const seen = /* @__PURE__ */ new Set();
|
|
44887
|
-
const lists = [
|
|
44888
|
-
["kits", kits],
|
|
44889
|
-
["libraries", libraries],
|
|
44890
|
-
["products", products],
|
|
44891
|
-
["prototypes", figma.prototypes ?? []]
|
|
44892
|
-
];
|
|
44893
|
-
for (const [list, entries] of lists) {
|
|
44894
|
-
entries.forEach((entry, index) => {
|
|
44895
|
-
if (seen.has(entry.key))
|
|
44896
|
-
ctx.addIssue({
|
|
44897
|
-
code: "custom",
|
|
44898
|
-
path: ["figma", list, index, "key"],
|
|
44899
|
-
message: `a second file with key ${entry.key}`
|
|
44900
|
-
});
|
|
44901
|
-
seen.add(entry.key);
|
|
44902
|
-
});
|
|
44903
|
-
}
|
|
44904
|
-
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
44905
|
-
const kitKeys = new Set(kits.map((kit) => kit.key));
|
|
44906
|
-
libraries.forEach((library, index) => {
|
|
44907
|
-
const path2 = ["figma", "libraries", index, "extends"];
|
|
44908
|
-
for (const key of library.extends) {
|
|
44909
|
-
const base = byKey.get(key);
|
|
44910
|
-
if (!base && !kitKeys.has(key)) {
|
|
44911
|
-
ctx.addIssue({
|
|
44912
|
-
code: "custom",
|
|
44913
|
-
path: path2,
|
|
44914
|
-
message: `${library.key} extends ${key}, which is no library or kit listed`
|
|
44915
|
-
});
|
|
44916
|
-
} else if (base?.layer === "components" && library.layer === "foundations") {
|
|
44917
|
-
ctx.addIssue({ code: "custom", path: path2, message: `foundations ${library.key} extends components ${key}` });
|
|
44918
|
-
} else if (base && !base.branches.some((branch) => library.branches.includes(branch))) {
|
|
44919
|
-
ctx.addIssue({
|
|
44920
|
-
code: "custom",
|
|
44921
|
-
path: path2,
|
|
44922
|
-
message: `${library.key} extends ${key}, which holds none of its branches`
|
|
44923
|
-
});
|
|
44924
|
-
}
|
|
44925
|
-
}
|
|
44926
|
-
});
|
|
44927
|
-
const cycle = findCycle(libraries);
|
|
44928
|
-
if (cycle)
|
|
44929
|
-
ctx.addIssue({ code: "custom", path: ["figma", "libraries"], message: `extends comes back: ${cycle}` });
|
|
44930
|
-
for (const [list, entries] of [
|
|
44931
|
-
["products", products],
|
|
44932
|
-
["prototypes", figma.prototypes ?? []]
|
|
44933
|
-
]) {
|
|
44934
|
-
const families2 = /* @__PURE__ */ new Set();
|
|
44935
|
-
entries.forEach((entry, index) => {
|
|
44936
|
-
if (families2.has(entry.family))
|
|
44937
|
-
ctx.addIssue({
|
|
44938
|
-
code: "custom",
|
|
44939
|
-
path: ["figma", list, index, "family"],
|
|
44940
|
-
message: `a second ${list === "products" ? "product" : "prototype"} file for ${entry.family}`
|
|
44941
|
-
});
|
|
44942
|
-
families2.add(entry.family);
|
|
44943
|
-
});
|
|
44944
|
-
}
|
|
44945
|
-
(figma.prototypes ?? []).forEach((prototype2, index) => {
|
|
44946
|
-
if (!products.some((product) => product.family === prototype2.family))
|
|
44947
|
-
ctx.addIssue({
|
|
44948
|
-
code: "custom",
|
|
44949
|
-
path: ["figma", "prototypes", index, "family"],
|
|
44950
|
-
message: `no product file for ${prototype2.family} to copy its frames from`
|
|
44951
|
-
});
|
|
44952
|
-
});
|
|
44953
|
-
config2.targets.forEach((target, index) => {
|
|
44954
|
-
const branch = target.branch ?? defaultBranch(target.family);
|
|
44955
|
-
const path2 = ["targets", index, "branch"];
|
|
44956
|
-
if (branch === void 0) {
|
|
44957
|
-
ctx.addIssue({ code: "custom", path: path2, message: `a ${target.family} target names its branch, ui or native` });
|
|
44958
|
-
} else if (libraries.length > 0 && !libraries.some((library) => library.branches.includes(branch))) {
|
|
44959
|
-
ctx.addIssue({ code: "custom", path: path2, message: `no library holds the ${branch} branch` });
|
|
44960
|
-
}
|
|
44961
|
-
});
|
|
44962
|
-
}
|
|
44963
|
-
function findCycle(libraries) {
|
|
44964
|
-
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
44965
|
-
const visit2 = (key, path2) => {
|
|
44966
|
-
if (path2.includes(key))
|
|
44967
|
-
return [...path2.slice(path2.indexOf(key)), key].join(" -> ");
|
|
44968
|
-
for (const next of byKey.get(key)?.extends ?? []) {
|
|
44969
|
-
const found = visit2(next, [...path2, key]);
|
|
44970
|
-
if (found)
|
|
44971
|
-
return found;
|
|
44972
|
-
}
|
|
44973
|
-
return void 0;
|
|
44974
|
-
};
|
|
44975
|
-
for (const library of libraries) {
|
|
44976
|
-
const found = visit2(library.key, []);
|
|
44977
|
-
if (found)
|
|
44978
|
-
return found;
|
|
44979
|
-
}
|
|
44980
|
-
return void 0;
|
|
44981
|
-
}
|
|
44982
|
-
|
|
44983
|
-
// packages/zaku/dist/lib/repositories/design-file.js
|
|
44984
|
-
var import_yaml = __toESM(require_dist(), 1);
|
|
44985
|
-
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
44986
|
-
function parseDesignFile(path2, text, schema) {
|
|
44987
|
-
let data;
|
|
44988
|
-
try {
|
|
44989
|
-
data = path2.endsWith(".json") ? JSON.parse(text) : (0, import_yaml.parse)(text);
|
|
44990
|
-
} catch (error62) {
|
|
44991
|
-
throw new DesignFileInvalid(path2, [error62.message]);
|
|
44992
|
-
}
|
|
44993
|
-
const result = schema.safeParse(data);
|
|
44994
|
-
if (!result.success) {
|
|
44995
|
-
throw new DesignFileInvalid(path2, result.error.issues.map((issue2) => `${issue2.path.map(String).join(".") || "(root)"}: ${issue2.message}`));
|
|
44996
|
-
}
|
|
44997
|
-
return result.data;
|
|
44998
|
-
}
|
|
44999
|
-
async function readDesignFile(path2, schema) {
|
|
45000
|
-
return parseDesignFile(path2, await readFile(path2, "utf8"), schema);
|
|
45001
|
-
}
|
|
45002
|
-
async function readOptionalDesignFile(path2, schema) {
|
|
45003
|
-
let text;
|
|
45004
|
-
try {
|
|
45005
|
-
text = await readFile(path2, "utf8");
|
|
45006
|
-
} catch (error62) {
|
|
45007
|
-
if (error62.code === "ENOENT")
|
|
45008
|
-
return null;
|
|
45009
|
-
throw error62;
|
|
45010
|
-
}
|
|
45011
|
-
return parseDesignFile(path2, text, schema);
|
|
45012
|
-
}
|
|
45013
|
-
async function writeDesignFile(path2, value) {
|
|
45014
|
-
const temporary = `${path2}.${process.pid}.tmp`;
|
|
45015
|
-
await writeFile(temporary, `${JSON.stringify(value, null, 2)}
|
|
45016
|
-
`);
|
|
45017
|
-
await rename(temporary, path2);
|
|
45018
|
-
}
|
|
45019
|
-
|
|
45020
|
-
// packages/zaku/dist/lib/repositories/design-paths.js
|
|
45021
|
-
import { join as join2 } from "node:path";
|
|
45022
|
-
function librarySnapshotDir(paths, key) {
|
|
45023
|
-
if (key === null)
|
|
45024
|
-
return paths;
|
|
45025
|
-
const library = join2(paths.library, key);
|
|
45026
|
-
return { root: paths.root, library, libraryIndex: join2(library, "index.json"), legacyLibrary: null };
|
|
45027
|
-
}
|
|
45028
|
-
function designPaths(root) {
|
|
45029
|
-
return {
|
|
45030
|
-
root,
|
|
45031
|
-
config: join2(root, "zaku.yaml"),
|
|
45032
|
-
maps: join2(root, "map"),
|
|
45033
|
-
outline: join2(root, "outline"),
|
|
45034
|
-
unmapped: join2(root, "outline", "unmapped.yaml"),
|
|
45035
|
-
library: join2(root, "library"),
|
|
45036
|
-
libraryIndex: join2(root, "library", "index.json"),
|
|
45037
|
-
legacyLibrary: join2(root, "library.json"),
|
|
45038
|
-
tokens: join2(root, "tokens.json"),
|
|
45039
|
-
recipe: join2(root, "recipe.json")
|
|
45040
|
-
};
|
|
45041
|
-
}
|
|
45042
|
-
|
|
45043
|
-
// packages/zaku/dist/lib/repositories/library-snapshot.js
|
|
45044
|
-
import { mkdir, readdir, readFile as readFile2, rename as rename2, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
45045
|
-
import { join as join3, relative } from "node:path";
|
|
45046
|
-
|
|
45047
44785
|
// packages/zaku/dist/lib/domain/library.js
|
|
45048
44786
|
var rgbaSchema = external_exports.object({ r: external_exports.number(), g: external_exports.number(), b: external_exports.number(), a: external_exports.number() }).strict();
|
|
45049
44787
|
var libraryItemSchema = external_exports.object({
|
|
@@ -45332,6 +45070,43 @@ function formatLibraryFile(value) {
|
|
|
45332
45070
|
`;
|
|
45333
45071
|
}
|
|
45334
45072
|
|
|
45073
|
+
// packages/zaku/dist/lib/repositories/design-file.js
|
|
45074
|
+
var import_yaml = __toESM(require_dist(), 1);
|
|
45075
|
+
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
45076
|
+
function parseDesignFile(path2, text, schema) {
|
|
45077
|
+
let data;
|
|
45078
|
+
try {
|
|
45079
|
+
data = path2.endsWith(".json") ? JSON.parse(text) : (0, import_yaml.parse)(text);
|
|
45080
|
+
} catch (error62) {
|
|
45081
|
+
throw new DesignFileInvalid(path2, [error62.message]);
|
|
45082
|
+
}
|
|
45083
|
+
const result = schema.safeParse(data);
|
|
45084
|
+
if (!result.success) {
|
|
45085
|
+
throw new DesignFileInvalid(path2, result.error.issues.map((issue2) => `${issue2.path.map(String).join(".") || "(root)"}: ${issue2.message}`));
|
|
45086
|
+
}
|
|
45087
|
+
return result.data;
|
|
45088
|
+
}
|
|
45089
|
+
async function readDesignFile(path2, schema) {
|
|
45090
|
+
return parseDesignFile(path2, await readFile(path2, "utf8"), schema);
|
|
45091
|
+
}
|
|
45092
|
+
async function readOptionalDesignFile(path2, schema) {
|
|
45093
|
+
let text;
|
|
45094
|
+
try {
|
|
45095
|
+
text = await readFile(path2, "utf8");
|
|
45096
|
+
} catch (error62) {
|
|
45097
|
+
if (error62.code === "ENOENT")
|
|
45098
|
+
return null;
|
|
45099
|
+
throw error62;
|
|
45100
|
+
}
|
|
45101
|
+
return parseDesignFile(path2, text, schema);
|
|
45102
|
+
}
|
|
45103
|
+
async function writeDesignFile(path2, value) {
|
|
45104
|
+
const temporary = `${path2}.${process.pid}.tmp`;
|
|
45105
|
+
await writeFile(temporary, `${JSON.stringify(value, null, 2)}
|
|
45106
|
+
`);
|
|
45107
|
+
await rename(temporary, path2);
|
|
45108
|
+
}
|
|
45109
|
+
|
|
45335
45110
|
// packages/zaku/dist/lib/repositories/library-snapshot.js
|
|
45336
45111
|
async function readText(path2) {
|
|
45337
45112
|
try {
|
|
@@ -45724,8 +45499,7 @@ function librarySaveTarget(config2, key) {
|
|
|
45724
45499
|
}
|
|
45725
45500
|
async function saveLibrary(options) {
|
|
45726
45501
|
const paths = designPaths(options.root);
|
|
45727
|
-
const
|
|
45728
|
-
const target = librarySaveTarget(config2, options.key);
|
|
45502
|
+
const target = librarySaveTarget(options.config, options.key);
|
|
45729
45503
|
if (target.kind === "kit") {
|
|
45730
45504
|
const at2 = librarySnapshotDir(paths, target.kit.key);
|
|
45731
45505
|
const kit = await readKit({ rest: options.rest, key: target.kit.key, family: target.kit.family });
|
|
@@ -45753,6 +45527,7 @@ var SaveLibraryHandler = class SaveLibraryHandler2 {
|
|
|
45753
45527
|
handle(command) {
|
|
45754
45528
|
return saveLibrary({
|
|
45755
45529
|
root: command.root,
|
|
45530
|
+
config: command.config,
|
|
45756
45531
|
rest: this.rest,
|
|
45757
45532
|
...command.key !== void 0 ? { key: command.key } : {},
|
|
45758
45533
|
...command.part !== void 0 ? { part: command.part } : {}
|
|
@@ -45771,6 +45546,85 @@ var import_yaml2 = __toESM(require_dist(), 1);
|
|
|
45771
45546
|
import { mkdir as mkdir2, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
45772
45547
|
import { dirname as dirname2, join as join6 } from "node:path";
|
|
45773
45548
|
|
|
45549
|
+
// packages/zaku/dist/lib/adapters/figma-rest.js
|
|
45550
|
+
var FigmaRateLimited = class extends Error {
|
|
45551
|
+
url;
|
|
45552
|
+
constructor(url2) {
|
|
45553
|
+
super(`Figma answered 429 twice for ${url2}; wait and run again`);
|
|
45554
|
+
this.url = url2;
|
|
45555
|
+
this.name = "FigmaRateLimited";
|
|
45556
|
+
}
|
|
45557
|
+
};
|
|
45558
|
+
var FigmaRequestFailed = class extends Error {
|
|
45559
|
+
url;
|
|
45560
|
+
status;
|
|
45561
|
+
constructor(url2, status, body) {
|
|
45562
|
+
super(`Figma answered ${status} for ${url2}: ${body.slice(0, 200)}`);
|
|
45563
|
+
this.url = url2;
|
|
45564
|
+
this.status = status;
|
|
45565
|
+
this.name = "FigmaRequestFailed";
|
|
45566
|
+
}
|
|
45567
|
+
};
|
|
45568
|
+
var BASE = "https://api.figma.com/v1";
|
|
45569
|
+
var BATCH = 50;
|
|
45570
|
+
var MAX_WAIT_MS = 12e4;
|
|
45571
|
+
function createFigmaRest(options) {
|
|
45572
|
+
const send = options.fetch ?? globalThis.fetch;
|
|
45573
|
+
const sleep = options.sleep ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
|
|
45574
|
+
const onCall = options.onCall ?? (() => void 0);
|
|
45575
|
+
async function call(url2) {
|
|
45576
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
45577
|
+
const res = await send(url2, { headers: { "X-Figma-Token": options.token } });
|
|
45578
|
+
onCall();
|
|
45579
|
+
if (res.status === 429) {
|
|
45580
|
+
if (attempt === 1)
|
|
45581
|
+
break;
|
|
45582
|
+
const seconds = Number(res.headers.get("Retry-After") ?? "60");
|
|
45583
|
+
await sleep(Math.min(Number.isFinite(seconds) ? seconds * 1e3 : 6e4, MAX_WAIT_MS));
|
|
45584
|
+
continue;
|
|
45585
|
+
}
|
|
45586
|
+
if (!res.ok)
|
|
45587
|
+
throw new FigmaRequestFailed(url2, res.status, await res.text());
|
|
45588
|
+
return await res.json();
|
|
45589
|
+
}
|
|
45590
|
+
throw new FigmaRateLimited(url2);
|
|
45591
|
+
}
|
|
45592
|
+
const chunks = (ids) => Array.from({ length: Math.ceil(ids.length / BATCH) }, (_, index) => ids.slice(index * BATCH, (index + 1) * BATCH));
|
|
45593
|
+
async function components(fileKey3) {
|
|
45594
|
+
const listed = await call(`${BASE}/files/${fileKey3}/components`);
|
|
45595
|
+
return listed.meta.components;
|
|
45596
|
+
}
|
|
45597
|
+
return {
|
|
45598
|
+
file: (fileKey3, depth) => call(`${BASE}/files/${fileKey3}?depth=${depth}`),
|
|
45599
|
+
async fileName(fileKey3) {
|
|
45600
|
+
const meta3 = await call(`${BASE}/files/${fileKey3}/meta`);
|
|
45601
|
+
return meta3.file.name;
|
|
45602
|
+
},
|
|
45603
|
+
async nodes(fileKey3, ids) {
|
|
45604
|
+
const merged = { version: "", nodes: {} };
|
|
45605
|
+
for (const chunk of chunks(ids)) {
|
|
45606
|
+
const part = await call(`${BASE}/files/${fileKey3}/nodes?ids=${encodeURIComponent(chunk.join(","))}`);
|
|
45607
|
+
merged.version = part.version;
|
|
45608
|
+
Object.assign(merged.nodes, part.nodes);
|
|
45609
|
+
}
|
|
45610
|
+
return merged;
|
|
45611
|
+
},
|
|
45612
|
+
async published(fileKey3) {
|
|
45613
|
+
const sets = await call(`${BASE}/files/${fileKey3}/component_sets`);
|
|
45614
|
+
return { sets: sets.meta.component_sets, components: await components(fileKey3) };
|
|
45615
|
+
},
|
|
45616
|
+
components,
|
|
45617
|
+
async images(fileKey3, ids) {
|
|
45618
|
+
const merged = {};
|
|
45619
|
+
for (const chunk of chunks(ids)) {
|
|
45620
|
+
const part = await call(`${BASE}/images/${fileKey3}?ids=${encodeURIComponent(chunk.join(","))}&format=png&scale=1`);
|
|
45621
|
+
Object.assign(merged, part.images);
|
|
45622
|
+
}
|
|
45623
|
+
return merged;
|
|
45624
|
+
}
|
|
45625
|
+
};
|
|
45626
|
+
}
|
|
45627
|
+
|
|
45774
45628
|
// packages/zaku/dist/lib/domain/documentation-measures.js
|
|
45775
45629
|
var COVER = {
|
|
45776
45630
|
page: "Thumbnail",
|
|
@@ -46348,7 +46202,7 @@ function outlineFrame(frame, where, ctx) {
|
|
|
46348
46202
|
const images2 = [];
|
|
46349
46203
|
const defaultNames = [];
|
|
46350
46204
|
const links = [];
|
|
46351
|
-
const
|
|
46205
|
+
const relative4 = (node2) => {
|
|
46352
46206
|
const box = node2.absoluteBoundingBox;
|
|
46353
46207
|
return box ? { x: box.x - origin.x, y: box.y - origin.y, width: box.width, height: box.height } : null;
|
|
46354
46208
|
};
|
|
@@ -46377,7 +46231,7 @@ function outlineFrame(frame, where, ctx) {
|
|
|
46377
46231
|
componentKey: ctx.components[child.componentId ?? ""]?.key ?? "",
|
|
46378
46232
|
component: component2,
|
|
46379
46233
|
interactive: ctx.interactive.has(component2),
|
|
46380
|
-
bounds:
|
|
46234
|
+
bounds: relative4(child)
|
|
46381
46235
|
});
|
|
46382
46236
|
} else if (child.type === "TEXT") {
|
|
46383
46237
|
instance.texts.push({
|
|
@@ -46418,7 +46272,7 @@ function outlineFrame(frame, where, ctx) {
|
|
|
46418
46272
|
texts: [],
|
|
46419
46273
|
interactive: ctx.interactive.has(component2),
|
|
46420
46274
|
local: meta3?.remote === false,
|
|
46421
|
-
bounds:
|
|
46275
|
+
bounds: relative4(node2),
|
|
46422
46276
|
sizing: {
|
|
46423
46277
|
horizontal: node2.layoutSizingHorizontal ?? "FIXED",
|
|
46424
46278
|
vertical: node2.layoutSizingVertical ?? "FIXED"
|
|
@@ -46610,6 +46464,7 @@ var unmappedSchema = external_exports.object({
|
|
|
46610
46464
|
/** A component drawn on a product page, which belongs in a Components library. */
|
|
46611
46465
|
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()
|
|
46612
46466
|
}).strict();
|
|
46467
|
+
var outlineFilesSchema = external_exports.object({ files: external_exports.array(external_exports.object({ key: external_exports.string(), name: external_exports.string() }).strict()) }).strict();
|
|
46613
46468
|
|
|
46614
46469
|
// packages/zaku/dist/lib/repositories/outlines.js
|
|
46615
46470
|
var FLOWS_DIR = "flows";
|
|
@@ -46629,12 +46484,12 @@ async function loadOutlines(dir) {
|
|
|
46629
46484
|
features = (await readdir3(dir, { withFileTypes: true })).filter((entry) => entry.isDirectory() && entry.name !== FLOWS_DIR).map((entry) => entry.name).sort();
|
|
46630
46485
|
} catch (error62) {
|
|
46631
46486
|
if (error62.code === "ENOENT")
|
|
46632
|
-
return { outlines, flows, unmapped: null, errors };
|
|
46487
|
+
return { outlines, flows, unmapped: null, files: null, errors };
|
|
46633
46488
|
throw error62;
|
|
46634
46489
|
}
|
|
46635
46490
|
for (const feature of features) {
|
|
46636
|
-
const
|
|
46637
|
-
for (const file2 of
|
|
46491
|
+
const files3 = (await readdir3(join5(dir, feature))).filter((name) => name.endsWith(".yaml")).sort();
|
|
46492
|
+
for (const file2 of files3) {
|
|
46638
46493
|
try {
|
|
46639
46494
|
outlines.push(await readDesignFile(join5(dir, feature, file2), screenOutlineSchema));
|
|
46640
46495
|
} catch (error62) {
|
|
@@ -46651,8 +46506,8 @@ async function loadOutlines(dir) {
|
|
|
46651
46506
|
throw error62;
|
|
46652
46507
|
});
|
|
46653
46508
|
for (const source of sources.sort()) {
|
|
46654
|
-
const
|
|
46655
|
-
for (const file2 of
|
|
46509
|
+
const files3 = (await readdir3(join5(dir, FLOWS_DIR, source))).filter((name) => name.endsWith(".yaml")).sort();
|
|
46510
|
+
for (const file2 of files3) {
|
|
46656
46511
|
try {
|
|
46657
46512
|
flows.push(await readDesignFile(join5(dir, FLOWS_DIR, source, file2), flowOutlineSchema));
|
|
46658
46513
|
} catch (error62) {
|
|
@@ -46672,7 +46527,16 @@ async function loadOutlines(dir) {
|
|
|
46672
46527
|
else
|
|
46673
46528
|
throw error62;
|
|
46674
46529
|
}
|
|
46675
|
-
|
|
46530
|
+
let files2 = null;
|
|
46531
|
+
try {
|
|
46532
|
+
files2 = await readOptionalDesignFile(join5(dir, "files.yaml"), outlineFilesSchema);
|
|
46533
|
+
} catch (error62) {
|
|
46534
|
+
if (error62 instanceof DesignFileInvalid)
|
|
46535
|
+
errors.push(error62);
|
|
46536
|
+
else
|
|
46537
|
+
throw error62;
|
|
46538
|
+
}
|
|
46539
|
+
return { outlines, flows, unmapped, files: files2, errors };
|
|
46676
46540
|
}
|
|
46677
46541
|
|
|
46678
46542
|
// packages/zaku/dist/lib/handlers/write-outline.js
|
|
@@ -46749,9 +46613,28 @@ function productFiles(config2) {
|
|
|
46749
46613
|
targets: graph.targetsOf(product.family)
|
|
46750
46614
|
}));
|
|
46751
46615
|
}
|
|
46616
|
+
async function readFileNames(rest, config2, read) {
|
|
46617
|
+
const graph = designGraph(config2);
|
|
46618
|
+
const files2 = [];
|
|
46619
|
+
for (const file2 of [...graph.products, ...graph.prototypes]) {
|
|
46620
|
+
const name = read.get(file2.key);
|
|
46621
|
+
if (name !== void 0)
|
|
46622
|
+
files2.push({ key: file2.key, name });
|
|
46623
|
+
}
|
|
46624
|
+
for (const library of graph.libraries.filter((each) => each.layer === "components")) {
|
|
46625
|
+
try {
|
|
46626
|
+
files2.push({ key: library.key, name: await rest.fileName(library.key) });
|
|
46627
|
+
} catch (error62) {
|
|
46628
|
+
if (error62 instanceof FigmaRequestFailed && (error62.status === 403 || error62.status === 404))
|
|
46629
|
+
continue;
|
|
46630
|
+
throw error62;
|
|
46631
|
+
}
|
|
46632
|
+
}
|
|
46633
|
+
return { files: files2 };
|
|
46634
|
+
}
|
|
46752
46635
|
async function runOutline(options) {
|
|
46753
46636
|
const paths = designPaths(options.root);
|
|
46754
|
-
const config2 =
|
|
46637
|
+
const { config: config2 } = options;
|
|
46755
46638
|
const { libraries: listed, kits, products: byFamily, prototypes: flows } = config2.figma;
|
|
46756
46639
|
const legacy = [listed, kits, byFamily, flows].every((files2) => files2 === void 0);
|
|
46757
46640
|
const products = productFiles(config2);
|
|
@@ -46766,6 +46649,7 @@ async function runOutline(options) {
|
|
|
46766
46649
|
const existing = await loadOutlines(paths.outline);
|
|
46767
46650
|
const prototypes = new Set(legacy ? config2.targets.map((target) => `${target.name} prototype`) : []);
|
|
46768
46651
|
const versions = {};
|
|
46652
|
+
const names = /* @__PURE__ */ new Map();
|
|
46769
46653
|
const flowPages = /* @__PURE__ */ new Map();
|
|
46770
46654
|
const flowFrame = (source, frame, targets) => {
|
|
46771
46655
|
const parsed = parseFrameName(frame.name, targets);
|
|
@@ -46783,6 +46667,7 @@ ${frame.page}`;
|
|
|
46783
46667
|
for (const product of products) {
|
|
46784
46668
|
const file2 = await options.rest.file(product.key, INDEX_DEPTH);
|
|
46785
46669
|
versions[product.key] = file2.version;
|
|
46670
|
+
names.set(product.key, file2.name);
|
|
46786
46671
|
const listed2 = listFrames(file2.document);
|
|
46787
46672
|
for (const frame of listed2.filter((candidate) => prototypes.has(candidate.page)))
|
|
46788
46673
|
flowFrame(product.key, frame, product.targets);
|
|
@@ -46806,6 +46691,7 @@ ${frame.page}`;
|
|
|
46806
46691
|
for (const file2 of legacy ? [] : graph.prototypes) {
|
|
46807
46692
|
const read = await options.rest.file(file2.key, INDEX_DEPTH);
|
|
46808
46693
|
versions[file2.key] = read.version;
|
|
46694
|
+
names.set(file2.key, read.name);
|
|
46809
46695
|
const targets = graph.targetsOf(file2.family);
|
|
46810
46696
|
for (const frame of listFrames(read.document).filter((candidate) => holdsScreens(candidate.page)))
|
|
46811
46697
|
flowFrame(file2.key, frame, targets);
|
|
@@ -46813,6 +46699,10 @@ ${frame.page}`;
|
|
|
46813
46699
|
unmapped.fileVersion = Object.values(versions).join(",");
|
|
46814
46700
|
if (!legacy)
|
|
46815
46701
|
unmapped.components = components;
|
|
46702
|
+
if (!legacy) {
|
|
46703
|
+
await mkdir2(paths.outline, { recursive: true });
|
|
46704
|
+
await writeFile3(paths.files, (0, import_yaml2.stringify)(await readFileNames(options.rest, config2, names)));
|
|
46705
|
+
}
|
|
46816
46706
|
const outlined = new Set(existing.outlines.flatMap((outline) => outline.frames.map((frame) => frame.nodeId)));
|
|
46817
46707
|
const drawnScreens = new Set([...resolved.values()].map(({ ref }) => `${ref.feature}/${ref.id}`));
|
|
46818
46708
|
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}`));
|
|
@@ -46933,7 +46823,7 @@ var WriteOutlineHandler = class WriteOutlineHandler2 {
|
|
|
46933
46823
|
this.rest = rest;
|
|
46934
46824
|
}
|
|
46935
46825
|
handle(command) {
|
|
46936
|
-
return runOutline({ root: command.root, rest: this.rest, frames: command.frames });
|
|
46826
|
+
return runOutline({ root: command.root, config: command.config, rest: this.rest, frames: command.frames });
|
|
46937
46827
|
}
|
|
46938
46828
|
};
|
|
46939
46829
|
WriteOutlineHandler = __decorate2([
|
|
@@ -46944,10 +46834,389 @@ WriteOutlineHandler = __decorate2([
|
|
|
46944
46834
|
// packages/zaku/dist/lib/handlers/write-schemas.js
|
|
46945
46835
|
var import_tsyringe5 = __toESM(require_cjs(), 1);
|
|
46946
46836
|
|
|
46837
|
+
// packages/zaku/dist/lib/schema/zaku-config.js
|
|
46838
|
+
import { posix } from "node:path";
|
|
46839
|
+
|
|
46840
|
+
// packages/zaku/dist/lib/domain/copy-defaults.js
|
|
46841
|
+
var DEFAULT_COPY = { locales: ["en"], currencies: [] };
|
|
46842
|
+
|
|
46843
|
+
// packages/zaku/dist/lib/schema/zaku-config.js
|
|
46844
|
+
var PLATFORM_FAMILIES = ["web", "ios", "android", "macos", "windows", "gnome", "kde"];
|
|
46845
|
+
var LAYERS = ["foundations", "components"];
|
|
46846
|
+
var BRANCHES = ["ui", "native"];
|
|
46847
|
+
var DEFAULT_INTERACTIVE = [
|
|
46848
|
+
"Button",
|
|
46849
|
+
"Button Group",
|
|
46850
|
+
"Checkbox",
|
|
46851
|
+
"Combobox",
|
|
46852
|
+
"Dropdown Menu",
|
|
46853
|
+
"Input",
|
|
46854
|
+
"Input Group",
|
|
46855
|
+
"Input OTP",
|
|
46856
|
+
"Native Select",
|
|
46857
|
+
"Pagination",
|
|
46858
|
+
"Radio Group",
|
|
46859
|
+
"Select",
|
|
46860
|
+
"Slider",
|
|
46861
|
+
"Switch",
|
|
46862
|
+
"Tabs",
|
|
46863
|
+
"Textarea",
|
|
46864
|
+
"Toggle",
|
|
46865
|
+
"Toggle Group"
|
|
46866
|
+
];
|
|
46867
|
+
var id = external_exports.string().regex(/^[a-z][a-z0-9-]*$/, "lowercase letters, digits and dashes, starting with a letter");
|
|
46868
|
+
var targetSchema = external_exports.object({
|
|
46869
|
+
id,
|
|
46870
|
+
family: external_exports.enum(PLATFORM_FAMILIES),
|
|
46871
|
+
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"),
|
|
46872
|
+
/** The frame size every frame of this target is drawn at; the frame check compares it. */
|
|
46873
|
+
size: external_exports.object({ width: external_exports.number().positive(), height: external_exports.number().positive() }).strict().optional(),
|
|
46874
|
+
/** The renderer whose libraries its frames draw from; `defaultBranch` in the design graph gives it when left out. */
|
|
46875
|
+
branch: external_exports.enum(BRANCHES).optional()
|
|
46876
|
+
}).strict();
|
|
46877
|
+
var DEFAULT_SYSTEM_BARS = {
|
|
46878
|
+
web: [],
|
|
46879
|
+
ios: [["Status Bar"], ["Home Indicator"]],
|
|
46880
|
+
android: [["Status Bar"], ["Navigation Bar", "Gesture Handle"]],
|
|
46881
|
+
macos: [["Window Controls"]],
|
|
46882
|
+
windows: [["Title Bar"]],
|
|
46883
|
+
gnome: [["Header Bar"]],
|
|
46884
|
+
kde: [["Title Bar"]]
|
|
46885
|
+
};
|
|
46886
|
+
function systemBarNames(config2) {
|
|
46887
|
+
const bars = { ...DEFAULT_SYSTEM_BARS, ...config2.systemBars };
|
|
46888
|
+
return new Set(Object.values(bars).flat(2));
|
|
46889
|
+
}
|
|
46890
|
+
var budgetSchema = external_exports.object({
|
|
46891
|
+
mcpPerDay: external_exports.number().int().positive().default(200),
|
|
46892
|
+
mcpPerRun: external_exports.number().int().positive().default(30),
|
|
46893
|
+
reserve: external_exports.number().min(0).max(1).default(0.2)
|
|
46894
|
+
}).strict();
|
|
46895
|
+
var fileKey = external_exports.string().min(1);
|
|
46896
|
+
var kitSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
46897
|
+
var librarySchema = external_exports.object({
|
|
46898
|
+
key: fileKey,
|
|
46899
|
+
layer: external_exports.enum(LAYERS),
|
|
46900
|
+
branches: external_exports.array(external_exports.enum(BRANCHES)).min(1),
|
|
46901
|
+
/** The libraries and kits this one is built on, by key. */
|
|
46902
|
+
extends: external_exports.array(fileKey).default([])
|
|
46903
|
+
}).strict();
|
|
46904
|
+
var productSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
46905
|
+
var prototypeSchema = external_exports.object({ key: fileKey, family: external_exports.enum(PLATFORM_FAMILIES) }).strict();
|
|
46906
|
+
var files = external_exports.object({
|
|
46907
|
+
library: fileKey.optional(),
|
|
46908
|
+
product: fileKey.optional(),
|
|
46909
|
+
kits: external_exports.array(kitSchema).optional(),
|
|
46910
|
+
libraries: external_exports.array(librarySchema).optional(),
|
|
46911
|
+
products: external_exports.array(productSchema).optional(),
|
|
46912
|
+
prototypes: external_exports.array(prototypeSchema).optional()
|
|
46913
|
+
}).strict();
|
|
46914
|
+
function byRole(figma) {
|
|
46915
|
+
return [figma.kits, figma.libraries, figma.products, figma.prototypes].some((list) => list !== void 0);
|
|
46916
|
+
}
|
|
46917
|
+
var shadcnSystem = external_exports.object({
|
|
46918
|
+
preset: external_exports.string().min(1),
|
|
46919
|
+
/** The stylesheet `zaku tokens` reads, relative to the directory of the workspace config. */
|
|
46920
|
+
css: external_exports.string().min(1).optional()
|
|
46921
|
+
}).strict();
|
|
46922
|
+
var tokenFiles = external_exports.array(external_exports.string().min(1)).min(1);
|
|
46923
|
+
var resolverInputs = external_exports.record(external_exports.string(), external_exports.string());
|
|
46924
|
+
var dtcgSystem = external_exports.object({
|
|
46925
|
+
resolver: external_exports.string().min(1).optional(),
|
|
46926
|
+
light: external_exports.union([tokenFiles, resolverInputs]),
|
|
46927
|
+
dark: external_exports.union([tokenFiles, resolverInputs]),
|
|
46928
|
+
/** The group whose tokens are the colour roles, and the one whose tokens are the radius steps. */
|
|
46929
|
+
colors: external_exports.string().min(1).default("color"),
|
|
46930
|
+
radii: external_exports.string().min(1).default("radius"),
|
|
46931
|
+
/** Foreground and background token pairs a text is read in, each needing 4.5:1. */
|
|
46932
|
+
contrast: external_exports.array(external_exports.tuple([external_exports.string().min(1), external_exports.string().min(1)])).default([])
|
|
46933
|
+
}).strict().superRefine((dtcg, ctx) => {
|
|
46934
|
+
for (const scheme of ["light", "dark"]) {
|
|
46935
|
+
const files2 = Array.isArray(dtcg[scheme]);
|
|
46936
|
+
if (dtcg.resolver !== void 0 && files2) {
|
|
46937
|
+
ctx.addIssue({
|
|
46938
|
+
code: "custom",
|
|
46939
|
+
path: [scheme],
|
|
46940
|
+
message: "with a resolver, name the modifier contexts, not files"
|
|
46941
|
+
});
|
|
46942
|
+
}
|
|
46943
|
+
if (dtcg.resolver === void 0 && !files2) {
|
|
46944
|
+
ctx.addIssue({
|
|
46945
|
+
code: "custom",
|
|
46946
|
+
path: [scheme],
|
|
46947
|
+
message: "without a resolver, list the token files"
|
|
46948
|
+
});
|
|
46949
|
+
}
|
|
46950
|
+
}
|
|
46951
|
+
});
|
|
46952
|
+
var designSystemSchema = external_exports.union([
|
|
46953
|
+
external_exports.object({ shadcn: shadcnSystem }).strict(),
|
|
46954
|
+
external_exports.object({ dtcg: dtcgSystem }).strict()
|
|
46955
|
+
]);
|
|
46956
|
+
var recipeSchema = external_exports.object({
|
|
46957
|
+
url: external_exports.url().optional(),
|
|
46958
|
+
dark: external_exports.enum(["class", "media"]).default("class"),
|
|
46959
|
+
darkClass: external_exports.string().min(1).default("dark")
|
|
46960
|
+
}).strict();
|
|
46961
|
+
function writtenInAScript(tag) {
|
|
46962
|
+
try {
|
|
46963
|
+
return new Intl.Locale(tag).maximize().script !== void 0;
|
|
46964
|
+
} catch {
|
|
46965
|
+
return false;
|
|
46966
|
+
}
|
|
46967
|
+
}
|
|
46968
|
+
var copySchema = external_exports.object({
|
|
46969
|
+
locales: external_exports.array(external_exports.string().refine(writtenInAScript, "a BCP 47 language tag, such as en or vi")).min(1).default(["en"]),
|
|
46970
|
+
currencies: external_exports.array(external_exports.string().refine((code) => Intl.supportedValuesOf("currency").includes(code), "an ISO 4217 code, such as VND or USD")).default([])
|
|
46971
|
+
}).strict();
|
|
46972
|
+
var configShape = external_exports.object({
|
|
46973
|
+
product: external_exports.string().min(1),
|
|
46974
|
+
designSystem: designSystemSchema,
|
|
46975
|
+
figma: files.default({}),
|
|
46976
|
+
targets: external_exports.array(targetSchema).min(1),
|
|
46977
|
+
modes: external_exports.record(external_exports.string(), external_exports.string()).default({}),
|
|
46978
|
+
interactive: external_exports.array(external_exports.string().min(1)).default([...DEFAULT_INTERACTIVE]),
|
|
46979
|
+
/** The bars of the families whose kit names them its own way; every family left out keeps its default. */
|
|
46980
|
+
systemBars: external_exports.partialRecord(external_exports.enum(PLATFORM_FAMILIES), external_exports.array(external_exports.array(external_exports.string().min(1)).min(1))).optional(),
|
|
46981
|
+
budget: budgetSchema.default({ mcpPerDay: 200, mcpPerRun: 30, reserve: 0.2 }),
|
|
46982
|
+
recipe: recipeSchema.optional(),
|
|
46983
|
+
copy: copySchema.default(DEFAULT_COPY)
|
|
46984
|
+
}).strict();
|
|
46985
|
+
var zakuConfigSchema = configShape.superRefine((config2, ctx) => {
|
|
46986
|
+
for (const key of ["id", "name"]) {
|
|
46987
|
+
const seen = /* @__PURE__ */ new Set();
|
|
46988
|
+
config2.targets.forEach((target, index) => {
|
|
46989
|
+
if (seen.has(target[key])) {
|
|
46990
|
+
ctx.addIssue({
|
|
46991
|
+
code: "custom",
|
|
46992
|
+
path: ["targets", index, key],
|
|
46993
|
+
message: `a second target with ${key} ${target[key]}`
|
|
46994
|
+
});
|
|
46995
|
+
}
|
|
46996
|
+
seen.add(target[key]);
|
|
46997
|
+
});
|
|
46998
|
+
}
|
|
46999
|
+
if (byRole(config2.figma))
|
|
47000
|
+
refineFilesByRole(config2, ctx);
|
|
47001
|
+
});
|
|
47002
|
+
function refineFilesByRole(config2, ctx) {
|
|
47003
|
+
const { figma } = config2;
|
|
47004
|
+
if (figma.library !== void 0 || figma.product !== void 0) {
|
|
47005
|
+
ctx.addIssue({
|
|
47006
|
+
code: "custom",
|
|
47007
|
+
path: ["figma"],
|
|
47008
|
+
message: "figma.library and figma.product describe one library and one product; list files by role instead"
|
|
47009
|
+
});
|
|
47010
|
+
}
|
|
47011
|
+
const kits = figma.kits ?? [];
|
|
47012
|
+
const libraries = figma.libraries ?? [];
|
|
47013
|
+
const products = figma.products ?? [];
|
|
47014
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47015
|
+
const lists = [
|
|
47016
|
+
["kits", kits],
|
|
47017
|
+
["libraries", libraries],
|
|
47018
|
+
["products", products],
|
|
47019
|
+
["prototypes", figma.prototypes ?? []]
|
|
47020
|
+
];
|
|
47021
|
+
for (const [list, entries] of lists) {
|
|
47022
|
+
entries.forEach((entry, index) => {
|
|
47023
|
+
if (seen.has(entry.key))
|
|
47024
|
+
ctx.addIssue({
|
|
47025
|
+
code: "custom",
|
|
47026
|
+
path: ["figma", list, index, "key"],
|
|
47027
|
+
message: `a second file with key ${entry.key}`
|
|
47028
|
+
});
|
|
47029
|
+
seen.add(entry.key);
|
|
47030
|
+
});
|
|
47031
|
+
}
|
|
47032
|
+
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
47033
|
+
const kitKeys = new Set(kits.map((kit) => kit.key));
|
|
47034
|
+
libraries.forEach((library, index) => {
|
|
47035
|
+
const path2 = ["figma", "libraries", index, "extends"];
|
|
47036
|
+
for (const key of library.extends) {
|
|
47037
|
+
const base = byKey.get(key);
|
|
47038
|
+
if (!base && !kitKeys.has(key)) {
|
|
47039
|
+
ctx.addIssue({
|
|
47040
|
+
code: "custom",
|
|
47041
|
+
path: path2,
|
|
47042
|
+
message: `${library.key} extends ${key}, which is no library or kit listed`
|
|
47043
|
+
});
|
|
47044
|
+
} else if (base?.layer === "components" && library.layer === "foundations") {
|
|
47045
|
+
ctx.addIssue({ code: "custom", path: path2, message: `foundations ${library.key} extends components ${key}` });
|
|
47046
|
+
} else if (base && !base.branches.some((branch) => library.branches.includes(branch))) {
|
|
47047
|
+
ctx.addIssue({
|
|
47048
|
+
code: "custom",
|
|
47049
|
+
path: path2,
|
|
47050
|
+
message: `${library.key} extends ${key}, which holds none of its branches`
|
|
47051
|
+
});
|
|
47052
|
+
}
|
|
47053
|
+
}
|
|
47054
|
+
});
|
|
47055
|
+
const cycle = findCycle(libraries);
|
|
47056
|
+
if (cycle)
|
|
47057
|
+
ctx.addIssue({ code: "custom", path: ["figma", "libraries"], message: `extends comes back: ${cycle}` });
|
|
47058
|
+
for (const [list, entries] of [
|
|
47059
|
+
["products", products],
|
|
47060
|
+
["prototypes", figma.prototypes ?? []]
|
|
47061
|
+
]) {
|
|
47062
|
+
const families2 = /* @__PURE__ */ new Set();
|
|
47063
|
+
entries.forEach((entry, index) => {
|
|
47064
|
+
if (families2.has(entry.family))
|
|
47065
|
+
ctx.addIssue({
|
|
47066
|
+
code: "custom",
|
|
47067
|
+
path: ["figma", list, index, "family"],
|
|
47068
|
+
message: `a second ${list === "products" ? "product" : "prototype"} file for ${entry.family}`
|
|
47069
|
+
});
|
|
47070
|
+
families2.add(entry.family);
|
|
47071
|
+
});
|
|
47072
|
+
}
|
|
47073
|
+
(figma.prototypes ?? []).forEach((prototype2, index) => {
|
|
47074
|
+
if (!products.some((product) => product.family === prototype2.family))
|
|
47075
|
+
ctx.addIssue({
|
|
47076
|
+
code: "custom",
|
|
47077
|
+
path: ["figma", "prototypes", index, "family"],
|
|
47078
|
+
message: `no product file for ${prototype2.family} to copy its frames from`
|
|
47079
|
+
});
|
|
47080
|
+
});
|
|
47081
|
+
config2.targets.forEach((target, index) => {
|
|
47082
|
+
const branch = target.branch ?? defaultBranch(target.family);
|
|
47083
|
+
const path2 = ["targets", index, "branch"];
|
|
47084
|
+
if (branch === void 0) {
|
|
47085
|
+
ctx.addIssue({ code: "custom", path: path2, message: `a ${target.family} target names its branch, ui or native` });
|
|
47086
|
+
} else if (libraries.length > 0 && !libraries.some((library) => library.branches.includes(branch))) {
|
|
47087
|
+
ctx.addIssue({ code: "custom", path: path2, message: `no library holds the ${branch} branch` });
|
|
47088
|
+
}
|
|
47089
|
+
});
|
|
47090
|
+
}
|
|
47091
|
+
function findCycle(libraries) {
|
|
47092
|
+
const byKey = new Map(libraries.map((library) => [library.key, library]));
|
|
47093
|
+
const visit2 = (key, path2) => {
|
|
47094
|
+
if (path2.includes(key))
|
|
47095
|
+
return [...path2.slice(path2.indexOf(key)), key].join(" -> ");
|
|
47096
|
+
for (const next of byKey.get(key)?.extends ?? []) {
|
|
47097
|
+
const found = visit2(next, [...path2, key]);
|
|
47098
|
+
if (found)
|
|
47099
|
+
return found;
|
|
47100
|
+
}
|
|
47101
|
+
return void 0;
|
|
47102
|
+
};
|
|
47103
|
+
for (const library of libraries) {
|
|
47104
|
+
const found = visit2(library.key, []);
|
|
47105
|
+
if (found)
|
|
47106
|
+
return found;
|
|
47107
|
+
}
|
|
47108
|
+
return void 0;
|
|
47109
|
+
}
|
|
47110
|
+
var SHARED_KEYS = ["designSystem", "modes", "copy", "interactive", "systemBars", "budget"];
|
|
47111
|
+
var sharedShape = {
|
|
47112
|
+
designSystem: designSystemSchema.optional(),
|
|
47113
|
+
modes: configShape.shape.modes.unwrap().optional(),
|
|
47114
|
+
copy: copySchema.optional(),
|
|
47115
|
+
interactive: configShape.shape.interactive.unwrap().optional(),
|
|
47116
|
+
systemBars: configShape.shape.systemBars,
|
|
47117
|
+
budget: budgetSchema.optional()
|
|
47118
|
+
};
|
|
47119
|
+
var PRODUCT_NAME = /^[A-Z0-9][A-Za-z0-9]*( [A-Z0-9][A-Za-z0-9]*)*$/;
|
|
47120
|
+
var workspaceProduct = external_exports.object({
|
|
47121
|
+
/** Title-case ASCII words: what people call the product and what its Figma files are named for. */
|
|
47122
|
+
name: external_exports.string().regex(PRODUCT_NAME, "title-case words of ASCII letters and digits, such as Back Office"),
|
|
47123
|
+
/** The directory of the product's design, relative to the config and inside its directory. */
|
|
47124
|
+
root: external_exports.string().min(1)
|
|
47125
|
+
}).strict();
|
|
47126
|
+
function cleanRoot(root) {
|
|
47127
|
+
if (root.includes("\\"))
|
|
47128
|
+
return { problem: "use forward slashes" };
|
|
47129
|
+
if (root.startsWith("/"))
|
|
47130
|
+
return { problem: "a root is relative to the config, not absolute" };
|
|
47131
|
+
const path2 = posix.normalize(root).replace(/\/$/, "");
|
|
47132
|
+
if (path2 === ".." || path2.startsWith("../"))
|
|
47133
|
+
return { problem: "a root stays inside the config's directory" };
|
|
47134
|
+
return { path: path2 };
|
|
47135
|
+
}
|
|
47136
|
+
function overlaps(a, b) {
|
|
47137
|
+
return a === "." || b === "." || a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
47138
|
+
}
|
|
47139
|
+
var workspaceConfigSchema = external_exports.object({
|
|
47140
|
+
...sharedShape,
|
|
47141
|
+
products: external_exports.array(workspaceProduct).min(1).optional(),
|
|
47142
|
+
product: external_exports.string().min(1).optional(),
|
|
47143
|
+
figma: files.optional(),
|
|
47144
|
+
targets: external_exports.array(targetSchema).optional(),
|
|
47145
|
+
recipe: recipeSchema.optional()
|
|
47146
|
+
}).strict().superRefine((config2, ctx) => {
|
|
47147
|
+
const { products, ...single } = config2;
|
|
47148
|
+
if (products === void 0) {
|
|
47149
|
+
const result = zakuConfigSchema.safeParse(single);
|
|
47150
|
+
if (!result.success) {
|
|
47151
|
+
for (const issue2 of result.error.issues) {
|
|
47152
|
+
ctx.addIssue({ code: "custom", path: issue2.path, message: issue2.message });
|
|
47153
|
+
}
|
|
47154
|
+
}
|
|
47155
|
+
return;
|
|
47156
|
+
}
|
|
47157
|
+
for (const key of ["product", "figma", "targets", "recipe"]) {
|
|
47158
|
+
if (config2[key] !== void 0) {
|
|
47159
|
+
ctx.addIssue({
|
|
47160
|
+
code: "custom",
|
|
47161
|
+
path: [key],
|
|
47162
|
+
message: `a workspace that lists products keeps ${key} in each product`
|
|
47163
|
+
});
|
|
47164
|
+
}
|
|
47165
|
+
}
|
|
47166
|
+
const names = /* @__PURE__ */ new Set();
|
|
47167
|
+
const roots = [];
|
|
47168
|
+
products.forEach((product, index) => {
|
|
47169
|
+
if (names.has(product.name)) {
|
|
47170
|
+
ctx.addIssue({
|
|
47171
|
+
code: "custom",
|
|
47172
|
+
path: ["products", index, "name"],
|
|
47173
|
+
message: `a second product named ${product.name}`
|
|
47174
|
+
});
|
|
47175
|
+
}
|
|
47176
|
+
names.add(product.name);
|
|
47177
|
+
const root = cleanRoot(product.root);
|
|
47178
|
+
if ("problem" in root) {
|
|
47179
|
+
ctx.addIssue({ code: "custom", path: ["products", index, "root"], message: root.problem });
|
|
47180
|
+
return;
|
|
47181
|
+
}
|
|
47182
|
+
const clash = roots.find((other) => overlaps(other, root.path));
|
|
47183
|
+
if (clash !== void 0) {
|
|
47184
|
+
ctx.addIssue({
|
|
47185
|
+
code: "custom",
|
|
47186
|
+
path: ["products", index, "root"],
|
|
47187
|
+
message: `${product.root} overlaps ${clash}, which another product holds`
|
|
47188
|
+
});
|
|
47189
|
+
}
|
|
47190
|
+
roots.push(root.path);
|
|
47191
|
+
});
|
|
47192
|
+
});
|
|
47193
|
+
var productConfigSchema = external_exports.object({
|
|
47194
|
+
...sharedShape,
|
|
47195
|
+
figma: files.default({}),
|
|
47196
|
+
targets: external_exports.array(targetSchema).min(1),
|
|
47197
|
+
recipe: recipeSchema.optional()
|
|
47198
|
+
}).strict();
|
|
47199
|
+
function mergeProductConfig(shared, name, product) {
|
|
47200
|
+
const own2 = productConfigSchema.safeParse(product);
|
|
47201
|
+
if (!own2.success)
|
|
47202
|
+
throw new DesignFileInvalid(`zaku.yaml of ${name}`, issueLines(own2.error));
|
|
47203
|
+
const merged = { ...own2.data, product: name };
|
|
47204
|
+
for (const key of SHARED_KEYS)
|
|
47205
|
+
merged[key] = own2.data[key] ?? shared[key];
|
|
47206
|
+
const result = zakuConfigSchema.safeParse(merged);
|
|
47207
|
+
if (!result.success)
|
|
47208
|
+
throw new DesignFileInvalid(`zaku.yaml of ${name}`, issueLines(result.error));
|
|
47209
|
+
return result.data;
|
|
47210
|
+
}
|
|
47211
|
+
function issueLines(error62) {
|
|
47212
|
+
return error62.issues.map((issue2) => `${issue2.path.map(String).join(".") || "(root)"}: ${issue2.message}`);
|
|
47213
|
+
}
|
|
47214
|
+
|
|
46947
47215
|
// packages/zaku/dist/lib/schema/json-schemas.js
|
|
46948
47216
|
function designJsonSchemas() {
|
|
46949
47217
|
return {
|
|
46950
47218
|
"zaku.schema.json": external_exports.toJSONSchema(zakuConfigSchema, { io: "input" }),
|
|
47219
|
+
"zaku-config.schema.json": external_exports.toJSONSchema(workspaceConfigSchema, { io: "input" }),
|
|
46951
47220
|
"map.schema.json": external_exports.toJSONSchema(featureMapSchema, { io: "input" })
|
|
46952
47221
|
};
|
|
46953
47222
|
}
|
|
@@ -46991,22 +47260,8 @@ RecordBudgetCallsHandler = __decorate2([
|
|
|
46991
47260
|
__param2(0, (0, import_tsyringe6.inject)(TOKENS.BUDGET_LEDGER))
|
|
46992
47261
|
], RecordBudgetCallsHandler);
|
|
46993
47262
|
|
|
46994
|
-
// packages/zaku/dist/lib/repositories/design-config-repository.js
|
|
46995
|
-
var import_tsyringe7 = __toESM(require_cjs(), 1);
|
|
46996
|
-
var DesignConfigRepository = class DesignConfigRepository2 {
|
|
46997
|
-
read(root) {
|
|
46998
|
-
return readDesignFile(designPaths(root).config, zakuConfigSchema);
|
|
46999
|
-
}
|
|
47000
|
-
readOptional(root) {
|
|
47001
|
-
return readOptionalDesignFile(designPaths(root).config, zakuConfigSchema);
|
|
47002
|
-
}
|
|
47003
|
-
};
|
|
47004
|
-
DesignConfigRepository = __decorate2([
|
|
47005
|
-
(0, import_tsyringe7.injectable)({ token: TOKENS.DESIGN_CONFIG_REPOSITORY })
|
|
47006
|
-
], DesignConfigRepository);
|
|
47007
|
-
|
|
47008
47263
|
// packages/zaku/dist/lib/repositories/token-document-repository.js
|
|
47009
|
-
var
|
|
47264
|
+
var import_tsyringe7 = __toESM(require_cjs(), 1);
|
|
47010
47265
|
var TokenDocumentRepository = class TokenDocumentRepository2 {
|
|
47011
47266
|
async save(root, doc) {
|
|
47012
47267
|
const path2 = designPaths(root).tokens;
|
|
@@ -47015,11 +47270,11 @@ var TokenDocumentRepository = class TokenDocumentRepository2 {
|
|
|
47015
47270
|
}
|
|
47016
47271
|
};
|
|
47017
47272
|
TokenDocumentRepository = __decorate2([
|
|
47018
|
-
(0,
|
|
47273
|
+
(0, import_tsyringe7.injectable)({ token: TOKENS.TOKEN_DOCUMENT_REPOSITORY })
|
|
47019
47274
|
], TokenDocumentRepository);
|
|
47020
47275
|
|
|
47021
47276
|
// packages/zaku/dist/lib/repositories/recipe-repository.js
|
|
47022
|
-
var
|
|
47277
|
+
var import_tsyringe8 = __toESM(require_cjs(), 1);
|
|
47023
47278
|
var RecipeRepository = class RecipeRepository2 {
|
|
47024
47279
|
async save(root, doc) {
|
|
47025
47280
|
const path2 = designPaths(root).recipe;
|
|
@@ -47028,11 +47283,11 @@ var RecipeRepository = class RecipeRepository2 {
|
|
|
47028
47283
|
}
|
|
47029
47284
|
};
|
|
47030
47285
|
RecipeRepository = __decorate2([
|
|
47031
|
-
(0,
|
|
47286
|
+
(0, import_tsyringe8.injectable)({ token: TOKENS.RECIPE_REPOSITORY })
|
|
47032
47287
|
], RecipeRepository);
|
|
47033
47288
|
|
|
47034
47289
|
// packages/zaku/dist/lib/repositories/json-schema-files.js
|
|
47035
|
-
var
|
|
47290
|
+
var import_tsyringe9 = __toESM(require_cjs(), 1);
|
|
47036
47291
|
import { mkdir as mkdir3 } from "node:fs/promises";
|
|
47037
47292
|
import { join as join7 } from "node:path";
|
|
47038
47293
|
var JsonSchemaFiles = class JsonSchemaFiles2 {
|
|
@@ -47048,11 +47303,11 @@ var JsonSchemaFiles = class JsonSchemaFiles2 {
|
|
|
47048
47303
|
}
|
|
47049
47304
|
};
|
|
47050
47305
|
JsonSchemaFiles = __decorate2([
|
|
47051
|
-
(0,
|
|
47306
|
+
(0, import_tsyringe9.injectable)({ token: TOKENS.JSON_SCHEMA_FILES })
|
|
47052
47307
|
], JsonSchemaFiles);
|
|
47053
47308
|
|
|
47054
47309
|
// packages/zaku/dist/lib/repositories/source-files.js
|
|
47055
|
-
var
|
|
47310
|
+
var import_tsyringe10 = __toESM(require_cjs(), 1);
|
|
47056
47311
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
47057
47312
|
var SourceFiles = class SourceFiles2 {
|
|
47058
47313
|
readText(path2) {
|
|
@@ -47063,7 +47318,7 @@ var SourceFiles = class SourceFiles2 {
|
|
|
47063
47318
|
}
|
|
47064
47319
|
};
|
|
47065
47320
|
SourceFiles = __decorate2([
|
|
47066
|
-
(0,
|
|
47321
|
+
(0, import_tsyringe10.injectable)({ token: TOKENS.SOURCE_FILES })
|
|
47067
47322
|
], SourceFiles);
|
|
47068
47323
|
|
|
47069
47324
|
// packages/zaku/dist/lib/repositories/budget-ledger.js
|
|
@@ -47165,81 +47420,6 @@ function printGraph(config2, snapshots) {
|
|
|
47165
47420
|
return lines;
|
|
47166
47421
|
}
|
|
47167
47422
|
|
|
47168
|
-
// packages/zaku/dist/lib/adapters/figma-rest.js
|
|
47169
|
-
var FigmaRateLimited = class extends Error {
|
|
47170
|
-
url;
|
|
47171
|
-
constructor(url2) {
|
|
47172
|
-
super(`Figma answered 429 twice for ${url2}; wait and run again`);
|
|
47173
|
-
this.url = url2;
|
|
47174
|
-
this.name = "FigmaRateLimited";
|
|
47175
|
-
}
|
|
47176
|
-
};
|
|
47177
|
-
var FigmaRequestFailed = class extends Error {
|
|
47178
|
-
url;
|
|
47179
|
-
status;
|
|
47180
|
-
constructor(url2, status, body) {
|
|
47181
|
-
super(`Figma answered ${status} for ${url2}: ${body.slice(0, 200)}`);
|
|
47182
|
-
this.url = url2;
|
|
47183
|
-
this.status = status;
|
|
47184
|
-
this.name = "FigmaRequestFailed";
|
|
47185
|
-
}
|
|
47186
|
-
};
|
|
47187
|
-
var BASE = "https://api.figma.com/v1";
|
|
47188
|
-
var BATCH = 50;
|
|
47189
|
-
var MAX_WAIT_MS = 12e4;
|
|
47190
|
-
function createFigmaRest(options) {
|
|
47191
|
-
const send = options.fetch ?? globalThis.fetch;
|
|
47192
|
-
const sleep = options.sleep ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
|
|
47193
|
-
const onCall = options.onCall ?? (() => void 0);
|
|
47194
|
-
async function call(url2) {
|
|
47195
|
-
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
47196
|
-
const res = await send(url2, { headers: { "X-Figma-Token": options.token } });
|
|
47197
|
-
onCall();
|
|
47198
|
-
if (res.status === 429) {
|
|
47199
|
-
if (attempt === 1)
|
|
47200
|
-
break;
|
|
47201
|
-
const seconds = Number(res.headers.get("Retry-After") ?? "60");
|
|
47202
|
-
await sleep(Math.min(Number.isFinite(seconds) ? seconds * 1e3 : 6e4, MAX_WAIT_MS));
|
|
47203
|
-
continue;
|
|
47204
|
-
}
|
|
47205
|
-
if (!res.ok)
|
|
47206
|
-
throw new FigmaRequestFailed(url2, res.status, await res.text());
|
|
47207
|
-
return await res.json();
|
|
47208
|
-
}
|
|
47209
|
-
throw new FigmaRateLimited(url2);
|
|
47210
|
-
}
|
|
47211
|
-
const chunks = (ids) => Array.from({ length: Math.ceil(ids.length / BATCH) }, (_, index) => ids.slice(index * BATCH, (index + 1) * BATCH));
|
|
47212
|
-
async function components(fileKey3) {
|
|
47213
|
-
const listed = await call(`${BASE}/files/${fileKey3}/components`);
|
|
47214
|
-
return listed.meta.components;
|
|
47215
|
-
}
|
|
47216
|
-
return {
|
|
47217
|
-
file: (fileKey3, depth) => call(`${BASE}/files/${fileKey3}?depth=${depth}`),
|
|
47218
|
-
async nodes(fileKey3, ids) {
|
|
47219
|
-
const merged = { version: "", nodes: {} };
|
|
47220
|
-
for (const chunk of chunks(ids)) {
|
|
47221
|
-
const part = await call(`${BASE}/files/${fileKey3}/nodes?ids=${encodeURIComponent(chunk.join(","))}`);
|
|
47222
|
-
merged.version = part.version;
|
|
47223
|
-
Object.assign(merged.nodes, part.nodes);
|
|
47224
|
-
}
|
|
47225
|
-
return merged;
|
|
47226
|
-
},
|
|
47227
|
-
async published(fileKey3) {
|
|
47228
|
-
const sets = await call(`${BASE}/files/${fileKey3}/component_sets`);
|
|
47229
|
-
return { sets: sets.meta.component_sets, components: await components(fileKey3) };
|
|
47230
|
-
},
|
|
47231
|
-
components,
|
|
47232
|
-
async images(fileKey3, ids) {
|
|
47233
|
-
const merged = {};
|
|
47234
|
-
for (const chunk of chunks(ids)) {
|
|
47235
|
-
const part = await call(`${BASE}/images/${fileKey3}?ids=${encodeURIComponent(chunk.join(","))}&format=png&scale=1`);
|
|
47236
|
-
Object.assign(merged, part.images);
|
|
47237
|
-
}
|
|
47238
|
-
return merged;
|
|
47239
|
-
}
|
|
47240
|
-
};
|
|
47241
|
-
}
|
|
47242
|
-
|
|
47243
47423
|
// packages/zaku/dist/lib/adapters/figma-variables-script.js
|
|
47244
47424
|
async function exportVariables(figma, options) {
|
|
47245
47425
|
const collections = [...await figma.variables.getLocalVariableCollectionsAsync()];
|
|
@@ -47944,9 +48124,9 @@ async function startPluginBridge(options = {}) {
|
|
|
47944
48124
|
if (!socket)
|
|
47945
48125
|
return Promise.resolve({ ok: false, error: `file ${fileKey3} is not open in Figma with the zaku plugin` });
|
|
47946
48126
|
const id2 = `c${++next}`;
|
|
47947
|
-
return new Promise((
|
|
48127
|
+
return new Promise((resolve4) => {
|
|
47948
48128
|
const timer = setTimeout(() => settle2(id2, { ok: false, error: `no answer from the zaku panel in ${timeoutMs / 1e3} s; ${PARTIAL}` }), timeoutMs);
|
|
47949
|
-
pending.set(id2, { socket, resolve:
|
|
48129
|
+
pending.set(id2, { socket, resolve: resolve4, timer });
|
|
47950
48130
|
send(socket, { ...message, id: id2 });
|
|
47951
48131
|
});
|
|
47952
48132
|
}
|
|
@@ -48265,6 +48445,71 @@ var copy = ({ config: config2, maps, outlines }) => {
|
|
|
48265
48445
|
return { findings };
|
|
48266
48446
|
};
|
|
48267
48447
|
|
|
48448
|
+
// packages/zaku/dist/lib/domain/file-labels.js
|
|
48449
|
+
var FAMILY_LABELS = {
|
|
48450
|
+
web: "Web",
|
|
48451
|
+
ios: "iOS",
|
|
48452
|
+
android: "Android",
|
|
48453
|
+
macos: "macOS",
|
|
48454
|
+
windows: "Windows",
|
|
48455
|
+
gnome: "Linux",
|
|
48456
|
+
kde: "Linux KDE"
|
|
48457
|
+
};
|
|
48458
|
+
var BRANCH_LABELS = { ui: "UI", native: "Native" };
|
|
48459
|
+
function branchLabel(branches) {
|
|
48460
|
+
const [only2] = branches;
|
|
48461
|
+
return branches.length === 1 && only2 ? BRANCH_LABELS[only2] : null;
|
|
48462
|
+
}
|
|
48463
|
+
function expectedFileName(product, role) {
|
|
48464
|
+
if (role.kind !== "library") {
|
|
48465
|
+
const family = `${product} - ${FAMILY_LABELS[role.family]}`;
|
|
48466
|
+
return role.kind === "prototype" ? `${family} Prototype` : family;
|
|
48467
|
+
}
|
|
48468
|
+
if (role.layer === "foundations")
|
|
48469
|
+
return null;
|
|
48470
|
+
const branch = branchLabel(role.branches);
|
|
48471
|
+
return branch ? `${product} - ${branch} Components` : `${product} - Components`;
|
|
48472
|
+
}
|
|
48473
|
+
function fileRoleLabel(role) {
|
|
48474
|
+
if (role.kind !== "library")
|
|
48475
|
+
return `${FAMILY_LABELS[role.family]} ${role.kind} file`;
|
|
48476
|
+
const branch = branchLabel(role.branches);
|
|
48477
|
+
return branch ? `${branch} ${role.layer} library` : `${role.layer} library`;
|
|
48478
|
+
}
|
|
48479
|
+
|
|
48480
|
+
// packages/zaku/dist/lib/domain/checks/file-names.js
|
|
48481
|
+
var fileNames = (input2) => {
|
|
48482
|
+
if (input2.fileNames === null)
|
|
48483
|
+
return { findings: [] };
|
|
48484
|
+
const graph = designGraph(input2.config);
|
|
48485
|
+
if (graph.legacy)
|
|
48486
|
+
return { findings: [] };
|
|
48487
|
+
const roles = [
|
|
48488
|
+
...graph.products.map((file2) => [file2.key, { kind: "product", family: file2.family }]),
|
|
48489
|
+
...graph.prototypes.map((file2) => [file2.key, { kind: "prototype", family: file2.family }]),
|
|
48490
|
+
...graph.libraries.map((file2) => [
|
|
48491
|
+
file2.key,
|
|
48492
|
+
{ kind: "library", layer: file2.layer, branches: file2.branches }
|
|
48493
|
+
])
|
|
48494
|
+
];
|
|
48495
|
+
const names = new Map(input2.fileNames.map((file2) => [file2.key, file2.name]));
|
|
48496
|
+
const { product } = input2.config;
|
|
48497
|
+
const findings = [];
|
|
48498
|
+
for (const [key, role] of roles) {
|
|
48499
|
+
const actual = names.get(key);
|
|
48500
|
+
const expected = expectedFileName(product, role);
|
|
48501
|
+
if (actual === void 0 || expected === null || actual === expected)
|
|
48502
|
+
continue;
|
|
48503
|
+
const label2 = fileRoleLabel(role);
|
|
48504
|
+
const article = /^(iOS|Android) /.test(label2) ? "an" : "a";
|
|
48505
|
+
findings.push({
|
|
48506
|
+
check: "file-names",
|
|
48507
|
+
message: `${key} is named ${actual}; ${article} ${label2} of ${product} is named ${expected}; rename it in Figma, then run zaku outline`
|
|
48508
|
+
});
|
|
48509
|
+
}
|
|
48510
|
+
return { findings };
|
|
48511
|
+
};
|
|
48512
|
+
|
|
48268
48513
|
// packages/zaku/dist/lib/domain/checks/coverage.js
|
|
48269
48514
|
function frameKey(feature, name) {
|
|
48270
48515
|
return `${feature}
|
|
@@ -49462,6 +49707,7 @@ var ALL_CHECKS = {
|
|
|
49462
49707
|
"system-bars": systemBars,
|
|
49463
49708
|
placement,
|
|
49464
49709
|
naming,
|
|
49710
|
+
"file-names": fileNames,
|
|
49465
49711
|
component,
|
|
49466
49712
|
prototype
|
|
49467
49713
|
};
|
|
@@ -49502,6 +49748,7 @@ var CHECK_IDS = [
|
|
|
49502
49748
|
"empty",
|
|
49503
49749
|
"documentation",
|
|
49504
49750
|
"naming",
|
|
49751
|
+
"file-names",
|
|
49505
49752
|
"component",
|
|
49506
49753
|
"prototype"
|
|
49507
49754
|
];
|
|
@@ -49619,17 +49866,10 @@ async function optional3(read, findings) {
|
|
|
49619
49866
|
throw error62;
|
|
49620
49867
|
}
|
|
49621
49868
|
}
|
|
49622
|
-
async function loadDesign(
|
|
49623
|
-
const paths = designPaths(root);
|
|
49869
|
+
async function loadDesign(product) {
|
|
49870
|
+
const paths = designPaths(product.root);
|
|
49624
49871
|
const findings = [];
|
|
49625
|
-
|
|
49626
|
-
try {
|
|
49627
|
-
config2 = await readDesignFile(paths.config, zakuConfigSchema);
|
|
49628
|
-
} catch (error62) {
|
|
49629
|
-
if (error62 instanceof DesignFileInvalid)
|
|
49630
|
-
return { input: null, findings: [schemaFinding(error62)] };
|
|
49631
|
-
throw error62;
|
|
49632
|
-
}
|
|
49872
|
+
const { config: config2 } = product;
|
|
49633
49873
|
const { maps, errors: mapErrors } = await loadMaps(paths.maps);
|
|
49634
49874
|
findings.push(...mapErrors.map(schemaFinding));
|
|
49635
49875
|
for (const key of indexTitles(maps).duplicates) {
|
|
@@ -49640,7 +49880,7 @@ async function loadDesign(root) {
|
|
|
49640
49880
|
message: `two screens share the title ${title}; a frame name could not tell them apart`
|
|
49641
49881
|
});
|
|
49642
49882
|
}
|
|
49643
|
-
const { outlines, flows, unmapped, errors: outlineErrors } = await loadOutlines(paths.outline);
|
|
49883
|
+
const { outlines, flows, unmapped, files: files2, errors: outlineErrors } = await loadOutlines(paths.outline);
|
|
49644
49884
|
findings.push(...outlineErrors.map(schemaFinding));
|
|
49645
49885
|
const { libraries, kits, errors: snapshotErrors } = await readDesignSnapshots(paths, config2);
|
|
49646
49886
|
findings.push(...snapshotErrors.map(schemaFinding));
|
|
@@ -49657,15 +49897,80 @@ async function loadDesign(root) {
|
|
|
49657
49897
|
libraries,
|
|
49658
49898
|
kits,
|
|
49659
49899
|
tokens,
|
|
49660
|
-
recipe: recipe2
|
|
49900
|
+
recipe: recipe2,
|
|
49901
|
+
fileNames: files2?.files ?? null
|
|
49661
49902
|
},
|
|
49662
49903
|
findings
|
|
49663
49904
|
};
|
|
49664
49905
|
}
|
|
49665
49906
|
|
|
49907
|
+
// packages/zaku/dist/lib/repositories/workspace.js
|
|
49908
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
49909
|
+
import { dirname as dirname4, join as join9, resolve as resolve2 } from "node:path";
|
|
49910
|
+
var WORKSPACE_CONFIG = "zaku.config.yaml";
|
|
49911
|
+
async function readOptionalText(path2) {
|
|
49912
|
+
try {
|
|
49913
|
+
return await readFile6(path2, "utf8");
|
|
49914
|
+
} catch (error62) {
|
|
49915
|
+
if (error62.code === "ENOENT")
|
|
49916
|
+
return null;
|
|
49917
|
+
throw error62;
|
|
49918
|
+
}
|
|
49919
|
+
}
|
|
49920
|
+
function only(products, name) {
|
|
49921
|
+
if (name === void 0)
|
|
49922
|
+
return products;
|
|
49923
|
+
const named = products.filter((product) => product.name === name);
|
|
49924
|
+
if (named.length === 0)
|
|
49925
|
+
throw new ProductUnknown(name, products.map((product) => product.name));
|
|
49926
|
+
return named;
|
|
49927
|
+
}
|
|
49928
|
+
async function readWorkspace(cwd, options) {
|
|
49929
|
+
const configPath = resolve2(cwd, options.config ?? WORKSPACE_CONFIG);
|
|
49930
|
+
const text = await readOptionalText(configPath);
|
|
49931
|
+
if (text === null) {
|
|
49932
|
+
if (options.config !== void 0)
|
|
49933
|
+
throw new WorkspaceConfigMissing(configPath, null);
|
|
49934
|
+
const root = resolve2(cwd, "docs", "design");
|
|
49935
|
+
const legacyPath = designPaths(root).config;
|
|
49936
|
+
const config2 = await readOptionalDesignFile(legacyPath, zakuConfigSchema);
|
|
49937
|
+
if (config2 === null)
|
|
49938
|
+
throw new WorkspaceConfigMissing(configPath, legacyPath);
|
|
49939
|
+
const products2 = only([{ name: config2.product, root, config: config2 }], options.product);
|
|
49940
|
+
return { configPath: null, dir: resolve2(cwd), products: products2, legacy: true, budget: config2.budget };
|
|
49941
|
+
}
|
|
49942
|
+
const dir = dirname4(configPath);
|
|
49943
|
+
const workspace = parseDesignFile(configPath, text, workspaceConfigSchema);
|
|
49944
|
+
if (workspace.products === void 0) {
|
|
49945
|
+
const config2 = parseDesignFile(configPath, text, zakuConfigSchema);
|
|
49946
|
+
const products2 = only([{ name: config2.product, root: join9(dir, "design"), config: config2 }], options.product);
|
|
49947
|
+
return { configPath, dir, products: products2, legacy: false, budget: config2.budget };
|
|
49948
|
+
}
|
|
49949
|
+
const listed = workspace.products.map((product) => ({ name: product.name, root: resolve2(dir, product.root) }));
|
|
49950
|
+
const products = [];
|
|
49951
|
+
for (const { name, root } of only(listed, options.product)) {
|
|
49952
|
+
const path2 = designPaths(root).config;
|
|
49953
|
+
try {
|
|
49954
|
+
const own2 = await readOptionalDesignFile(path2, external_exports.unknown());
|
|
49955
|
+
if (own2 === null)
|
|
49956
|
+
throw new ProductConfigMissing(path2, name);
|
|
49957
|
+
products.push({ name, root, config: mergeProductConfig(workspace, name, own2) });
|
|
49958
|
+
} catch (error62) {
|
|
49959
|
+
if (error62 instanceof ProductConfigMissing)
|
|
49960
|
+
products.push({ name, root, refusal: error62 });
|
|
49961
|
+
else if (error62 instanceof DesignFileInvalid) {
|
|
49962
|
+
const refusal = error62.path === path2 ? error62 : new DesignFileInvalid(path2, error62.issues);
|
|
49963
|
+
products.push({ name, root, refusal });
|
|
49964
|
+
} else
|
|
49965
|
+
throw error62;
|
|
49966
|
+
}
|
|
49967
|
+
}
|
|
49968
|
+
return { configPath, dir, products, legacy: false, budget: workspace.budget ?? budgetSchema.parse({}) };
|
|
49969
|
+
}
|
|
49970
|
+
|
|
49666
49971
|
// apps/zaku-cli/src/dependencies.ts
|
|
49667
49972
|
function compose(seams) {
|
|
49668
|
-
const scope =
|
|
49973
|
+
const scope = import_tsyringe11.container.createChildContainer();
|
|
49669
49974
|
scope.register(TOKENS.CLOCK, { useValue: { now: seams.now } });
|
|
49670
49975
|
scope.register(TOKENS.RUN_COMMAND, { useValue: seams.run });
|
|
49671
49976
|
scope.register(TOKENS.BUDGET_LEDGER, {
|
|
@@ -49694,6 +49999,9 @@ function refusalOf(error62) {
|
|
|
49694
49999
|
if (error62 instanceof FigmaFileKeyMissing) return { code: 3, line: error62.message };
|
|
49695
50000
|
if (error62 instanceof FigmaTokenMissing) return { code: 3, line: error62.message };
|
|
49696
50001
|
if (error62 instanceof LibraryKeyMissing) return { code: 3, line: error62.message };
|
|
50002
|
+
if (error62 instanceof WorkspaceConfigMissing) return { code: 3, line: error62.message };
|
|
50003
|
+
if (error62 instanceof ProductConfigMissing) return { code: 3, line: error62.message };
|
|
50004
|
+
if (error62 instanceof ProductUnknown || error62 instanceof ProductRequired) return { code: 3, line: error62.message };
|
|
49697
50005
|
if (error62 instanceof RecipePageFailed) return { code: 2, line: `zaku recipe: ${error62.message}` };
|
|
49698
50006
|
return null;
|
|
49699
50007
|
}
|
|
@@ -57203,7 +57511,7 @@ var Protocol = class {
|
|
|
57203
57511
|
return;
|
|
57204
57512
|
}
|
|
57205
57513
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
57206
|
-
await new Promise((
|
|
57514
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
|
|
57207
57515
|
options?.signal?.throwIfAborted();
|
|
57208
57516
|
}
|
|
57209
57517
|
} catch (error62) {
|
|
@@ -57220,7 +57528,7 @@ var Protocol = class {
|
|
|
57220
57528
|
*/
|
|
57221
57529
|
request(request, resultSchema, options) {
|
|
57222
57530
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
57223
|
-
return new Promise((
|
|
57531
|
+
return new Promise((resolve4, reject) => {
|
|
57224
57532
|
const earlyReject = (error62) => {
|
|
57225
57533
|
reject(error62);
|
|
57226
57534
|
};
|
|
@@ -57298,7 +57606,7 @@ var Protocol = class {
|
|
|
57298
57606
|
if (!parseResult.success) {
|
|
57299
57607
|
reject(parseResult.error);
|
|
57300
57608
|
} else {
|
|
57301
|
-
|
|
57609
|
+
resolve4(parseResult.data);
|
|
57302
57610
|
}
|
|
57303
57611
|
} catch (error62) {
|
|
57304
57612
|
reject(error62);
|
|
@@ -57560,12 +57868,12 @@ var Protocol = class {
|
|
|
57560
57868
|
}
|
|
57561
57869
|
} catch {
|
|
57562
57870
|
}
|
|
57563
|
-
return new Promise((
|
|
57871
|
+
return new Promise((resolve4, reject) => {
|
|
57564
57872
|
if (signal.aborted) {
|
|
57565
57873
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
57566
57874
|
return;
|
|
57567
57875
|
}
|
|
57568
|
-
const timeoutId = setTimeout(
|
|
57876
|
+
const timeoutId = setTimeout(resolve4, interval);
|
|
57569
57877
|
signal.addEventListener("abort", () => {
|
|
57570
57878
|
clearTimeout(timeoutId);
|
|
57571
57879
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -58705,7 +59013,7 @@ var McpServer = class {
|
|
|
58705
59013
|
let task = createTaskResult.task;
|
|
58706
59014
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
58707
59015
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
58708
|
-
await new Promise((
|
|
59016
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
|
|
58709
59017
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
58710
59018
|
if (!updatedTask) {
|
|
58711
59019
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -59369,12 +59677,12 @@ var StdioServerTransport = class {
|
|
|
59369
59677
|
this.onclose?.();
|
|
59370
59678
|
}
|
|
59371
59679
|
send(message) {
|
|
59372
|
-
return new Promise((
|
|
59680
|
+
return new Promise((resolve4) => {
|
|
59373
59681
|
const json2 = serializeMessage(message);
|
|
59374
59682
|
if (this._stdout.write(json2)) {
|
|
59375
|
-
|
|
59683
|
+
resolve4();
|
|
59376
59684
|
} else {
|
|
59377
|
-
this._stdout.once("drain",
|
|
59685
|
+
this._stdout.once("drain", resolve4);
|
|
59378
59686
|
}
|
|
59379
59687
|
});
|
|
59380
59688
|
}
|
|
@@ -59383,11 +59691,11 @@ var StdioServerTransport = class {
|
|
|
59383
59691
|
// apps/zaku-cli/src/mcp/server.ts
|
|
59384
59692
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
59385
59693
|
import { tmpdir } from "node:os";
|
|
59386
|
-
import { join as
|
|
59694
|
+
import { join as join12 } from "node:path";
|
|
59387
59695
|
|
|
59388
59696
|
// apps/zaku-cli/src/mcp/screenshots.ts
|
|
59389
59697
|
import { readdir as readdir4, rm as rm3, stat } from "node:fs/promises";
|
|
59390
|
-
import { join as
|
|
59698
|
+
import { join as join10 } from "node:path";
|
|
59391
59699
|
var KEPT_MS = 24 * 60 * 60 * 1e3;
|
|
59392
59700
|
async function pruneScreenshots(dir, now) {
|
|
59393
59701
|
let names;
|
|
@@ -59397,7 +59705,7 @@ async function pruneScreenshots(dir, now) {
|
|
|
59397
59705
|
return;
|
|
59398
59706
|
}
|
|
59399
59707
|
for (const name of names.filter((entry) => entry.endsWith(".png"))) {
|
|
59400
|
-
const path2 =
|
|
59708
|
+
const path2 = join10(dir, name);
|
|
59401
59709
|
const written = await stat(path2).then(
|
|
59402
59710
|
(stats) => stats.mtimeMs,
|
|
59403
59711
|
() => now
|
|
@@ -59408,7 +59716,7 @@ async function pruneScreenshots(dir, now) {
|
|
|
59408
59716
|
|
|
59409
59717
|
// apps/zaku-cli/src/mcp/tools.ts
|
|
59410
59718
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
59411
|
-
import { join as
|
|
59719
|
+
import { join as join11 } from "node:path";
|
|
59412
59720
|
var fileKey2 = external_exports.string().min(1).regex(/^[0-9a-zA-Z]{22,128}$/).describe(
|
|
59413
59721
|
"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."
|
|
59414
59722
|
);
|
|
@@ -59452,7 +59760,7 @@ function registerFigmaTools(server, bridge, options) {
|
|
|
59452
59760
|
options.timeoutMs
|
|
59453
59761
|
);
|
|
59454
59762
|
if (!answer.ok) return { isError: true, content: [{ type: "text", text: answer.error }] };
|
|
59455
|
-
const path2 =
|
|
59763
|
+
const path2 = join11(options.imageDir, `${id2.replace(":", "-")}-${Date.now()}.png`);
|
|
59456
59764
|
await writeFile5(path2, Buffer.from(answer.png, "base64"));
|
|
59457
59765
|
const text = JSON.stringify({
|
|
59458
59766
|
path: path2,
|
|
@@ -59478,7 +59786,7 @@ async function serveMcp(log) {
|
|
|
59478
59786
|
log(
|
|
59479
59787
|
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}`
|
|
59480
59788
|
);
|
|
59481
|
-
const imageDir =
|
|
59789
|
+
const imageDir = join12(tmpdir(), "zaku-screenshots");
|
|
59482
59790
|
await mkdir5(imageDir, { recursive: true });
|
|
59483
59791
|
await pruneScreenshots(imageDir, Date.now());
|
|
59484
59792
|
const server = new McpServer({ name: "zaku", version: "1" });
|
|
@@ -59495,59 +59803,175 @@ async function serveMcp(log) {
|
|
|
59495
59803
|
|
|
59496
59804
|
// apps/zaku-cli/src/cli.ts
|
|
59497
59805
|
var USE_FIGMA_CODE_LIMIT = 5e4;
|
|
59498
|
-
var USAGE = "usage: zaku <check|outline|tokens|recipe|library|libraries|rules|budget|schema|mcp> [--
|
|
59499
|
-
|
|
59500
|
-
try {
|
|
59501
|
-
return await cli.bus.send(command);
|
|
59502
|
-
} catch (error62) {
|
|
59503
|
-
const refusal = refusalOf(error62);
|
|
59504
|
-
if (!refusal) throw error62;
|
|
59505
|
-
io.err(refusal.line);
|
|
59506
|
-
finish(refusal.code);
|
|
59507
|
-
return null;
|
|
59508
|
-
}
|
|
59509
|
-
}
|
|
59806
|
+
var USAGE = "usage: zaku <check|outline|tokens|recipe|library|libraries|products|rules|budget|schema|mcp> [--config zaku.config.yaml] [--product <name>]";
|
|
59807
|
+
var LEGACY_WARNING = "zaku: read docs/design/zaku.yaml; move it to zaku.config.yaml at the repository root and the design to design/";
|
|
59510
59808
|
async function recordRestCalls(cli, io) {
|
|
59511
59809
|
const count = cli.restCalls();
|
|
59512
59810
|
if (count === 0) return;
|
|
59513
59811
|
const { seat, run } = seatAndRun(io.env);
|
|
59514
59812
|
await cli.bus.send(new RecordBudgetCalls({ day: today(clock.now()), seat, run, kind: "rest", count }));
|
|
59515
59813
|
}
|
|
59814
|
+
var CONFIG_OPTION = ["--config <path>", "the workspace config, when it is not zaku.config.yaml here"];
|
|
59815
|
+
var PRODUCT_OPTION = ["--product <name>", "only this product, by the name the workspace config gives it"];
|
|
59816
|
+
function warnLegacy(io, workspace) {
|
|
59817
|
+
if (workspace.legacy) io.err(LEGACY_WARNING);
|
|
59818
|
+
}
|
|
59819
|
+
async function workspaceOf(io, options) {
|
|
59820
|
+
const workspace = await readWorkspace(io.cwd, options);
|
|
59821
|
+
warnLegacy(io, workspace);
|
|
59822
|
+
return workspace;
|
|
59823
|
+
}
|
|
59824
|
+
function oneProduct(workspace, command) {
|
|
59825
|
+
const [product, ...rest] = workspace.products;
|
|
59826
|
+
if (product === void 0 || rest.length > 0) {
|
|
59827
|
+
throw new ProductRequired(
|
|
59828
|
+
command,
|
|
59829
|
+
workspace.products.map((each) => each.name)
|
|
59830
|
+
);
|
|
59831
|
+
}
|
|
59832
|
+
if ("refusal" in product) throw product.refusal;
|
|
59833
|
+
return product;
|
|
59834
|
+
}
|
|
59835
|
+
function onlyWithOne(workspace, command, option, given) {
|
|
59836
|
+
if (given !== void 0 && workspace.products.length > 1) {
|
|
59837
|
+
throw new ProductRequired(
|
|
59838
|
+
`${command} ${option}`,
|
|
59839
|
+
workspace.products.map((product) => product.name)
|
|
59840
|
+
);
|
|
59841
|
+
}
|
|
59842
|
+
}
|
|
59843
|
+
function productFailure(error62) {
|
|
59844
|
+
const refusal = refusalOf(error62);
|
|
59845
|
+
if (refusal) return refusal;
|
|
59846
|
+
if (error62 instanceof DesignFileInvalid || error62 instanceof FigmaRequestFailed) {
|
|
59847
|
+
return { code: 1, line: `zaku: ${error62.message}` };
|
|
59848
|
+
}
|
|
59849
|
+
throw error62;
|
|
59850
|
+
}
|
|
59851
|
+
function reportRefusal(io, error62) {
|
|
59852
|
+
const failure2 = productFailure(error62);
|
|
59853
|
+
io.err(failure2.line);
|
|
59854
|
+
return failure2.code;
|
|
59855
|
+
}
|
|
59856
|
+
async function forEachProduct(io, workspace, run) {
|
|
59857
|
+
let code = 0;
|
|
59858
|
+
for (const product of workspace.products) {
|
|
59859
|
+
if (workspace.products.length > 1) io.out(`== ${product.name}`);
|
|
59860
|
+
let exit;
|
|
59861
|
+
try {
|
|
59862
|
+
if ("refusal" in product) throw product.refusal;
|
|
59863
|
+
exit = await run(product);
|
|
59864
|
+
} catch (error62) {
|
|
59865
|
+
exit = reportRefusal(io, error62);
|
|
59866
|
+
}
|
|
59867
|
+
code = Math.max(code, exit);
|
|
59868
|
+
}
|
|
59869
|
+
return code;
|
|
59870
|
+
}
|
|
59516
59871
|
var librariesCommand = (program2, io, finish) => {
|
|
59517
|
-
program2.command("libraries").description("print the design graph: what each target draws from, and what each file extends and is extended by").option(
|
|
59518
|
-
const
|
|
59519
|
-
|
|
59520
|
-
|
|
59872
|
+
program2.command("libraries").description("print the design graph: what each target draws from, and what each file extends and is extended by").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).action(async (options) => {
|
|
59873
|
+
const workspace = await workspaceOf(io, options);
|
|
59874
|
+
finish(
|
|
59875
|
+
await forEachProduct(io, workspace, async ({ root, config: config2 }) => {
|
|
59876
|
+
for (const line of printGraph(config2, await readDesignSnapshots(designPaths(root), config2))) io.out(line);
|
|
59877
|
+
return 0;
|
|
59878
|
+
})
|
|
59879
|
+
);
|
|
59880
|
+
});
|
|
59881
|
+
};
|
|
59882
|
+
var productsCommand = (program2, io, finish) => {
|
|
59883
|
+
program2.command("products").description("print each product the workspace config lists, with its design directory").option(...CONFIG_OPTION).option("--json", "print them as JSON").action(async (options) => {
|
|
59884
|
+
const workspace = await workspaceOf(io, options.config === void 0 ? {} : { config: options.config });
|
|
59885
|
+
const rows = workspace.products.map((product) => ({
|
|
59886
|
+
name: product.name,
|
|
59887
|
+
root: relative3(io.cwd, product.root) || "."
|
|
59888
|
+
}));
|
|
59889
|
+
if (options.json) io.out(JSON.stringify(rows, null, 2));
|
|
59890
|
+
else for (const row of rows) io.out(`${row.name} ${row.root}`);
|
|
59521
59891
|
finish(0);
|
|
59522
59892
|
});
|
|
59523
59893
|
};
|
|
59524
59894
|
var schemaCommand = (program2, io, finish, cli) => {
|
|
59525
|
-
program2.command("schema").description("write the JSON Schemas an editor reads for the design files").option("--out <dir>", "where to write them
|
|
59526
|
-
const
|
|
59895
|
+
program2.command("schema").description("write the JSON Schemas an editor reads for the design files").option("--out <dir>", "where to write them; the workspace config's directory when left out").option(...CONFIG_OPTION).action(async (options) => {
|
|
59896
|
+
const out = options.out !== void 0 ? resolve3(io.cwd, options.out) : options.config !== void 0 ? dirname5(resolve3(io.cwd, options.config)) : resolve3(io.cwd);
|
|
59897
|
+
const written = await cli.bus.send(new WriteSchemas({ out }));
|
|
59527
59898
|
for (const path2 of written) io.out(`wrote ${path2}`);
|
|
59528
59899
|
finish(0);
|
|
59529
59900
|
});
|
|
59530
59901
|
};
|
|
59902
|
+
function checkExit(codes) {
|
|
59903
|
+
const rank = (code) => code === 1 ? 2 : code === 2 ? 1 : code;
|
|
59904
|
+
return codes.reduce((worst, code) => rank(code) > rank(worst) ? code : worst, 0);
|
|
59905
|
+
}
|
|
59906
|
+
async function checkProduct(product, ran) {
|
|
59907
|
+
let loaded;
|
|
59908
|
+
if ("refusal" in product) {
|
|
59909
|
+
if (!(product.refusal instanceof DesignFileInvalid)) return { refusal: product.refusal };
|
|
59910
|
+
loaded = { input: null, findings: [{ check: "schema", message: product.refusal.message }] };
|
|
59911
|
+
} else {
|
|
59912
|
+
try {
|
|
59913
|
+
loaded = await loadDesign(product);
|
|
59914
|
+
} catch (error62) {
|
|
59915
|
+
if (!(error62 instanceof DesignFileInvalid)) throw error62;
|
|
59916
|
+
loaded = { input: null, findings: [{ check: "schema", message: error62.message }] };
|
|
59917
|
+
}
|
|
59918
|
+
}
|
|
59919
|
+
const report = loaded.input ? runChecks(loaded.input, ALL_CHECKS) : { findings: [], notRun: [], passed: [] };
|
|
59920
|
+
report.findings.unshift(...loaded.findings);
|
|
59921
|
+
if (ran) report.findings.push(...ran.findings);
|
|
59922
|
+
const left = ran ? leftOut(ran) : [];
|
|
59923
|
+
return {
|
|
59924
|
+
report: { ...report, ...left.length > 0 ? { leftOut: left } : {} },
|
|
59925
|
+
code: loaded.input ? exitCode(report) : 1
|
|
59926
|
+
};
|
|
59927
|
+
}
|
|
59531
59928
|
var checkCommand = (program2, io, finish) => {
|
|
59532
|
-
program2.command("check").description("run every check over
|
|
59533
|
-
|
|
59534
|
-
|
|
59535
|
-
|
|
59536
|
-
|
|
59537
|
-
|
|
59538
|
-
|
|
59929
|
+
program2.command("check").description("run every check over each product's committed design files").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).option("--json", "print the report as JSON, keyed by product when there are several").option("--input <rules.json>", "what use_figma returned for zaku rules script, with or without --after").action(async (options) => {
|
|
59930
|
+
let workspace;
|
|
59931
|
+
try {
|
|
59932
|
+
workspace = await workspaceOf(io, options);
|
|
59933
|
+
} catch (error62) {
|
|
59934
|
+
if (!(error62 instanceof DesignFileInvalid)) throw error62;
|
|
59935
|
+
const report = { findings: [{ check: "schema", message: error62.message }], notRun: [], passed: [] };
|
|
59936
|
+
if (options.json) io.out(JSON.stringify(report, null, 2));
|
|
59937
|
+
else for (const line of formatReport(report)) io.out(line);
|
|
59539
59938
|
finish(1);
|
|
59540
59939
|
return;
|
|
59541
59940
|
}
|
|
59542
|
-
|
|
59543
|
-
const
|
|
59544
|
-
if (
|
|
59545
|
-
|
|
59546
|
-
|
|
59941
|
+
onlyWithOne(workspace, "zaku check", "--input", options.input);
|
|
59942
|
+
const answer = options.input ? parseDesignFile(options.input, await readFile7(resolve3(io.cwd, options.input), "utf8"), rulesAnswerSchema) : null;
|
|
59943
|
+
if (answer && "rulesError" in answer) {
|
|
59944
|
+
io.err(`zaku check: the rules did not run after the write: ${answer.rulesError}`);
|
|
59945
|
+
finish(1);
|
|
59946
|
+
return;
|
|
59947
|
+
}
|
|
59948
|
+
const several = workspace.products.length > 1;
|
|
59949
|
+
const reports = {};
|
|
59950
|
+
const codes = [];
|
|
59951
|
+
for (const product of workspace.products) {
|
|
59952
|
+
if (several && !options.json) io.out(`== ${product.name}`);
|
|
59953
|
+
const checked = await checkProduct(product, answer);
|
|
59954
|
+
if ("refusal" in checked) {
|
|
59955
|
+
const failure2 = productFailure(checked.refusal);
|
|
59956
|
+
io.err(failure2.line);
|
|
59957
|
+
codes.push(failure2.code);
|
|
59958
|
+
if (options.json) reports[product.name] = { refusal: failure2.line };
|
|
59959
|
+
continue;
|
|
59960
|
+
}
|
|
59961
|
+
codes.push(checked.code);
|
|
59962
|
+
if (options.json) reports[product.name] = checked.report;
|
|
59963
|
+
else for (const line of [...checked.report.leftOut ?? [], ...formatReport(checked.report)]) io.out(line);
|
|
59964
|
+
}
|
|
59965
|
+
if (options.json) {
|
|
59966
|
+
const [only2] = Object.values(reports);
|
|
59967
|
+
if (several) io.out(JSON.stringify(reports, null, 2));
|
|
59968
|
+
else if (only2) io.out(JSON.stringify(only2, null, 2));
|
|
59969
|
+
}
|
|
59970
|
+
finish(checkExit(codes));
|
|
59547
59971
|
});
|
|
59548
59972
|
};
|
|
59549
59973
|
async function productPlaywright(cwd) {
|
|
59550
|
-
const require2 = createRequire(
|
|
59974
|
+
const require2 = createRequire(join13(cwd, "package.json"));
|
|
59551
59975
|
let resolved;
|
|
59552
59976
|
try {
|
|
59553
59977
|
resolved = require2.resolve("playwright");
|
|
@@ -59558,15 +59982,15 @@ async function productPlaywright(cwd) {
|
|
|
59558
59982
|
return require2("playwright");
|
|
59559
59983
|
}
|
|
59560
59984
|
function fromProductTree(cwd, resolved) {
|
|
59561
|
-
for (let dir =
|
|
59562
|
-
if (resolved.startsWith(
|
|
59563
|
-
if (
|
|
59985
|
+
for (let dir = resolve3(cwd); ; dir = dirname5(dir)) {
|
|
59986
|
+
if (resolved.startsWith(join13(dir, "node_modules") + sep)) return true;
|
|
59987
|
+
if (dirname5(dir) === dir) return false;
|
|
59564
59988
|
}
|
|
59565
59989
|
}
|
|
59566
59990
|
var runners = {
|
|
59567
59991
|
run: execRun,
|
|
59568
59992
|
loadPlaywright: productPlaywright,
|
|
59569
|
-
rulesLibrary: () =>
|
|
59993
|
+
rulesLibrary: () => readFile7(fileURLToPath(new URL("./rules.js", import.meta.url)), "utf8")
|
|
59570
59994
|
};
|
|
59571
59995
|
var mcpCommand = (program2, io, finish) => {
|
|
59572
59996
|
program2.command("mcp").description(
|
|
@@ -59577,30 +60001,35 @@ var mcpCommand = (program2, io, finish) => {
|
|
|
59577
60001
|
});
|
|
59578
60002
|
};
|
|
59579
60003
|
var tokensCommand = (program2, io, finish, cli) => {
|
|
59580
|
-
program2.command("tokens").description("write the code's tokens to tokens.json, from the design system zaku.yaml names").option("--css <path>", "the stylesheet that declares :root and .dark (shadcn)").option(
|
|
59581
|
-
const
|
|
59582
|
-
|
|
59583
|
-
|
|
59584
|
-
|
|
59585
|
-
|
|
59586
|
-
|
|
59587
|
-
|
|
59588
|
-
|
|
59589
|
-
|
|
60004
|
+
program2.command("tokens").description("write the code's tokens to tokens.json, from the design system zaku.yaml names").option("--css <path>", "the stylesheet that declares :root and .dark (shadcn), over designSystem.shadcn.css").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).action(async (options) => {
|
|
60005
|
+
const workspace = await workspaceOf(io, options);
|
|
60006
|
+
onlyWithOne(workspace, "zaku tokens", "--css", options.css);
|
|
60007
|
+
finish(
|
|
60008
|
+
await forEachProduct(io, workspace, async ({ root, config: config2 }) => {
|
|
60009
|
+
const named = "shadcn" in config2.designSystem ? config2.designSystem.shadcn.css : void 0;
|
|
60010
|
+
const css = options.css ? resolve3(io.cwd, options.css) : named !== void 0 ? resolve3(workspace.dir, named) : null;
|
|
60011
|
+
const command = new WriteTokens({ root, config: config2, cwd: workspace.dir, css });
|
|
60012
|
+
const written = await cli.bus.send(command);
|
|
60013
|
+
io.out(`wrote ${written.path}: ${written.colours} colours, ${written.from}`);
|
|
60014
|
+
return 0;
|
|
60015
|
+
})
|
|
60016
|
+
);
|
|
59590
60017
|
});
|
|
59591
60018
|
};
|
|
59592
60019
|
var recipeCommand = (program2, io, finish, cli) => {
|
|
59593
|
-
program2.command("recipe").description("write what the code computes for every variant to recipe.json, from the product's recipe page").option("--url <url>", "the recipe page, when it is not zaku.yaml's recipe.url").option(
|
|
59594
|
-
const
|
|
59595
|
-
|
|
59596
|
-
|
|
59597
|
-
|
|
59598
|
-
|
|
59599
|
-
|
|
59600
|
-
|
|
59601
|
-
|
|
60020
|
+
program2.command("recipe").description("write what the code computes for every variant to recipe.json, from the product's recipe page").option("--url <url>", "the recipe page, when it is not zaku.yaml's recipe.url").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).action(async (options) => {
|
|
60021
|
+
const workspace = await workspaceOf(io, options);
|
|
60022
|
+
onlyWithOne(workspace, "zaku recipe", "--url", options.url);
|
|
60023
|
+
finish(
|
|
60024
|
+
await forEachProduct(io, workspace, async ({ root, config: config2 }) => {
|
|
60025
|
+
const command = new WriteRecipe({ root, config: config2, url: options.url ?? null });
|
|
60026
|
+
const written = await cli.bus.send(command);
|
|
60027
|
+
io.out(
|
|
60028
|
+
`wrote ${written.path}: ${written.components} components, ${written.variants} variants, in light and dark`
|
|
60029
|
+
);
|
|
60030
|
+
return 0;
|
|
60031
|
+
})
|
|
59602
60032
|
);
|
|
59603
|
-
finish(0);
|
|
59604
60033
|
});
|
|
59605
60034
|
};
|
|
59606
60035
|
var clock = { now: () => /* @__PURE__ */ new Date() };
|
|
@@ -59621,10 +60050,21 @@ var budgetCommand = (program2, io, finish, cli) => {
|
|
|
59621
60050
|
await cli.bus.send(new RecordBudgetCalls({ day, seat, run, kind: options.kind, count: options.count }));
|
|
59622
60051
|
finish(0);
|
|
59623
60052
|
});
|
|
59624
|
-
budget.command("status").description("exit 4 when the budget refuses another MCP call").option(
|
|
60053
|
+
budget.command("status").description("exit 4 when the budget refuses another MCP call").option(...CONFIG_OPTION).action(async (options) => {
|
|
59625
60054
|
const { path: path2, seat, run, day } = ledger();
|
|
59626
|
-
|
|
59627
|
-
|
|
60055
|
+
let budgets;
|
|
60056
|
+
try {
|
|
60057
|
+
const workspace = await workspaceOf(io, options.config === void 0 ? {} : { config: options.config });
|
|
60058
|
+
budgets = workspace.products.map(
|
|
60059
|
+
(product) => "refusal" in product ? workspace.budget : product.config.budget
|
|
60060
|
+
);
|
|
60061
|
+
} catch (error62) {
|
|
60062
|
+
if (!(error62 instanceof WorkspaceConfigMissing) || options.config !== void 0) throw error62;
|
|
60063
|
+
budgets = [budgetSchema.parse({})];
|
|
60064
|
+
}
|
|
60065
|
+
const read = await readLedger(path2, day);
|
|
60066
|
+
const allowances = budgets.map((budget2) => mcpAllowance(read, seat, run, budget2));
|
|
60067
|
+
const allowance = allowances.reduce((chosen, each) => chosen.ok && !each.ok ? each : chosen);
|
|
59628
60068
|
io.out(
|
|
59629
60069
|
`mcp ${allowance.usedToday} today, ${allowance.usedThisRun} this run${allowance.reason ? `: ${allowance.reason}` : ""}`
|
|
59630
60070
|
);
|
|
@@ -59632,8 +60072,7 @@ var budgetCommand = (program2, io, finish, cli) => {
|
|
|
59632
60072
|
});
|
|
59633
60073
|
};
|
|
59634
60074
|
var outlineCommand = (program2, io, finish, cli) => {
|
|
59635
|
-
program2.command("outline").description("read
|
|
59636
|
-
const root = resolve2(io.cwd, options.root);
|
|
60075
|
+
program2.command("outline").description("read each product file's frames into its design's outline/").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).option("--frames <ids>", "only these frame ids, comma separated").action(async (options) => {
|
|
59637
60076
|
const report = (summary) => io.out(
|
|
59638
60077
|
summary.skipped ? "outline is current; nothing read" : `read ${summary.read} frames, wrote ${summary.written.length} outlines, ${summary.unmapped} unmapped`
|
|
59639
60078
|
);
|
|
@@ -59643,9 +60082,15 @@ var outlineCommand = (program2, io, finish, cli) => {
|
|
|
59643
60082
|
return;
|
|
59644
60083
|
}
|
|
59645
60084
|
try {
|
|
60085
|
+
const workspace = await workspaceOf(io, options);
|
|
60086
|
+
onlyWithOne(workspace, "zaku outline", "--frames", options.frames);
|
|
59646
60087
|
const frames = options.frames ? options.frames.split(",") : null;
|
|
59647
|
-
|
|
59648
|
-
|
|
60088
|
+
finish(
|
|
60089
|
+
await forEachProduct(io, workspace, async ({ root, config: config2 }) => {
|
|
60090
|
+
report(await cli.bus.send(new WriteOutline({ root, config: config2, frames })));
|
|
60091
|
+
return 0;
|
|
60092
|
+
})
|
|
60093
|
+
);
|
|
59649
60094
|
} finally {
|
|
59650
60095
|
await recordRestCalls(cli, io);
|
|
59651
60096
|
}
|
|
@@ -59653,8 +60098,8 @@ var outlineCommand = (program2, io, finish, cli) => {
|
|
|
59653
60098
|
};
|
|
59654
60099
|
var libraryCommand = (program2, io, finish, cli) => {
|
|
59655
60100
|
const library = program2.command("library").description("snapshot the library's components and tokens");
|
|
59656
|
-
library.command("script").description("print the Plugin API code that exports the library variables, for use_figma").option(
|
|
59657
|
-
const config2 = await
|
|
60101
|
+
library.command("script").description("print the Plugin API code that exports the library variables, for use_figma").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).option("--local", "also list the file's own components, for a library in the product file").option("--page <name>", "with --local, list only this page; one use_figma call per page").action(async (options) => {
|
|
60102
|
+
const { config: config2 } = oneProduct(await workspaceOf(io, options), "zaku library script");
|
|
59658
60103
|
io.out(
|
|
59659
60104
|
libraryExportScript({
|
|
59660
60105
|
combos: [config2.modes],
|
|
@@ -59686,23 +60131,13 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
59686
60131
|
);
|
|
59687
60132
|
library.command("save").description(
|
|
59688
60133
|
"write a library's snapshot from its components over Figma REST, joined to the variables export, or a kit's published components"
|
|
59689
|
-
).option(
|
|
60134
|
+
).option(...CONFIG_OPTION).option(...PRODUCT_OPTION).option("--key <key>", "the library or kit to save, as zaku.yaml lists it; needed when it lists several").option(
|
|
59690
60135
|
"--input <variables.json>",
|
|
59691
60136
|
"what use_figma returned for zaku library script; once per page export for a library in the product file",
|
|
59692
60137
|
(value, previous = []) => [...previous, value]
|
|
59693
60138
|
).action(async (options) => {
|
|
59694
|
-
const root =
|
|
59695
|
-
const
|
|
59696
|
-
let target;
|
|
59697
|
-
try {
|
|
59698
|
-
target = librarySaveTarget(config2, options.key);
|
|
59699
|
-
} catch (error62) {
|
|
59700
|
-
const refusal = refusalOf(error62);
|
|
59701
|
-
if (!refusal) throw error62;
|
|
59702
|
-
io.err(refusal.line);
|
|
59703
|
-
finish(refusal.code);
|
|
59704
|
-
return;
|
|
59705
|
-
}
|
|
60139
|
+
const { root, config: config2 } = oneProduct(await workspaceOf(io, options), "zaku library save");
|
|
60140
|
+
const target = librarySaveTarget(config2, options.key);
|
|
59706
60141
|
if (target.kind === "library" && (!options.input || options.input.length === 0)) {
|
|
59707
60142
|
io.err("zaku library save needs --input, the variables use_figma returned for zaku library script");
|
|
59708
60143
|
finish(3);
|
|
@@ -59716,7 +60151,7 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
59716
60151
|
const part = target.kind === "library" ? mergeParts(
|
|
59717
60152
|
await Promise.all(
|
|
59718
60153
|
(options.input ?? []).map(
|
|
59719
|
-
async (input2) => parseDesignFile(input2, await
|
|
60154
|
+
async (input2) => parseDesignFile(input2, await readFile7(resolve3(io.cwd, input2), "utf8"), variablePartSchema)
|
|
59720
60155
|
)
|
|
59721
60156
|
)
|
|
59722
60157
|
) : void 0;
|
|
@@ -59724,6 +60159,7 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
59724
60159
|
const saved = await cli.bus.send(
|
|
59725
60160
|
new SaveLibrary({
|
|
59726
60161
|
root,
|
|
60162
|
+
config: config2,
|
|
59727
60163
|
...options.key !== void 0 ? { key: options.key } : {},
|
|
59728
60164
|
...part ? { part } : {}
|
|
59729
60165
|
})
|
|
@@ -59752,13 +60188,13 @@ var libraryCommand = (program2, io, finish, cli) => {
|
|
|
59752
60188
|
};
|
|
59753
60189
|
var rulesCommand = (program2, io, finish) => {
|
|
59754
60190
|
const rules = program2.command("rules").description("zaku's rule checks, for a run that reaches Figma through use_figma");
|
|
59755
|
-
rules.command("script").description("print the Plugin API code that runs the rules over a page or a node, for use_figma").option(
|
|
60191
|
+
rules.command("script").description("print the Plugin API code that runs the rules over a page or a node, for use_figma").option(...CONFIG_OPTION).option(...PRODUCT_OPTION).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) => {
|
|
59756
60192
|
if (options.page === void 0 === (options.node === void 0)) {
|
|
59757
60193
|
io.err("zaku rules script needs --page or --node, one of them");
|
|
59758
60194
|
finish(3);
|
|
59759
60195
|
return;
|
|
59760
60196
|
}
|
|
59761
|
-
const config2 = await
|
|
60197
|
+
const { config: config2 } = oneProduct(await workspaceOf(io, options), "zaku rules script");
|
|
59762
60198
|
const scope = options.node !== void 0 ? { nodeId: options.node } : { page: options.page };
|
|
59763
60199
|
const graph = designGraph(config2);
|
|
59764
60200
|
const file2 = options.key === void 0 ? graph.libraries.length === 1 ? graph.libraries[0] : void 0 : graph.libraries.find((library2) => library2.key === options.key);
|
|
@@ -59778,7 +60214,7 @@ return ${check2};`);
|
|
|
59778
60214
|
finish(0);
|
|
59779
60215
|
return;
|
|
59780
60216
|
}
|
|
59781
|
-
const write2 = await
|
|
60217
|
+
const write2 = await readFile7(resolve3(io.cwd, options.after), "utf8");
|
|
59782
60218
|
const body = [
|
|
59783
60219
|
library,
|
|
59784
60220
|
`const zakuWrite = async () => {
|
|
@@ -59810,6 +60246,7 @@ var COMMANDS = [
|
|
|
59810
60246
|
budgetCommand,
|
|
59811
60247
|
schemaCommand,
|
|
59812
60248
|
librariesCommand,
|
|
60249
|
+
productsCommand,
|
|
59813
60250
|
mcpCommand
|
|
59814
60251
|
];
|
|
59815
60252
|
async function main(argv, io) {
|
|
@@ -59846,6 +60283,11 @@ async function main(argv, io) {
|
|
|
59846
60283
|
io.err(USAGE);
|
|
59847
60284
|
return 3;
|
|
59848
60285
|
}
|
|
60286
|
+
const refusal = refusalOf(error62);
|
|
60287
|
+
if (refusal) {
|
|
60288
|
+
io.err(refusal.line);
|
|
60289
|
+
return refusal.code;
|
|
60290
|
+
}
|
|
59849
60291
|
io.err(`zaku: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
59850
60292
|
return 1;
|
|
59851
60293
|
}
|