@nudojs/core 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,587 @@
1
+ import {
2
+ canSkipLiteralCallScan,
3
+ checkInjectedDomainEvidence,
4
+ extractAllLoadSpecs,
5
+ fnFingerprints,
6
+ generalizeFromAst,
7
+ generalizeSourceKeyPart,
8
+ getFnNameAndBodies,
9
+ hashSource,
10
+ interfaceTierOf,
11
+ listTopFunctions,
12
+ loadModuleDepsFingerprint,
13
+ normPath,
14
+ resetFnFpCache,
15
+ resetHashSourceCache,
16
+ resolveDepPath,
17
+ sidecarSpecsOf,
18
+ stableAnalyzeKeySource
19
+ } from "./chunk-V2I7VXFZ.js";
20
+ import {
21
+ $tryDigestSoft,
22
+ $tryMarkSoft,
23
+ $tryReleaseSoft,
24
+ ERROR_FAMILY,
25
+ FORK_TRUNCATION_LABEL,
26
+ HOST_EFFECT_LABEL_PREFIX,
27
+ MAX_B_TOTAL_FORKS,
28
+ MAX_CALL_DEPTH,
29
+ MAX_TOTAL_CALLS,
30
+ OBJECT_PROTO_NAMES,
31
+ abortDerivationSession,
32
+ absTemplateViews,
33
+ allFixedTextOfViews,
34
+ anyMemberResult,
35
+ awaitAbs,
36
+ beginDerivationSession,
37
+ bumpBForkBudget,
38
+ callBudgetKey,
39
+ classChainNames,
40
+ classFromMethods,
41
+ coerceAsyncReturn,
42
+ concatString,
43
+ createTemplateAbs,
44
+ decideEndsWith,
45
+ decideIncludes,
46
+ decideStartsWith,
47
+ defaultLeakBudget,
48
+ defineClass,
49
+ definitelyUncallableMember,
50
+ derivationChain,
51
+ endDerivationSession,
52
+ enterCall,
53
+ errorTypeAbs,
54
+ exceedsBudget,
55
+ exitCall,
56
+ filterDeclaredThrows,
57
+ filterGateThrows,
58
+ filterIgnoredThrows,
59
+ fixedLengthOfViews,
60
+ flushMayThrowEffects,
61
+ formatShape,
62
+ formatTemplateNameViews,
63
+ formatThrowsAbs,
64
+ getAbsCallBudgetStats,
65
+ getAbsOrigin,
66
+ getBForkBudgetLimit,
67
+ getBForkCount,
68
+ getClass,
69
+ getClassChain,
70
+ getDerivation,
71
+ getMayThrowCollector,
72
+ hasDerivationSession,
73
+ instanceOf,
74
+ instantiateClass,
75
+ isEvalMissingSlotEnabled,
76
+ isNullishAbs,
77
+ isTemplateLike,
78
+ isThrowsIgnored,
79
+ knownPrefixOfViews,
80
+ knownSuffixOfViews,
81
+ leakIfNeeded,
82
+ litValue,
83
+ lookupMethod,
84
+ lookupMethodWithOwner,
85
+ lookupSuperMethod,
86
+ mayThrowEffectsToAbs,
87
+ maybeLeak,
88
+ mergeAdjacentFixedViews,
89
+ noteAbsTruncation,
90
+ noteAnyMemberMayThrow,
91
+ noteBForkTruncation,
92
+ noteDerivationAdd,
93
+ noteDerivationJoin,
94
+ noteHostEffectBlocked,
95
+ noteMemberDispatchMiss,
96
+ noteNullishMemberThrows,
97
+ noteObjSlotMissing,
98
+ notePrimMemberMissing,
99
+ noteUnknownMemberMissing,
100
+ orphanMayThrowEffects,
101
+ parseSource,
102
+ popCallLoc,
103
+ popMayThrowFrame,
104
+ predToString,
105
+ projectBrand,
106
+ projectDerivationDsl,
107
+ pushCallLoc,
108
+ pushMayThrowFrame,
109
+ recordMayThrow,
110
+ recordMemberDiag,
111
+ resetAbsCallBudget,
112
+ resetBForkBudget,
113
+ resetLeakCounter,
114
+ runWithEvalMissingSlot,
115
+ runWithMayThrowSession,
116
+ setAbsTruncationCollector,
117
+ setBForkBudgetLimit,
118
+ setDerivation,
119
+ setDerivationCollector,
120
+ setEvalMissingSlotEnabled,
121
+ setMayThrowCollector,
122
+ setMemberDiagCollector,
123
+ stableCallId,
124
+ superNameOf,
125
+ tagAbsOrigin,
126
+ tagDerivationRoot,
127
+ templateMatchesValue,
128
+ templatePartsOf,
129
+ termDepth,
130
+ termKey,
131
+ termNodes,
132
+ termToString,
133
+ throwAbsToKinds,
134
+ throwsKindCovered,
135
+ truncatedAbs,
136
+ viewTemplateParts,
137
+ wrapPromise
138
+ } from "./chunk-CDH7QCGQ.js";
139
+
140
+ // src/algebra/inlay.ts
141
+ function listFunctions(source) {
142
+ const file = parseSource(source);
143
+ const out = [];
144
+ const visitDecl = (decl) => {
145
+ if (decl.type === "FunctionDeclaration" && decl.id) {
146
+ const fd = decl;
147
+ out.push({ name: fd.id.name, node: fd });
148
+ }
149
+ if (decl.type === "VariableDeclaration") {
150
+ const dcls = decl.declarations ?? [];
151
+ for (const d of dcls) {
152
+ const id = d.id;
153
+ const init = d.init;
154
+ if (id?.type === "Identifier" && id.name && init && (init.type === "ArrowFunctionExpression" || init.type === "FunctionExpression")) {
155
+ out.push({ name: id.name, node: init });
156
+ }
157
+ }
158
+ }
159
+ };
160
+ for (const stmt of file.program.body) {
161
+ if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
162
+ visitDecl(stmt.declaration);
163
+ } else if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration) {
164
+ visitDecl(stmt.declaration);
165
+ } else {
166
+ visitDecl(stmt);
167
+ }
168
+ }
169
+ return out;
170
+ }
171
+ function renameTypeVars(s, varMap) {
172
+ let out = s;
173
+ const ids = [...varMap.keys()].sort((a, b) => b.length - a.length);
174
+ for (const id of ids) {
175
+ out = out.replaceAll(id, varMap.get(id));
176
+ }
177
+ return out;
178
+ }
179
+ function formatReturnDisplay(g) {
180
+ const varMap = /* @__PURE__ */ new Map();
181
+ for (let i = 0; i < (g.typeParams?.length ?? 0); i++) {
182
+ const id = g.typeParams[i].id;
183
+ const pname = g.params[i];
184
+ if (pname) varMap.set(id, pname);
185
+ }
186
+ const stripParens = (t) => t.startsWith("(") && t.endsWith(")") ? t.slice(1, -1) : t;
187
+ const memberPath = (m) => {
188
+ if (m.term?.op === "var") {
189
+ const name = renameTypeVars(m.term.id, varMap);
190
+ return { key: `var:${name}`, text: name };
191
+ }
192
+ if (m.term?.op === "app") {
193
+ const t = stripParens(renameTypeVars(termToString(m.term), varMap));
194
+ return { key: `app:${t}`, text: t };
195
+ }
196
+ const lv = litValue(m);
197
+ if (typeof lv === "number" && !Number.isFinite(lv)) {
198
+ return { key: `lit:${String(lv)}`, text: String(lv) };
199
+ }
200
+ if (lv !== void 0) {
201
+ return { key: `lit:${String(lv)}`, text: JSON.stringify(lv) };
202
+ }
203
+ return { key: `shape:${formatShape(m)}`, text: formatShape(m) };
204
+ };
205
+ const abs = g.symbolic;
206
+ if (abs.term && abs.term.op !== "lit") {
207
+ return stripParens(renameTypeVars(termToString(abs.term), varMap));
208
+ }
209
+ if (abs.shape.k === "sum") {
210
+ const parts = [];
211
+ const seen = /* @__PURE__ */ new Set();
212
+ for (const m of abs.shape.members) {
213
+ const { key, text } = memberPath(m);
214
+ if (seen.has(key)) continue;
215
+ seen.add(key);
216
+ parts.push(text);
217
+ }
218
+ return parts.join(" | ");
219
+ }
220
+ return memberPath(abs).text;
221
+ }
222
+ function collectAbsInlays(source, opts) {
223
+ const inlays = [];
224
+ const refineOpts = opts?.loadModule || opts?.fromFile ? {
225
+ ...opts.loadModule ? { loadModule: opts.loadModule } : {},
226
+ ...opts.fromFile ? { fromFile: opts.fromFile } : {}
227
+ } : void 0;
228
+ for (const { name, node } of listFunctions(source)) {
229
+ let g;
230
+ try {
231
+ g = generalizeFromAst(name, source, refineOpts ? { refine: refineOpts } : {});
232
+ } catch {
233
+ continue;
234
+ }
235
+ if (!g) continue;
236
+ const tier = opts?.fromFile !== void 0 ? interfaceTierOf(source, name, opts.fromFile, {
237
+ ...opts.loadModule ? { loadModule: opts.loadModule } : {},
238
+ ...opts.autoBind !== void 0 ? { autoBind: opts.autoBind } : {}
239
+ }) : void 0;
240
+ const tierSrc = tier?.source;
241
+ const isImplicitExport = tierSrc === "implicit";
242
+ const params = g.params;
243
+ const predsByName = /* @__PURE__ */ new Map();
244
+ if (g.entryReqs) {
245
+ for (const r of g.entryReqs) {
246
+ predsByName.set(r.param, [r.pred]);
247
+ }
248
+ }
249
+ const fnNode = node;
250
+ const paramList = fnNode.params ?? [];
251
+ for (let i = 0; i < paramList.length; i++) {
252
+ const p = paramList[i];
253
+ const pname = params[i] ?? p?.name;
254
+ if (!p?.loc || !pname) continue;
255
+ const preds = predsByName.get(pname);
256
+ if (preds && preds.length > 0) {
257
+ const text = preds.map(predToString).join(" \u2227 ");
258
+ inlays.push({
259
+ line: p.loc.end.line,
260
+ character: p.loc.end.column,
261
+ label: ` where ${text}`,
262
+ kind: "parameter",
263
+ ...tierSrc ? { interfaceSource: tierSrc } : {}
264
+ });
265
+ }
266
+ }
267
+ const bodyLoc = fnNode.body?.loc;
268
+ if (bodyLoc?.start) {
269
+ let label;
270
+ try {
271
+ label = `: ${formatReturnDisplay(g)}`;
272
+ } catch {
273
+ label = `: ${formatShape(g.symbolic)}`;
274
+ }
275
+ if (isImplicitExport) label += " \xB7 derived";
276
+ inlays.push({
277
+ line: bodyLoc.start.line,
278
+ character: Math.max(0, bodyLoc.start.column),
279
+ label: `${label} `,
280
+ kind: "type",
281
+ ...tierSrc ? { interfaceSource: tierSrc } : {},
282
+ ...isImplicitExport ? { derived: true } : {}
283
+ });
284
+ }
285
+ }
286
+ return inlays;
287
+ }
288
+
289
+ // src/algebra/denote.ts
290
+ function denoteGuard(a, v) {
291
+ const lv = litValue(a);
292
+ if (lv !== void 0 && (!a.pred || a.pred.op === "true")) {
293
+ return eqGuard(v, lv);
294
+ }
295
+ const shape = denoteShape(a.shape, v);
296
+ const pred = denotePred(a, v);
297
+ if (shape === "true") return pred;
298
+ if (pred === "true") return shape;
299
+ return `(${shape}) && (${pred})`;
300
+ }
301
+ function denoteShape(s, v) {
302
+ switch (s.k) {
303
+ case "never":
304
+ return "false";
305
+ case "unknown":
306
+ case "any":
307
+ return "true";
308
+ case "prim":
309
+ switch (s.type) {
310
+ case "number":
311
+ return `typeof ${v} === "number"`;
312
+ case "string":
313
+ return `typeof ${v} === "string"`;
314
+ case "boolean":
315
+ return `typeof ${v} === "boolean"`;
316
+ case "bigint":
317
+ return `typeof ${v} === "bigint"`;
318
+ case "symbol":
319
+ return `typeof ${v} === "symbol"`;
320
+ default:
321
+ return "true";
322
+ }
323
+ case "obj": {
324
+ const checks = [`typeof ${v} === "object"`, `${v} !== null`];
325
+ for (const [key, slot] of Object.entries(s.slots)) {
326
+ const access = `${v}.${key}`;
327
+ const inner = denoteGuard(slot.value, access);
328
+ if (slot.optional) {
329
+ if (inner !== "true") checks.push(`(${access} === undefined || ${inner})`);
330
+ } else {
331
+ if (inner !== "true") checks.push(inner);
332
+ }
333
+ }
334
+ return checks.join(" && ");
335
+ }
336
+ case "arr":
337
+ return `Array.isArray(${v}) && ${v}.every((item) => ${denoteGuard(s.element, "item")})`;
338
+ case "tuple": {
339
+ const checks = [`Array.isArray(${v})`];
340
+ const minLen = s.elements.length;
341
+ checks.push(s.rest ? `${v}.length >= ${minLen}` : `${v}.length === ${minLen}`);
342
+ s.elements.forEach((el, i) => {
343
+ const inner = denoteGuard(el, `${v}[${i}]`);
344
+ if (inner !== "true") checks.push(inner);
345
+ });
346
+ if (s.rest) {
347
+ const rest = denoteGuard(s.rest, "item");
348
+ if (rest !== "true") {
349
+ checks.push(`${v}.slice(${minLen}).every((item) => ${rest})`);
350
+ }
351
+ }
352
+ return checks.join(" && ");
353
+ }
354
+ case "fn":
355
+ return `typeof ${v} === "function"`;
356
+ case "eff":
357
+ if (s.eff === "promise") return `${v} instanceof Promise`;
358
+ return "true";
359
+ case "brand":
360
+ return denoteShape(s.shape.shape, v);
361
+ case "sum": {
362
+ if (s.members.length === 0) return "false";
363
+ const parts = s.members.map((m) => denoteGuard(m, v));
364
+ return `(${parts.join(" || ")})`;
365
+ }
366
+ }
367
+ }
368
+ function denotePred(a, v) {
369
+ const p = a.pred;
370
+ if (!p || p.op === "true") {
371
+ const lv = litValue(a);
372
+ if (lv !== void 0) return eqGuard(v, lv);
373
+ return "true";
374
+ }
375
+ return predAsJs(p, v, a);
376
+ }
377
+ function predAsJs(p, v, a) {
378
+ switch (p.op) {
379
+ case "true":
380
+ return "true";
381
+ case "false":
382
+ return "false";
383
+ case "and":
384
+ return p.args.map((x) => predAsJs(x, v, a)).join(" && ");
385
+ case "or":
386
+ return `(${p.args.map((x) => predAsJs(x, v, a)).join(" || ")})`;
387
+ case "not": {
388
+ const inner = predAsJs(p.arg, v, a);
389
+ return inner === "true" ? "false" : `!(${inner})`;
390
+ }
391
+ case "gt":
392
+ case "ge":
393
+ case "lt":
394
+ case "le":
395
+ case "eq":
396
+ case "ne": {
397
+ const op = { gt: ">", ge: ">=", lt: "<", le: "<=", eq: "===", ne: "!==" }[p.op];
398
+ const leftIsValue = termIsValue(p.a, a);
399
+ const rightLit = litOfTerm(p.b);
400
+ if (leftIsValue && rightLit !== void 0) {
401
+ return cmpOp(v, op, rightLit);
402
+ }
403
+ const leftLit = litOfTerm(p.a);
404
+ const rightIsValue = termIsValue(p.b, a);
405
+ if (rightIsValue && leftLit !== void 0) {
406
+ return cmpLitValue(leftLit, op, v);
407
+ }
408
+ if (leftLit !== void 0 && rightLit !== void 0) {
409
+ return `${jsLit(leftLit)} ${op} ${jsLit(rightLit)}`;
410
+ }
411
+ return "true";
412
+ }
413
+ default:
414
+ return "true";
415
+ }
416
+ }
417
+ function litOfTerm(t) {
418
+ return t.op === "lit" ? t.value : void 0;
419
+ }
420
+ function jsLit(v) {
421
+ if (v === void 0) return "undefined";
422
+ if (v === null) return "null";
423
+ if (typeof v === "number") {
424
+ if (Number.isNaN(v)) return "NaN";
425
+ if (v === Infinity) return "Infinity";
426
+ if (v === -Infinity) return "-Infinity";
427
+ return String(v);
428
+ }
429
+ return JSON.stringify(v);
430
+ }
431
+ function eqGuard(v, lv) {
432
+ if (typeof lv === "number" && Number.isNaN(lv)) return `Number.isNaN(${v})`;
433
+ return `${v} === ${jsLit(lv)}`;
434
+ }
435
+ function cmpOp(v, op, lit) {
436
+ if (typeof lit === "number" && Number.isNaN(lit)) {
437
+ if (op === "===") return `Number.isNaN(${v})`;
438
+ if (op === "!==") return `!Number.isNaN(${v})`;
439
+ }
440
+ return `${v} ${op} ${jsLit(lit)}`;
441
+ }
442
+ function cmpLitValue(lit, op, v) {
443
+ if (typeof lit === "number" && Number.isNaN(lit)) {
444
+ if (op === "===") return `Number.isNaN(${v})`;
445
+ if (op === "!==") return `!Number.isNaN(${v})`;
446
+ }
447
+ return `${jsLit(lit)} ${op} ${v}`;
448
+ }
449
+ function termIsValue(t, a) {
450
+ if (t.op === "var") return true;
451
+ if (t.op === "lit") {
452
+ const lv = litValue(a);
453
+ return lv !== void 0 && Object.is(lv, t.value);
454
+ }
455
+ return false;
456
+ }
457
+ export {
458
+ $tryDigestSoft,
459
+ $tryMarkSoft,
460
+ $tryReleaseSoft,
461
+ ERROR_FAMILY,
462
+ FORK_TRUNCATION_LABEL,
463
+ HOST_EFFECT_LABEL_PREFIX,
464
+ MAX_B_TOTAL_FORKS,
465
+ MAX_CALL_DEPTH,
466
+ MAX_TOTAL_CALLS,
467
+ OBJECT_PROTO_NAMES,
468
+ abortDerivationSession,
469
+ absTemplateViews,
470
+ allFixedTextOfViews,
471
+ anyMemberResult,
472
+ awaitAbs,
473
+ beginDerivationSession,
474
+ bumpBForkBudget,
475
+ callBudgetKey,
476
+ canSkipLiteralCallScan,
477
+ checkInjectedDomainEvidence,
478
+ classChainNames,
479
+ classFromMethods,
480
+ coerceAsyncReturn,
481
+ collectAbsInlays,
482
+ concatString,
483
+ createTemplateAbs,
484
+ decideEndsWith,
485
+ decideIncludes,
486
+ decideStartsWith,
487
+ defaultLeakBudget,
488
+ defineClass,
489
+ definitelyUncallableMember,
490
+ denoteGuard,
491
+ derivationChain,
492
+ endDerivationSession,
493
+ enterCall,
494
+ errorTypeAbs,
495
+ exceedsBudget,
496
+ exitCall,
497
+ extractAllLoadSpecs,
498
+ filterDeclaredThrows,
499
+ filterGateThrows,
500
+ filterIgnoredThrows,
501
+ fixedLengthOfViews,
502
+ flushMayThrowEffects,
503
+ fnFingerprints,
504
+ formatTemplateNameViews,
505
+ formatThrowsAbs,
506
+ generalizeSourceKeyPart,
507
+ getAbsCallBudgetStats,
508
+ getAbsOrigin,
509
+ getBForkBudgetLimit,
510
+ getBForkCount,
511
+ getClass,
512
+ getClassChain,
513
+ getDerivation,
514
+ getFnNameAndBodies,
515
+ getMayThrowCollector,
516
+ hasDerivationSession,
517
+ hashSource,
518
+ instanceOf,
519
+ instantiateClass,
520
+ isEvalMissingSlotEnabled,
521
+ isNullishAbs,
522
+ isTemplateLike,
523
+ isThrowsIgnored,
524
+ knownPrefixOfViews,
525
+ knownSuffixOfViews,
526
+ leakIfNeeded,
527
+ listTopFunctions,
528
+ loadModuleDepsFingerprint,
529
+ lookupMethod,
530
+ lookupMethodWithOwner,
531
+ lookupSuperMethod,
532
+ mayThrowEffectsToAbs,
533
+ maybeLeak,
534
+ mergeAdjacentFixedViews,
535
+ normPath,
536
+ noteAbsTruncation,
537
+ noteAnyMemberMayThrow,
538
+ noteBForkTruncation,
539
+ noteDerivationAdd,
540
+ noteDerivationJoin,
541
+ noteHostEffectBlocked,
542
+ noteMemberDispatchMiss,
543
+ noteNullishMemberThrows,
544
+ noteObjSlotMissing,
545
+ notePrimMemberMissing,
546
+ noteUnknownMemberMissing,
547
+ orphanMayThrowEffects,
548
+ popCallLoc,
549
+ popMayThrowFrame,
550
+ projectBrand,
551
+ projectDerivationDsl,
552
+ pushCallLoc,
553
+ pushMayThrowFrame,
554
+ recordMayThrow,
555
+ recordMemberDiag,
556
+ resetAbsCallBudget,
557
+ resetBForkBudget,
558
+ resetFnFpCache,
559
+ resetHashSourceCache,
560
+ resetLeakCounter,
561
+ resolveDepPath,
562
+ runWithEvalMissingSlot,
563
+ runWithMayThrowSession,
564
+ setAbsTruncationCollector,
565
+ setBForkBudgetLimit,
566
+ setDerivation,
567
+ setDerivationCollector,
568
+ setEvalMissingSlotEnabled,
569
+ setMayThrowCollector,
570
+ setMemberDiagCollector,
571
+ sidecarSpecsOf,
572
+ stableAnalyzeKeySource,
573
+ stableCallId,
574
+ superNameOf,
575
+ tagAbsOrigin,
576
+ tagDerivationRoot,
577
+ templateMatchesValue,
578
+ templatePartsOf,
579
+ termDepth,
580
+ termKey,
581
+ termNodes,
582
+ throwAbsToKinds,
583
+ throwsKindCovered,
584
+ truncatedAbs,
585
+ viewTemplateParts,
586
+ wrapPromise
587
+ };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@nudojs/core",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },
7
- "description": "Nudo type system: type-as-computation (Abs) with TypeValue evaluation IR",
7
+ "description": "Nudo type system: type-as-computation (Abs = shape × term × pred × conf)",
8
8
  "type": "module",
