@fougere/core 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/binding.d.ts +63 -0
- package/dist/binding.d.ts.map +1 -0
- package/dist/binding.js +107 -0
- package/dist/binding.js.map +1 -0
- package/dist/boot.d.ts +38 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/boot.js +53 -0
- package/dist/boot.js.map +1 -0
- package/dist/bootstrap.d.ts +4 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +825 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/builtins/config.d.ts +4 -0
- package/dist/builtins/config.d.ts.map +1 -0
- package/dist/builtins/config.js +6 -0
- package/dist/builtins/config.js.map +1 -0
- package/dist/builtins/logger.d.ts +28 -0
- package/dist/builtins/logger.d.ts.map +1 -0
- package/dist/builtins/logger.js +76 -0
- package/dist/builtins/logger.js.map +1 -0
- package/dist/call.d.ts +172 -0
- package/dist/call.d.ts.map +1 -0
- package/dist/call.js +209 -0
- package/dist/call.js.map +1 -0
- package/dist/collector.d.ts +28 -0
- package/dist/collector.d.ts.map +1 -0
- package/dist/collector.js +32 -0
- package/dist/collector.js.map +1 -0
- package/dist/config-loader.d.ts +59 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +97 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/contract.d.ts +43 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +29 -0
- package/dist/contract.js.map +1 -0
- package/dist/crud.d.ts +61 -0
- package/dist/crud.d.ts.map +1 -0
- package/dist/crud.js +85 -0
- package/dist/crud.js.map +1 -0
- package/dist/define.d.ts +8 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +9 -0
- package/dist/define.js.map +1 -0
- package/dist/egress.d.ts +78 -0
- package/dist/egress.d.ts.map +1 -0
- package/dist/egress.js +185 -0
- package/dist/egress.js.map +1 -0
- package/dist/emit.d.ts +51 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +57 -0
- package/dist/emit.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +74 -0
- package/dist/errors.js.map +1 -0
- package/dist/frond-config.d.ts +80 -0
- package/dist/frond-config.d.ts.map +1 -0
- package/dist/frond-config.js +32 -0
- package/dist/frond-config.js.map +1 -0
- package/dist/graph.d.ts +33 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +142 -0
- package/dist/graph.js.map +1 -0
- package/dist/handler-parser.d.ts +82 -0
- package/dist/handler-parser.d.ts.map +1 -0
- package/dist/handler-parser.js +505 -0
- package/dist/handler-parser.js.map +1 -0
- package/dist/imports.d.ts +22 -0
- package/dist/imports.d.ts.map +1 -0
- package/dist/imports.js +80 -0
- package/dist/imports.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/invocation.d.ts +20 -0
- package/dist/invocation.d.ts.map +1 -0
- package/dist/invocation.js +15 -0
- package/dist/invocation.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +15 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +29 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/logger.d.ts +14 -0
- package/dist/middleware/logger.d.ts.map +1 -0
- package/dist/middleware/logger.js +25 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware.d.ts +75 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +89 -0
- package/dist/middleware.js.map +1 -0
- package/dist/operation.d.ts +87 -0
- package/dist/operation.d.ts.map +1 -0
- package/dist/operation.js +95 -0
- package/dist/operation.js.map +1 -0
- package/dist/orm.d.ts +96 -0
- package/dist/orm.d.ts.map +1 -0
- package/dist/orm.js +33 -0
- package/dist/orm.js.map +1 -0
- package/dist/presenter.d.ts +63 -0
- package/dist/presenter.d.ts.map +1 -0
- package/dist/presenter.js +72 -0
- package/dist/presenter.js.map +1 -0
- package/dist/remote.d.ts +48 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +135 -0
- package/dist/remote.js.map +1 -0
- package/dist/repository.d.ts +55 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +26 -0
- package/dist/repository.js.map +1 -0
- package/dist/scan-cache.d.ts +10 -0
- package/dist/scan-cache.d.ts.map +1 -0
- package/dist/scan-cache.js +92 -0
- package/dist/scan-cache.js.map +1 -0
- package/dist/scanner.d.ts +34 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +595 -0
- package/dist/scanner.js.map +1 -0
- package/dist/seed.d.ts +28 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +110 -0
- package/dist/seed.js.map +1 -0
- package/dist/types.d.ts +387 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +57 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +147 -0
- package/dist/verify.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join, dirname, resolve as resolvePath } from 'node:path';
|
|
3
|
+
/** Lazy-loaded TypeScript module — avoids bundling the 9MB compiler. */
|
|
4
|
+
let _ts;
|
|
5
|
+
async function loadTS() {
|
|
6
|
+
if (!_ts)
|
|
7
|
+
_ts = (await import('typescript')).default;
|
|
8
|
+
return _ts;
|
|
9
|
+
}
|
|
10
|
+
function getTS() {
|
|
11
|
+
if (!_ts)
|
|
12
|
+
throw new Error('TypeScript not loaded — call an async parse function first');
|
|
13
|
+
return _ts;
|
|
14
|
+
}
|
|
15
|
+
/** Parse a TypeScript type node into a ParsedType. */
|
|
16
|
+
function parseTypeNode(node, source) {
|
|
17
|
+
const ts = getTS();
|
|
18
|
+
const raw = node.getText(source);
|
|
19
|
+
// Union types — extract nullable, strip Promise
|
|
20
|
+
if (ts.isUnionTypeNode(node)) {
|
|
21
|
+
const nonNull = node.types.filter((t) => !(ts.isLiteralTypeNode(t) && t.literal.kind === ts.SyntaxKind.NullKeyword)
|
|
22
|
+
&& !(t.kind === ts.SyntaxKind.UndefinedKeyword)
|
|
23
|
+
&& !(t.kind === ts.SyntaxKind.VoidKeyword)
|
|
24
|
+
&& !(t.kind === ts.SyntaxKind.NullKeyword));
|
|
25
|
+
const nullable = nonNull.length < node.types.length;
|
|
26
|
+
if (nonNull.length === 1) {
|
|
27
|
+
const inner = parseTypeNode(nonNull[0], source);
|
|
28
|
+
return { ...inner, nullable: nullable || inner.nullable, raw };
|
|
29
|
+
}
|
|
30
|
+
return { raw, name: raw, nullable };
|
|
31
|
+
}
|
|
32
|
+
// Promise<T> — unwrap
|
|
33
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
34
|
+
const typeName = node.typeName.getText(source);
|
|
35
|
+
if (typeName === 'Promise' && node.typeArguments?.length === 1) {
|
|
36
|
+
const inner = parseTypeNode(node.typeArguments[0], source);
|
|
37
|
+
return { ...inner, promise: true, raw };
|
|
38
|
+
}
|
|
39
|
+
// Array<T>
|
|
40
|
+
if (typeName === 'Array' && node.typeArguments?.length === 1) {
|
|
41
|
+
const inner = parseTypeNode(node.typeArguments[0], source);
|
|
42
|
+
return { ...inner, array: true, arrayDepth: (inner.arrayDepth ?? 0) + 1, raw };
|
|
43
|
+
}
|
|
44
|
+
// Generic type: Foo<Bar, Baz>
|
|
45
|
+
if (node.typeArguments && node.typeArguments.length > 0) {
|
|
46
|
+
const generics = node.typeArguments.map((arg) => parseTypeNode(arg, source));
|
|
47
|
+
return { raw, name: typeName, generics };
|
|
48
|
+
}
|
|
49
|
+
// Simple type reference: Post, string, etc.
|
|
50
|
+
return { raw, name: typeName };
|
|
51
|
+
}
|
|
52
|
+
// T[]
|
|
53
|
+
if (ts.isArrayTypeNode(node)) {
|
|
54
|
+
const inner = parseTypeNode(node.elementType, source);
|
|
55
|
+
return { ...inner, array: true, arrayDepth: (inner.arrayDepth ?? 0) + 1, raw };
|
|
56
|
+
}
|
|
57
|
+
// Keyword types: string, number, boolean, void
|
|
58
|
+
switch (node.kind) {
|
|
59
|
+
case ts.SyntaxKind.StringKeyword: return { raw, name: 'string' };
|
|
60
|
+
case ts.SyntaxKind.NumberKeyword: return { raw, name: 'number' };
|
|
61
|
+
case ts.SyntaxKind.BooleanKeyword: return { raw, name: 'boolean' };
|
|
62
|
+
case ts.SyntaxKind.VoidKeyword: return { raw, name: 'void' };
|
|
63
|
+
case ts.SyntaxKind.UndefinedKeyword: return { raw, name: 'undefined' };
|
|
64
|
+
case ts.SyntaxKind.NullKeyword: return { raw, name: 'null' };
|
|
65
|
+
case ts.SyntaxKind.AnyKeyword: return { raw, name: 'any' };
|
|
66
|
+
case ts.SyntaxKind.UnknownKeyword: return { raw, name: 'unknown' };
|
|
67
|
+
}
|
|
68
|
+
// Object literal type: { title: string; limit: number }
|
|
69
|
+
if (ts.isTypeLiteralNode(node)) {
|
|
70
|
+
return { raw, name: raw };
|
|
71
|
+
}
|
|
72
|
+
// Fallback
|
|
73
|
+
return { raw, name: raw };
|
|
74
|
+
}
|
|
75
|
+
// ── Module resolution ────────────────────────
|
|
76
|
+
const TS_KEYWORDS = new Set([
|
|
77
|
+
'string', 'number', 'boolean', 'void', 'undefined', 'null', 'any', 'unknown',
|
|
78
|
+
'never', 'object', 'symbol', 'bigint',
|
|
79
|
+
]);
|
|
80
|
+
/**
|
|
81
|
+
* Resolve an imported identifier to its source file path.
|
|
82
|
+
* Handles relative imports (./) and workspace packages (@fougere/*).
|
|
83
|
+
*/
|
|
84
|
+
function resolveImportPath(source, identifierName, filePath, projectRoot) {
|
|
85
|
+
const ts = getTS();
|
|
86
|
+
for (const stmt of source.statements) {
|
|
87
|
+
if (!ts.isImportDeclaration(stmt))
|
|
88
|
+
continue;
|
|
89
|
+
if (!ts.isStringLiteral(stmt.moduleSpecifier))
|
|
90
|
+
continue;
|
|
91
|
+
const bindings = stmt.importClause;
|
|
92
|
+
if (!bindings)
|
|
93
|
+
continue;
|
|
94
|
+
// Named imports: import { Crud } from '...'
|
|
95
|
+
if (bindings.namedBindings && ts.isNamedImports(bindings.namedBindings)) {
|
|
96
|
+
const found = bindings.namedBindings.elements.some((e) => e.name.text === identifierName);
|
|
97
|
+
if (!found)
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// Default import: import X from '...'
|
|
101
|
+
else if (bindings.name?.text !== identifierName) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const specifier = stmt.moduleSpecifier.text;
|
|
105
|
+
return resolveSpecifier(specifier, filePath, projectRoot);
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
/** Resolve an import specifier to an absolute file path. */
|
|
110
|
+
function resolveSpecifier(specifier, fromFile, projectRoot) {
|
|
111
|
+
// Relative import
|
|
112
|
+
if (specifier.startsWith('.')) {
|
|
113
|
+
const dir = dirname(fromFile);
|
|
114
|
+
let resolved = resolvePath(dir, specifier);
|
|
115
|
+
// .js → .ts
|
|
116
|
+
if (resolved.endsWith('.js'))
|
|
117
|
+
resolved = resolved.slice(0, -3) + '.ts';
|
|
118
|
+
if (!resolved.endsWith('.ts'))
|
|
119
|
+
resolved += '.ts';
|
|
120
|
+
if (existsSync(resolved))
|
|
121
|
+
return resolved;
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
// Workspace package: @fougere/core → packages/core/src/index.ts
|
|
125
|
+
const match = specifier.match(/^@fougere\/([^/]+)$/);
|
|
126
|
+
if (match) {
|
|
127
|
+
const pkgDir = join(projectRoot, 'packages', match[1], 'src');
|
|
128
|
+
const indexPath = join(pkgDir, 'index.ts');
|
|
129
|
+
if (existsSync(indexPath))
|
|
130
|
+
return indexPath;
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Follow re-exports in an index file to find the source of a named export.
|
|
136
|
+
* e.g. `export { Crud } from './crud.js'` → resolves to crud.ts
|
|
137
|
+
*/
|
|
138
|
+
function followReExport(indexPath, identifierName, projectRoot) {
|
|
139
|
+
const ts = getTS();
|
|
140
|
+
const content = readFileSync(indexPath, 'utf-8');
|
|
141
|
+
const source = ts.createSourceFile(indexPath, content, ts.ScriptTarget.Latest, true);
|
|
142
|
+
for (const stmt of source.statements) {
|
|
143
|
+
if (!ts.isExportDeclaration(stmt))
|
|
144
|
+
continue;
|
|
145
|
+
if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier))
|
|
146
|
+
continue;
|
|
147
|
+
// export { Crud } from './crud.js'
|
|
148
|
+
if (stmt.exportClause && ts.isNamedExports(stmt.exportClause)) {
|
|
149
|
+
const found = stmt.exportClause.elements.some((e) => {
|
|
150
|
+
const exportedName = e.name.text;
|
|
151
|
+
const localName = e.propertyName?.text ?? e.name.text;
|
|
152
|
+
return exportedName === identifierName || localName === identifierName;
|
|
153
|
+
});
|
|
154
|
+
if (!found)
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
// export * from './crud.js' — also follow (could contain the identifier)
|
|
158
|
+
const resolved = resolveSpecifier(stmt.moduleSpecifier.text, indexPath, projectRoot);
|
|
159
|
+
if (resolved)
|
|
160
|
+
return resolved;
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Find the full source file for an identifier, following re-exports if needed.
|
|
166
|
+
*/
|
|
167
|
+
function resolveIdentifierSource(source, identifierName, filePath, projectRoot) {
|
|
168
|
+
const importPath = resolveImportPath(source, identifierName, filePath, projectRoot);
|
|
169
|
+
if (!importPath)
|
|
170
|
+
return undefined;
|
|
171
|
+
// If it's an index file, follow re-exports
|
|
172
|
+
if (importPath.endsWith('index.ts')) {
|
|
173
|
+
return followReExport(importPath, identifierName, projectRoot) ?? importPath;
|
|
174
|
+
}
|
|
175
|
+
return importPath;
|
|
176
|
+
}
|
|
177
|
+
// ── Mixin / heritage parsing ─────────────────
|
|
178
|
+
/**
|
|
179
|
+
* The class a returned expression carries, however it is wrapped.
|
|
180
|
+
*
|
|
181
|
+
* A mixin does not always hand its class back bare. `Crud` returns
|
|
182
|
+
* `asCrudConstructor(class CrudHandler { … })` — one assertion helper standing between
|
|
183
|
+
* `return` and the class — and a parser accepting only a bare `return class` found
|
|
184
|
+
* nothing there, silently: the five inherited CRUD ops stopped being derived, and a warm
|
|
185
|
+
* scan cache kept answering the old parse for weeks (`scan-cache.ts` keys on source, not
|
|
186
|
+
* on parser version).
|
|
187
|
+
*
|
|
188
|
+
* So unwrap rather than match one shape: descend through call arguments, `as` and
|
|
189
|
+
* `satisfies` assertions, and parentheses. What is looked for is a class; where the
|
|
190
|
+
* author put it is their business.
|
|
191
|
+
*/
|
|
192
|
+
function classInExpression(expr, depth = 0) {
|
|
193
|
+
const ts = getTS();
|
|
194
|
+
if (depth > 8)
|
|
195
|
+
return undefined;
|
|
196
|
+
if (ts.isClassExpression(expr))
|
|
197
|
+
return expr;
|
|
198
|
+
if (ts.isCallExpression(expr)) {
|
|
199
|
+
for (const arg of expr.arguments) {
|
|
200
|
+
const found = classInExpression(arg, depth + 1);
|
|
201
|
+
if (found)
|
|
202
|
+
return found;
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
if (ts.isAsExpression(expr) || ts.isSatisfiesExpression(expr) || ts.isParenthesizedExpression(expr)) {
|
|
207
|
+
return classInExpression(expr.expression, depth + 1);
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
/** Find a class declaration inside a function (mixin pattern). */
|
|
212
|
+
function findClassInFunction(source, functionName) {
|
|
213
|
+
const ts = getTS();
|
|
214
|
+
for (const stmt of source.statements) {
|
|
215
|
+
if (!ts.isFunctionDeclaration(stmt))
|
|
216
|
+
continue;
|
|
217
|
+
if (stmt.name?.text !== functionName)
|
|
218
|
+
continue;
|
|
219
|
+
if (!stmt.body)
|
|
220
|
+
continue;
|
|
221
|
+
// Walk statements inside the function
|
|
222
|
+
for (const inner of stmt.body.statements) {
|
|
223
|
+
// return class CrudHandler { … }, or the same class behind a wrapper
|
|
224
|
+
if (ts.isReturnStatement(inner) && inner.expression) {
|
|
225
|
+
const found = classInExpression(inner.expression);
|
|
226
|
+
if (found)
|
|
227
|
+
return found;
|
|
228
|
+
}
|
|
229
|
+
// class CrudHandler { ... } (followed by return)
|
|
230
|
+
if (ts.isClassDeclaration(inner))
|
|
231
|
+
return inner;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
/** Recursively substitute type names in a ParsedType. */
|
|
237
|
+
function substituteType(type, sub) {
|
|
238
|
+
const newName = sub.get(type.name) ?? type.name;
|
|
239
|
+
const newGenerics = type.generics?.map((g) => substituteType(g, sub));
|
|
240
|
+
if (newName === type.name && !newGenerics)
|
|
241
|
+
return type;
|
|
242
|
+
return {
|
|
243
|
+
...type,
|
|
244
|
+
name: newName,
|
|
245
|
+
raw: type.raw, // keep original raw for debugging
|
|
246
|
+
generics: newGenerics ?? type.generics,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/** Substitute all type references in parsed methods. */
|
|
250
|
+
function substituteMethods(methods, sub) {
|
|
251
|
+
return methods.map((m) => ({
|
|
252
|
+
...m,
|
|
253
|
+
params: m.params.map((p) => ({
|
|
254
|
+
...p,
|
|
255
|
+
type: substituteType(p.type, sub),
|
|
256
|
+
})),
|
|
257
|
+
returnType: m.returnType ? substituteType(m.returnType, sub) : undefined,
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Detect generic type references in methods — names that are not keywords
|
|
262
|
+
* and not imported in the given source file.
|
|
263
|
+
*/
|
|
264
|
+
function detectGenericNames(methods, source) {
|
|
265
|
+
const ts = getTS();
|
|
266
|
+
const imported = new Set();
|
|
267
|
+
for (const stmt of source.statements) {
|
|
268
|
+
if (!ts.isImportDeclaration(stmt))
|
|
269
|
+
continue;
|
|
270
|
+
const bindings = stmt.importClause;
|
|
271
|
+
if (!bindings)
|
|
272
|
+
continue;
|
|
273
|
+
if (bindings.name)
|
|
274
|
+
imported.add(bindings.name.text);
|
|
275
|
+
if (bindings.namedBindings && ts.isNamedImports(bindings.namedBindings)) {
|
|
276
|
+
for (const el of bindings.namedBindings.elements)
|
|
277
|
+
imported.add(el.name.text);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const generics = new Set();
|
|
281
|
+
const collectFromType = (t) => {
|
|
282
|
+
if (t.name.length <= 2 && /^[A-Z]/.test(t.name) && !TS_KEYWORDS.has(t.name) && !imported.has(t.name)) {
|
|
283
|
+
generics.add(t.name);
|
|
284
|
+
}
|
|
285
|
+
t.generics?.forEach(collectFromType);
|
|
286
|
+
};
|
|
287
|
+
for (const m of methods) {
|
|
288
|
+
m.params.forEach((p) => collectFromType(p.type));
|
|
289
|
+
if (m.returnType)
|
|
290
|
+
collectFromType(m.returnType);
|
|
291
|
+
}
|
|
292
|
+
return generics;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Extract methods from a class node (no file reading — works on already-parsed AST).
|
|
296
|
+
*/
|
|
297
|
+
function extractClassMethods(cls, source, skip) {
|
|
298
|
+
const ts = getTS();
|
|
299
|
+
const results = [];
|
|
300
|
+
for (const member of cls.members) {
|
|
301
|
+
if (!ts.isMethodDeclaration(member))
|
|
302
|
+
continue;
|
|
303
|
+
if (!member.name || !ts.isIdentifier(member.name))
|
|
304
|
+
continue;
|
|
305
|
+
// `private`/`protected` is a statement about the surface, and the AST carries it —
|
|
306
|
+
// it was read past. Every helper a handler names by intent (`mustOwn`, `readMany`,
|
|
307
|
+
// `refuse`) became a callable op: measured on the bench, `list.readMany` executed
|
|
308
|
+
// and `list.mayPublish` judged its argument. A door is what the author declares
|
|
309
|
+
// public, and TypeScript already has the word for it. `#name` is private too, but
|
|
310
|
+
// it is not an identifier, so it never reached here in the first place.
|
|
311
|
+
if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword))
|
|
312
|
+
continue;
|
|
313
|
+
const name = member.name.text;
|
|
314
|
+
if (skip.has(name))
|
|
315
|
+
continue;
|
|
316
|
+
const params = member.parameters.map((p) => ({
|
|
317
|
+
name: ts.isIdentifier(p.name) ? p.name.text : p.name.getText(source),
|
|
318
|
+
type: p.type ? parseTypeNode(p.type, source) : { raw: 'unknown', name: 'unknown' },
|
|
319
|
+
optional: p.questionToken !== undefined || p.initializer !== undefined,
|
|
320
|
+
}));
|
|
321
|
+
const returnType = member.type ? parseTypeNode(member.type, source) : undefined;
|
|
322
|
+
results.push({ name, params, returnType, description: docSentenceOf(member, source) });
|
|
323
|
+
}
|
|
324
|
+
return results;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* The first sentence of a member's doc comment, or nothing.
|
|
328
|
+
*
|
|
329
|
+
* One sentence on purpose: what a caller needs to choose an operation is a claim,
|
|
330
|
+
* not an essay, and the rest of the comment addresses whoever edits the method.
|
|
331
|
+
* Reads the leading trivia rather than `ts.getJSDocTags` — the comment is what the
|
|
332
|
+
* author wrote, tags are a schema they never agreed to.
|
|
333
|
+
*/
|
|
334
|
+
function docSentenceOf(member, source) {
|
|
335
|
+
const ts = getTS();
|
|
336
|
+
const ranges = ts.getLeadingCommentRanges(source.text, member.pos) ?? [];
|
|
337
|
+
const block = ranges.filter((r) => source.text.slice(r.pos, r.pos + 3) === '/**').pop();
|
|
338
|
+
if (!block)
|
|
339
|
+
return undefined;
|
|
340
|
+
const body = source.text
|
|
341
|
+
.slice(block.pos + 3, block.end - 2)
|
|
342
|
+
.split('\n')
|
|
343
|
+
.map((line) => line.replace(/^\s*\*/, '').trim())
|
|
344
|
+
.join(' ')
|
|
345
|
+
.trim();
|
|
346
|
+
const [sentence] = body.split(/(?<=\.)\s/);
|
|
347
|
+
return sentence?.trim() || undefined;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Parse inherited methods from a class's heritage clause.
|
|
351
|
+
* Handles both `extends Crud(Entity)` (mixin) and `extends BaseClass` patterns.
|
|
352
|
+
*/
|
|
353
|
+
function parseInheritedMethods(cls, source, filePath, projectRoot, skip,
|
|
354
|
+
/**
|
|
355
|
+
* Base classes this pass could not open — an INSTALLED one, typically, whose
|
|
356
|
+
* source is not in the workspace. Reported rather than treated as "no inherited
|
|
357
|
+
* method": the two used to be the same answer, so an op inherited from a
|
|
358
|
+
* published base class was absent from the façade without a word.
|
|
359
|
+
*/
|
|
360
|
+
unresolved) {
|
|
361
|
+
const ts = getTS();
|
|
362
|
+
if (!cls.heritageClauses)
|
|
363
|
+
return [];
|
|
364
|
+
for (const clause of cls.heritageClauses) {
|
|
365
|
+
if (clause.token !== ts.SyntaxKind.ExtendsKeyword)
|
|
366
|
+
continue;
|
|
367
|
+
for (const baseType of clause.types) {
|
|
368
|
+
const expr = baseType.expression;
|
|
369
|
+
// extends Crud(Entity) — mixin pattern (CallExpression)
|
|
370
|
+
if (ts.isCallExpression(expr) && ts.isIdentifier(expr.expression)) {
|
|
371
|
+
const mixinName = expr.expression.text;
|
|
372
|
+
// Extract mixin argument name (the entity identifier)
|
|
373
|
+
const mixinArgs = expr.arguments
|
|
374
|
+
.filter(ts.isIdentifier)
|
|
375
|
+
.map((a) => a.text);
|
|
376
|
+
const mixinFile = resolveIdentifierSource(source, mixinName, filePath, projectRoot);
|
|
377
|
+
if (!mixinFile) {
|
|
378
|
+
unresolved.push(`${mixinName}(…)`);
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const mixinContent = readFileSync(mixinFile, 'utf-8');
|
|
382
|
+
const mixinSource = ts.createSourceFile(mixinFile, mixinContent, ts.ScriptTarget.Latest, true);
|
|
383
|
+
const innerClass = findClassInFunction(mixinSource, mixinName);
|
|
384
|
+
if (!innerClass) {
|
|
385
|
+
unresolved.push(`${mixinName}(…)`);
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
const parentMethods = extractClassMethods(innerClass, mixinSource, skip);
|
|
389
|
+
// Build substitution map: detect generics in parent methods, map to mixin args
|
|
390
|
+
const genericNames = detectGenericNames(parentMethods, mixinSource);
|
|
391
|
+
if (genericNames.size > 0 && mixinArgs.length > 0) {
|
|
392
|
+
const sub = new Map();
|
|
393
|
+
const genericArr = [...genericNames];
|
|
394
|
+
// Map generics to mixin arguments by position (usually just T → Entity)
|
|
395
|
+
for (let i = 0; i < Math.min(genericArr.length, mixinArgs.length); i++) {
|
|
396
|
+
sub.set(genericArr[i], mixinArgs[i]);
|
|
397
|
+
}
|
|
398
|
+
return substituteMethods(parentMethods, sub);
|
|
399
|
+
}
|
|
400
|
+
return parentMethods;
|
|
401
|
+
}
|
|
402
|
+
// extends BaseClass — simple inheritance (Identifier)
|
|
403
|
+
if (ts.isIdentifier(expr)) {
|
|
404
|
+
const parentName = expr.text;
|
|
405
|
+
const parentFile = resolveIdentifierSource(source, parentName, filePath, projectRoot);
|
|
406
|
+
if (!parentFile) {
|
|
407
|
+
unresolved.push(parentName);
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
const parentContent = readFileSync(parentFile, 'utf-8');
|
|
411
|
+
const parentSource = ts.createSourceFile(parentFile, parentContent, ts.ScriptTarget.Latest, true);
|
|
412
|
+
const parentClass = findDefaultClass(parentSource);
|
|
413
|
+
if (!parentClass) {
|
|
414
|
+
unresolved.push(parentName);
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
return extractClassMethods(parentClass, parentSource, skip);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return [];
|
|
422
|
+
}
|
|
423
|
+
// ── Class finding ────────────────────────────
|
|
424
|
+
/** Find the default exported class in a source file. */
|
|
425
|
+
function findDefaultClass(source) {
|
|
426
|
+
const ts = getTS();
|
|
427
|
+
for (const stmt of source.statements) {
|
|
428
|
+
// export default class Foo { ... }
|
|
429
|
+
if (ts.isClassDeclaration(stmt) && stmt.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) && stmt.modifiers?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)) {
|
|
430
|
+
return stmt;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// export default Foo (separate statement) — find the class it points to
|
|
434
|
+
for (const stmt of source.statements) {
|
|
435
|
+
if (ts.isExportAssignment(stmt) && !stmt.isExportEquals && ts.isIdentifier(stmt.expression)) {
|
|
436
|
+
const name = stmt.expression.text;
|
|
437
|
+
for (const s of source.statements) {
|
|
438
|
+
if (ts.isClassDeclaration(s) && s.name?.text === name)
|
|
439
|
+
return s;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return undefined;
|
|
444
|
+
}
|
|
445
|
+
export async function parseAllHandlerMethods(filePath, projectRoot) {
|
|
446
|
+
await loadTS();
|
|
447
|
+
return parseClassMethods(filePath, CONSTRUCTOR_ONLY, projectRoot);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Parse a presenter source file and extract all method signatures.
|
|
451
|
+
*
|
|
452
|
+
* Returns all methods (no CRUD filtering) — each method is a computed field.
|
|
453
|
+
*/
|
|
454
|
+
export async function parsePresenterMethods(filePath) {
|
|
455
|
+
await loadTS();
|
|
456
|
+
// No `projectRoot`, so no heritage pass and nothing to report: a presenter's
|
|
457
|
+
// computed fields are its own methods.
|
|
458
|
+
return parseClassMethods(filePath, CONSTRUCTOR_ONLY).methods;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Parse constructor parameter types from a source file's default class.
|
|
462
|
+
* Returns type names (e.g. ['PostOrm', 'Logger']) for DI resolution.
|
|
463
|
+
*/
|
|
464
|
+
export async function parseConstructorParams(filePath) {
|
|
465
|
+
const ts = await loadTS();
|
|
466
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
467
|
+
const source = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
468
|
+
const cls = findDefaultClass(source);
|
|
469
|
+
if (!cls)
|
|
470
|
+
return [];
|
|
471
|
+
for (const member of cls.members) {
|
|
472
|
+
if (ts.isConstructorDeclaration(member)) {
|
|
473
|
+
return member.parameters.map((p) => ({
|
|
474
|
+
name: ts.isIdentifier(p.name) ? p.name.text : p.name.getText(source),
|
|
475
|
+
type: p.type ? parseTypeNode(p.type, source) : { raw: 'unknown', name: 'unknown' },
|
|
476
|
+
optional: p.questionToken !== undefined || p.initializer !== undefined,
|
|
477
|
+
}));
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return [];
|
|
481
|
+
}
|
|
482
|
+
const CONSTRUCTOR_ONLY = new Set(['constructor']);
|
|
483
|
+
function parseClassMethods(filePath, skip, projectRoot) {
|
|
484
|
+
const ts = getTS();
|
|
485
|
+
const unresolved = [];
|
|
486
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
487
|
+
const source = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
488
|
+
const cls = findDefaultClass(source);
|
|
489
|
+
if (!cls)
|
|
490
|
+
return { methods: [], unresolvedHeritage: unresolved };
|
|
491
|
+
// Parse child class methods
|
|
492
|
+
const childMethods = extractClassMethods(cls, source, skip);
|
|
493
|
+
const childNames = new Set(childMethods.map((m) => m.name));
|
|
494
|
+
// Parse inherited methods (if projectRoot is provided for resolution)
|
|
495
|
+
if (projectRoot) {
|
|
496
|
+
const inherited = parseInheritedMethods(cls, source, filePath, projectRoot, skip, unresolved);
|
|
497
|
+
// Merge: child methods win over inherited
|
|
498
|
+
const parentOnly = inherited
|
|
499
|
+
.filter((m) => !childNames.has(m.name))
|
|
500
|
+
.map((m) => ({ ...m, inherited: true }));
|
|
501
|
+
return { methods: [...childMethods, ...parentOnly], unresolvedHeritage: unresolved };
|
|
502
|
+
}
|
|
503
|
+
return { methods: childMethods, unresolvedHeritage: unresolved };
|
|
504
|
+
}
|
|
505
|
+
//# sourceMappingURL=handler-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-parser.js","sourceRoot":"","sources":["../src/handler-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FrondDescriptor } from './types.js';
|
|
2
|
+
export interface CrossFrondImport {
|
|
3
|
+
/** Stable rule name — the same vocabulary `verify()` uses. */
|
|
4
|
+
rule: 'cross-frond-import';
|
|
5
|
+
/** The frond doing the reaching. */
|
|
6
|
+
frond: string;
|
|
7
|
+
filePath: string;
|
|
8
|
+
/** The specifier as written. */
|
|
9
|
+
specifier: string;
|
|
10
|
+
/** The frond the path lands in — absent when it lands outside every frond. */
|
|
11
|
+
target?: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Every relative import that resolves outside its own frond.
|
|
16
|
+
*
|
|
17
|
+
* `preProcessFile` rather than a regex or a full parse: it is TypeScript's own scanner for
|
|
18
|
+
* exactly this question, so `// import x from '../../other'` in a comment is not a finding
|
|
19
|
+
* and a specifier split across lines still is.
|
|
20
|
+
*/
|
|
21
|
+
export declare function crossFrondImports(fronds: ReadonlyArray<Pick<FrondDescriptor, 'name' | 'source'>>): Promise<CrossFrondImport[]>;
|
|
22
|
+
//# sourceMappingURL=imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../src/imports.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAQlD,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,IAAI,EAAE,oBAAoB,CAAC;IAC3B,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AA2BD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,GAC9D,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoC7B"}
|
package/dist/imports.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { join, resolve, dirname, relative, isAbsolute } from 'node:path';
|
|
3
|
+
let _ts;
|
|
4
|
+
async function loadTs() {
|
|
5
|
+
if (!_ts)
|
|
6
|
+
_ts = (await import('typescript')).default;
|
|
7
|
+
return _ts;
|
|
8
|
+
}
|
|
9
|
+
/** Is `child` inside `parent`? Path-based, so it says nothing about either existing. */
|
|
10
|
+
function inside(parent, child) {
|
|
11
|
+
const rel = relative(parent, child);
|
|
12
|
+
return rel !== '' && !rel.startsWith('..') && !isAbsolute(rel);
|
|
13
|
+
}
|
|
14
|
+
async function sourcesUnder(dir) {
|
|
15
|
+
const out = [];
|
|
16
|
+
let entries;
|
|
17
|
+
try {
|
|
18
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Unreadable is the scan's complaint, not this rule's — and an absent directory is
|
|
22
|
+
// ordinary (a frond with no handlers).
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
for (const entry of entries) {
|
|
26
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.'))
|
|
27
|
+
continue;
|
|
28
|
+
const full = join(dir, entry.name);
|
|
29
|
+
if (entry.isDirectory())
|
|
30
|
+
out.push(...await sourcesUnder(full));
|
|
31
|
+
else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts'))
|
|
32
|
+
out.push(full);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Every relative import that resolves outside its own frond.
|
|
38
|
+
*
|
|
39
|
+
* `preProcessFile` rather than a regex or a full parse: it is TypeScript's own scanner for
|
|
40
|
+
* exactly this question, so `// import x from '../../other'` in a comment is not a finding
|
|
41
|
+
* and a specifier split across lines still is.
|
|
42
|
+
*/
|
|
43
|
+
export async function crossFrondImports(fronds) {
|
|
44
|
+
const typescript = await loadTs();
|
|
45
|
+
const roots = fronds.map((frond) => ({ name: frond.name, path: resolve(frond.source.path) }));
|
|
46
|
+
const found = [];
|
|
47
|
+
for (const root of roots) {
|
|
48
|
+
for (const filePath of await sourcesUnder(root.path)) {
|
|
49
|
+
const text = await readFile(filePath, 'utf8').catch(() => undefined);
|
|
50
|
+
if (text === undefined)
|
|
51
|
+
continue;
|
|
52
|
+
for (const { fileName: specifier } of typescript.preProcessFile(text, true, true).importedFiles) {
|
|
53
|
+
if (!specifier.startsWith('.'))
|
|
54
|
+
continue;
|
|
55
|
+
const landed = resolve(dirname(filePath), specifier);
|
|
56
|
+
if (inside(root.path, landed))
|
|
57
|
+
continue;
|
|
58
|
+
const target = roots.find((other) => other.name !== root.name && inside(other.path, landed));
|
|
59
|
+
found.push({
|
|
60
|
+
rule: 'cross-frond-import',
|
|
61
|
+
frond: root.name,
|
|
62
|
+
filePath,
|
|
63
|
+
specifier,
|
|
64
|
+
...(target ? { target: target.name } : {}),
|
|
65
|
+
message: target
|
|
66
|
+
? `'${specifier}' resolves into frond '${target.name}'. A relative path states that `
|
|
67
|
+
+ `these two fronds share a directory tree — a constraint nothing declares, and one `
|
|
68
|
+
+ `that nothing here can see. Write '@frond/${target.name}/…' instead: it says the `
|
|
69
|
+
+ `same dependency in terms the model reads, and it is the form \`fougere sync\` writes, `
|
|
70
|
+
+ `so it survives '${target.name}' moving out.`
|
|
71
|
+
: `'${specifier}' resolves outside frond '${root.name}', into no frond at all. `
|
|
72
|
+
+ `Whatever it reaches is not part of any frond's contract, so nothing carries it `
|
|
73
|
+
+ `when this one is deployed on its own.`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return found;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../src/imports.ts"],"names":[],"mappings":"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"}
|