apcore-toolkit 0.1.0 → 0.2.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/CHANGELOG.md +36 -0
- package/README.md +26 -0
- package/dist/ai-enhancer.d.ts +34 -0
- package/dist/ai-enhancer.d.ts.map +1 -0
- package/dist/ai-enhancer.js +313 -0
- package/dist/ai-enhancer.js.map +1 -0
- package/dist/flatten-params.d.ts +16 -0
- package/dist/flatten-params.d.ts.map +1 -0
- package/dist/flatten-params.js +18 -0
- package/dist/flatten-params.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/output/errors.d.ts +5 -0
- package/dist/output/errors.d.ts.map +1 -0
- package/dist/output/errors.js +9 -0
- package/dist/output/errors.js.map +1 -0
- package/dist/output/index.d.ts +4 -0
- package/dist/output/index.d.ts.map +1 -1
- package/dist/output/index.js +3 -0
- package/dist/output/index.js.map +1 -1
- package/dist/output/registry-writer.d.ts +5 -1
- package/dist/output/registry-writer.d.ts.map +1 -1
- package/dist/output/registry-writer.js +21 -4
- package/dist/output/registry-writer.js.map +1 -1
- package/dist/output/types.d.ts +15 -0
- package/dist/output/types.d.ts.map +1 -0
- package/dist/output/types.js +4 -0
- package/dist/output/types.js.map +1 -0
- package/dist/output/typescript-writer.d.ts +4 -1
- package/dist/output/typescript-writer.d.ts.map +1 -1
- package/dist/output/typescript-writer.js +36 -10
- package/dist/output/typescript-writer.js.map +1 -1
- package/dist/output/verifiers.d.ts +26 -0
- package/dist/output/verifiers.d.ts.map +1 -0
- package/dist/output/verifiers.js +103 -0
- package/dist/output/verifiers.js.map +1 -0
- package/dist/output/yaml-writer.d.ts +4 -1
- package/dist/output/yaml-writer.d.ts.map +1 -1
- package/dist/output/yaml-writer.js +48 -23
- package/dist/output/yaml-writer.js.map +1 -1
- package/dist/resolve-target.d.ts +7 -1
- package/dist/resolve-target.d.ts.map +1 -1
- package/dist/resolve-target.js +17 -1
- package/dist/resolve-target.js.map +1 -1
- package/dist/scanner.d.ts +5 -0
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +50 -5
- package/dist/scanner.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,19 +1,36 @@
|
|
|
1
1
|
import { FunctionModule, jsonSchemaToTypeBox } from 'apcore-js';
|
|
2
2
|
import { annotationsToDict } from '../serializers.js';
|
|
3
3
|
import { resolveTarget } from '../resolve-target.js';
|
|
4
|
+
import { createWriteResult } from './types.js';
|
|
5
|
+
import { RegistryVerifier, runVerifierChain } from './verifiers.js';
|
|
4
6
|
export class RegistryWriter {
|
|
5
7
|
async write(modules, registry, options) {
|
|
6
|
-
const
|
|
8
|
+
const shouldVerify = options?.verify ?? false;
|
|
9
|
+
const verifiers = options?.verifiers ?? [];
|
|
10
|
+
const results = [];
|
|
7
11
|
for (const mod of modules) {
|
|
8
12
|
if (options?.dryRun) {
|
|
9
|
-
|
|
13
|
+
results.push(createWriteResult(mod.moduleId, null));
|
|
10
14
|
continue;
|
|
11
15
|
}
|
|
12
16
|
const fm = await this._toFunctionModule(mod);
|
|
13
17
|
registry.register(mod.moduleId, fm);
|
|
14
|
-
|
|
18
|
+
let result = createWriteResult(mod.moduleId, null);
|
|
19
|
+
if (shouldVerify) {
|
|
20
|
+
const builtinResult = new RegistryVerifier(registry).verify('', mod.moduleId);
|
|
21
|
+
if (!builtinResult.ok) {
|
|
22
|
+
result = createWriteResult(mod.moduleId, null, false, builtinResult.error ?? null);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (result.verified && verifiers.length > 0) {
|
|
26
|
+
const vResult = runVerifierChain(verifiers, '', mod.moduleId);
|
|
27
|
+
if (!vResult.ok) {
|
|
28
|
+
result = createWriteResult(mod.moduleId, null, false, vResult.error ?? null);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
results.push(result);
|
|
15
32
|
}
|
|
16
|
-
return
|
|
33
|
+
return results;
|
|
17
34
|
}
|
|
18
35
|
async _toFunctionModule(mod) {
|
|
19
36
|
const targetFn = (await resolveTarget(mod.target));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-writer.js","sourceRoot":"","sources":["../../src/output/registry-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,KAAK,CACT,OAAwB,EACxB,
|
|
1
|
+
{"version":3,"file":"registry-writer.js","sourceRoot":"","sources":["../../src/output/registry-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface WriteResult {
|
|
2
|
+
readonly moduleId: string;
|
|
3
|
+
readonly path: string | null;
|
|
4
|
+
readonly verified: boolean;
|
|
5
|
+
readonly verificationError: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface VerifyResult {
|
|
8
|
+
readonly ok: boolean;
|
|
9
|
+
readonly error?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Verifier {
|
|
12
|
+
verify(path: string, moduleId: string): VerifyResult;
|
|
13
|
+
}
|
|
14
|
+
export declare function createWriteResult(moduleId: string, path?: string | null, verified?: boolean, verificationError?: string | null): WriteResult;
|
|
15
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/output/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;CACtD;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAM,GAAG,IAAW,EAC1B,QAAQ,UAAO,EACf,iBAAiB,GAAE,MAAM,GAAG,IAAW,GACtC,WAAW,CAEb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/output/types.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,OAAsB,IAAI,EAC1B,QAAQ,GAAG,IAAI,EACf,oBAAmC,IAAI;IAEvC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ScannedModule } from '../types.js';
|
|
2
|
+
import type { WriteResult, Verifier } from './types.js';
|
|
2
3
|
export declare class TypeScriptWriter {
|
|
3
4
|
write(modules: ScannedModule[], outputDir: string, options?: {
|
|
4
5
|
dryRun?: boolean;
|
|
5
|
-
|
|
6
|
+
verify?: boolean;
|
|
7
|
+
verifiers?: Verifier[];
|
|
8
|
+
}): WriteResult[];
|
|
6
9
|
private _generateCode;
|
|
7
10
|
private _parseTarget;
|
|
8
11
|
private _sanitizeIdentifier;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-writer.d.ts","sourceRoot":"","sources":["../../src/output/typescript-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"typescript-writer.d.ts","sourceRoot":"","sources":["../../src/output/typescript-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKxD,qBAAa,gBAAgB;IAC3B,KAAK,CACH,OAAO,EAAE,aAAa,EAAE,EACxB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,GACvE,WAAW,EAAE;IAyDhB,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,mBAAmB;CAO5B"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { resolve, join } from 'node:path';
|
|
3
|
+
import { createWriteResult } from './types.js';
|
|
4
|
+
import { WriteError } from './errors.js';
|
|
5
|
+
import { SyntaxVerifier, runVerifierChain } from './verifiers.js';
|
|
3
6
|
export class TypeScriptWriter {
|
|
4
7
|
write(modules, outputDir, options) {
|
|
5
8
|
const dryRun = options?.dryRun ?? false;
|
|
9
|
+
const shouldVerify = options?.verify ?? false;
|
|
10
|
+
const verifiers = options?.verifiers ?? [];
|
|
6
11
|
const results = [];
|
|
7
12
|
const timestamp = new Date().toISOString();
|
|
8
13
|
const resolvedOut = dryRun ? '' : resolve(outputDir);
|
|
@@ -11,18 +16,39 @@ export class TypeScriptWriter {
|
|
|
11
16
|
}
|
|
12
17
|
for (const mod of modules) {
|
|
13
18
|
const code = this._generateCode(mod, timestamp);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
if (dryRun) {
|
|
20
|
+
results.push(createWriteResult(mod.moduleId, null));
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
// Path traversal protection: check raw moduleId before sanitization
|
|
24
|
+
const rawResolved = resolve(join(resolvedOut, mod.moduleId));
|
|
25
|
+
if (!rawResolved.startsWith(resolvedOut + '/') && rawResolved !== resolvedOut) {
|
|
26
|
+
console.warn('Skipping module with path traversal in id: %s', mod.moduleId);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const sanitized = this._sanitizeIdentifier(mod.moduleId);
|
|
30
|
+
const filename = `${sanitized}.ts`;
|
|
31
|
+
const filePath = resolve(join(resolvedOut, filename));
|
|
32
|
+
try {
|
|
33
|
+
writeFileSync(filePath, code, 'utf-8');
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
throw new WriteError(filePath, err);
|
|
37
|
+
}
|
|
38
|
+
let result = createWriteResult(mod.moduleId, filePath);
|
|
39
|
+
if (shouldVerify) {
|
|
40
|
+
const builtinResult = new SyntaxVerifier().verify(filePath, mod.moduleId);
|
|
41
|
+
if (!builtinResult.ok) {
|
|
42
|
+
result = createWriteResult(mod.moduleId, filePath, false, builtinResult.error ?? null);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (result.verified && verifiers.length > 0) {
|
|
46
|
+
const vResult = runVerifierChain(verifiers, filePath, mod.moduleId);
|
|
47
|
+
if (!vResult.ok) {
|
|
48
|
+
result = createWriteResult(mod.moduleId, filePath, false, vResult.error ?? null);
|
|
21
49
|
}
|
|
22
|
-
const sanitized = this._sanitizeIdentifier(mod.moduleId);
|
|
23
|
-
const filename = `${sanitized}.ts`;
|
|
24
|
-
writeFileSync(resolve(join(resolvedOut, filename)), code, 'utf-8');
|
|
25
50
|
}
|
|
51
|
+
results.push(result);
|
|
26
52
|
}
|
|
27
53
|
return results;
|
|
28
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-writer.js","sourceRoot":"","sources":["../../src/output/typescript-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,OAAO,gBAAgB;IAC3B,KAAK,CACH,OAAwB,EACxB,SAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"typescript-writer.js","sourceRoot":"","sources":["../../src/output/typescript-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Verifier, VerifyResult } from './types.js';
|
|
2
|
+
export declare class YAMLVerifier implements Verifier {
|
|
3
|
+
verify(path: string, _moduleId: string): VerifyResult;
|
|
4
|
+
}
|
|
5
|
+
export declare class SyntaxVerifier implements Verifier {
|
|
6
|
+
verify(path: string, _moduleId: string): VerifyResult;
|
|
7
|
+
}
|
|
8
|
+
export declare class RegistryVerifier implements Verifier {
|
|
9
|
+
private readonly registry;
|
|
10
|
+
constructor(registry: {
|
|
11
|
+
getModule?(id: string): unknown;
|
|
12
|
+
});
|
|
13
|
+
verify(_path: string, moduleId: string): VerifyResult;
|
|
14
|
+
}
|
|
15
|
+
export declare class MagicBytesVerifier implements Verifier {
|
|
16
|
+
private readonly expected;
|
|
17
|
+
constructor(expected: Buffer);
|
|
18
|
+
verify(path: string, _moduleId: string): VerifyResult;
|
|
19
|
+
}
|
|
20
|
+
export declare class JSONVerifier implements Verifier {
|
|
21
|
+
private readonly schema;
|
|
22
|
+
constructor(schema?: Record<string, unknown>);
|
|
23
|
+
verify(path: string, _moduleId: string): VerifyResult;
|
|
24
|
+
}
|
|
25
|
+
export declare function runVerifierChain(verifiers: Verifier[], path: string, moduleId: string): VerifyResult;
|
|
26
|
+
//# sourceMappingURL=verifiers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifiers.d.ts","sourceRoot":"","sources":["../../src/output/verifiers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEzD,qBAAa,YAAa,YAAW,QAAQ;IAC3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;CAetD;AAED,qBAAa,cAAe,YAAW,QAAQ;IAC7C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;CAYtD;AAED,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;gBAEnD,QAAQ,EAAE;QAAE,SAAS,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE;IAIzD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY;CActD;AAED,qBAAa,kBAAmB,YAAW,QAAQ;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,EAAE,MAAM;IAI5B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;CAYtD;AAED,qBAAa,YAAa,YAAW,QAAQ;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;gBAE5C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAI5C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;CAWtD;AAED,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,QAAQ,EAAE,EACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,YAAY,CAQd"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import yaml from 'js-yaml';
|
|
3
|
+
export class YAMLVerifier {
|
|
4
|
+
verify(path, _moduleId) {
|
|
5
|
+
try {
|
|
6
|
+
const content = readFileSync(path, 'utf-8');
|
|
7
|
+
const doc = yaml.load(content);
|
|
8
|
+
if (doc == null || typeof doc !== 'object') {
|
|
9
|
+
return { ok: false, error: 'YAML parsed to non-object value' };
|
|
10
|
+
}
|
|
11
|
+
if (!('bindings' in doc)) {
|
|
12
|
+
return { ok: false, error: 'Missing required "bindings" key' };
|
|
13
|
+
}
|
|
14
|
+
return { ok: true };
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
return { ok: false, error: `YAML parse error: ${err.message}` };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class SyntaxVerifier {
|
|
22
|
+
verify(path, _moduleId) {
|
|
23
|
+
try {
|
|
24
|
+
const content = readFileSync(path, 'utf-8');
|
|
25
|
+
// Basic syntax check: ensure file is non-empty and parseable
|
|
26
|
+
if (content.trim().length === 0) {
|
|
27
|
+
return { ok: false, error: 'File is empty' };
|
|
28
|
+
}
|
|
29
|
+
return { ok: true };
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
return { ok: false, error: `Read error: ${err.message}` };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class RegistryVerifier {
|
|
37
|
+
registry;
|
|
38
|
+
constructor(registry) {
|
|
39
|
+
this.registry = registry;
|
|
40
|
+
}
|
|
41
|
+
verify(_path, moduleId) {
|
|
42
|
+
try {
|
|
43
|
+
if (typeof this.registry.getModule !== 'function') {
|
|
44
|
+
return { ok: false, error: 'Registry does not have a getModule method' };
|
|
45
|
+
}
|
|
46
|
+
const mod = this.registry.getModule(moduleId);
|
|
47
|
+
if (mod == null) {
|
|
48
|
+
return { ok: false, error: `Module "${moduleId}" not found in registry` };
|
|
49
|
+
}
|
|
50
|
+
return { ok: true };
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
return { ok: false, error: `Registry lookup error: ${err.message}` };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class MagicBytesVerifier {
|
|
58
|
+
expected;
|
|
59
|
+
constructor(expected) {
|
|
60
|
+
this.expected = expected;
|
|
61
|
+
}
|
|
62
|
+
verify(path, _moduleId) {
|
|
63
|
+
try {
|
|
64
|
+
const content = readFileSync(path);
|
|
65
|
+
const header = content.subarray(0, this.expected.length);
|
|
66
|
+
if (!header.equals(this.expected)) {
|
|
67
|
+
return { ok: false, error: 'File header does not match expected magic bytes' };
|
|
68
|
+
}
|
|
69
|
+
return { ok: true };
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
return { ok: false, error: `Read error: ${err.message}` };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export class JSONVerifier {
|
|
77
|
+
schema;
|
|
78
|
+
constructor(schema) {
|
|
79
|
+
this.schema = schema ?? null;
|
|
80
|
+
}
|
|
81
|
+
verify(path, _moduleId) {
|
|
82
|
+
try {
|
|
83
|
+
const content = readFileSync(path, 'utf-8');
|
|
84
|
+
JSON.parse(content);
|
|
85
|
+
// Schema validation is accepted for API parity with Python but requires
|
|
86
|
+
// a JSON Schema validator (e.g., ajv) for actual validation.
|
|
87
|
+
return { ok: true };
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
return { ok: false, error: `JSON parse error: ${err.message}` };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function runVerifierChain(verifiers, path, moduleId) {
|
|
95
|
+
for (const verifier of verifiers) {
|
|
96
|
+
const result = verifier.verify(path, moduleId);
|
|
97
|
+
if (!result.ok) {
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { ok: true };
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=verifiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifiers.js","sourceRoot":"","sources":["../../src/output/verifiers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ScannedModule } from '../types.js';
|
|
2
|
+
import type { WriteResult, Verifier } from './types.js';
|
|
2
3
|
export declare class YAMLWriter {
|
|
3
4
|
write(modules: ScannedModule[], outputDir: string, options?: {
|
|
4
5
|
dryRun?: boolean;
|
|
5
|
-
|
|
6
|
+
verify?: boolean;
|
|
7
|
+
verifiers?: Verifier[];
|
|
8
|
+
}): WriteResult[];
|
|
6
9
|
private _buildBinding;
|
|
7
10
|
}
|
|
8
11
|
//# sourceMappingURL=yaml-writer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-writer.d.ts","sourceRoot":"","sources":["../../src/output/yaml-writer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"yaml-writer.d.ts","sourceRoot":"","sources":["../../src/output/yaml-writer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKxD,qBAAa,UAAU;IACrB,KAAK,CACH,OAAO,EAAE,aAAa,EAAE,EACxB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,GACvE,WAAW,EAAE;IA4EhB,OAAO,CAAC,aAAa;CAqBtB"}
|
|
@@ -2,9 +2,14 @@ import yaml from 'js-yaml';
|
|
|
2
2
|
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { annotationsToDict } from '../serializers.js';
|
|
5
|
+
import { createWriteResult } from './types.js';
|
|
6
|
+
import { WriteError } from './errors.js';
|
|
7
|
+
import { YAMLVerifier, runVerifierChain } from './verifiers.js';
|
|
5
8
|
export class YAMLWriter {
|
|
6
9
|
write(modules, outputDir, options) {
|
|
7
10
|
const dryRun = options?.dryRun ?? false;
|
|
11
|
+
const shouldVerify = options?.verify ?? false;
|
|
12
|
+
const verifiers = options?.verifiers ?? [];
|
|
8
13
|
if (modules.length === 0) {
|
|
9
14
|
return [];
|
|
10
15
|
}
|
|
@@ -16,29 +21,49 @@ export class YAMLWriter {
|
|
|
16
21
|
const timestamp = new Date().toISOString();
|
|
17
22
|
for (const module of modules) {
|
|
18
23
|
const bindingData = this._buildBinding(module);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
if (dryRun) {
|
|
25
|
+
results.push(createWriteResult(module.moduleId, null));
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
let safeId = module.moduleId.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
29
|
+
safeId = safeId.replace(/\.{2,}/g, '_');
|
|
30
|
+
const filename = `${safeId}.binding.yaml`;
|
|
31
|
+
const filePath = resolve(join(outputPath, filename));
|
|
32
|
+
// Path traversal protection
|
|
33
|
+
if (!filePath.startsWith(outputPath)) {
|
|
34
|
+
console.warn('Skipping file outside output directory: %s', filePath);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (existsSync(filePath)) {
|
|
38
|
+
console.warn('Overwriting existing file: %s', filePath);
|
|
39
|
+
}
|
|
40
|
+
const header = `# Auto-generated by apcore-toolkit scanner\n` +
|
|
41
|
+
`# Generated: ${timestamp}\n` +
|
|
42
|
+
`# Do not edit manually unless you intend to customize schemas.\n\n`;
|
|
43
|
+
const yamlContent = yaml.dump(bindingData, {
|
|
44
|
+
flowLevel: -1,
|
|
45
|
+
sortKeys: false,
|
|
46
|
+
});
|
|
47
|
+
try {
|
|
48
|
+
writeFileSync(filePath, header + yamlContent, 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
throw new WriteError(filePath, err);
|
|
52
|
+
}
|
|
53
|
+
let result = createWriteResult(module.moduleId, filePath);
|
|
54
|
+
if (shouldVerify) {
|
|
55
|
+
const builtinResult = new YAMLVerifier().verify(filePath, module.moduleId);
|
|
56
|
+
if (!builtinResult.ok) {
|
|
57
|
+
result = createWriteResult(module.moduleId, filePath, false, builtinResult.error ?? null);
|
|
29
58
|
}
|
|
30
|
-
|
|
31
|
-
|
|
59
|
+
}
|
|
60
|
+
if (result.verified && verifiers.length > 0) {
|
|
61
|
+
const vResult = runVerifierChain(verifiers, filePath, module.moduleId);
|
|
62
|
+
if (!vResult.ok) {
|
|
63
|
+
result = createWriteResult(module.moduleId, filePath, false, vResult.error ?? null);
|
|
32
64
|
}
|
|
33
|
-
const header = `# Auto-generated by apcore-toolkit scanner\n` +
|
|
34
|
-
`# Generated: ${timestamp}\n` +
|
|
35
|
-
`# Do not edit manually unless you intend to customize schemas.\n\n`;
|
|
36
|
-
const yamlContent = yaml.dump(bindingData, {
|
|
37
|
-
flowLevel: -1,
|
|
38
|
-
sortKeys: false,
|
|
39
|
-
});
|
|
40
|
-
writeFileSync(filePath, header + yamlContent, 'utf-8');
|
|
41
65
|
}
|
|
66
|
+
results.push(result);
|
|
42
67
|
}
|
|
43
68
|
return results;
|
|
44
69
|
}
|
|
@@ -56,9 +81,9 @@ export class YAMLWriter {
|
|
|
56
81
|
examples: module.examples.length > 0
|
|
57
82
|
? module.examples.map((e) => ({ ...e }))
|
|
58
83
|
: [],
|
|
59
|
-
metadata:
|
|
60
|
-
input_schema:
|
|
61
|
-
output_schema:
|
|
84
|
+
metadata: structuredClone(module.metadata),
|
|
85
|
+
input_schema: structuredClone(module.inputSchema),
|
|
86
|
+
output_schema: structuredClone(module.outputSchema),
|
|
62
87
|
},
|
|
63
88
|
],
|
|
64
89
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-writer.js","sourceRoot":"","sources":["../../src/output/yaml-writer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,OAAO,UAAU;IACrB,KAAK,CACH,OAAwB,EACxB,SAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"yaml-writer.js","sourceRoot":"","sources":["../../src/output/yaml-writer.ts"],"names":[],"mappings":"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"}
|
package/dist/resolve-target.d.ts
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
* Target format: `"module/path:exportName"`.
|
|
5
5
|
* The LAST `:` is used as the separator so that Node.js built-in prefixes
|
|
6
6
|
* like `node:path` are supported (e.g. `"node:path:join"`).
|
|
7
|
+
*
|
|
8
|
+
* @param target - The target string in "module:export" format.
|
|
9
|
+
* @param allowedPrefixes - Optional list of allowed directory prefixes for
|
|
10
|
+
* absolute/relative paths. If provided, file-path imports must resolve
|
|
11
|
+
* under one of these directories. Package-name imports (no leading `.` or `/`)
|
|
12
|
+
* are always allowed.
|
|
7
13
|
*/
|
|
8
|
-
export declare function resolveTarget(target: string): Promise<unknown>;
|
|
14
|
+
export declare function resolveTarget(target: string, allowedPrefixes?: string[]): Promise<unknown>;
|
|
9
15
|
//# sourceMappingURL=resolve-target.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-target.d.ts","sourceRoot":"","sources":["../src/resolve-target.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve-target.d.ts","sourceRoot":"","sources":["../src/resolve-target.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,OAAO,CAAC,OAAO,CAAC,CAwClB"}
|
package/dist/resolve-target.js
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
|
+
import { resolve, isAbsolute } from 'node:path';
|
|
1
2
|
/**
|
|
2
3
|
* Dynamically imports a module and resolves a named export.
|
|
3
4
|
*
|
|
4
5
|
* Target format: `"module/path:exportName"`.
|
|
5
6
|
* The LAST `:` is used as the separator so that Node.js built-in prefixes
|
|
6
7
|
* like `node:path` are supported (e.g. `"node:path:join"`).
|
|
8
|
+
*
|
|
9
|
+
* @param target - The target string in "module:export" format.
|
|
10
|
+
* @param allowedPrefixes - Optional list of allowed directory prefixes for
|
|
11
|
+
* absolute/relative paths. If provided, file-path imports must resolve
|
|
12
|
+
* under one of these directories. Package-name imports (no leading `.` or `/`)
|
|
13
|
+
* are always allowed.
|
|
7
14
|
*/
|
|
8
|
-
export async function resolveTarget(target) {
|
|
15
|
+
export async function resolveTarget(target, allowedPrefixes) {
|
|
9
16
|
const lastColon = target.lastIndexOf(":");
|
|
10
17
|
if (lastColon === -1) {
|
|
11
18
|
throw new Error(`Invalid target format: "${target}". Expected "module/path:exportName".`);
|
|
12
19
|
}
|
|
13
20
|
const modulePath = target.slice(0, lastColon);
|
|
14
21
|
const exportName = target.slice(lastColon + 1);
|
|
22
|
+
// Validate file-path imports against allowedPrefixes
|
|
23
|
+
const isFilePath = modulePath.startsWith('.') || isAbsolute(modulePath);
|
|
24
|
+
if (isFilePath && allowedPrefixes != null && allowedPrefixes.length > 0) {
|
|
25
|
+
const resolved = resolve(modulePath);
|
|
26
|
+
const allowed = allowedPrefixes.some((prefix) => resolved.startsWith(resolve(prefix)));
|
|
27
|
+
if (!allowed) {
|
|
28
|
+
throw new Error(`Import path "${modulePath}" is not under any allowed prefix: ${allowedPrefixes.join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
15
31
|
let mod;
|
|
16
32
|
try {
|
|
17
33
|
mod = (await import(modulePath));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-target.js","sourceRoot":"","sources":["../src/resolve-target.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"resolve-target.js","sourceRoot":"","sources":["../src/resolve-target.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,eAA0B;IAE1B,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,uCAAuC,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAE/C,qDAAqD;IACrD,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;IACxE,IAAI,UAAU,IAAI,eAAe,IAAI,IAAI,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9C,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CACrC,CAAC;QACF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,gBAAgB,UAAU,sCAAsC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,GAA4B,CAAC;IACjC,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAA4B,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,4BAA4B,UAAU,MAAM,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,0BAA0B,UAAU,IAAI,CAC9D,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC;AACzB,CAAC"}
|
package/dist/scanner.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ import type { ScannedModule } from './types.js';
|
|
|
3
3
|
export declare abstract class BaseScanner {
|
|
4
4
|
abstract scan(...args: unknown[]): ScannedModule[] | Promise<ScannedModule[]>;
|
|
5
5
|
abstract getSourceName(): string;
|
|
6
|
+
extractDocstring(func: unknown): {
|
|
7
|
+
description: string | null;
|
|
8
|
+
documentation: string | null;
|
|
9
|
+
params: Record<string, string>;
|
|
10
|
+
};
|
|
6
11
|
filterModules(modules: ScannedModule[], options?: {
|
|
7
12
|
include?: string;
|
|
8
13
|
exclude?: string;
|
package/dist/scanner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD,8BAAsB,WAAW;IAC/B,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAC7E,QAAQ,CAAC,aAAa,IAAI,MAAM;IAEhC,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG;QAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC;IAwCD,aAAa,CACX,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,aAAa,EAAE;IAgBlB,MAAM,CAAC,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB;IAgBpE,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE;CA2B1D"}
|
package/dist/scanner.js
CHANGED
|
@@ -1,22 +1,67 @@
|
|
|
1
1
|
import { DEFAULT_ANNOTATIONS } from 'apcore-js';
|
|
2
2
|
import { cloneModule } from './types.js';
|
|
3
|
+
function safeRegExp(pattern) {
|
|
4
|
+
try {
|
|
5
|
+
return new RegExp(pattern);
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
// If the pattern is invalid regex, treat it as a literal string
|
|
9
|
+
return new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
3
12
|
export class BaseScanner {
|
|
13
|
+
extractDocstring(func) {
|
|
14
|
+
if (func == null || typeof func !== 'function') {
|
|
15
|
+
return { description: null, documentation: null, params: {} };
|
|
16
|
+
}
|
|
17
|
+
// Extract JSDoc-style documentation from function's toString representation
|
|
18
|
+
const source = func.toString();
|
|
19
|
+
const jsdocMatch = source.match(/\/\*\*([\s\S]*?)\*\//);
|
|
20
|
+
if (!jsdocMatch) {
|
|
21
|
+
return { description: null, documentation: null, params: {} };
|
|
22
|
+
}
|
|
23
|
+
const raw = jsdocMatch[1];
|
|
24
|
+
const lines = raw
|
|
25
|
+
.split('\n')
|
|
26
|
+
.map((l) => l.replace(/^\s*\*\s?/, '').trim())
|
|
27
|
+
.filter((l) => l.length > 0);
|
|
28
|
+
const descLines = [];
|
|
29
|
+
const params = {};
|
|
30
|
+
let hitTag = false;
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
if (line.startsWith('@param')) {
|
|
33
|
+
hitTag = true;
|
|
34
|
+
const m = line.match(/@param\s+\{?\w*\}?\s*(\w+)\s*(.*)/);
|
|
35
|
+
if (m)
|
|
36
|
+
params[m[1]] = m[2].replace(/^-\s*/, '').trim();
|
|
37
|
+
}
|
|
38
|
+
else if (line.startsWith('@')) {
|
|
39
|
+
hitTag = true;
|
|
40
|
+
}
|
|
41
|
+
else if (!hitTag) {
|
|
42
|
+
descLines.push(line);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const description = descLines.length > 0 ? descLines[0] : null;
|
|
46
|
+
const documentation = descLines.length > 1 ? descLines.join('\n') : null;
|
|
47
|
+
return { description, documentation, params };
|
|
48
|
+
}
|
|
4
49
|
filterModules(modules, options) {
|
|
5
50
|
let result = modules;
|
|
6
51
|
if (options?.include != null) {
|
|
7
|
-
const
|
|
8
|
-
result = result.filter((m) =>
|
|
52
|
+
const re = safeRegExp(options.include);
|
|
53
|
+
result = result.filter((m) => re.test(m.moduleId));
|
|
9
54
|
}
|
|
10
55
|
if (options?.exclude != null) {
|
|
11
|
-
const
|
|
12
|
-
result = result.filter((m) => !
|
|
56
|
+
const re = safeRegExp(options.exclude);
|
|
57
|
+
result = result.filter((m) => !re.test(m.moduleId));
|
|
13
58
|
}
|
|
14
59
|
return result;
|
|
15
60
|
}
|
|
16
61
|
static inferAnnotationsFromMethod(method) {
|
|
17
62
|
const upper = method.toUpperCase();
|
|
18
63
|
if (upper === 'GET') {
|
|
19
|
-
return { ...DEFAULT_ANNOTATIONS, readonly: true };
|
|
64
|
+
return { ...DEFAULT_ANNOTATIONS, readonly: true, cacheable: true };
|
|
20
65
|
}
|
|
21
66
|
if (upper === 'DELETE') {
|
|
22
67
|
return { ...DEFAULT_ANNOTATIONS, destructive: true };
|