9
9
  "license": "MIT",
10
10
  "keywords": [
@@ -24,6 +24,10 @@
24
24
  "./exec": {
25
25
  "types": "./dist/exec.d.ts",
26
26
  "default": "./dist/exec.js"
27
+ },
28
+ "./internal": {
29
+ "types": "./dist/internal.d.ts",
30
+ "default": "./dist/internal.js"
27
31
  }
28
32
  },
29
33
  "files": [
@@ -42,20 +46,21 @@
42
46
  "registry": "https://registry.npmjs.org"
43
47
  },
44
48
  "dependencies": {
45
- "@babel/parser": "^7.29.0",
46
- "@babel/types": "^7.29.0"
49
+ "@babel/parser": "^8.0.6",
50
+ "@babel/types": "^8.0.6"
47
51
  },
48
52
  "devDependencies": {
49
- "commander": "^13.0.0",
53
+ "commander": "^15.0.0",
50
54
  "debug": "^4.4.3",
51
55
  "escape-string-regexp": "^5.0.0",
52
56
  "eventemitter3": "^5.0.4",
53
57
  "is-plain-obj": "^4.1.0",
54
58
  "kleur": "^4.1.5",
55
- "lodash": "^4.17.21",
59
+ "lodash": "^4.18.1",
56
60
  "ms": "^2.1.3",
57
- "p-limit": "^7.3.2",
58
- "yocto-queue": "^1.2.2"
61
+ "p-limit": "^7.3.3",
62
+ "yocto-queue": "^1.2.2",
63
+ "@types/node": "^26.6.2"
59
64
  },
60
65
  "scripts": {
61
66
  "build": "tsup"