@akanjs/cli 3.0.0-alpha.15 → 3.0.0-alpha.17

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.
Files changed (57) hide show
  1. package/.build-stamp +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/{abstractCompactor-e5yq60qz.js → abstractCompactor-khr60389.js} +1 -1
  5. package/{agent.command-h6tc0pzh.js → agent.command-e835fjem.js} +6 -6
  6. package/{application.command-kphnfwyg.js → application.command-bexm4597.js} +5 -5
  7. package/{applicationBuildRunner-9ps10a0h.js → applicationBuildRunner-sgr3aq5b.js} +5 -6
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-93nzdfsy.js} +1 -1
  9. package/buildBatch.proc.js +4 -4
  10. package/{capacitorApp-9ejk3k7q.js → capacitorApp-qv7g3dp2.js} +27 -27
  11. package/{cloud.command-zn6mfscb.js → cloud.command-v44fdp23.js} +8 -8
  12. package/{context.command-pkbccyys.js → context.command-q8r0tge3.js} +13 -13
  13. package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
  14. package/{getDirname-m9s0cmhq.js → getDirname-ka11hm7e.js} +1 -1
  15. package/{guideline.command-0jj2k77g.js → guideline.command-pye36g73.js} +3 -3
  16. package/guidelines/conventions/conventions.instruction.md +122 -43
  17. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +1 -3
  18. package/incrementalBuilder.proc.js +3 -3
  19. package/{index-xwfkgss0.js → index-33zce8gt.js} +8 -4
  20. package/{index-w7farjxd.js → index-3dp7x6rc.js} +3 -3
  21. package/{index-p42te6qb.js → index-73rnbwgg.js} +14 -6
  22. package/{index-1twehz1x.js → index-8vkkm7v0.js} +8 -18
  23. package/{index-g3brq942.js → index-9djnsdgf.js} +5 -5
  24. package/{index-b9m84bjp.js → index-d4d3q2r8.js} +10 -10
  25. package/{index-96vpa123.js → index-fb2wa7j3.js} +3 -3
  26. package/{index-djh5gpb7.js → index-g9e2fhw2.js} +2 -2
  27. package/{index-4v0wvt37.js → index-hxp90q94.js} +4 -4
  28. package/{index-7ecpft60.js → index-k6fvbcj1.js} +3 -3
  29. package/{index-aak9cctp.js → index-myy6xy5w.js} +4 -4
  30. package/{index-gz91pc3p.js → index-mz5jtaq7.js} +1 -1
  31. package/{index-bkwnr08k.js → index-n706txcv.js} +2 -2
  32. package/{index-gyvrhtpm.js → index-qc0tnhs2.js} +1 -1
  33. package/{index-j9cxndc0.js → index-qyffprfs.js} +7 -5
  34. package/{index-8d9r0df5.js → index-sn71brf9.js} +2 -2
  35. package/{index-9s991k9v.js → index-tsmjxph2.js} +1 -1
  36. package/{index-2m11t9ek.js → index-v5vmgh0z.js} +3 -208
  37. package/{index-rv16ck4r.js → index-x2w0y8sz.js} +8 -8
  38. package/{index-4agbdds8.js → index-xyrb7pk5.js} +3 -3
  39. package/index.js +19 -19
  40. package/{library.command-wbptp6q3.js → library.command-v5cyaw9t.js} +4 -4
  41. package/{localRegistry.command-6ea3pgq0.js → localRegistry.command-tqnh5g77.js} +7 -7
  42. package/{module.command-ghkf919z.js → module.command-wxsvyadc.js} +6 -6
  43. package/{package.command-ph2m34tv.js → package.command-qkcs60ts.js} +4 -4
  44. package/package.json +3 -4
  45. package/{page.command-atnzfn88.js → page.command-qj5bfnh9.js} +4 -4
  46. package/{primitive.command-7qbdhfc2.js → primitive.command-c5jtk3e9.js} +7 -7
  47. package/{quality.command-1ff2xcra.js → quality.command-f8drhx6c.js} +91 -362
  48. package/{recipeScanner-tghkzrrt.js → recipeScanner-zrzev25x.js} +3 -3
  49. package/{repair.command-weakn0yr.js → repair.command-mzwtejpk.js} +6 -6
  50. package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-7fycdqyv.js} +1 -1
  51. package/{scalar.command-xdjhvsgb.js → scalar.command-0yvwfv8m.js} +5 -5
  52. package/templates/appSample/srvkit/AuthGuard.ts +2 -2
  53. package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
  54. package/typecheck.proc.js +1 -1
  55. package/{workflow.command-msm2tjee.js → workflow.command-ak6at7nz.js} +10 -10
  56. package/{workspace.command-gr8z82z9.js → workspace.command-9ncr56g4.js} +19 -20
  57. /package/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
@@ -7,176 +7,26 @@ import {
7
7
  command,
8
8
  runner,
9
9
  script
10
- } from "./index-bkwnr08k.js";
10
+ } from "./index-n706txcv.js";
11
11
  import {
12
12
  appRootAllowedFiles,
13
13
  libFacetRootAllowedFiles
14
- } from "./index-1twehz1x.js";
14
+ } from "./index-8vkkm7v0.js";
15
15
  import"./index-mxvakhsm.js";
16
16
  import"./index-1577bej2.js";
17
17
  import"./index-67546d0j.js";
18
- import"./index-r24hmh0q.js";
18
+ import"./index-yb2wsc7f.js";
19
19
 
20
20
  // pkgs/@akanjs/devkit/qualityScanner.ts
21
21
  import { createHash } from "crypto";
22
22
  import { readdir, readFile, stat } from "fs/promises";
23
- import path3 from "path";
23
+ import path from "path";
24
24
  import { RESERVED_ROUTE_CONFIG_EXPORTS } from "akanjs/common";
25
25
  import ignore from "ignore";
