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.
Files changed (51) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +26 -0
  3. package/dist/ai-enhancer.d.ts +34 -0
  4. package/dist/ai-enhancer.d.ts.map +1 -0
  5. package/dist/ai-enhancer.js +313 -0
  6. package/dist/ai-enhancer.js.map +1 -0
  7. package/dist/flatten-params.d.ts +16 -0
  8. package/dist/flatten-params.d.ts.map +1 -0
  9. package/dist/flatten-params.js +18 -0
  10. package/dist/flatten-params.js.map +1 -0
  11. package/dist/index.d.ts +7 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +5 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/output/errors.d.ts +5 -0
  16. package/dist/output/errors.d.ts.map +1 -0
  17. package/dist/output/errors.js +9 -0
  18. package/dist/output/errors.js.map +1 -0
  19. package/dist/output/index.d.ts +4 -0
  20. package/dist/output/index.d.ts.map +1 -1
  21. package/dist/output/index.js +3 -0
  22. package/dist/output/index.js.map +1 -1
  23. package/dist/output/registry-writer.d.ts +5 -1
  24. package/dist/output/registry-writer.d.ts.map +1 -1
  25. package/dist/output/registry-writer.js +21 -4
  26. package/dist/output/registry-writer.js.map +1 -1
  27. package/dist/output/types.d.ts +15 -0
  28. package/dist/output/types.d.ts.map +1 -0
  29. package/dist/output/types.js +4 -0
  30. package/dist/output/types.js.map +1 -0
  31. package/dist/output/typescript-writer.d.ts +4 -1
  32. package/dist/output/typescript-writer.d.ts.map +1 -1
  33. package/dist/output/typescript-writer.js +36 -10
  34. package/dist/output/typescript-writer.js.map +1 -1
  35. package/dist/output/verifiers.d.ts +26 -0
  36. package/dist/output/verifiers.d.ts.map +1 -0
  37. package/dist/output/verifiers.js +103 -0
  38. package/dist/output/verifiers.js.map +1 -0
  39. package/dist/output/yaml-writer.d.ts +4 -1
  40. package/dist/output/yaml-writer.d.ts.map +1 -1
  41. package/dist/output/yaml-writer.js +48 -23
  42. package/dist/output/yaml-writer.js.map +1 -1
  43. package/dist/resolve-target.d.ts +7 -1
  44. package/dist/resolve-target.d.ts.map +1 -1
  45. package/dist/resolve-target.js +17 -1
  46. package/dist/resolve-target.js.map +1 -1
  47. package/dist/scanner.d.ts +5 -0
  48. package/dist/scanner.d.ts.map +1 -1
  49. package/dist/scanner.js +50 -5
  50. package/dist/scanner.js.map +1 -1
  51. 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 registered = [];
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
- registered.push(mod.moduleId);
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
- registered.push(mod.moduleId);
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 registered;
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,QAA+D,EAC/D,OAA8B;QAE9B,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;gBACpB,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC9B,SAAS;YACX,CAAC;YACD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAC7C,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACpC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,GAAkB;QAChD,MAAM,QAAQ,GAAG,CAAC,MAAM,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAErC,CAAC;QAEb,OAAO,IAAI,cAAc,CAAC;YACxB,OAAO,EAAE,KAAK,EAAE,MAA+B,EAAE,QAAiB,EAAE,EAAE;gBACpE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACtC,IAAI,MAAM,IAAI,IAAI;oBAAE,OAAO,EAAE,CAAC;gBAC9B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAE,OAAO,EAAE,MAAM,EAAE,CAAC;gBAC3E,OAAO,MAAiC,CAAC;YAC3C,CAAC;YACD,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,WAAW,EAAE,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC;YACjD,YAAY,EAAE,mBAAmB,CAAC,GAAG,CAAC,YAAY,CAAC;YACnD,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;YAChD,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,WAAW,EAAE,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAA6B;YAC3E,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI;YAC3E,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAqB,CAAC,CAAC,CAAC,IAAI;SAClF,CAAC,CAAC;IACL,CAAC;CACF"}
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,4 @@
1
+ export function createWriteResult(moduleId, path = null, verified = true, verificationError = null) {
2
+ return { moduleId, path, verified, verificationError };
3
+ }
4
+ //# sourceMappingURL=types.js.map
@@ -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
- }): string[];
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;AAEjD,qBAAa,gBAAgB;IAC3B,KAAK,CACH,OAAO,EAAE,aAAa,EAAE,EACxB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7B,MAAM,EAAE;IAgCX,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,mBAAmB;CAO5B"}
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
- results.push(code);
15
- if (!dryRun) {
16
- // Path traversal protection: check raw moduleId before sanitization
17
- const rawResolved = resolve(join(resolvedOut, mod.moduleId));
18
- if (!rawResolved.startsWith(resolvedOut + '/') && rawResolved !== resolvedOut) {
19
- console.warn('Skipping module with path traversal in id: %s', mod.moduleId);
20
- continue;
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,OAA8B;QAE9B,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC;QACxC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE3C,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAErD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEnB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,oEAAoE;gBACpE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC7D,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,WAAW,KAAK,WAAW,EAAE,CAAC;oBAC9E,OAAO,CAAC,IAAI,CAAC,+CAA+C,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAC5E,SAAS;gBACX,CAAC;gBAED,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACzD,MAAM,QAAQ,GAAG,GAAG,SAAS,KAAK,CAAC;gBACnC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,aAAa,CAAC,GAAkB,EAAE,SAAiB;QACzD,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEjE,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,oCAAoC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC/E,KAAK,CAAC,IAAI,CAAC,iBAAiB,SAAS,EAAE,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAC/E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEzD,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACnE,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,eAAe,UAAU,gCAAgC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpG,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAEO,YAAY,CAAC,MAAc;QACjC,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO;YACL,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;YACtC,UAAU;SACX,CAAC;IACJ,CAAC;IAEO,mBAAmB,CAAC,IAAY;QACtC,IAAI,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
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
- }): Record<string, unknown>[];
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;AAGjD,qBAAa,UAAU;IACrB,KAAK,CACH,OAAO,EAAE,aAAa,EAAE,EACxB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;IAqD5B,OAAO,CAAC,aAAa;CAqBtB"}
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
- results.push(bindingData);
20
- if (!dryRun) {
21
- let safeId = module.moduleId.replace(/[^a-zA-Z0-9._-]/g, '_');
22
- safeId = safeId.replace(/\.{2,}/g, '_');
23
- const filename = `${safeId}.binding.yaml`;
24
- const filePath = resolve(join(outputPath, filename));
25
- // Path traversal protection
26
- if (!filePath.startsWith(outputPath)) {
27
- console.warn('Skipping file outside output directory: %s', filePath);
28
- continue;
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
- if (existsSync(filePath)) {
31
- console.warn('Overwriting existing file: %s', filePath);
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: { ...module.metadata },
60
- input_schema: { ...module.inputSchema },
61
- output_schema: { ...module.outputSchema },
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":"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"}
1
+ {"version":3,"file":"yaml-writer.js","sourceRoot":"","sources":["../../src/output/yaml-writer.ts"],"names":[],"mappings":"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"}
@@ -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":"AAAA;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BpE"}
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"}
@@ -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;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc;IAChD,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,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"}
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;
@@ -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;AAGhD,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,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"}
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 include = options.include;
8
- result = result.filter((m) => new RegExp(include).test(m.moduleId));
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 exclude = options.exclude;
12
- result = result.filter((m) => !new RegExp(exclude).test(m.moduleId));
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 };