@akanjs/cli 3.0.0-alpha.7 → 3.0.0-alpha.71
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/.build-stamp +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/{abstractCompactor-e5yq60qz.js → abstractCompactor-20e0cwbs.js} +2 -2
- package/{agent.command-pggr92jj.js → agent.command-xdvw642m.js} +9 -7
- package/{application.command-692yap1d.js → application.command-g3f7xj25.js} +31 -6
- package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-af0wtspv.js} +19 -14
- package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-93nzdfsy.js} +1 -1
- package/buildBatch.proc.js +7 -5
- package/{capacitorApp-p0z5yab2.js → capacitorApp-b0ppke3m.js} +29 -27
- package/{cloud.command-wqfsyzv2.js → cloud.command-0hmsv44q.js} +12 -10
- package/commandManifest.json +1 -1
- package/{context.command-9bxtdn0w.js → context.command-x92afrnf.js} +17 -15
- package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
- package/getDirname-ka11hm7e.js +8 -0
- package/{guideline.command-nfqahxex.js → guideline.command-hpq08q66.js} +8 -6
- package/guidelines/agentRule/agentRule.generate.json +31 -0
- package/guidelines/agentRule/agentRule.instruction.md +525 -0
- package/guidelines/conventions/conventions.generate.json +25 -0
- package/guidelines/conventions/conventions.instruction.md +839 -0
- package/guidelines/cssRule/cssRule.instruction.md +7 -0
- package/guidelines/framework/framework.generate.json +3 -2
- package/guidelines/framework/framework.instruction.md +1 -9
- package/guidelines/mcpRule/mcpRule.generate.json +25 -0
- package/guidelines/mcpRule/mcpRule.instruction.md +217 -0
- package/guidelines/queryRule/queryRule.generate.json +31 -0
- package/guidelines/queryRule/queryRule.instruction.md +143 -0
- package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
- package/guidelines/runtimeRule/runtimeRule.instruction.md +176 -0
- package/guidelines/transportRule/transportRule.generate.json +31 -0
- package/guidelines/transportRule/transportRule.instruction.md +60 -0
- package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +24 -0
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +263 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
- package/incrementalBuilder.proc.js +8 -6
- package/index-1577bej2.js +7 -0
- package/{index-vg0sj9nc.js → index-5f4gnt4c.js} +258 -97
- package/{index-bjpxzr6s.js → index-5vy2jzar.js} +1 -1
- package/{index-mssqn2sq.js → index-6d5r8q6k.js} +54 -15
- package/{index-p3f4q532.js → index-737aj4fm.js} +14 -13
- package/{index-2c3e2xh8.js → index-8besc14m.js} +1 -1
- package/{index-qb61h0k7.js → index-abyjt72y.js} +333 -540
- package/{index-xhgtkekh.js → index-cbfp5wyp.js} +1 -1
- package/{index-5dw57f0d.js → index-cp00yns2.js} +80 -14
- package/{index-ztpw544k.js → index-ety6takb.js} +3 -3
- package/index-f39512t6.js +255 -0
- package/{index-6rhabeev.js → index-gvq17wqn.js} +5 -3
- package/{index-js368gk9.js → index-hs70d8ed.js} +6 -6
- package/{index-7myvn0f0.js → index-j37qq1f2.js} +1 -1
- package/{index-azv0xjb5.js → index-jybbmwed.js} +8 -4
- package/{index-4hek879p.js → index-m5gfc86a.js} +1 -1
- package/{index-w6wbb612.js → index-nq3avsf6.js} +13 -13
- package/{index-vtj3zps1.js → index-p27h7535.js} +8 -8
- package/{index-5pmx7bkg.js → index-pehn44hr.js} +3 -3
- package/{index-j9cxndc0.js → index-qnv0aqmm.js} +9 -6
- package/{index-gmy45vz2.js → index-r691v756.js} +4 -4
- package/{index-0cj2zxbm.js → index-sh01r3pm.js} +1 -1
- package/{index-a1e0j63x.js → index-sqsfv8wg.js} +15 -7
- package/{index-gex7c8kd.js → index-wbbswwqt.js} +51 -24
- package/{index-bz2sfzzt.js → index-wybbcgxn.js} +4 -4
- package/index.js +21 -19
- package/{library.command-md9715jz.js → library.command-8vgrdtwy.js} +6 -4
- package/{localRegistry.command-exkbamyj.js → localRegistry.command-0gtqj0r0.js} +11 -9
- package/{module.command-w5aaddxk.js → module.command-rama4zya.js} +10 -8
- package/{package.command-yfkrcy0z.js → package.command-6jxapdsg.js} +6 -4
- package/package.json +4 -5
- package/{page.command-echbavp4.js → page.command-hxy7x525.js} +6 -4
- package/{primitive.command-9fbhspw2.js → primitive.command-4bf6xcc3.js} +11 -9
- package/{quality.command-3pnt9yep.js → quality.command-h5edwegz.js} +192 -97
- package/{recipeScanner-tghkzrrt.js → recipeScanner-zrzev25x.js} +3 -3
- package/{repair.command-carj4vax.js → repair.command-rgqf6px6.js} +8 -6
- package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-7fycdqyv.js} +1 -1
- package/{scalar.command-51ryzypc.js → scalar.command-6krkz6tw.js} +9 -7
- package/templates/app/env/env.client.debug.ts.template +1 -5
- package/templates/app/env/env.client.develop.ts.template +1 -5
- package/templates/app/env/env.client.local.ts.template +1 -5
- package/templates/app/env/env.client.main.ts.template +1 -5
- package/templates/app/env/env.client.testing.ts.template +1 -5
- package/templates/app/env/env.client.type.ts +2 -6
- package/templates/app/env/env.server.debug.ts.template +1 -5
- package/templates/app/env/env.server.develop.ts.template +1 -5
- package/templates/app/env/env.server.local.ts.template +1 -5
- package/templates/app/env/env.server.main.ts.template +1 -5
- package/templates/app/main.ts +3 -1
- package/templates/app/page/styles.css.template +3 -3
- package/templates/appSample/srvkit/AuthGuard.ts +9 -5
- package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
- package/templates/crudPages/[__model__Id]/edit/page.tsx +1 -1
- package/templates/crudPages/new/page.tsx +1 -1
- package/templates/crudSinglePage/page.tsx +1 -1
- package/templates/env/_env.server.type.ts +7 -5
- package/templates/lib/db.ts +1 -1
- package/templates/lib/dict.ts +1 -1
- package/templates/lib/sig.ts +1 -1
- package/templates/lib/srv.ts +6 -2
- package/templates/module/__Model__.Util.tsx +1 -1
- package/templates/module/__Model__.Zone.tsx +3 -5
- package/templates/workspaceRoot/AGENTS.md.template +4 -972
- package/templates/workspaceRoot/CLAUDE.md.template +19 -0
- package/templates/workspaceRoot/biome.json.template +4 -244
- package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
- package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
- package/templates/workspaceRoot/package.json.template +1 -1
- package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/{workflow.command-91wmvm8k.js → workflow.command-dwhwrqhd.js} +16 -14
- package/{workspace.command-wa10mfd9.js → workspace.command-f5h11gjn.js} +71 -52
- package/templates/workspaceRoot/.cursor/rules/akan-page-routing.mdc.template +0 -43
- package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +0 -34
- package/templates/workspaceRoot/.cursor/rules/application-test-commands.mdc.template +0 -16
- package/templates/workspaceRoot/.cursor/rules/change-scope.mdc.template +0 -12
- package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +0 -18
- package/templates/workspaceRoot/.cursor/rules/coding-comments.mdc.template +0 -25
- package/templates/workspaceRoot/.cursor/rules/coding-style.mdc.template +0 -44
- package/templates/workspaceRoot/.cursor/rules/domain-module-conventions.mdc.template +0 -17
- package/templates/workspaceRoot/.cursor/rules/format-lint.mdc.template +0 -12
- package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +0 -19
- package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +0 -62
- package/templates/workspaceRoot/.cursor/rules/naming-conventions.mdc.template +0 -15
- package/templates/workspaceRoot/.cursor/rules/react-component-style.mdc.template +0 -21
- package/templates/workspaceRoot/.cursor/rules/repo-overview.mdc.template +0 -17
- package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +0 -99
- package/templates/workspaceRoot/.cursor/rules/secrets-and-env.mdc.template +0 -13
- package/templates/workspaceRoot/.cursor/rules/service-signal-conventions.mdc.template +0 -83
- package/templates/workspaceRoot/.cursor/rules/srvkit-adapters-and-guards.mdc.template +0 -50
- package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +0 -59
- package/templates/workspaceRoot/.cursor/rules/typescript-imports.mdc.template +0 -16
- /package/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
|
@@ -7,14 +7,17 @@ import {
|
|
|
7
7
|
command,
|
|
8
8
|
runner,
|
|
9
9
|
script
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-gvq17wqn.js";
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
isAllowedLibFacetRootFile,
|
|
13
|
+
rootAllowedDirs,
|
|
14
|
+
rootAllowedFiles
|
|
15
|
+
} from "./index-5f4gnt4c.js";
|
|
16
|
+
import"./index-f39512t6.js";
|
|
15
17
|
import"./index-mxvakhsm.js";
|
|
18
|
+
import"./index-1577bej2.js";
|
|
16
19
|
import"./index-67546d0j.js";
|
|
17
|
-
import"./index-
|
|
20
|
+
import"./index-yb2wsc7f.js";
|
|
18
21
|
|
|
19
22
|
// pkgs/@akanjs/devkit/qualityScanner.ts
|
|
20
23
|
import { createHash } from "crypto";
|
|
@@ -22,10 +25,79 @@ import { readdir, readFile, stat } from "fs/promises";
|
|
|
22
25
|
import path from "path";
|
|
23
26
|
import { RESERVED_ROUTE_CONFIG_EXPORTS } from "akanjs/common";
|
|
24
27
|
import ignore from "ignore";
|
|
25
|
-
import
|
|
28
|
+
import ts3 from "typescript";
|
|
26
29
|
|
|
27
|
-
// pkgs/@akanjs/devkit/
|
|
30
|
+
// pkgs/@akanjs/devkit/formSetterScanner.ts
|
|
28
31
|
import ts from "typescript";
|
|
32
|
+
|
|
33
|
+
class FormSetterScanner {
|
|
34
|
+
static #fieldSetter = /^set[A-Za-z0-9_$]*On[A-Za-z0-9_$]*$/;
|
|
35
|
+
scan(sourceFiles) {
|
|
36
|
+
return sourceFiles.filter((sourceFile) => sourceFile.file.endsWith(".tsx")).flatMap((f) => this.#scanFile(f));
|
|
37
|
+
}
|
|
38
|
+
#scanFile({ file, sourceFile }) {
|
|
39
|
+
const wrapped = [];
|
|
40
|
+
const visit = (node) => {
|
|
41
|
+
if (ts.isJsxAttribute(node)) {
|
|
42
|
+
const setter = FormSetterScanner.#wrappedSetterOf(node);
|
|
43
|
+
if (setter)
|
|
44
|
+
wrapped.push({ setter, line: FormSetterScanner.#lineOf(sourceFile, node) });
|
|
45
|
+
}
|
|
46
|
+
ts.forEachChild(node, visit);
|
|
47
|
+
};
|
|
48
|
+
visit(sourceFile);
|
|
49
|
+
if (!wrapped.length)
|
|
50
|
+
return [];
|
|
51
|
+
const setters = [...new Set(wrapped.map((entry) => entry.setter))].sort();
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
rule: "akan.agent.unpublished-form-setter",
|
|
55
|
+
scope: "agent",
|
|
56
|
+
severity: "warning",
|
|
57
|
+
message: setters.length === 1 ? `${setters[0]} is reached through a wrapper, so that field publishes no agent tool and carries no data-akan-action.` : `${setters.length} field setters are reached through a wrapper, so those fields publish no agent tool and carry no data-akan-action: ${setters.join(", ")}.`,
|
|
58
|
+
file,
|
|
59
|
+
line: wrapped[0]?.line,
|
|
60
|
+
locations: wrapped.map(({ line }) => ({ file, line }))
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
static #wrappedSetterOf(attribute) {
|
|
65
|
+
if (!ts.isIdentifier(attribute.name) || !/^on[A-Z]/.test(attribute.name.text))
|
|
66
|
+
return null;
|
|
67
|
+
const initializer = attribute.initializer;
|
|
68
|
+
if (!initializer || !ts.isJsxExpression(initializer) || !initializer.expression)
|
|
69
|
+
return null;
|
|
70
|
+
const handler = initializer.expression;
|
|
71
|
+
if (!ts.isArrowFunction(handler) && !ts.isFunctionExpression(handler))
|
|
72
|
+
return null;
|
|
73
|
+
if (!handler.parameters.length)
|
|
74
|
+
return null;
|
|
75
|
+
return FormSetterScanner.#setterCallIn(handler.body);
|
|
76
|
+
}
|
|
77
|
+
static #setterCallIn(node) {
|
|
78
|
+
let found = null;
|
|
79
|
+
const visit = (current) => {
|
|
80
|
+
if (found)
|
|
81
|
+
return;
|
|
82
|
+
if (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
|
|
83
|
+
const { expression, name } = current.expression;
|
|
84
|
+
if (ts.isPropertyAccessExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "st" && expression.name.text === "do" && FormSetterScanner.#fieldSetter.test(name.text)) {
|
|
85
|
+
found = name.text;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
ts.forEachChild(current, visit);
|
|
90
|
+
};
|
|
91
|
+
visit(node);
|
|
92
|
+
return found;
|
|
93
|
+
}
|
|
94
|
+
static #lineOf(sourceFile, node) {
|
|
95
|
+
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// pkgs/@akanjs/devkit/ssrScanner.ts
|
|
100
|
+
import ts2 from "typescript";
|
|
29
101
|
var STATIC_COMPONENT_MIN_MASS = 4;
|
|
30
102
|
var MIXED_COMPONENT_MIN_MASS = 10;
|
|
31
103
|
var MIXED_COMPONENT_MAX_TOUCHES = 2;
|
|
@@ -143,31 +215,31 @@ class SsrScanner {
|
|
|
143
215
|
});
|
|
144
216
|
}
|
|
145
217
|
}
|
|
146
|
-
|
|
218
|
+
ts2.forEachChild(node, visit);
|
|
147
219
|
};
|
|
148
|
-
|
|
220
|
+
ts2.forEachChild(sourceFile.sourceFile, visit);
|
|
149
221
|
return warnings;
|
|
150
222
|
}
|
|
151
223
|
#isMountEffect(sourceFile, node) {
|
|
152
|
-
if (!
|
|
224
|
+
if (!ts2.isCallExpression(node))
|
|
153
225
|
return false;
|
|
154
226
|
const callee = node.expression.getText(sourceFile);
|
|
155
227
|
if (callee !== "useEffect" && callee !== "useLayoutEffect")
|
|
156
228
|
return false;
|
|
157
229
|
const deps = node.arguments[1];
|
|
158
|
-
return !!deps &&
|
|
230
|
+
return !!deps && ts2.isArrayLiteralExpression(deps) && deps.elements.length === 0;
|
|
159
231
|
}
|
|
160
232
|
#getLoadCalls(sourceFile, node) {
|
|
161
233
|
const calls = [];
|
|
162
234
|
const visit = (child) => {
|
|
163
|
-
if (
|
|
235
|
+
if (ts2.isCallExpression(child)) {
|
|
164
236
|
const callee = child.expression.getText(sourceFile);
|
|
165
237
|
if (/^fetch\.[a-z]/.test(callee) || /^st\.do\.(init|get|view|load|list|count|insight)[A-Z]/.test(callee))
|
|
166
238
|
calls.push({ callee, node: child });
|
|
167
239
|
}
|
|
168
|
-
|
|
240
|
+
ts2.forEachChild(child, visit);
|
|
169
241
|
};
|
|
170
|
-
|
|
242
|
+
ts2.forEachChild(node, visit);
|
|
171
243
|
return calls;
|
|
172
244
|
}
|
|
173
245
|
#getTemplateStateWarnings(sourceFile) {
|
|
@@ -175,7 +247,7 @@ class SsrScanner {
|
|
|
175
247
|
return [];
|
|
176
248
|
const warnings = [];
|
|
177
249
|
const visit = (node) => {
|
|
178
|
-
if (
|
|
250
|
+
if (ts2.isCallExpression(node) && node.expression.getText(sourceFile.sourceFile) === "useState") {
|
|
179
251
|
warnings.push({
|
|
180
252
|
rule: "akan.ssr.template-client-state",
|
|
181
253
|
scope: "ssr",
|
|
@@ -185,9 +257,9 @@ class SsrScanner {
|
|
|
185
257
|
message: "Template holds form state in useState. Templates are store-driven and carry no local state."
|
|
186
258
|
});
|
|
187
259
|
}
|
|
188
|
-
|
|
260
|
+
ts2.forEachChild(node, visit);
|
|
189
261
|
};
|
|
190
|
-
|
|
262
|
+
ts2.forEachChild(sourceFile.sourceFile, visit);
|
|
191
263
|
return warnings;
|
|
192
264
|
}
|
|
193
265
|
#measureBalance(sourceFiles) {
|
|
@@ -228,14 +300,14 @@ class SsrScanner {
|
|
|
228
300
|
return components;
|
|
229
301
|
}
|
|
230
302
|
#getComponentNodes(statement) {
|
|
231
|
-
if (
|
|
303
|
+
if (ts2.isFunctionDeclaration(statement) && statement.body)
|
|
232
304
|
return [{ name: statement.name?.text ?? "default", node: statement.body }];
|
|
233
|
-
if (!
|
|
305
|
+
if (!ts2.isVariableStatement(statement))
|
|
234
306
|
return [];
|
|
235
307
|
return statement.declarationList.declarations.flatMap((declaration) => {
|
|
236
|
-
if (!
|
|
308
|
+
if (!ts2.isIdentifier(declaration.name) || !declaration.initializer)
|
|
237
309
|
return [];
|
|
238
|
-
if (!
|
|
310
|
+
if (!ts2.isArrowFunction(declaration.initializer) && !ts2.isFunctionExpression(declaration.initializer))
|
|
239
311
|
return [];
|
|
240
312
|
return [{ name: declaration.name.text, node: declaration.initializer }];
|
|
241
313
|
});
|
|
@@ -243,7 +315,7 @@ class SsrScanner {
|
|
|
243
315
|
#getTouches(sourceFile, node) {
|
|
244
316
|
const touches = [];
|
|
245
317
|
const visit = (child) => {
|
|
246
|
-
if (
|
|
318
|
+
if (ts2.isCallExpression(child)) {
|
|
247
319
|
const callee = child.expression.getText(sourceFile);
|
|
248
320
|
const bareName = callee.split(".").pop() ?? callee;
|
|
249
321
|
if (callee === "createContext" || callee === "lazy")
|
|
@@ -251,60 +323,60 @@ class SsrScanner {
|
|
|
251
323
|
else if (/^use[A-Z]/.test(bareName) && !SsrScanner.#serverSafeCalls.has(bareName))
|
|
252
324
|
touches.push(bareName);
|
|
253
325
|
}
|
|
254
|
-
if (
|
|
326
|
+
if (ts2.isJsxAttribute(child) && /^on[A-Z]/.test(child.name.getText(sourceFile)))
|
|
255
327
|
touches.push(child.name.getText(sourceFile));
|
|
256
|
-
if (
|
|
328
|
+
if (ts2.isPropertyAccessExpression(child)) {
|
|
257
329
|
const root = getAccessRoot(child);
|
|
258
330
|
if (root === "st")
|
|
259
331
|
touches.push("st");
|
|
260
332
|
else if (SsrScanner.#clientGlobals.has(root))
|
|
261
333
|
touches.push(root);
|
|
262
334
|
}
|
|
263
|
-
|
|
335
|
+
ts2.forEachChild(child, visit);
|
|
264
336
|
};
|
|
265
|
-
|
|
337
|
+
ts2.forEachChild(node, visit);
|
|
266
338
|
return touches;
|
|
267
339
|
}
|
|
268
340
|
#getTagNames(sourceFile, node) {
|
|
269
341
|
const tags = new Set;
|
|
270
342
|
const visit = (child) => {
|
|
271
|
-
if (
|
|
343
|
+
if (ts2.isJsxOpeningElement(child) || ts2.isJsxSelfClosingElement(child))
|
|
272
344
|
tags.add(child.tagName.getText(sourceFile).split(".")[0]);
|
|
273
|
-
|
|
345
|
+
ts2.forEachChild(child, visit);
|
|
274
346
|
};
|
|
275
|
-
|
|
347
|
+
ts2.forEachChild(node, visit);
|
|
276
348
|
return tags;
|
|
277
349
|
}
|
|
278
350
|
#getMass(node) {
|
|
279
351
|
let mass = 0;
|
|
280
352
|
const visit = (child) => {
|
|
281
|
-
if (
|
|
353
|
+
if (ts2.isJsxOpeningElement(child) || ts2.isJsxSelfClosingElement(child))
|
|
282
354
|
mass += 1;
|
|
283
|
-
|
|
355
|
+
ts2.forEachChild(child, visit);
|
|
284
356
|
};
|
|
285
|
-
|
|
357
|
+
ts2.forEachChild(node, visit);
|
|
286
358
|
return mass;
|
|
287
359
|
}
|
|
288
360
|
#hasUseClient(sourceFile) {
|
|
289
361
|
const first = sourceFile.statements[0];
|
|
290
|
-
if (!first || !
|
|
362
|
+
if (!first || !ts2.isExpressionStatement(first) || !ts2.isStringLiteral(first.expression))
|
|
291
363
|
return false;
|
|
292
364
|
return first.expression.text === "use client";
|
|
293
365
|
}
|
|
294
366
|
#hasVendorImport(sourceFile) {
|
|
295
|
-
return sourceFile.statements.some((statement) =>
|
|
367
|
+
return sourceFile.statements.some((statement) => ts2.isImportDeclaration(statement) && isVendorSpecifier(getSpecifier(statement)));
|
|
296
368
|
}
|
|
297
369
|
#getVendorNames(sourceFile) {
|
|
298
370
|
const names = new Set;
|
|
299
371
|
for (const statement of sourceFile.statements) {
|
|
300
|
-
if (!
|
|
372
|
+
if (!ts2.isImportDeclaration(statement) || !isVendorSpecifier(getSpecifier(statement)))
|
|
301
373
|
continue;
|
|
302
374
|
const clause = statement.importClause;
|
|
303
375
|
if (clause?.name)
|
|
304
376
|
names.add(clause.name.text);
|
|
305
|
-
if (clause?.namedBindings &&
|
|
377
|
+
if (clause?.namedBindings && ts2.isNamespaceImport(clause.namedBindings))
|
|
306
378
|
names.add(clause.namedBindings.name.text);
|
|
307
|
-
if (clause?.namedBindings &&
|
|
379
|
+
if (clause?.namedBindings && ts2.isNamedImports(clause.namedBindings))
|
|
308
380
|
for (const element of clause.namedBindings.elements)
|
|
309
381
|
names.add(element.name.text);
|
|
310
382
|
}
|
|
@@ -312,10 +384,10 @@ class SsrScanner {
|
|
|
312
384
|
}
|
|
313
385
|
#importsClientRuntime(sourceFile) {
|
|
314
386
|
for (const statement of sourceFile.statements) {
|
|
315
|
-
if (!
|
|
387
|
+
if (!ts2.isImportDeclaration(statement))
|
|
316
388
|
continue;
|
|
317
389
|
const bindings = statement.importClause?.namedBindings;
|
|
318
|
-
if (!bindings || !
|
|
390
|
+
if (!bindings || !ts2.isNamedImports(bindings))
|
|
319
391
|
continue;
|
|
320
392
|
if (bindings.elements.some((element) => SsrScanner.#clientRuntimeImports.has(element.name.text)))
|
|
321
393
|
return true;
|
|
@@ -366,7 +438,7 @@ function getShare(serverMass, clientMass) {
|
|
|
366
438
|
return total === 0 ? 1 : serverMass / total;
|
|
367
439
|
}
|
|
368
440
|
function getSpecifier(statement) {
|
|
369
|
-
return
|
|
441
|
+
return ts2.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : "";
|
|
370
442
|
}
|
|
371
443
|
function isVendorSpecifier(specifier) {
|
|
372
444
|
if (specifier === "" || specifier.startsWith(".") || specifier.startsWith("/"))
|
|
@@ -379,9 +451,9 @@ function isVendorSpecifier(specifier) {
|
|
|
379
451
|
}
|
|
380
452
|
function getAccessRoot(node) {
|
|
381
453
|
let current = node;
|
|
382
|
-
while (
|
|
454
|
+
while (ts2.isPropertyAccessExpression(current))
|
|
383
455
|
current = current.expression;
|
|
384
|
-
return
|
|
456
|
+
return ts2.isIdentifier(current) ? current.text : "";
|
|
385
457
|
}
|
|
386
458
|
|
|
387
459
|
// pkgs/@akanjs/devkit/qualityScanner.ts
|
|
@@ -405,7 +477,8 @@ var SUGGESTED_RULES = [
|
|
|
405
477
|
"Keep apps/*/lib and libs/*/lib root files limited to generated support facets such as cnst.ts, db.ts, dict.ts, sig.ts, srv.ts, st.ts, useClient.ts, and useServer.ts.",
|
|
406
478
|
"Use domain module folders consistently: lib/<model> for database modules, lib/_<service> for service modules, and lib/__scalar/<scalar> for scalar modules.",
|
|
407
479
|
"Keep module UI filenames predictable: database modules use <Model>.Template/Unit/Util/View/Zone.tsx, service modules use <Service>.Util/Zone.tsx, and scalar modules use <Scalar>.Template/Unit.tsx.",
|
|
408
|
-
"
|
|
480
|
+
"Hand a form control its store setter by reference so the field publishes an agent tool; put normalization in the control's transform prop and a multi-write in a _postSet<Field> hook on the store.",
|
|
481
|
+
"Move shared app and lib utilities to common/ instead of creating apps/*/base or libs/*/base.",
|
|
409
482
|
"Avoid large mixed-purpose class files; class export files should import helpers from neighboring utility files instead of declaring them inline."
|
|
410
483
|
];
|
|
411
484
|
var CONVENTION_SUFFIXES = [
|
|
@@ -428,10 +501,14 @@ var RULE_FIXES = {
|
|
|
428
501
|
"akan.file.window-augmentation": "Move the Window augmentation into an approved browser integration file and keep it isolated.",
|
|
429
502
|
"akan.file.prototype-mutation": "Avoid prototype mutation, or isolate it in an approved low-level integration file.",
|
|
430
503
|
"akan.file.class-export-global-declaration": "Move the helper to a sibling file and import it into the class module.",
|
|
504
|
+
"akan.agent.unpublished-form-setter": "Pass the setter by reference where the wrapper only forwards (onChange={st.do.setTitleOnTask}); move normalization into the control's own transform prop; move a multi-write into a _postSet<Field> hook on the store, keeping the generated setter on the control.",
|
|
431
505
|
"akan.file.component-internal-declaration": "Move the type or helper to a type/util file in ui/, webkit/, or common/ by purpose. If it is the component's props, declare it as `interface <Component>Props`.",
|
|
432
506
|
"akan.file.component-export": "Move the value or type to a util/constant/type file in ui/, webkit/, or common/ and import it. Adding `export` is not a valid fix \u2014 only PascalCase components and their `<Component>Props` interface belong here.",
|
|
433
507
|
"akan.layout.app-root-file": "Move the file into a conventional app folder (common, env, lib, page, private, public, script, srvkit, ui, or webkit).",
|
|
434
|
-
"akan.layout.
|
|
508
|
+
"akan.layout.app-root-folder": "Move the folder's contents into a conventional app folder (common, env, lib, page, private, public, script, srvkit, ui, or webkit) and delete it.",
|
|
509
|
+
"akan.layout.lib-root-file": "Move the file into a conventional lib folder (common, env, lib, page, private, public, srvkit, ui, or webkit).",
|
|
510
|
+
"akan.layout.lib-root-folder": "Move the folder's contents into a conventional lib folder (common, env, lib, page, private, public, srvkit, ui, or webkit) and delete it.",
|
|
511
|
+
"akan.layout.lib-facet-file": "Move the file into a domain module folder under lib/; keep the lib facet root limited to generated support facets.",
|
|
435
512
|
"akan.layout.module-ui-file": "Rename the file to an allowed module UI name, or move it to ui/ if it is not a module component.",
|
|
436
513
|
"akan.ssr.unnecessary-use-client": 'Delete the "use client" directive so the file renders on the server. If it exists only to wrap one client child, drop the wrapper and use the child directly.',
|
|
437
514
|
"akan.ssr.client-static-component": "Move the component to a server file \u2014 a <Model>.Unit.tsx / <Model>.View.tsx for a module, or a ui/ file with no directive \u2014 and reference it from the client file.",
|
|
@@ -459,6 +536,7 @@ class AkanQualityScanner {
|
|
|
459
536
|
...sourceFiles.flatMap((sourceFile) => this.#scanConventionQuality(sourceFile)),
|
|
460
537
|
...sourceFiles.flatMap((sourceFile) => this.#scanLayoutQuality(sourceFile)),
|
|
461
538
|
...abstractFiles.flatMap((abstractFile) => this.#scanAbstractQuality(abstractFile)),
|
|
539
|
+
...new FormSetterScanner().scan(sourceFiles),
|
|
462
540
|
...ssr.warnings
|
|
463
541
|
];
|
|
464
542
|
return {
|
|
@@ -511,7 +589,7 @@ class AkanQualityScanner {
|
|
|
511
589
|
file,
|
|
512
590
|
absolutePath,
|
|
513
591
|
content,
|
|
514
|
-
sourceFile:
|
|
592
|
+
sourceFile: ts3.createSourceFile(file, content, ts3.ScriptTarget.Latest, true, getScriptKind(file))
|
|
515
593
|
};
|
|
516
594
|
}
|
|
517
595
|
async#readTextFile(workspaceRoot, file) {
|
|
@@ -670,25 +748,30 @@ class AkanQualityScanner {
|
|
|
670
748
|
];
|
|
671
749
|
}
|
|
672
750
|
#scanLayoutQuality(sourceFile) {
|
|
673
|
-
const segments = sourceFile.file.split("/");
|
|
674
751
|
const warnings = [];
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
752
|
+
const rootEntry = getSysRootEntry(sourceFile.file);
|
|
753
|
+
if (rootEntry) {
|
|
754
|
+
const { type, name, isDir } = rootEntry;
|
|
755
|
+
const allowed = isDir ? rootAllowedDirs[type].has(name) : rootAllowedFiles[type].has(name);
|
|
756
|
+
const kind = isDir ? "folder" : "file";
|
|
757
|
+
if (!allowed) {
|
|
758
|
+
warnings.push({
|
|
759
|
+
rule: `akan.layout.${type}-root-${kind}`,
|
|
760
|
+
scope: "layout",
|
|
761
|
+
severity: "warning",
|
|
762
|
+
file: sourceFile.file,
|
|
763
|
+
message: `Unexpected ${type} root ${kind} "${name}". Keep ${type} code in conventional ${type} folders.`
|
|
764
|
+
});
|
|
765
|
+
}
|
|
683
766
|
}
|
|
684
|
-
const
|
|
685
|
-
if (
|
|
767
|
+
const libFacetFile = getLibFacetRootFile(sourceFile.file);
|
|
768
|
+
if (libFacetFile && !isAllowedLibFacetRootFile(libFacetFile)) {
|
|
686
769
|
warnings.push({
|
|
687
|
-
rule: "akan.layout.lib-
|
|
770
|
+
rule: "akan.layout.lib-facet-file",
|
|
688
771
|
scope: "layout",
|
|
689
772
|
severity: "warning",
|
|
690
773
|
file: sourceFile.file,
|
|
691
|
-
message: `Unexpected lib root file "${
|
|
774
|
+
message: `Unexpected lib facet root file "${libFacetFile}". Keep direct lib/ root files limited to generated support facets.`
|
|
692
775
|
});
|
|
693
776
|
}
|
|
694
777
|
const moduleUiWarning = getModuleUiWarning(sourceFile.file);
|
|
@@ -758,7 +841,7 @@ function getExportedFunctionLikes(sourceFile) {
|
|
|
758
841
|
const declarations = [];
|
|
759
842
|
const nameExempt = isPageRouteFile(sourceFile.file) || isUiComponentFile(sourceFile.file);
|
|
760
843
|
for (const statement of sourceFile.sourceFile.statements) {
|
|
761
|
-
if (
|
|
844
|
+
if (ts3.isFunctionDeclaration(statement) && statement.name && isExported(statement)) {
|
|
762
845
|
declarations.push({
|
|
763
846
|
name: statement.name.text,
|
|
764
847
|
kind: "function",
|
|
@@ -768,7 +851,7 @@ function getExportedFunctionLikes(sourceFile) {
|
|
|
768
851
|
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile.file, false)
|
|
769
852
|
});
|
|
770
853
|
}
|
|
771
|
-
if (
|
|
854
|
+
if (ts3.isClassDeclaration(statement) && statement.name && isExported(statement)) {
|
|
772
855
|
declarations.push({
|
|
773
856
|
name: statement.name.text,
|
|
774
857
|
kind: "class",
|
|
@@ -778,9 +861,9 @@ function getExportedFunctionLikes(sourceFile) {
|
|
|
778
861
|
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile.file, isEnumClassStatement(sourceFile.sourceFile, statement))
|
|
779
862
|
});
|
|
780
863
|
}
|
|
781
|
-
if (
|
|
864
|
+
if (ts3.isVariableStatement(statement) && isExported(statement)) {
|
|
782
865
|
for (const declaration of statement.declarationList.declarations) {
|
|
783
|
-
if (!
|
|
866
|
+
if (!ts3.isIdentifier(declaration.name) || !isFunctionLikeInitializer(declaration.initializer))
|
|
784
867
|
continue;
|
|
785
868
|
declarations.push({
|
|
786
869
|
name: declaration.name.text,
|
|
@@ -819,14 +902,14 @@ function isInLibModule(file) {
|
|
|
819
902
|
return (segments[0] === "apps" || segments[0] === "libs") && segments.includes("lib");
|
|
820
903
|
}
|
|
821
904
|
function isEnumClassStatement(sourceFile, statement) {
|
|
822
|
-
if (!
|
|
905
|
+
if (!ts3.isClassDeclaration(statement))
|
|
823
906
|
return false;
|
|
824
|
-
const heritageClause = statement.heritageClauses?.find((clause) => clause.token ===
|
|
907
|
+
const heritageClause = statement.heritageClauses?.find((clause) => clause.token === ts3.SyntaxKind.ExtendsKeyword);
|
|
825
908
|
const expression = heritageClause?.types[0]?.expression;
|
|
826
909
|
return !!expression && expression.getText(sourceFile).startsWith("enumOf(");
|
|
827
910
|
}
|
|
828
911
|
function getExportedClassNames(sourceFile) {
|
|
829
|
-
return sourceFile.statements.filter((statement) =>
|
|
912
|
+
return sourceFile.statements.filter((statement) => ts3.isClassDeclaration(statement) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
|
|
830
913
|
}
|
|
831
914
|
function isComponentDeclarationFile(file) {
|
|
832
915
|
if (!file.endsWith(".tsx"))
|
|
@@ -842,7 +925,7 @@ function isComponentDeclarationFile(file) {
|
|
|
842
925
|
function getComponentFileDeclarations(sourceFile) {
|
|
843
926
|
const reExportedNames = new Set;
|
|
844
927
|
for (const statement of sourceFile.statements) {
|
|
845
|
-
if (
|
|
928
|
+
if (ts3.isExportDeclaration(statement) && statement.exportClause && ts3.isNamedExports(statement.exportClause)) {
|
|
846
929
|
for (const element of statement.exportClause.elements)
|
|
847
930
|
reExportedNames.add((element.propertyName ?? element.name).text);
|
|
848
931
|
}
|
|
@@ -852,19 +935,19 @@ function getComponentFileDeclarations(sourceFile) {
|
|
|
852
935
|
const isDefaultExport = isDefaultExportStatement(statement);
|
|
853
936
|
const inlineExported = isExported(statement);
|
|
854
937
|
const add = (name, kind, line) => declarations.push({ name, kind, line, exported: inlineExported || reExportedNames.has(name), isDefaultExport });
|
|
855
|
-
if (
|
|
938
|
+
if (ts3.isInterfaceDeclaration(statement))
|
|
856
939
|
add(statement.name.text, "interface", getLine(sourceFile, statement));
|
|
857
|
-
else if (
|
|
940
|
+
else if (ts3.isTypeAliasDeclaration(statement))
|
|
858
941
|
add(statement.name.text, "type", getLine(sourceFile, statement));
|
|
859
|
-
else if (
|
|
942
|
+
else if (ts3.isEnumDeclaration(statement))
|
|
860
943
|
add(statement.name.text, "enum", getLine(sourceFile, statement));
|
|
861
|
-
else if (
|
|
944
|
+
else if (ts3.isFunctionDeclaration(statement) && statement.name)
|
|
862
945
|
add(statement.name.text, "function", getLine(sourceFile, statement));
|
|
863
|
-
else if (
|
|
946
|
+
else if (ts3.isClassDeclaration(statement) && statement.name)
|
|
864
947
|
add(statement.name.text, "class", getLine(sourceFile, statement));
|
|
865
|
-
else if (
|
|
948
|
+
else if (ts3.isVariableStatement(statement)) {
|
|
866
949
|
for (const declaration of statement.declarationList.declarations) {
|
|
867
|
-
if (!
|
|
950
|
+
if (!ts3.isIdentifier(declaration.name))
|
|
868
951
|
continue;
|
|
869
952
|
const kind = isFunctionLikeInitializer(declaration.initializer) ? "function" : "variable";
|
|
870
953
|
add(declaration.name.text, kind, getLine(sourceFile, declaration));
|
|
@@ -876,15 +959,15 @@ function getComponentFileDeclarations(sourceFile) {
|
|
|
876
959
|
function getCompoundComponentNames(sourceFile) {
|
|
877
960
|
const names = new Set;
|
|
878
961
|
for (const statement of sourceFile.statements) {
|
|
879
|
-
if (!
|
|
962
|
+
if (!ts3.isExpressionStatement(statement))
|
|
880
963
|
continue;
|
|
881
964
|
const { expression } = statement;
|
|
882
|
-
if (!
|
|
965
|
+
if (!ts3.isBinaryExpression(expression) || expression.operatorToken.kind !== ts3.SyntaxKind.EqualsToken)
|
|
883
966
|
continue;
|
|
884
|
-
if (!
|
|
967
|
+
if (!ts3.isPropertyAccessExpression(expression.left) || !isPascalCaseName(expression.left.name.text))
|
|
885
968
|
continue;
|
|
886
969
|
names.add(expression.left.name.text);
|
|
887
|
-
if (
|
|
970
|
+
if (ts3.isIdentifier(expression.right) && isPascalCaseName(expression.right.text))
|
|
888
971
|
names.add(expression.right.text);
|
|
889
972
|
}
|
|
890
973
|
return names;
|
|
@@ -904,9 +987,9 @@ function isPascalCaseName(name) {
|
|
|
904
987
|
return /^[A-Z]/.test(name) && !/^[A-Z0-9_]+$/.test(name);
|
|
905
988
|
}
|
|
906
989
|
function isDefaultExportStatement(statement) {
|
|
907
|
-
if (
|
|
990
|
+
if (ts3.isExportAssignment(statement))
|
|
908
991
|
return !statement.isExportEquals;
|
|
909
|
-
return !!(
|
|
992
|
+
return !!(ts3.getCombinedModifierFlags(statement) & ts3.ModifierFlags.Default);
|
|
910
993
|
}
|
|
911
994
|
function getPlaceholderExportWarnings(sourceFile) {
|
|
912
995
|
if (!sourceFile.file.endsWith("/index.ts") && !sourceFile.file.endsWith("/index.tsx"))
|
|
@@ -936,7 +1019,7 @@ function getDictionaryTextWarnings(sourceFile) {
|
|
|
936
1019
|
function getGlobalMutationWarnings(sourceFile) {
|
|
937
1020
|
const warnings = [];
|
|
938
1021
|
for (const statement of sourceFile.sourceFile.statements) {
|
|
939
|
-
if (
|
|
1022
|
+
if (ts3.isModuleDeclaration(statement) && statement.name.getText(sourceFile.sourceFile) === "global") {
|
|
940
1023
|
warnings.push({
|
|
941
1024
|
rule: "akan.file.global-declaration",
|
|
942
1025
|
scope: "file",
|
|
@@ -946,7 +1029,7 @@ function getGlobalMutationWarnings(sourceFile) {
|
|
|
946
1029
|
message: "Global declarations require an explicit low-level integration allowlist."
|
|
947
1030
|
});
|
|
948
1031
|
}
|
|
949
|
-
if (
|
|
1032
|
+
if (ts3.isInterfaceDeclaration(statement) && statement.name.text === "Window") {
|
|
950
1033
|
warnings.push({
|
|
951
1034
|
rule: "akan.file.window-augmentation",
|
|
952
1035
|
scope: "file",
|
|
@@ -956,7 +1039,7 @@ function getGlobalMutationWarnings(sourceFile) {
|
|
|
956
1039
|
message: "Window augmentation should be isolated to approved browser integration files."
|
|
957
1040
|
});
|
|
958
1041
|
}
|
|
959
|
-
if (
|
|
1042
|
+
if (ts3.isExpressionStatement(statement) && statement.expression.getText(sourceFile.sourceFile).includes(".prototype.")) {
|
|
960
1043
|
warnings.push({
|
|
961
1044
|
rule: "akan.file.prototype-mutation",
|
|
962
1045
|
scope: "file",
|
|
@@ -974,23 +1057,23 @@ function getTopLevelDeclarations(sourceFile) {
|
|
|
974
1057
|
}
|
|
975
1058
|
function getTopLevelDeclaration(sourceFile, statement) {
|
|
976
1059
|
const line = getLine(sourceFile, statement);
|
|
977
|
-
if (
|
|
1060
|
+
if (ts3.isClassDeclaration(statement) && statement.name) {
|
|
978
1061
|
return [{ name: statement.name.text, kind: "class", line, exported: isExported(statement), node: statement }];
|
|
979
1062
|
}
|
|
980
|
-
if (
|
|
1063
|
+
if (ts3.isFunctionDeclaration(statement) && statement.name) {
|
|
981
1064
|
return [{ name: statement.name.text, kind: "function", line, exported: isExported(statement), node: statement }];
|
|
982
1065
|
}
|
|
983
|
-
if (
|
|
1066
|
+
if (ts3.isInterfaceDeclaration(statement)) {
|
|
984
1067
|
return [{ name: statement.name.text, kind: "interface", line, exported: isExported(statement), node: statement }];
|
|
985
1068
|
}
|
|
986
|
-
if (
|
|
1069
|
+
if (ts3.isTypeAliasDeclaration(statement)) {
|
|
987
1070
|
return [{ name: statement.name.text, kind: "type", line, exported: isExported(statement), node: statement }];
|
|
988
1071
|
}
|
|
989
|
-
if (
|
|
1072
|
+
if (ts3.isEnumDeclaration(statement)) {
|
|
990
1073
|
return [{ name: statement.name.text, kind: "enum", line, exported: isExported(statement), node: statement }];
|
|
991
1074
|
}
|
|
992
|
-
if (
|
|
993
|
-
return statement.declarationList.declarations.filter((declaration) =>
|
|
1075
|
+
if (ts3.isVariableStatement(statement)) {
|
|
1076
|
+
return statement.declarationList.declarations.filter((declaration) => ts3.isIdentifier(declaration.name)).map((declaration) => ({
|
|
994
1077
|
name: declaration.name.text,
|
|
995
1078
|
kind: "variable",
|
|
996
1079
|
line: getLine(sourceFile, declaration),
|
|
@@ -998,7 +1081,7 @@ function getTopLevelDeclaration(sourceFile, statement) {
|
|
|
998
1081
|
node: statement
|
|
999
1082
|
}));
|
|
1000
1083
|
}
|
|
1001
|
-
if (
|
|
1084
|
+
if (ts3.isExportDeclaration(statement)) {
|
|
1002
1085
|
return [{ name: "export declaration", kind: "export", line, exported: true, node: statement }];
|
|
1003
1086
|
}
|
|
1004
1087
|
return [];
|
|
@@ -1023,9 +1106,9 @@ function isAllowedConstantDeclaration(modelName, declaration) {
|
|
|
1023
1106
|
return false;
|
|
1024
1107
|
if ([`${modelName}Input`, `${modelName}Object`, modelName, `Light${modelName}`, `${modelName}Insight`].includes(declaration.name))
|
|
1025
1108
|
return true;
|
|
1026
|
-
if (!
|
|
1109
|
+
if (!ts3.isClassDeclaration(declaration.node))
|
|
1027
1110
|
return false;
|
|
1028
|
-
const heritageClause = declaration.node.heritageClauses?.find((clause) => clause.token ===
|
|
1111
|
+
const heritageClause = declaration.node.heritageClauses?.find((clause) => clause.token === ts3.SyntaxKind.ExtendsKeyword);
|
|
1029
1112
|
const expression = heritageClause?.types[0]?.expression;
|
|
1030
1113
|
return !!expression && expression.getText().startsWith("enumOf(");
|
|
1031
1114
|
}
|
|
@@ -1042,7 +1125,19 @@ function getConventionDescription(suffix, modelName) {
|
|
|
1042
1125
|
return `${modelName}Internal, ${modelName}Slice, or ${modelName}Endpoint`;
|
|
1043
1126
|
return `${modelName}Store`;
|
|
1044
1127
|
}
|
|
1045
|
-
|
|
1128
|
+
var sysRootTypes = { apps: "app", libs: "lib" };
|
|
1129
|
+
function getSysRootEntry(file) {
|
|
1130
|
+
const segments = file.split("/");
|
|
1131
|
+
const root = segments[0];
|
|
1132
|
+
const name = segments[2];
|
|
1133
|
+
if (!root || !name || segments.length < 3)
|
|
1134
|
+
return null;
|
|
1135
|
+
const type = sysRootTypes[root];
|
|
1136
|
+
if (!type)
|
|
1137
|
+
return null;
|
|
1138
|
+
return { type, name, isDir: segments.length > 3 };
|
|
1139
|
+
}
|
|
1140
|
+
function getLibFacetRootFile(file) {
|
|
1046
1141
|
const segments = file.split("/");
|
|
1047
1142
|
if ((segments[0] === "libs" || segments[0] === "apps") && segments.length === 4 && segments[2] === "lib")
|
|
1048
1143
|
return segments[3];
|
|
@@ -1091,13 +1186,13 @@ function getModuleInfo(file) {
|
|
|
1091
1186
|
return { moduleName, fileName, kind: "database" };
|
|
1092
1187
|
}
|
|
1093
1188
|
function isExportedConst(declaration) {
|
|
1094
|
-
return declaration.exported &&
|
|
1189
|
+
return declaration.exported && ts3.isVariableStatement(declaration.node) && (declaration.node.declarationList.flags & ts3.NodeFlags.Const) !== 0;
|
|
1095
1190
|
}
|
|
1096
1191
|
function isExported(node) {
|
|
1097
|
-
return !!
|
|
1192
|
+
return !!ts3.getCombinedModifierFlags(node) && !!(ts3.getCombinedModifierFlags(node) & ts3.ModifierFlags.Export);
|
|
1098
1193
|
}
|
|
1099
1194
|
function isFunctionLikeInitializer(node) {
|
|
1100
|
-
return !!node && (
|
|
1195
|
+
return !!node && (ts3.isArrowFunction(node) || ts3.isFunctionExpression(node));
|
|
1101
1196
|
}
|
|
1102
1197
|
function getBodyFingerprint(sourceFile, node) {
|
|
1103
1198
|
if (!node)
|
|
@@ -1119,7 +1214,7 @@ async function isDirectory(absolutePath) {
|
|
|
1119
1214
|
}
|
|
1120
1215
|
}
|
|
1121
1216
|
function getScriptKind(file) {
|
|
1122
|
-
return file.endsWith(".tsx") ?
|
|
1217
|
+
return file.endsWith(".tsx") ? ts3.ScriptKind.TSX : ts3.ScriptKind.TS;
|
|
1123
1218
|
}
|
|
1124
1219
|
function getLine(sourceFile, node) {
|
|
1125
1220
|
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
findInlineRecipeDuplicates,
|
|
5
5
|
scanRecipes
|
|
6
6
|
} from "./index-xys926f2.js";
|
|
7
|
-
import"./index-
|
|
7
|
+
import"./index-yb2wsc7f.js";
|
|
8
8
|
export {
|
|
9
|
-
|
|
9
|
+
collectRecipeSources,
|
|
10
10
|
findInlineRecipeDuplicates,
|
|
11
|
-
|
|
11
|
+
scanRecipes
|
|
12
12
|
};
|