26
- import ts4 from "typescript";
27
-
28
- // pkgs/@akanjs/devkit/mcpScanner.ts
29
- import path from "path";
30
- import ts from "typescript";
31
-
32
- class McpScanner {
33
- scan(sourceFiles) {
34
- const dictionaries = new Map(sourceFiles.filter((sourceFile) => sourceFile.file.endsWith(".dictionary.ts")).map((sourceFile) => [path.dirname(sourceFile.file), sourceFile]));
35
- return sourceFiles.filter((sourceFile) => sourceFile.file.endsWith(".signal.ts")).flatMap((sourceFile) => this.#scanSignal(sourceFile, dictionaries.get(path.dirname(sourceFile.file))));
36
- }
37
- #scanSignal(signal, dictionary) {
38
- const exposed = McpScanner.#exposedDeclarations(signal);
39
- if (!exposed.length)
40
- return [];
41
- const refName = path.basename(signal.file, ".signal.ts").replace(/^_+/, "");
42
- const described = dictionary ? McpScanner.#describedEntries(dictionary) : new Map;
43
- return [
44
- ...exposed.filter(({ name, kind }) => !McpScanner.#isDescribed(described, refName, name, kind)).map(({ name, kind, line }) => ({
45
- rule: "akan.mcp.missing-description",
46
- scope: "mcp",
47
- severity: "warning",
48
- file: signal.file,
49
- line,
50
- message: `MCP-exposed ${kind} "${name}" has no dictionary .desc(); an agent sees its name and nothing else.`
51
- })),
52
- ...exposed.filter(({ guards }) => guards === "missing").map(({ name, kind, line }) => ({
53
- rule: "akan.mcp.unguarded-exposure",
54
- scope: "mcp",
55
- severity: "warning",
56
- file: signal.file,
57
- line,
58
- message: `MCP-exposed ${kind} "${name}" declares no guards; a slice's guards map never reaches a named slice.`
59
- }))
60
- ];
61
- }
62
- static #isDescribed(described, refName, name, kind) {
63
- if (described.get(kind)?.has(name))
64
- return true;
65
- return kind === "slice" && !!described.get("endpoint")?.has(`${refName}List${McpScanner.#capitalize(name)}`);
66
- }
67
- static #exposedDeclarations(signal) {
68
- const found = [];
69
- const visit = (node) => {
70
- if (McpScanner.#isExposeOption(node)) {
71
- const declaration = McpScanner.#enclosingDeclaration(node, signal.sourceFile);
72
- if (declaration)
73
- found.push(declaration);
74
- }
75
- ts.forEachChild(node, visit);
76
- };
77
- visit(signal.sourceFile);
78
- return found;
79
- }
80
- static #isExposeOption(node) {
81
- if (!ts.isPropertyAssignment(node) || McpScanner.#propertyName(node) !== "mcp")
82
- return false;
83
- if (!ts.isObjectLiteralExpression(node.initializer))
84
- return false;
85
- return node.initializer.properties.some((property) => ts.isPropertyAssignment(property) && McpScanner.#propertyName(property) === "expose" && property.initializer.kind === ts.SyntaxKind.TrueKeyword);
86
- }
87
- static #enclosingDeclaration(option, sourceFile) {
88
- let declaration = null;
89
- for (let node = option.parent;node; node = node.parent) {
90
- if (!declaration && ts.isPropertyAssignment(node)) {
91
- declaration = node;
92
- continue;
93
- }
94
- const kind = McpScanner.#factoryKind(node);
95
- if (!kind || !declaration)
96
- continue;
97
- const name = McpScanner.#propertyName(declaration);
98
- if (!name)
99
- return null;
100
- const line = sourceFile.getLineAndCharacterOfPosition(declaration.getStart(sourceFile)).line + 1;
101
- return { name, kind, line, guards: McpScanner.#guardState(option) };
102
- }
103
- return null;
104
- }
105
- static #guardState(option) {
106
- const options = option.parent;
107
- if (!ts.isObjectLiteralExpression(options))
108
- return "unknown";
109
- if (options.properties.some((property) => ts.isSpreadAssignment(property)))
110
- return "unknown";
111
- return options.properties.some((property) => ts.isPropertyAssignment(property) && McpScanner.#propertyName(property) === "guards") ? "declared" : "missing";
112
- }
113
- static #factoryKind(node) {
114
- if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression))
115
- return null;
116
- const factory = node.expression.text;
117
- return factory === "slice" || factory === "endpoint" ? factory : null;
118
- }
119
- static #describedEntries(dictionary) {
120
- const described = new Map;
121
- const visit = (node) => {
122
- const stage = McpScanner.#dictionaryStage(node);
123
- if (stage) {
124
- for (const [name, chain] of McpScanner.#stageEntries(node)) {
125
- if (!chain.has("desc"))
126
- continue;
127
- const names = described.get(stage) ?? new Set;
128
- names.add(name);
129
- described.set(stage, names);
130
- }
131
- }
132
- ts.forEachChild(node, visit);
133
- };
134
- visit(dictionary.sourceFile);
135
- return described;
136
- }
137
- static #dictionaryStage(node) {
138
- if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression))
139
- return null;
140
- const stage = node.expression.name.text;
141
- return stage === "endpoint" || stage === "slice" ? stage : null;
142
- }
143
- static #stageEntries(stage) {
144
- const callback = stage.arguments[0];
145
- if (!callback || !ts.isArrowFunction(callback))
146
- return [];
147
- const body = ts.isParenthesizedExpression(callback.body) ? callback.body.expression : callback.body;
148
- if (!ts.isObjectLiteralExpression(body))
149
- return [];
150
- return body.properties.flatMap((property) => {
151
- if (!ts.isPropertyAssignment(property))
152
- return [];
153
- const name = McpScanner.#propertyName(property);
154
- return name ? [[name, McpScanner.#chainCalls(property.initializer)]] : [];
155
- });
156
- }
157
- static #chainCalls(expression) {
158
- const calls = new Set;
159
- let current = expression;
160
- while (ts.isCallExpression(current) || ts.isPropertyAccessExpression(current)) {
161
- if (ts.isPropertyAccessExpression(current))
162
- calls.add(current.name.text);
163
- current = current.expression;
164
- }
165
- return calls;
166
- }
167
- static #propertyName(property) {
168
- const { name } = property;
169
- if (ts.isIdentifier(name) || ts.isStringLiteral(name))
170
- return name.text;
171
- return null;
172
- }
173
- static #capitalize(value) {
174
- return value.charAt(0).toUpperCase() + value.slice(1);
175
- }
176
- }
26
+ import ts2 from "typescript";
177
27
 
178
28
  // pkgs/@akanjs/devkit/ssrScanner.ts
179
- import ts2 from "typescript";
29
+ import ts from "typescript";
180
30
  var STATIC_COMPONENT_MIN_MASS = 4;
181
31
  var MIXED_COMPONENT_MIN_MASS = 10;
182
32
  var MIXED_COMPONENT_MAX_TOUCHES = 2;
