@ophan/core 0.0.2 → 0.0.3
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/dist/community-detectors/index.d.ts +20 -0
- package/dist/community-detectors/index.d.ts.map +1 -0
- package/dist/community-detectors/index.js +45 -0
- package/dist/community-detectors/label-prop.d.ts +20 -0
- package/dist/community-detectors/label-prop.d.ts.map +1 -0
- package/dist/community-detectors/label-prop.js +77 -0
- package/dist/community-detectors/leiden.d.ts +22 -0
- package/dist/community-detectors/leiden.d.ts.map +1 -0
- package/dist/community-detectors/leiden.js +312 -0
- package/dist/community-detectors/louvain.d.ts +13 -0
- package/dist/community-detectors/louvain.d.ts.map +1 -0
- package/dist/community-detectors/louvain.js +29 -0
- package/dist/community-detectors/types.d.ts +36 -0
- package/dist/community-detectors/types.d.ts.map +1 -0
- package/dist/{parsers/__fixtures__/no-functions.js → community-detectors/types.js} +0 -2
- package/dist/edge-resolvers/call.d.ts +13 -0
- package/dist/edge-resolvers/call.d.ts.map +1 -0
- package/dist/edge-resolvers/call.js +40 -0
- package/dist/edge-resolvers/co-location.d.ts +16 -0
- package/dist/edge-resolvers/co-location.d.ts.map +1 -0
- package/dist/edge-resolvers/co-location.js +129 -0
- package/dist/edge-resolvers/import.d.ts +16 -0
- package/dist/edge-resolvers/import.d.ts.map +1 -0
- package/dist/edge-resolvers/import.js +118 -0
- package/dist/edge-resolvers/index.d.ts +9 -0
- package/dist/edge-resolvers/index.d.ts.map +1 -0
- package/dist/edge-resolvers/index.js +29 -0
- package/dist/edge-resolvers/jsx-ref.d.ts +13 -0
- package/dist/edge-resolvers/jsx-ref.d.ts.map +1 -0
- package/dist/edge-resolvers/jsx-ref.js +40 -0
- package/dist/edge-resolvers/types.d.ts +40 -0
- package/dist/edge-resolvers/types.d.ts.map +1 -0
- package/dist/edge-resolvers/types.js +2 -0
- package/dist/graph.d.ts +293 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +1295 -0
- package/dist/index.d.ts +37 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +385 -183
- package/dist/migrations.d.ts +25 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +323 -0
- package/dist/module-resolvers/index.d.ts +11 -0
- package/dist/module-resolvers/index.d.ts.map +1 -0
- package/dist/module-resolvers/index.js +67 -0
- package/dist/module-resolvers/javascript.d.ts +18 -0
- package/dist/module-resolvers/javascript.d.ts.map +1 -0
- package/dist/module-resolvers/javascript.js +130 -0
- package/dist/module-resolvers/types.d.ts +18 -0
- package/dist/module-resolvers/types.d.ts.map +1 -0
- package/dist/module-resolvers/types.js +2 -0
- package/dist/parsers/python.d.ts.map +1 -1
- package/dist/parsers/python.js +38 -4
- package/dist/parsers/typescript.d.ts.map +1 -1
- package/dist/parsers/typescript.js +133 -0
- package/dist/practices.d.ts +28 -0
- package/dist/practices.d.ts.map +1 -0
- package/dist/practices.js +95 -0
- package/dist/schemas.d.ts +251 -3
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +121 -6
- package/dist/shared.d.ts +8 -0
- package/dist/shared.d.ts.map +1 -1
- package/dist/summarize.d.ts +165 -0
- package/dist/summarize.d.ts.map +1 -0
- package/dist/summarize.js +1067 -0
- package/ophan_logo.png +0 -0
- package/package.json +9 -2
- package/dist/parsers/__fixtures__/arrow-functions.d.ts +0 -5
- package/dist/parsers/__fixtures__/arrow-functions.d.ts.map +0 -1
- package/dist/parsers/__fixtures__/arrow-functions.js +0 -16
- package/dist/parsers/__fixtures__/class-methods.d.ts +0 -6
- package/dist/parsers/__fixtures__/class-methods.d.ts.map +0 -1
- package/dist/parsers/__fixtures__/class-methods.js +0 -12
- package/dist/parsers/__fixtures__/no-functions.d.ts +0 -9
- package/dist/parsers/__fixtures__/no-functions.d.ts.map +0 -1
package/dist/parsers/python.js
CHANGED
|
@@ -65,6 +65,28 @@ for node in ast.walk(tree):
|
|
|
65
65
|
for child in ast.iter_child_nodes(node):
|
|
66
66
|
child._parent = node
|
|
67
67
|
|
|
68
|
+
# Extract file-level imports
|
|
69
|
+
file_imports = []
|
|
70
|
+
for node in ast.iter_child_nodes(tree):
|
|
71
|
+
if isinstance(node, ast.Import):
|
|
72
|
+
for alias in node.names:
|
|
73
|
+
file_imports.append({"module": alias.name, "names": [alias.asname or alias.name]})
|
|
74
|
+
elif isinstance(node, ast.ImportFrom):
|
|
75
|
+
module = node.module or ""
|
|
76
|
+
names = [alias.name for alias in node.names]
|
|
77
|
+
file_imports.append({"module": module, "names": names})
|
|
78
|
+
|
|
79
|
+
# Extract call names from a function body
|
|
80
|
+
# Only direct function calls (ast.Name), not method calls (ast.Attribute)
|
|
81
|
+
# Method calls like obj.method() produce false matches against library APIs
|
|
82
|
+
def get_calls(func_node):
|
|
83
|
+
calls = set()
|
|
84
|
+
for node in ast.walk(func_node):
|
|
85
|
+
if isinstance(node, ast.Call):
|
|
86
|
+
if isinstance(node.func, ast.Name):
|
|
87
|
+
calls.add(node.func.id)
|
|
88
|
+
return sorted(calls)
|
|
89
|
+
|
|
68
90
|
functions = []
|
|
69
91
|
lines = source.split('\\n')
|
|
70
92
|
|
|
@@ -76,15 +98,20 @@ for node in ast.walk(tree):
|
|
|
76
98
|
parent = getattr(node, '_parent', None)
|
|
77
99
|
entity_type = "method" if isinstance(parent, ast.ClassDef) else "function"
|
|
78
100
|
|
|
101
|
+
# Module-level functions (not nested in class or other function) are "exported"
|
|
102
|
+
exported = isinstance(parent, ast.Module)
|
|
103
|
+
|
|
79
104
|
functions.append({
|
|
80
105
|
"name": node.name,
|
|
81
106
|
"startLine": node.lineno,
|
|
82
107
|
"endLine": end_line,
|
|
83
108
|
"sourceCode": source_code,
|
|
84
|
-
"entityType": entity_type
|
|
109
|
+
"entityType": entity_type,
|
|
110
|
+
"calls": get_calls(node),
|
|
111
|
+
"exported": exported
|
|
85
112
|
})
|
|
86
113
|
|
|
87
|
-
json.dump(functions, sys.stdout)
|
|
114
|
+
json.dump({"functions": functions, "imports": file_imports}, sys.stdout)
|
|
88
115
|
`;
|
|
89
116
|
let pythonAvailable = null;
|
|
90
117
|
function isPythonAvailable() {
|
|
@@ -116,8 +143,12 @@ class PythonParser {
|
|
|
116
143
|
encoding: "utf-8",
|
|
117
144
|
timeout: 10000, // 10s timeout per file
|
|
118
145
|
});
|
|
119
|
-
const
|
|
120
|
-
|
|
146
|
+
const result = JSON.parse(output);
|
|
147
|
+
const fileImports = result.imports.map((imp) => ({
|
|
148
|
+
module: imp.module,
|
|
149
|
+
names: imp.names,
|
|
150
|
+
}));
|
|
151
|
+
return result.functions.map((fn) => ({
|
|
121
152
|
name: fn.name,
|
|
122
153
|
filePath,
|
|
123
154
|
startLine: fn.startLine,
|
|
@@ -126,6 +157,9 @@ class PythonParser {
|
|
|
126
157
|
contentHash: (0, shared_1.computeHash)(fn.sourceCode),
|
|
127
158
|
language: "python",
|
|
128
159
|
entityType: fn.entityType,
|
|
160
|
+
calls: fn.calls,
|
|
161
|
+
imports: fileImports,
|
|
162
|
+
exported: fn.exported,
|
|
129
163
|
}));
|
|
130
164
|
}
|
|
131
165
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/parsers/typescript.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/parsers/typescript.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,WAAW,CAAC;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAa9C,qBAAa,gBAAiB,YAAW,cAAc;IACrD,QAAQ,CAAC,QAAQ,gBAAgB;IACjC,QAAQ,CAAC,UAAU,WAAkC;IAErD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE;CAiEnD"}
|
|
@@ -67,6 +67,8 @@ class TypeScriptParser {
|
|
|
67
67
|
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
68
68
|
const language = detectLanguage(filePath);
|
|
69
69
|
const functions = [];
|
|
70
|
+
// Collect file-level imports (shared across all functions in this file)
|
|
71
|
+
const fileImports = extractImports(sourceFile);
|
|
70
72
|
function visit(node) {
|
|
71
73
|
if (ts.isFunctionDeclaration(node) ||
|
|
72
74
|
ts.isMethodDeclaration(node) ||
|
|
@@ -78,6 +80,7 @@ class TypeScriptParser {
|
|
|
78
80
|
const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
79
81
|
const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
80
82
|
const sourceCode = node.getText(sourceFile);
|
|
83
|
+
const { calls, jsxRefs } = extractCallExpressions(node, sourceFile);
|
|
81
84
|
functions.push({
|
|
82
85
|
name,
|
|
83
86
|
filePath,
|
|
@@ -87,6 +90,10 @@ class TypeScriptParser {
|
|
|
87
90
|
contentHash: (0, shared_1.computeHash)(sourceCode),
|
|
88
91
|
language,
|
|
89
92
|
entityType: detectEntityType(node),
|
|
93
|
+
calls,
|
|
94
|
+
jsxRefs: jsxRefs.length > 0 ? jsxRefs : undefined,
|
|
95
|
+
imports: fileImports,
|
|
96
|
+
exported: isExported(node),
|
|
90
97
|
});
|
|
91
98
|
}
|
|
92
99
|
ts.forEachChild(node, visit);
|
|
@@ -108,3 +115,129 @@ class TypeScriptParser {
|
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
117
|
exports.TypeScriptParser = TypeScriptParser;
|
|
118
|
+
// ============ RELATIONSHIP EXTRACTION ============
|
|
119
|
+
/**
|
|
120
|
+
* Extract call expression names and JSX component references from inside a function body.
|
|
121
|
+
* Returns separate arrays: `calls` for direct function calls (strong signal) and
|
|
122
|
+
* `jsxRefs` for JSX component references (weaker signal — UI composition, not domain logic).
|
|
123
|
+
*/
|
|
124
|
+
function extractCallExpressions(node, sourceFile) {
|
|
125
|
+
const calls = new Set();
|
|
126
|
+
const jsxRefs = new Set();
|
|
127
|
+
function walkCalls(n) {
|
|
128
|
+
if (ts.isCallExpression(n)) {
|
|
129
|
+
const name = getCallName(n.expression, sourceFile);
|
|
130
|
+
if (name)
|
|
131
|
+
calls.add(name);
|
|
132
|
+
}
|
|
133
|
+
// JSX elements: <Foo /> treated as a component reference (separate from calls)
|
|
134
|
+
if (ts.isJsxOpeningElement(n) || ts.isJsxSelfClosingElement(n)) {
|
|
135
|
+
const tagName = n.tagName;
|
|
136
|
+
if (ts.isIdentifier(tagName)) {
|
|
137
|
+
const name = tagName.getText(sourceFile);
|
|
138
|
+
// Only PascalCase (React components), not HTML elements (div, span)
|
|
139
|
+
if (name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase()) {
|
|
140
|
+
jsxRefs.add(name);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
ts.forEachChild(n, walkCalls);
|
|
145
|
+
}
|
|
146
|
+
// Walk the function body (not the signature)
|
|
147
|
+
const body = getFunctionBody(node);
|
|
148
|
+
if (body)
|
|
149
|
+
walkCalls(body);
|
|
150
|
+
return { calls: [...calls], jsxRefs: [...jsxRefs] };
|
|
151
|
+
}
|
|
152
|
+
function getCallName(expr, sourceFile) {
|
|
153
|
+
// Direct call: foo()
|
|
154
|
+
if (ts.isIdentifier(expr)) {
|
|
155
|
+
return expr.getText(sourceFile);
|
|
156
|
+
}
|
|
157
|
+
// Method calls (obj.method()) are excluded — they typically reference
|
|
158
|
+
// library APIs (db.prepare, res.json, arr.map) and produce false matches.
|
|
159
|
+
// Intra-project method calls are captured by co-location and import edges instead.
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
function getFunctionBody(node) {
|
|
163
|
+
if (ts.isFunctionDeclaration(node) ||
|
|
164
|
+
ts.isMethodDeclaration(node) ||
|
|
165
|
+
ts.isFunctionExpression(node)) {
|
|
166
|
+
return node.body || null;
|
|
167
|
+
}
|
|
168
|
+
if (ts.isArrowFunction(node)) {
|
|
169
|
+
return node.body;
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Extract import declarations from the top level of a source file.
|
|
175
|
+
*/
|
|
176
|
+
function extractImports(sourceFile) {
|
|
177
|
+
const imports = [];
|
|
178
|
+
for (const stmt of sourceFile.statements) {
|
|
179
|
+
if (!ts.isImportDeclaration(stmt))
|
|
180
|
+
continue;
|
|
181
|
+
const moduleSpec = stmt.moduleSpecifier;
|
|
182
|
+
if (!ts.isStringLiteral(moduleSpec))
|
|
183
|
+
continue;
|
|
184
|
+
const module = moduleSpec.text;
|
|
185
|
+
const names = [];
|
|
186
|
+
const clause = stmt.importClause;
|
|
187
|
+
if (clause) {
|
|
188
|
+
// Skip entire type-only imports: import type { X } from "..."
|
|
189
|
+
if (clause.isTypeOnly)
|
|
190
|
+
continue;
|
|
191
|
+
// Default import: import Foo from "..."
|
|
192
|
+
if (clause.name) {
|
|
193
|
+
names.push(clause.name.getText(sourceFile));
|
|
194
|
+
}
|
|
195
|
+
// Named imports: import { a, b } from "..."
|
|
196
|
+
if (clause.namedBindings) {
|
|
197
|
+
if (ts.isNamedImports(clause.namedBindings)) {
|
|
198
|
+
for (const el of clause.namedBindings.elements) {
|
|
199
|
+
// Skip individual type-only specifiers: import { type X, Y } from "..."
|
|
200
|
+
if (el.isTypeOnly)
|
|
201
|
+
continue;
|
|
202
|
+
names.push(el.name.getText(sourceFile));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Namespace import: import * as ns from "..."
|
|
206
|
+
if (ts.isNamespaceImport(clause.namedBindings)) {
|
|
207
|
+
names.push(clause.namedBindings.name.getText(sourceFile));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
imports.push({ module, names });
|
|
212
|
+
}
|
|
213
|
+
return imports;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Check if a function/variable declaration has the `export` modifier.
|
|
217
|
+
*/
|
|
218
|
+
function isExported(node) {
|
|
219
|
+
// Function declarations: check modifiers directly
|
|
220
|
+
if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
|
|
221
|
+
return hasExportModifier(node);
|
|
222
|
+
}
|
|
223
|
+
// Arrow functions / function expressions: check parent variable statement
|
|
224
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
225
|
+
const parent = node.parent; // VariableDeclaration
|
|
226
|
+
if (parent && ts.isVariableDeclaration(parent)) {
|
|
227
|
+
const declList = parent.parent; // VariableDeclarationList
|
|
228
|
+
if (declList && ts.isVariableDeclarationList(declList)) {
|
|
229
|
+
const varStmt = declList.parent; // VariableStatement
|
|
230
|
+
if (varStmt && ts.isVariableStatement(varStmt)) {
|
|
231
|
+
return hasExportModifier(varStmt);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
function hasExportModifier(node) {
|
|
239
|
+
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
240
|
+
if (!modifiers)
|
|
241
|
+
return false;
|
|
242
|
+
return modifiers.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
|
|
243
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { MAX_PRACTICES, MAX_RULE_LENGTH } from "./schemas";
|
|
3
|
+
export interface Practice {
|
|
4
|
+
id: string;
|
|
5
|
+
rule: string;
|
|
6
|
+
severity: "error" | "warning" | "info";
|
|
7
|
+
}
|
|
8
|
+
export { MAX_PRACTICES, MAX_RULE_LENGTH };
|
|
9
|
+
/**
|
|
10
|
+
* Load practices from the local SQLite practices table.
|
|
11
|
+
* Returns [] if table is empty or doesn't exist.
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadPracticesFromDb(db: Database.Database): Practice[];
|
|
14
|
+
/**
|
|
15
|
+
* Import practices from Supabase into the local SQLite practices table.
|
|
16
|
+
* Replaces all existing practices (full sync).
|
|
17
|
+
*/
|
|
18
|
+
export declare function importPractices(db: Database.Database, practices: Practice[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Validate practices array. Enforces limits and format.
|
|
21
|
+
* Returns the validated (possibly truncated) array.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validatePractices(practices: Practice[]): Practice[];
|
|
24
|
+
/**
|
|
25
|
+
* Build the prompt section for practices. Returns empty string if no practices.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildPracticesPrompt(practices: Practice[]): string;
|
|
28
|
+
//# sourceMappingURL=practices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"practices.d.ts","sourceRoot":"","sources":["../src/practices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;CACxC;AAED,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC;AAI1C;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,EAAE,CAcrE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,QAAQ,EAAE,GACpB,IAAI,CAWN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CA2BnE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAoBlE"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_RULE_LENGTH = exports.MAX_PRACTICES = void 0;
|
|
4
|
+
exports.loadPracticesFromDb = loadPracticesFromDb;
|
|
5
|
+
exports.importPractices = importPractices;
|
|
6
|
+
exports.validatePractices = validatePractices;
|
|
7
|
+
exports.buildPracticesPrompt = buildPracticesPrompt;
|
|
8
|
+
const schemas_1 = require("./schemas");
|
|
9
|
+
Object.defineProperty(exports, "MAX_PRACTICES", { enumerable: true, get: function () { return schemas_1.MAX_PRACTICES; } });
|
|
10
|
+
Object.defineProperty(exports, "MAX_RULE_LENGTH", { enumerable: true, get: function () { return schemas_1.MAX_RULE_LENGTH; } });
|
|
11
|
+
const ID_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
12
|
+
/**
|
|
13
|
+
* Load practices from the local SQLite practices table.
|
|
14
|
+
* Returns [] if table is empty or doesn't exist.
|
|
15
|
+
*/
|
|
16
|
+
function loadPracticesFromDb(db) {
|
|
17
|
+
try {
|
|
18
|
+
const rows = db
|
|
19
|
+
.prepare("SELECT practice_id, rule, severity FROM practices")
|
|
20
|
+
.all();
|
|
21
|
+
return rows.map((r) => ({
|
|
22
|
+
id: r.practice_id,
|
|
23
|
+
rule: r.rule,
|
|
24
|
+
severity: r.severity,
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Table doesn't exist yet (old DB without initDb migration)
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Import practices from Supabase into the local SQLite practices table.
|
|
34
|
+
* Replaces all existing practices (full sync).
|
|
35
|
+
*/
|
|
36
|
+
function importPractices(db, practices) {
|
|
37
|
+
const validated = validatePractices(practices);
|
|
38
|
+
db.transaction(() => {
|
|
39
|
+
db.prepare("DELETE FROM practices").run();
|
|
40
|
+
const insert = db.prepare("INSERT INTO practices (practice_id, rule, severity) VALUES (?, ?, ?)");
|
|
41
|
+
for (const p of validated) {
|
|
42
|
+
insert.run(p.id, p.rule, p.severity);
|
|
43
|
+
}
|
|
44
|
+
})();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate practices array. Enforces limits and format.
|
|
48
|
+
* Returns the validated (possibly truncated) array.
|
|
49
|
+
*/
|
|
50
|
+
function validatePractices(practices) {
|
|
51
|
+
if (!Array.isArray(practices))
|
|
52
|
+
return [];
|
|
53
|
+
const capped = practices.slice(0, schemas_1.MAX_PRACTICES);
|
|
54
|
+
return capped.map((p, i) => {
|
|
55
|
+
if (!p.id || typeof p.id !== "string") {
|
|
56
|
+
throw new Error(`Practice at index ${i} has invalid id: ${JSON.stringify(p.id)}`);
|
|
57
|
+
}
|
|
58
|
+
if (!ID_PATTERN.test(p.id)) {
|
|
59
|
+
throw new Error(`Practice id "${p.id}" must be kebab-case (lowercase letters, numbers, hyphens)`);
|
|
60
|
+
}
|
|
61
|
+
if (!p.rule || typeof p.rule !== "string") {
|
|
62
|
+
throw new Error(`Practice "${p.id}" has invalid rule`);
|
|
63
|
+
}
|
|
64
|
+
const severity = p.severity ?? "warning";
|
|
65
|
+
if (!["error", "warning", "info"].includes(severity)) {
|
|
66
|
+
throw new Error(`Practice "${p.id}" has invalid severity: ${severity}`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
id: p.id,
|
|
70
|
+
rule: p.rule.slice(0, schemas_1.MAX_RULE_LENGTH),
|
|
71
|
+
severity: severity,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the prompt section for practices. Returns empty string if no practices.
|
|
77
|
+
*/
|
|
78
|
+
function buildPracticesPrompt(practices) {
|
|
79
|
+
if (practices.length === 0)
|
|
80
|
+
return "";
|
|
81
|
+
const lines = practices.map((p) => `- ${p.id} [${p.severity}]: ${p.rule}`);
|
|
82
|
+
return `
|
|
83
|
+
Also check for violations of these coding practices:
|
|
84
|
+
${lines.join("\n")}
|
|
85
|
+
|
|
86
|
+
For each violation found, add an entry to practiceViolations (empty array if none), each with:
|
|
87
|
+
- flag: the practice id from the list above
|
|
88
|
+
- title: short one-line title
|
|
89
|
+
- description: what's wrong (1-2 sentences)
|
|
90
|
+
- explanation: how to fix (2-4 sentences)
|
|
91
|
+
- line: the line number (read the label, don't count)
|
|
92
|
+
- startText: first ~30 characters of the problematic code on that line
|
|
93
|
+
- endText: last ~20 characters of the problematic code on that line
|
|
94
|
+
- severity: use the severity shown in brackets above`;
|
|
95
|
+
}
|
package/dist/schemas.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
export declare const AnalysisType: z.ZodEnum<{
|
|
3
3
|
documentation: "documentation";
|
|
4
4
|
security: "security";
|
|
5
|
+
practices: "practices";
|
|
5
6
|
}>;
|
|
6
7
|
export type AnalysisType = z.infer<typeof AnalysisType>;
|
|
7
8
|
export declare const KNOWN_DATA_TAGS: readonly ["user_input", "pii", "credentials", "database", "external_api", "file_system", "config", "internal"];
|
|
@@ -34,15 +35,87 @@ export declare const DocumentationAnalysis: z.ZodObject<{
|
|
|
34
35
|
}, z.core.$strip>;
|
|
35
36
|
export type DocumentationAnalysis = z.infer<typeof DocumentationAnalysis>;
|
|
36
37
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
38
|
+
* A rich security or practice issue with location, description, and fix guidance.
|
|
39
|
+
* Every field uses .catch() so malformed Claude responses degrade gracefully.
|
|
40
|
+
* The `line` field is 1-indexed within the function (from line-numbered prompt context).
|
|
41
|
+
* `startText`/`endText` are anchor snippets for character-level precision.
|
|
42
|
+
*/
|
|
43
|
+
export declare const DetailedIssue: z.ZodObject<{
|
|
44
|
+
flag: z.ZodString;
|
|
45
|
+
title: z.ZodCatch<z.ZodString>;
|
|
46
|
+
description: z.ZodCatch<z.ZodString>;
|
|
47
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
48
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
49
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
50
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
51
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
52
|
+
error: "error";
|
|
53
|
+
warning: "warning";
|
|
54
|
+
info: "info";
|
|
55
|
+
}>>;
|
|
56
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
57
|
+
high: "high";
|
|
58
|
+
medium: "medium";
|
|
59
|
+
low: "low";
|
|
60
|
+
}>>;
|
|
61
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
62
|
+
}, z.core.$strip>;
|
|
63
|
+
export type DetailedIssue = z.infer<typeof DetailedIssue>;
|
|
64
|
+
/**
|
|
65
|
+
* Security analysis: data flow tags, vulnerability flags, and detailed issues.
|
|
66
|
+
* `securityFlags` is kept as a lightweight summary (for CodeLens icons, filtering, badge counts).
|
|
67
|
+
* `issues` provides rich details (title, description, explanation, line location).
|
|
68
|
+
* `issues` uses .catch([]) so v1 rows (without issues) parse successfully.
|
|
40
69
|
*/
|
|
41
70
|
export declare const SecurityAnalysis: z.ZodObject<{
|
|
42
71
|
dataTags: z.ZodArray<z.ZodString>;
|
|
43
72
|
securityFlags: z.ZodArray<z.ZodString>;
|
|
73
|
+
issues: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
74
|
+
flag: z.ZodString;
|
|
75
|
+
title: z.ZodCatch<z.ZodString>;
|
|
76
|
+
description: z.ZodCatch<z.ZodString>;
|
|
77
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
78
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
79
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
80
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
81
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
82
|
+
error: "error";
|
|
83
|
+
warning: "warning";
|
|
84
|
+
info: "info";
|
|
85
|
+
}>>;
|
|
86
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
87
|
+
high: "high";
|
|
88
|
+
medium: "medium";
|
|
89
|
+
low: "low";
|
|
90
|
+
}>>;
|
|
91
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
92
|
+
}, z.core.$strip>>>;
|
|
44
93
|
}, z.core.$strip>;
|
|
45
94
|
export type SecurityAnalysis = z.infer<typeof SecurityAnalysis>;
|
|
95
|
+
/** Practices analysis: violations of team-defined coding practices. */
|
|
96
|
+
export declare const PracticesAnalysis: z.ZodObject<{
|
|
97
|
+
violations: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
98
|
+
flag: z.ZodString;
|
|
99
|
+
title: z.ZodCatch<z.ZodString>;
|
|
100
|
+
description: z.ZodCatch<z.ZodString>;
|
|
101
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
102
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
103
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
104
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
105
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
106
|
+
error: "error";
|
|
107
|
+
warning: "warning";
|
|
108
|
+
info: "info";
|
|
109
|
+
}>>;
|
|
110
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
111
|
+
high: "high";
|
|
112
|
+
medium: "medium";
|
|
113
|
+
low: "low";
|
|
114
|
+
}>>;
|
|
115
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
116
|
+
}, z.core.$strip>>>;
|
|
117
|
+
}, z.core.$strip>;
|
|
118
|
+
export type PracticesAnalysis = z.infer<typeof PracticesAnalysis>;
|
|
46
119
|
export declare const TypedAnalysis: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
47
120
|
analysisType: z.ZodLiteral<"documentation">;
|
|
48
121
|
data: z.ZodObject<{
|
|
@@ -62,6 +135,50 @@ export declare const TypedAnalysis: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
62
135
|
data: z.ZodObject<{
|
|
63
136
|
dataTags: z.ZodArray<z.ZodString>;
|
|
64
137
|
securityFlags: z.ZodArray<z.ZodString>;
|
|
138
|
+
issues: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
139
|
+
flag: z.ZodString;
|
|
140
|
+
title: z.ZodCatch<z.ZodString>;
|
|
141
|
+
description: z.ZodCatch<z.ZodString>;
|
|
142
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
143
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
144
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
145
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
146
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
147
|
+
error: "error";
|
|
148
|
+
warning: "warning";
|
|
149
|
+
info: "info";
|
|
150
|
+
}>>;
|
|
151
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
152
|
+
high: "high";
|
|
153
|
+
medium: "medium";
|
|
154
|
+
low: "low";
|
|
155
|
+
}>>;
|
|
156
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
157
|
+
}, z.core.$strip>>>;
|
|
158
|
+
}, z.core.$strip>;
|
|
159
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
160
|
+
analysisType: z.ZodLiteral<"practices">;
|
|
161
|
+
data: z.ZodObject<{
|
|
162
|
+
violations: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
163
|
+
flag: z.ZodString;
|
|
164
|
+
title: z.ZodCatch<z.ZodString>;
|
|
165
|
+
description: z.ZodCatch<z.ZodString>;
|
|
166
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
167
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
168
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
169
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
170
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
171
|
+
error: "error";
|
|
172
|
+
warning: "warning";
|
|
173
|
+
info: "info";
|
|
174
|
+
}>>;
|
|
175
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
176
|
+
high: "high";
|
|
177
|
+
medium: "medium";
|
|
178
|
+
low: "low";
|
|
179
|
+
}>>;
|
|
180
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
181
|
+
}, z.core.$strip>>>;
|
|
65
182
|
}, z.core.$strip>;
|
|
66
183
|
}, z.core.$strip>], "analysisType">;
|
|
67
184
|
export type TypedAnalysis = z.infer<typeof TypedAnalysis>;
|
|
@@ -87,14 +204,145 @@ export declare const ClaudeAnalysisResponse: z.ZodObject<{
|
|
|
87
204
|
}, z.core.$strip>>;
|
|
88
205
|
dataTags: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
89
206
|
securityFlags: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
207
|
+
issues: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
208
|
+
flag: z.ZodString;
|
|
209
|
+
title: z.ZodCatch<z.ZodString>;
|
|
210
|
+
description: z.ZodCatch<z.ZodString>;
|
|
211
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
212
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
213
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
214
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
215
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
216
|
+
error: "error";
|
|
217
|
+
warning: "warning";
|
|
218
|
+
info: "info";
|
|
219
|
+
}>>;
|
|
220
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
221
|
+
high: "high";
|
|
222
|
+
medium: "medium";
|
|
223
|
+
low: "low";
|
|
224
|
+
}>>;
|
|
225
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
226
|
+
}, z.core.$strip>>>;
|
|
227
|
+
practiceViolations: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
228
|
+
flag: z.ZodString;
|
|
229
|
+
title: z.ZodCatch<z.ZodString>;
|
|
230
|
+
description: z.ZodCatch<z.ZodString>;
|
|
231
|
+
explanation: z.ZodCatch<z.ZodString>;
|
|
232
|
+
line: z.ZodCatch<z.ZodNumber>;
|
|
233
|
+
startText: z.ZodCatch<z.ZodString>;
|
|
234
|
+
endText: z.ZodCatch<z.ZodString>;
|
|
235
|
+
severity: z.ZodCatch<z.ZodEnum<{
|
|
236
|
+
error: "error";
|
|
237
|
+
warning: "warning";
|
|
238
|
+
info: "info";
|
|
239
|
+
}>>;
|
|
240
|
+
confidence: z.ZodCatch<z.ZodEnum<{
|
|
241
|
+
high: "high";
|
|
242
|
+
medium: "medium";
|
|
243
|
+
low: "low";
|
|
244
|
+
}>>;
|
|
245
|
+
lineText: z.ZodCatch<z.ZodString>;
|
|
246
|
+
}, z.core.$strip>>>;
|
|
90
247
|
}, z.core.$strip>;
|
|
91
248
|
export type ClaudeAnalysisResponse = z.infer<typeof ClaudeAnalysisResponse>;
|
|
249
|
+
export declare const SummaryMeta: z.ZodObject<{
|
|
250
|
+
securityPosture: z.ZodCatch<z.ZodString>;
|
|
251
|
+
dataClassification: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
252
|
+
boundaries: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
253
|
+
keyFunctions: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
254
|
+
complexity: z.ZodCatch<z.ZodEnum<{
|
|
255
|
+
high: "high";
|
|
256
|
+
medium: "medium";
|
|
257
|
+
low: "low";
|
|
258
|
+
}>>;
|
|
259
|
+
}, z.core.$strip>;
|
|
260
|
+
export type SummaryMeta = z.infer<typeof SummaryMeta>;
|
|
261
|
+
/** L1 subsystem summary: docs for a group of closely-related functions */
|
|
262
|
+
export declare const L1Summary: z.ZodObject<{
|
|
263
|
+
title: z.ZodCatch<z.ZodString>;
|
|
264
|
+
documentation: z.ZodCatch<z.ZodString>;
|
|
265
|
+
meta: z.ZodCatch<z.ZodObject<{
|
|
266
|
+
securityPosture: z.ZodCatch<z.ZodString>;
|
|
267
|
+
dataClassification: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
268
|
+
boundaries: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
269
|
+
keyFunctions: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
270
|
+
complexity: z.ZodCatch<z.ZodEnum<{
|
|
271
|
+
high: "high";
|
|
272
|
+
medium: "medium";
|
|
273
|
+
low: "low";
|
|
274
|
+
}>>;
|
|
275
|
+
}, z.core.$strip>>;
|
|
276
|
+
}, z.core.$strip>;
|
|
277
|
+
export type L1Summary = z.infer<typeof L1Summary>;
|
|
278
|
+
/** L2 system summary: docs for a group of L1 subsystems */
|
|
279
|
+
export declare const L2Summary: z.ZodObject<{
|
|
280
|
+
title: z.ZodCatch<z.ZodString>;
|
|
281
|
+
documentation: z.ZodCatch<z.ZodString>;
|
|
282
|
+
meta: z.ZodCatch<z.ZodObject<{
|
|
283
|
+
securityPosture: z.ZodCatch<z.ZodString>;
|
|
284
|
+
dataClassification: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
285
|
+
boundaries: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
286
|
+
keyFunctions: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
287
|
+
complexity: z.ZodCatch<z.ZodEnum<{
|
|
288
|
+
high: "high";
|
|
289
|
+
medium: "medium";
|
|
290
|
+
low: "low";
|
|
291
|
+
}>>;
|
|
292
|
+
}, z.core.$strip>>;
|
|
293
|
+
}, z.core.$strip>;
|
|
294
|
+
export type L2Summary = z.infer<typeof L2Summary>;
|
|
295
|
+
/** L3 architecture overview: top-level docs from L2 summaries */
|
|
296
|
+
export declare const L3Summary: z.ZodObject<{
|
|
297
|
+
title: z.ZodCatch<z.ZodString>;
|
|
298
|
+
documentation: z.ZodCatch<z.ZodString>;
|
|
299
|
+
meta: z.ZodCatch<z.ZodObject<{
|
|
300
|
+
securityPosture: z.ZodCatch<z.ZodString>;
|
|
301
|
+
dataClassification: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
302
|
+
boundaries: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
303
|
+
keyFunctions: z.ZodCatch<z.ZodArray<z.ZodString>>;
|
|
304
|
+
complexity: z.ZodCatch<z.ZodEnum<{
|
|
305
|
+
high: "high";
|
|
306
|
+
medium: "medium";
|
|
307
|
+
low: "low";
|
|
308
|
+
}>>;
|
|
309
|
+
}, z.core.$strip>>;
|
|
310
|
+
}, z.core.$strip>;
|
|
311
|
+
export type L3Summary = z.infer<typeof L3Summary>;
|
|
312
|
+
/** Cross-cutting concern summary: docs for a data flow or security pattern spanning communities */
|
|
313
|
+
export declare const CrossCuttingConcernSummary: z.ZodObject<{
|
|
314
|
+
title: z.ZodCatch<z.ZodString>;
|
|
315
|
+
concernType: z.ZodCatch<z.ZodString>;
|
|
316
|
+
tag: z.ZodCatch<z.ZodString>;
|
|
317
|
+
documentation: z.ZodCatch<z.ZodString>;
|
|
318
|
+
bridgeFunctions: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
319
|
+
functionName: z.ZodString;
|
|
320
|
+
contentHash: z.ZodString;
|
|
321
|
+
communityId: z.ZodString;
|
|
322
|
+
centrality: z.ZodNumber;
|
|
323
|
+
}, z.core.$strip>>>;
|
|
324
|
+
affectedCommunities: z.ZodCatch<z.ZodArray<z.ZodObject<{
|
|
325
|
+
communityId: z.ZodString;
|
|
326
|
+
communityTitle: z.ZodString;
|
|
327
|
+
}, z.core.$strip>>>;
|
|
328
|
+
severity: z.ZodCatch<z.ZodString>;
|
|
329
|
+
}, z.core.$strip>;
|
|
330
|
+
export type CrossCuttingConcernSummary = z.infer<typeof CrossCuttingConcernSummary>;
|
|
92
331
|
/**
|
|
93
332
|
* Each analysis type has an independent schema version.
|
|
94
333
|
* Bump when the JSON shape changes. Old rows remain readable.
|
|
95
334
|
* Stored alongside each row for forward-compatibility.
|
|
96
335
|
*/
|
|
97
336
|
export declare const SCHEMA_VERSIONS: Record<AnalysisType, number>;
|
|
337
|
+
export declare const MAX_PRACTICES = 10;
|
|
338
|
+
export declare const MAX_RULE_LENGTH = 200;
|
|
98
339
|
export declare const SECURITY_FLAG_LABELS: Record<string, string>;
|
|
340
|
+
export interface SecurityFlagMeta {
|
|
341
|
+
tier: 1 | 2 | 3 | 4;
|
|
342
|
+
cwe: string;
|
|
343
|
+
owasp: string;
|
|
344
|
+
}
|
|
345
|
+
export declare const SECURITY_FLAG_META: Record<string, SecurityFlagMeta>;
|
|
346
|
+
export declare const SECURITY_TIER_LABELS: Record<number, string>;
|
|
99
347
|
export declare const DATA_TAG_LABELS: Record<string, string>;
|
|
100
348
|
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/schemas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,YAAY;;;;EAAqD,CAAC;AAC/E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAaxD,eAAO,MAAM,eAAe,gHASlB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,eAAO,MAAM,oBAAoB,wMAWvB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAItE,eAAO,MAAM,WAAW;;;;iBAItB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,aAAa;;;iBAGxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,mEAAmE;AACnE,eAAO,MAAM,qBAAqB;;;;;;;;;;;iBAIhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;iBAWxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;iBAI3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,uEAAuE;AACvE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;iBAE5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAIlE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCAaxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAI1D;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAW5E,eAAO,MAAM,WAAW;;;;;;;;;;iBAMtB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAUtD,0EAA0E;AAC1E,eAAO,MAAM,SAAS;;;;;;;;;;;;;;iBAIpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD,2DAA2D;AAC3D,eAAO,MAAM,SAAS;;;;;;;;;;;;;;iBAIpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD,iEAAiE;AACjE,eAAO,MAAM,SAAS;;;;;;;;;;;;;;iBAIpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AASlD,mGAAmG;AACnG,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;iBAgBrC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAIpF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAIxD,CAAC;AAIF,eAAO,MAAM,aAAa,KAAK,CAAC;AAChC,eAAO,MAAM,eAAe,MAAM,CAAC;AAQnC,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWvD,CAAC;AAaF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAW/D,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKvD,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASlD,CAAC"}
|