@@ -294,31 +144,31 @@ class SsrScanner {
294
144
  });
295
145
  }
296
146
  }
297
- ts2.forEachChild(node, visit);
147
+ ts.forEachChild(node, visit);
298
148
  };
299
- ts2.forEachChild(sourceFile.sourceFile, visit);
149
+ ts.forEachChild(sourceFile.sourceFile, visit);
300
150
  return warnings;
301
151
  }
302
152
  #isMountEffect(sourceFile, node) {
303
- if (!ts2.isCallExpression(node))
153
+ if (!ts.isCallExpression(node))
304
154
  return false;
305
155
  const callee = node.expression.getText(sourceFile);
306
156
  if (callee !== "useEffect" && callee !== "useLayoutEffect")
307
157
  return false;
308
158
  const deps = node.arguments[1];
309
- return !!deps && ts2.isArrayLiteralExpression(deps) && deps.elements.length === 0;
159
+ return !!deps && ts.isArrayLiteralExpression(deps) && deps.elements.length === 0;
310
160
  }
311
161
  #getLoadCalls(sourceFile, node) {
312
162
  const calls = [];
313
163
  const visit = (child) => {
314
- if (ts2.isCallExpression(child)) {
164
+ if (ts.isCallExpression(child)) {
315
165
  const callee = child.expression.getText(sourceFile);
316
166
  if (/^fetch\.[a-z]/.test(callee) || /^st\.do\.(init|get|view|load|list|count|insight)[A-Z]/.test(callee))
317
167
  calls.push({ callee, node: child });
318
168
  }
319
- ts2.forEachChild(child, visit);
169
+ ts.forEachChild(child, visit);
320
170
  };
321
- ts2.forEachChild(node, visit);
171
+ ts.forEachChild(node, visit);
322
172
  return calls;
323
173
  }
324
174
  #getTemplateStateWarnings(sourceFile) {
@@ -326,7 +176,7 @@ class SsrScanner {
326
176
  return [];
327
177
  const warnings = [];
328
178
  const visit = (node) => {
329
- if (ts2.isCallExpression(node) && node.expression.getText(sourceFile.sourceFile) === "useState") {
179
+ if (ts.isCallExpression(node) && node.expression.getText(sourceFile.sourceFile) === "useState") {
330
180
  warnings.push({
331
181
  rule: "akan.ssr.template-client-state",
332
182
  scope: "ssr",
@@ -336,9 +186,9 @@ class SsrScanner {
336
186
  message: "Template holds form state in useState. Templates are store-driven and carry no local state."
337
187
  });
338
188
  }
339
- ts2.forEachChild(node, visit);
189
+ ts.forEachChild(node, visit);
340
190
  };
341
- ts2.forEachChild(sourceFile.sourceFile, visit);
191
+ ts.forEachChild(sourceFile.sourceFile, visit);
342
192
  return warnings;
343
193
  }
344
194
  #measureBalance(sourceFiles) {
@@ -379,14 +229,14 @@ class SsrScanner {
379
229
  return components;
380
230
  }
381
231
  #getComponentNodes(statement) {
382
- if (ts2.isFunctionDeclaration(statement) && statement.body)
232
+ if (ts.isFunctionDeclaration(statement) && statement.body)
383
233
  return [{ name: statement.name?.text ?? "default", node: statement.body }];
384
- if (!ts2.isVariableStatement(statement))
234
+ if (!ts.isVariableStatement(statement))
385
235
  return [];
386
236
  return statement.declarationList.declarations.flatMap((declaration) => {
387
- if (!ts2.isIdentifier(declaration.name) || !declaration.initializer)
237
+ if (!ts.isIdentifier(declaration.name) || !declaration.initializer)
388
238
  return [];
389
- if (!ts2.isArrowFunction(declaration.initializer) && !ts2.isFunctionExpression(declaration.initializer))
239
+ if (!ts.isArrowFunction(declaration.initializer) && !ts.isFunctionExpression(declaration.initializer))
390
240
  return [];
391
241
  return [{ name: declaration.name.text, node: declaration.initializer }];
392
242
  });
@@ -394,7 +244,7 @@ class SsrScanner {
394
244
  #getTouches(sourceFile, node) {
395
245
  const touches = [];
396
246
  const visit = (child) => {
397
- if (ts2.isCallExpression(child)) {
247
+ if (ts.isCallExpression(child)) {
398
248
  const callee = child.expression.getText(sourceFile);
399
249
  const bareName = callee.split(".").pop() ?? callee;
400
250
  if (callee === "createContext" || callee === "lazy")
@@ -402,60 +252,60 @@ class SsrScanner {
402
252
  else if (/^use[A-Z]/.test(bareName) && !SsrScanner.#serverSafeCalls.has(bareName))
403
253
  touches.push(bareName);
404
254
  }
405
- if (ts2.isJsxAttribute(child) && /^on[A-Z]/.test(child.name.getText(sourceFile)))
255
+ if (ts.isJsxAttribute(child) && /^on[A-Z]/.test(child.name.getText(sourceFile)))
406
256
  touches.push(child.name.getText(sourceFile));
407
- if (ts2.isPropertyAccessExpression(child)) {
257
+ if (ts.isPropertyAccessExpression(child)) {
408
258
  const root = getAccessRoot(child);
409
259
  if (root === "st")
410
260
  touches.push("st");
411
261
  else if (SsrScanner.#clientGlobals.has(root))
412
262
  touches.push(root);
413
263
  }
414
- ts2.forEachChild(child, visit);
264
+ ts.forEachChild(child, visit);
415
265
  };
416
- ts2.forEachChild(node, visit);
266
+ ts.forEachChild(node, visit);
417
267
  return touches;
418
268
  }
419
269
  #getTagNames(sourceFile, node) {
420
270
  const tags = new Set;
421
271
  const visit = (child) => {
422
- if (ts2.isJsxOpeningElement(child) || ts2.isJsxSelfClosingElement(child))
272
+ if (ts.isJsxOpeningElement(child) || ts.isJsxSelfClosingElement(child))
423
273
  tags.add(child.tagName.getText(sourceFile).split(".")[0]);
424
- ts2.forEachChild(child, visit);
274
+ ts.forEachChild(child, visit);
425
275
  };
426
- ts2.forEachChild(node, visit);
276
+ ts.forEachChild(node, visit);
427
277
  return tags;
428
278
  }
429
279
  #getMass(node) {
430
280
  let mass = 0;
431
281
  const visit = (child) => {
432
- if (ts2.isJsxOpeningElement(child) || ts2.isJsxSelfClosingElement(child))
282
+ if (ts.isJsxOpeningElement(child) || ts.isJsxSelfClosingElement(child))
433
283
  mass += 1;
434
- ts2.forEachChild(child, visit);
284
+ ts.forEachChild(child, visit);
435
285
  };
436
- ts2.forEachChild(node, visit);
286
+ ts.forEachChild(node, visit);
437
287
  return mass;
438
288
  }
439
289
  #hasUseClient(sourceFile) {
440
290
  const first = sourceFile.statements[0];
441
- if (!first || !ts2.isExpressionStatement(first) || !ts2.isStringLiteral(first.expression))
291
+ if (!first || !ts.isExpressionStatement(first) || !ts.isStringLiteral(first.expression))
442
292
  return false;
443
293
  return first.expression.text === "use client";
444
294
  }
445
295
  #hasVendorImport(sourceFile) {
446
- return sourceFile.statements.some((statement) => ts2.isImportDeclaration(statement) && isVendorSpecifier(getSpecifier(statement)));
296
+ return sourceFile.statements.some((statement) => ts.isImportDeclaration(statement) && isVendorSpecifier(getSpecifier(statement)));
447
297
  }
448
298
  #getVendorNames(sourceFile) {
449
299
  const names = new Set;
450
300
  for (const statement of sourceFile.statements) {
451
- if (!ts2.isImportDeclaration(statement) || !isVendorSpecifier(getSpecifier(statement)))
301
+ if (!ts.isImportDeclaration(statement) || !isVendorSpecifier(getSpecifier(statement)))
452
302
  continue;
453
303
  const clause = statement.importClause;
454
304
  if (clause?.name)
455
305
  names.add(clause.name.text);
456
- if (clause?.namedBindings && ts2.isNamespaceImport(clause.namedBindings))
306
+ if (clause?.namedBindings && ts.isNamespaceImport(clause.namedBindings))
457
307
  names.add(clause.namedBindings.name.text);
458
- if (clause?.namedBindings && ts2.isNamedImports(clause.namedBindings))
308
+ if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings))
459
309
  for (const element of clause.namedBindings.elements)
460
310
  names.add(element.name.text);
461
311
  }
@@ -463,10 +313,10 @@ class SsrScanner {
463
313
  }
464
314
  #importsClientRuntime(sourceFile) {
465
315
  for (const statement of sourceFile.statements) {
466
- if (!ts2.isImportDeclaration(statement))
316
+ if (!ts.isImportDeclaration(statement))
467
317
  continue;
468
318
  const bindings = statement.importClause?.namedBindings;
469
- if (!bindings || !ts2.isNamedImports(bindings))
319
+ if (!bindings || !ts.isNamedImports(bindings))
470
320
  continue;
471
321
  if (bindings.elements.some((element) => SsrScanner.#clientRuntimeImports.has(element.name.text)))
472
322
  return true;
@@ -517,7 +367,7 @@ function getShare(serverMass, clientMass) {
517
367
  return total === 0 ? 1 : serverMass / total;
518
368
  }
519
369
  function getSpecifier(statement) {
520
- return ts2.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : "";
370
+ return ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : "";
521
371
  }
522
372
  function isVendorSpecifier(specifier) {
523
373
  if (specifier === "" || specifier.startsWith(".") || specifier.startsWith("/"))
@@ -530,125 +380,9 @@ function isVendorSpecifier(specifier) {
530
380
  }
531
381
  function getAccessRoot(node) {
532
382
  let current = node;
533
- while (ts2.isPropertyAccessExpression(current))
383
+ while (ts.isPropertyAccessExpression(current))
534
384
  current = current.expression;
535
- return ts2.isIdentifier(current) ? current.text : "";
536
- }
537
-
538
- // pkgs/@akanjs/devkit/storeScanner.ts
539
- import path2 from "path";
540
- import ts3 from "typescript";
541
-
542
- class StoreScanner {
543
- scan(sourceFiles) {
544
- const dictionaries = new Map(sourceFiles.filter((sourceFile) => sourceFile.file.endsWith(".dictionary.ts")).map((sourceFile) => [path2.dirname(sourceFile.file), sourceFile]));
545
- return sourceFiles.filter((sourceFile) => sourceFile.file.endsWith(".store.ts")).flatMap((sourceFile) => this.#scanStore(sourceFile, dictionaries.get(path2.dirname(sourceFile.file))));
546
- }
547
- #scanStore(store, dictionary) {
548
- const actions = StoreScanner.#customActions(store);
549
- if (!actions.length)
550
- return [];
551
- const described = dictionary ? StoreScanner.#describedEntries(dictionary) : new Map;
552
- return actions.filter(({ name, fetched }) => fetched.length && !fetched.includes(name)).filter(({ name }) => !described.get("store")?.has(name) && !described.get("endpoint")?.has(name)).map(({ name, line, fetched }) => ({
553
- rule: "akan.agent.missing-store-description",
554
- scope: "agent",
555
- severity: "warning",
556
- file: store.file,
557
- line,
558
- message: `Store action "${name}" calls ${fetched.map((key) => `${key}()`).join(", ")} under a different name and has no dictionary .store() entry, so an agent reading it has the name and nothing else.`
559
- }));
560
- }
561
- static #customActions(store) {
562
- const actions = [];
563
- const visit = (node) => {
564
- if (ts3.isClassDeclaration(node) && StoreScanner.#extendsStore(node)) {
565
- for (const member of node.members) {
566
- if (!ts3.isMethodDeclaration(member))
567
- continue;
568
- if (member.modifiers?.some((modifier) => modifier.kind === ts3.SyntaxKind.StaticKeyword))
569
- continue;
570
- const name = StoreScanner.#memberName(member);
571
- if (!name)
572
- continue;
573
- const line = store.sourceFile.getLineAndCharacterOfPosition(member.getStart(store.sourceFile)).line + 1;
574
- actions.push({ name, line, fetched: StoreScanner.#fetchedEndpoints(member) });
575
- }
576
- }
577
- ts3.forEachChild(node, visit);
578
- };
579
- visit(store.sourceFile);
580
- return actions;
581
- }
582
- static #extendsStore(node) {
583
- return !!node.heritageClauses?.some((clause) => clause.types.some((type) => ts3.isCallExpression(type.expression) && StoreScanner.#isStoreCall(type.expression)));
584
- }
585
- static #isStoreCall(expression) {
586
- return ts3.isIdentifier(expression.expression) && expression.expression.text === "store";
587
- }
588
- static #fetchedEndpoints(member) {
589
- const fetched = new Set;
590
- const visit = (node) => {
591
- if (ts3.isCallExpression(node) && ts3.isPropertyAccessExpression(node.expression) && ts3.isIdentifier(node.expression.expression) && node.expression.expression.text === "fetch")
592
- fetched.add(node.expression.name.text);
593
- ts3.forEachChild(node, visit);
594
- };
595
- visit(member);
596
- return [...fetched];
597
- }
598
- static #describedEntries(dictionary) {
599
- const described = new Map;
600
- const visit = (node) => {
601
- const stage = StoreScanner.#dictionaryStage(node);
602
- if (stage) {
603
- for (const [name, chain] of StoreScanner.#stageEntries(node)) {
604
- if (!chain.has("desc"))
605
- continue;
606
- const names = described.get(stage) ?? new Set;
607
- names.add(name);
608
- described.set(stage, names);
609
- }
610
- }
611
- ts3.forEachChild(node, visit);
612
- };
613
- visit(dictionary.sourceFile);
614
- return described;
615
- }
616
- static #dictionaryStage(node) {
617
- if (!ts3.isCallExpression(node) || !ts3.isPropertyAccessExpression(node.expression))
618
- return null;
619
- const stage = node.expression.name.text;
620
- return stage === "store" || stage === "endpoint" ? stage : null;
621
- }
622
- static #stageEntries(stage) {
623
- const callback = stage.arguments[0];
624
- if (!callback || !ts3.isArrowFunction(callback))
625
- return [];
626
- const body = ts3.isParenthesizedExpression(callback.body) ? callback.body.expression : callback.body;
627
- if (!ts3.isObjectLiteralExpression(body))
628
- return [];
629
- return body.properties.flatMap((property) => {
630
- if (!ts3.isPropertyAssignment(property))
631
- return [];
632
- const name = StoreScanner.#memberName(property);
633
- return name ? [[name, StoreScanner.#chainCalls(property.initializer)]] : [];
634
- });
635
- }
636
- static #chainCalls(expression) {
637
- const calls = new Set;
638
- let current = expression;
639
- while (ts3.isCallExpression(current) || ts3.isPropertyAccessExpression(current)) {
640
- if (ts3.isPropertyAccessExpression(current))
641
- calls.add(current.name.text);
642
- current = current.expression;
643
- }
644
- return calls;
645
- }
646
- static #memberName(member) {
647
- const { name } = member;
648
- if (!name || !ts3.isIdentifier(name) && !ts3.isStringLiteral(name))
649
- return null;
650
- return name.text;
651
- }
385
+ return ts.isIdentifier(current) ? current.text : "";
652
386
  }
653
387
 
654
388
  // pkgs/@akanjs/devkit/qualityScanner.ts
@@ -705,10 +439,7 @@ var RULE_FIXES = {
705
439
  "akan.ssr.client-static-markup": "Keep the interactive element in the client component and hoist the static subtree into a server component, then accept it as `children` or render it through a Unit/View reference.",
706
440
  "akan.ssr.client-mount-load": "Load the data in the route with `fetch.initX(...)` / `fetch.viewX(...)` and pass the init/view object down as a prop; the client store hydrates from it and the effect goes away.",
707
441
  "akan.ssr.module-missing-server-view": "Add a <Model>.Unit.tsx for list/card rendering and a <Model>.View.tsx for the detail surface, then have the Zone delegate to them.",
708
- "akan.ssr.template-client-state": "Bind the field to the store instead: `value={xForm.field}` with `onChange={st.do.setFieldOnX}`.",
709
- "akan.mcp.missing-description": "Add `.desc([en, ko])` to this entry in the module's dictionary \u2014 for a slice, either on the slice entry or on the `<model>List<Slice>` endpoint it generates. Describe when to reach for it, not what it is named.",
710
- "akan.agent.missing-store-description": "Add the action to the module dictionary's `.store()` stage with a `.desc([en, ko])` saying what it does for the user \u2014 not what the endpoint it calls does. That stage is optional everywhere else: an action named after its endpoint already reads as that endpoint's description.",
711
- "akan.mcp.unguarded-exposure": "Name the guards in the same option object as `mcp`: `init({ guards: [SignedIn], mcp: { expose: true } })`. Write `guards: [Public]` if anonymous reads are the intent \u2014 the access is the same, but only one of the two is a decision. The `slice()` call's guards map reaches the root slice and base CRUD, never a named slice."
442
+ "akan.ssr.template-client-state": "Bind the field to the store instead: `value={xForm.field}` with `onChange={st.do.setFieldOnX}`."
712
443
  };
713
444
  function getRuleFix(rule) {
714
445
  if (rule.startsWith("akan.convention"))
@@ -729,9 +460,7 @@ class AkanQualityScanner {
729
460
  ...sourceFiles.flatMap((sourceFile) => this.#scanConventionQuality(sourceFile)),
730
461
  ...sourceFiles.flatMap((sourceFile) => this.#scanLayoutQuality(sourceFile)),
731
462
  ...abstractFiles.flatMap((abstractFile) => this.#scanAbstractQuality(abstractFile)),
732
- ...ssr.warnings,
733
- ...new McpScanner().scan(sourceFiles),
734
- ...new StoreScanner().scan(sourceFiles)
463
+ ...ssr.warnings
735
464
  ];
736
465
  return {
737
466
  workspaceRoot,
@@ -745,7 +474,7 @@ class AkanQualityScanner {
745
474
  const ignoreFilter = ignore().add(await this.#readGitIgnore(workspaceRoot));
746
475
  const files = [];
747
476
  for (const targetRoot of ["apps", "libs"]) {
748
- const absoluteTargetRoot = path3.join(workspaceRoot, targetRoot);
477
+ const absoluteTargetRoot = path.join(workspaceRoot, targetRoot);
749
478
  if (!await isDirectory(absoluteTargetRoot))
750
479
  continue;
751
480
  await this.#walkTargetFiles(workspaceRoot, absoluteTargetRoot, ignoreFilter, files);
@@ -753,7 +482,7 @@ class AkanQualityScanner {
753
482
  return files.sort();
754
483
  }
755
484
  async#readGitIgnore(workspaceRoot) {
756
- const gitIgnorePath = path3.join(workspaceRoot, ".gitignore");
485
+ const gitIgnorePath = path.join(workspaceRoot, ".gitignore");
757
486
  if (!await Bun.file(gitIgnorePath).exists())
758
487
  return [];
759
488
  return (await readFile(gitIgnorePath, "utf8")).split(/\r?\n/);
@@ -761,8 +490,8 @@ class AkanQualityScanner {
761
490
  async#walkTargetFiles(workspaceRoot, currentPath, ignoreFilter, files) {
762
491
  const entries = await readdir(currentPath, { withFileTypes: true });
763
492
  for (const entry of entries) {
764
- const absolutePath = path3.join(currentPath, entry.name);
765
- const relativePath = toPosix(path3.relative(workspaceRoot, absolutePath));
493
+ const absolutePath = path.join(currentPath, entry.name);
494
+ const relativePath = toPosix(path.relative(workspaceRoot, absolutePath));
766
495
  if (shouldSkipPath(relativePath, entry.isDirectory(), ignoreFilter))
767
496
  continue;
768
497
  if (entry.isDirectory()) {
@@ -777,17 +506,17 @@ class AkanQualityScanner {
777
506
  }
778
507
  }
779
508
  async#readSourceFile(workspaceRoot, file) {
780
- const absolutePath = path3.join(workspaceRoot, file);
509
+ const absolutePath = path.join(workspaceRoot, file);
781
510
  const content = await readFile(absolutePath, "utf8");
782
511
  return {
783
512
  file,
784
513
  absolutePath,
785
514
  content,
786
- sourceFile: ts4.createSourceFile(file, content, ts4.ScriptTarget.Latest, true, getScriptKind(file))
515
+ sourceFile: ts2.createSourceFile(file, content, ts2.ScriptTarget.Latest, true, getScriptKind(file))
787
516
  };
788
517
  }
789
518
  async#readTextFile(workspaceRoot, file) {
790
- return { file, content: await readFile(path3.join(workspaceRoot, file), "utf8") };
519
+ return { file, content: await readFile(path.join(workspaceRoot, file), "utf8") };
791
520
  }
792
521
  #scanGlobalQuality(sourceFiles) {
793
522
  const exportedFunctionLikes = sourceFiles.flatMap((sourceFile) => getExportedFunctionLikes(sourceFile));
@@ -911,7 +640,7 @@ class AkanQualityScanner {
911
640
  const suffix = CONVENTION_SUFFIXES.find((candidate) => sourceFile.file.endsWith(candidate));
912
641
  if (!suffix)
913
642
  return [];
914
- const modelName = toPascalCase(path3.basename(sourceFile.file, suffix));
643
+ const modelName = toPascalCase(path.basename(sourceFile.file, suffix));
915
644
  const warnings = [];
916
645
  for (const declaration of getTopLevelDeclarations(sourceFile)) {
917
646
  if (isAllowedConventionDeclaration(suffix, modelName, declaration))
@@ -922,7 +651,7 @@ class AkanQualityScanner {
922
651
  severity: "warning",
923
652
  file: sourceFile.file,
924
653
  line: declaration.line,
925
- message: `${path3.basename(sourceFile.file)} should not declare top-level ${declaration.kind} "${declaration.name}". Allowed declarations: ${getConventionDescription(suffix, modelName)}.`
654
+ message: `${path.basename(sourceFile.file)} should not declare top-level ${declaration.kind} "${declaration.name}". Allowed declarations: ${getConventionDescription(suffix, modelName)}.`
926
655
  });
927
656
  }
928
657
  return warnings;
@@ -1030,7 +759,7 @@ function getExportedFunctionLikes(sourceFile) {
1030
759
  const declarations = [];
1031
760
  const nameExempt = isPageRouteFile(sourceFile.file) || isUiComponentFile(sourceFile.file);
1032
761
  for (const statement of sourceFile.sourceFile.statements) {
1033
- if (ts4.isFunctionDeclaration(statement) && statement.name && isExported(statement)) {
762
+ if (ts2.isFunctionDeclaration(statement) && statement.name && isExported(statement)) {
1034
763
  declarations.push({
1035
764
  name: statement.name.text,
1036
765
  kind: "function",
@@ -1040,7 +769,7 @@ function getExportedFunctionLikes(sourceFile) {
1040
769
  duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile.file, false)
1041
770
  });
1042
771
  }
1043
- if (ts4.isClassDeclaration(statement) && statement.name && isExported(statement)) {
772
+ if (ts2.isClassDeclaration(statement) && statement.name && isExported(statement)) {
1044
773
  declarations.push({
1045
774
  name: statement.name.text,
1046
775
  kind: "class",
@@ -1050,9 +779,9 @@ function getExportedFunctionLikes(sourceFile) {
1050
779
  duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile.file, isEnumClassStatement(sourceFile.sourceFile, statement))
1051
780
  });
1052
781
  }
1053
- if (ts4.isVariableStatement(statement) && isExported(statement)) {
782
+ if (ts2.isVariableStatement(statement) && isExported(statement)) {
1054
783
  for (const declaration of statement.declarationList.declarations) {
1055
- if (!ts4.isIdentifier(declaration.name) || !isFunctionLikeInitializer(declaration.initializer))
784
+ if (!ts2.isIdentifier(declaration.name) || !isFunctionLikeInitializer(declaration.initializer))
1056
785
  continue;
1057
786
  declarations.push({
1058
787
  name: declaration.name.text,
@@ -1091,14 +820,14 @@ function isInLibModule(file) {
1091
820
  return (segments[0] === "apps" || segments[0] === "libs") && segments.includes("lib");
1092
821
  }
1093
822
  function isEnumClassStatement(sourceFile, statement) {
1094
- if (!ts4.isClassDeclaration(statement))
823
+ if (!ts2.isClassDeclaration(statement))
1095
824
  return false;
1096
- const heritageClause = statement.heritageClauses?.find((clause) => clause.token === ts4.SyntaxKind.ExtendsKeyword);
825
+ const heritageClause = statement.heritageClauses?.find((clause) => clause.token === ts2.SyntaxKind.ExtendsKeyword);
1097
826
  const expression = heritageClause?.types[0]?.expression;
1098
827
  return !!expression && expression.getText(sourceFile).startsWith("enumOf(");
1099
828
  }
1100
829
  function getExportedClassNames(sourceFile) {
1101
- return sourceFile.statements.filter((statement) => ts4.isClassDeclaration(statement) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
830
+ return sourceFile.statements.filter((statement) => ts2.isClassDeclaration(statement) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
1102
831
  }
1103
832
  function isComponentDeclarationFile(file) {
1104
833
  if (!file.endsWith(".tsx"))
@@ -1114,7 +843,7 @@ function isComponentDeclarationFile(file) {
1114
843
  function getComponentFileDeclarations(sourceFile) {
1115
844
  const reExportedNames = new Set;
1116
845
  for (const statement of sourceFile.statements) {
1117
- if (ts4.isExportDeclaration(statement) && statement.exportClause && ts4.isNamedExports(statement.exportClause)) {
846
+ if (ts2.isExportDeclaration(statement) && statement.exportClause && ts2.isNamedExports(statement.exportClause)) {
1118
847
  for (const element of statement.exportClause.elements)
1119
848
  reExportedNames.add((element.propertyName ?? element.name).text);
1120
849
  }
@@ -1124,19 +853,19 @@ function getComponentFileDeclarations(sourceFile) {
1124
853
  const isDefaultExport = isDefaultExportStatement(statement);
1125
854
  const inlineExported = isExported(statement);
1126
855
  const add = (name, kind, line) => declarations.push({ name, kind, line, exported: inlineExported || reExportedNames.has(name), isDefaultExport });
1127
- if (ts4.isInterfaceDeclaration(statement))
856
+ if (ts2.isInterfaceDeclaration(statement))
1128
857
  add(statement.name.text, "interface", getLine(sourceFile, statement));
1129
- else if (ts4.isTypeAliasDeclaration(statement))
858
+ else if (ts2.isTypeAliasDeclaration(statement))
1130
859
  add(statement.name.text, "type", getLine(sourceFile, statement));
1131
- else if (ts4.isEnumDeclaration(statement))
860
+ else if (ts2.isEnumDeclaration(statement))
1132
861
  add(statement.name.text, "enum", getLine(sourceFile, statement));
1133
- else if (ts4.isFunctionDeclaration(statement) && statement.name)
862
+ else if (ts2.isFunctionDeclaration(statement) && statement.name)
1134
863
  add(statement.name.text, "function", getLine(sourceFile, statement));
1135
- else if (ts4.isClassDeclaration(statement) && statement.name)
864
+ else if (ts2.isClassDeclaration(statement) && statement.name)
1136
865
  add(statement.name.text, "class", getLine(sourceFile, statement));
1137
- else if (ts4.isVariableStatement(statement)) {
866
+ else if (ts2.isVariableStatement(statement)) {
1138
867
  for (const declaration of statement.declarationList.declarations) {
1139
- if (!ts4.isIdentifier(declaration.name))
868
+ if (!ts2.isIdentifier(declaration.name))
1140
869
  continue;
1141
870
  const kind = isFunctionLikeInitializer(declaration.initializer) ? "function" : "variable";
1142
871
  add(declaration.name.text, kind, getLine(sourceFile, declaration));
@@ -1148,15 +877,15 @@ function getComponentFileDeclarations(sourceFile) {
1148
877
  function getCompoundComponentNames(sourceFile) {
1149
878
  const names = new Set;
1150
879
  for (const statement of sourceFile.statements) {
1151
- if (!ts4.isExpressionStatement(statement))
880
+ if (!ts2.isExpressionStatement(statement))
1152
881
  continue;
1153
882
  const { expression } = statement;
1154
- if (!ts4.isBinaryExpression(expression) || expression.operatorToken.kind !== ts4.SyntaxKind.EqualsToken)
883
+ if (!ts2.isBinaryExpression(expression) || expression.operatorToken.kind !== ts2.SyntaxKind.EqualsToken)
1155
884
  continue;
1156
- if (!ts4.isPropertyAccessExpression(expression.left) || !isPascalCaseName(expression.left.name.text))
885
+ if (!ts2.isPropertyAccessExpression(expression.left) || !isPascalCaseName(expression.left.name.text))
1157
886
  continue;
1158
887
  names.add(expression.left.name.text);
1159
- if (ts4.isIdentifier(expression.right) && isPascalCaseName(expression.right.text))
888
+ if (ts2.isIdentifier(expression.right) && isPascalCaseName(expression.right.text))
1160
889
  names.add(expression.right.text);
1161
890
  }
1162
891
  return names;
@@ -1176,9 +905,9 @@ function isPascalCaseName(name) {
1176
905
  return /^[A-Z]/.test(name) && !/^[A-Z0-9_]+$/.test(name);
1177
906
  }
1178
907
  function isDefaultExportStatement(statement) {
1179
- if (ts4.isExportAssignment(statement))
908
+ if (ts2.isExportAssignment(statement))
1180
909
  return !statement.isExportEquals;
1181
- return !!(ts4.getCombinedModifierFlags(statement) & ts4.ModifierFlags.Default);
910
+ return !!(ts2.getCombinedModifierFlags(statement) & ts2.ModifierFlags.Default);
1182
911
  }
1183
912
  function getPlaceholderExportWarnings(sourceFile) {
1184
913
  if (!sourceFile.file.endsWith("/index.ts") && !sourceFile.file.endsWith("/index.tsx"))
@@ -1208,7 +937,7 @@ function getDictionaryTextWarnings(sourceFile) {
1208
937
  function getGlobalMutationWarnings(sourceFile) {
1209
938
  const warnings = [];
1210
939
  for (const statement of sourceFile.sourceFile.statements) {
1211
- if (ts4.isModuleDeclaration(statement) && statement.name.getText(sourceFile.sourceFile) === "global") {
940
+ if (ts2.isModuleDeclaration(statement) && statement.name.getText(sourceFile.sourceFile) === "global") {
1212
941
  warnings.push({
1213
942
  rule: "akan.file.global-declaration",
1214
943
  scope: "file",
@@ -1218,7 +947,7 @@ function getGlobalMutationWarnings(sourceFile) {
1218
947
  message: "Global declarations require an explicit low-level integration allowlist."
1219
948
  });
1220
949
  }
1221
- if (ts4.isInterfaceDeclaration(statement) && statement.name.text === "Window") {
950
+ if (ts2.isInterfaceDeclaration(statement) && statement.name.text === "Window") {
1222
951
  warnings.push({
1223
952
  rule: "akan.file.window-augmentation",
1224
953
  scope: "file",
@@ -1228,7 +957,7 @@ function getGlobalMutationWarnings(sourceFile) {
1228
957
  message: "Window augmentation should be isolated to approved browser integration files."
1229
958
  });
1230
959
  }
1231
- if (ts4.isExpressionStatement(statement) && statement.expression.getText(sourceFile.sourceFile).includes(".prototype.")) {
960
+ if (ts2.isExpressionStatement(statement) && statement.expression.getText(sourceFile.sourceFile).includes(".prototype.")) {
1232
961
  warnings.push({
1233
962
  rule: "akan.file.prototype-mutation",
1234
963
  scope: "file",
@@ -1246,23 +975,23 @@ function getTopLevelDeclarations(sourceFile) {
1246
975
  }
1247
976
  function getTopLevelDeclaration(sourceFile, statement) {
1248
977
  const line = getLine(sourceFile, statement);
1249
- if (ts4.isClassDeclaration(statement) && statement.name) {
978
+ if (ts2.isClassDeclaration(statement) && statement.name) {
1250
979
  return [{ name: statement.name.text, kind: "class", line, exported: isExported(statement), node: statement }];
1251
980
  }
1252
- if (ts4.isFunctionDeclaration(statement) && statement.name) {
981
+ if (ts2.isFunctionDeclaration(statement) && statement.name) {
1253
982
  return [{ name: statement.name.text, kind: "function", line, exported: isExported(statement), node: statement }];
1254
983
  }
1255
- if (ts4.isInterfaceDeclaration(statement)) {
984
+ if (ts2.isInterfaceDeclaration(statement)) {
1256
985
  return [{ name: statement.name.text, kind: "interface", line, exported: isExported(statement), node: statement }];
1257
986
  }
1258
- if (ts4.isTypeAliasDeclaration(statement)) {
987
+ if (ts2.isTypeAliasDeclaration(statement)) {
1259
988
  return [{ name: statement.name.text, kind: "type", line, exported: isExported(statement), node: statement }];
1260
989
  }
1261
- if (ts4.isEnumDeclaration(statement)) {
990
+ if (ts2.isEnumDeclaration(statement)) {
1262
991
  return [{ name: statement.name.text, kind: "enum", line, exported: isExported(statement), node: statement }];
1263
992
  }
1264
- if (ts4.isVariableStatement(statement)) {
1265
- return statement.declarationList.declarations.filter((declaration) => ts4.isIdentifier(declaration.name)).map((declaration) => ({
993
+ if (ts2.isVariableStatement(statement)) {
994
+ return statement.declarationList.declarations.filter((declaration) => ts2.isIdentifier(declaration.name)).map((declaration) => ({
1266
995
  name: declaration.name.text,
1267
996
  kind: "variable",
1268
997
  line: getLine(sourceFile, declaration),
@@ -1270,7 +999,7 @@ function getTopLevelDeclaration(sourceFile, statement) {
1270
999
  node: statement
1271
1000
  }));
1272
1001
  }
1273
- if (ts4.isExportDeclaration(statement)) {
1002
+ if (ts2.isExportDeclaration(statement)) {
1274
1003
  return [{ name: "export declaration", kind: "export", line, exported: true, node: statement }];
1275
1004
  }
1276
1005
  return [];
@@ -1295,9 +1024,9 @@ function isAllowedConstantDeclaration(modelName, declaration) {
1295
1024
  return false;
1296
1025
  if ([`${modelName}Input`, `${modelName}Object`, modelName, `Light${modelName}`, `${modelName}Insight`].includes(declaration.name))
1297
1026
  return true;
1298
- if (!ts4.isClassDeclaration(declaration.node))
1027
+ if (!ts2.isClassDeclaration(declaration.node))
1299
1028
  return false;
1300
- const heritageClause = declaration.node.heritageClauses?.find((clause) => clause.token === ts4.SyntaxKind.ExtendsKeyword);
1029
+ const heritageClause = declaration.node.heritageClauses?.find((clause) => clause.token === ts2.SyntaxKind.ExtendsKeyword);
1301
1030
  const expression = heritageClause?.types[0]?.expression;
1302
1031
  return !!expression && expression.getText().startsWith("enumOf(");
1303
1032
  }
@@ -1363,13 +1092,13 @@ function getModuleInfo(file) {
1363
1092
  return { moduleName, fileName, kind: "database" };
1364
1093
  }
1365
1094
  function isExportedConst(declaration) {
1366
- return declaration.exported && ts4.isVariableStatement(declaration.node) && (declaration.node.declarationList.flags & ts4.NodeFlags.Const) !== 0;
1095
+ return declaration.exported && ts2.isVariableStatement(declaration.node) && (declaration.node.declarationList.flags & ts2.NodeFlags.Const) !== 0;
1367
1096
  }
1368
1097
  function isExported(node) {
1369
- return !!ts4.getCombinedModifierFlags(node) && !!(ts4.getCombinedModifierFlags(node) & ts4.ModifierFlags.Export);
1098
+ return !!ts2.getCombinedModifierFlags(node) && !!(ts2.getCombinedModifierFlags(node) & ts2.ModifierFlags.Export);
1370
1099
  }
1371
1100
  function isFunctionLikeInitializer(node) {
1372
- return !!node && (ts4.isArrowFunction(node) || ts4.isFunctionExpression(node));
1101
+ return !!node && (ts2.isArrowFunction(node) || ts2.isFunctionExpression(node));
1373
1102
  }
1374
1103
  function getBodyFingerprint(sourceFile, node) {
1375
1104
  if (!node)
@@ -1391,7 +1120,7 @@ async function isDirectory(absolutePath) {
1391
1120
  }
1392
1121
  }
1393
1122
  function getScriptKind(file) {
1394
- return file.endsWith(".tsx") ? ts4.ScriptKind.TSX : ts4.ScriptKind.TS;
1123
+ return file.endsWith(".tsx") ? ts2.ScriptKind.TSX : ts2.ScriptKind.TS;
1395
1124
  }
1396
1125
  function getLine(sourceFile, node) {
1397
1126
  return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
@@ -1412,7 +1141,7 @@ function toPascalCase(value) {
1412
1141
  return value.replace(/(^|[-_./])([a-zA-Z0-9])/g, (_, __, char) => char.toUpperCase()).replace(/[-_./]/g, "");
1413
1142
  }
1414
1143
  function toPosix(value) {
1415
- return value.split(path3.sep).join("/");
1144
+ return value.split(path.sep).join("/");
1416
1145
  }
1417
1146
  function groupBy(items, getKey) {
1418
1147
  const grouped = new Map;