@specferret/core 0.1.4 → 0.3.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 (103) hide show
  1. package/dist/config.d.ts +3 -0
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js.map +1 -1
  4. package/dist/contract.d.ts +16 -0
  5. package/dist/contract.d.ts.map +1 -0
  6. package/dist/contract.js +17 -0
  7. package/dist/contract.js.map +1 -0
  8. package/dist/extractor/__fixtures__/cross-file-id.fixture.d.ts +15 -0
  9. package/dist/extractor/__fixtures__/cross-file-id.fixture.d.ts.map +1 -0
  10. package/dist/extractor/__fixtures__/cross-file-id.fixture.js +9 -0
  11. package/dist/extractor/__fixtures__/cross-file-id.fixture.js.map +1 -0
  12. package/dist/extractor/__fixtures__/cross-file-unresolved.fixture.d.ts +14 -0
  13. package/dist/extractor/__fixtures__/cross-file-unresolved.fixture.d.ts.map +1 -0
  14. package/dist/extractor/__fixtures__/cross-file-unresolved.fixture.js +9 -0
  15. package/dist/extractor/__fixtures__/cross-file-unresolved.fixture.js.map +1 -0
  16. package/dist/extractor/__fixtures__/empty.fixture.d.ts +6 -0
  17. package/dist/extractor/__fixtures__/empty.fixture.d.ts.map +1 -0
  18. package/dist/extractor/__fixtures__/empty.fixture.js +5 -0
  19. package/dist/extractor/__fixtures__/empty.fixture.js.map +1 -0
  20. package/dist/extractor/__fixtures__/external-no-id.fixture.d.ts +8 -0
  21. package/dist/extractor/__fixtures__/external-no-id.fixture.d.ts.map +1 -0
  22. package/dist/extractor/__fixtures__/external-no-id.fixture.js +7 -0
  23. package/dist/extractor/__fixtures__/external-no-id.fixture.js.map +1 -0
  24. package/dist/extractor/__fixtures__/external-with-id.fixture.d.ts +9 -0
  25. package/dist/extractor/__fixtures__/external-with-id.fixture.d.ts.map +1 -0
  26. package/dist/extractor/__fixtures__/external-with-id.fixture.js +8 -0
  27. package/dist/extractor/__fixtures__/external-with-id.fixture.js.map +1 -0
  28. package/dist/extractor/__fixtures__/mixed.fixture.d.ts +24 -0
  29. package/dist/extractor/__fixtures__/mixed.fixture.d.ts.map +1 -0
  30. package/dist/extractor/__fixtures__/mixed.fixture.js +15 -0
  31. package/dist/extractor/__fixtures__/mixed.fixture.js.map +1 -0
  32. package/dist/extractor/__fixtures__/one-contract.fixture.d.ts +10 -0
  33. package/dist/extractor/__fixtures__/one-contract.fixture.d.ts.map +1 -0
  34. package/dist/extractor/__fixtures__/one-contract.fixture.js +10 -0
  35. package/dist/extractor/__fixtures__/one-contract.fixture.js.map +1 -0
  36. package/dist/extractor/__fixtures__/optional-fields.fixture.d.ts +10 -0
  37. package/dist/extractor/__fixtures__/optional-fields.fixture.d.ts.map +1 -0
  38. package/dist/extractor/__fixtures__/optional-fields.fixture.js +10 -0
  39. package/dist/extractor/__fixtures__/optional-fields.fixture.js.map +1 -0
  40. package/dist/extractor/__fixtures__/same-file-consumes.fixture.d.ts +20 -0
  41. package/dist/extractor/__fixtures__/same-file-consumes.fixture.d.ts.map +1 -0
  42. package/dist/extractor/__fixtures__/same-file-consumes.fixture.js +11 -0
  43. package/dist/extractor/__fixtures__/same-file-consumes.fixture.js.map +1 -0
  44. package/dist/extractor/__fixtures__/three-unresolved.fixture.d.ts +38 -0
  45. package/dist/extractor/__fixtures__/three-unresolved.fixture.d.ts.map +1 -0
  46. package/dist/extractor/__fixtures__/three-unresolved.fixture.js +21 -0
  47. package/dist/extractor/__fixtures__/three-unresolved.fixture.js.map +1 -0
  48. package/dist/extractor/__fixtures__/throws-on-import.fixture.d.ts +2 -0
  49. package/dist/extractor/__fixtures__/throws-on-import.fixture.d.ts.map +1 -0
  50. package/dist/extractor/__fixtures__/throws-on-import.fixture.js +5 -0
  51. package/dist/extractor/__fixtures__/throws-on-import.fixture.js.map +1 -0
  52. package/dist/extractor/frontmatter.d.ts +5 -1
  53. package/dist/extractor/frontmatter.d.ts.map +1 -1
  54. package/dist/extractor/frontmatter.js +5 -0
  55. package/dist/extractor/frontmatter.js.map +1 -1
  56. package/dist/extractor/typescript-contract.d.ts +3 -0
  57. package/dist/extractor/typescript-contract.d.ts.map +1 -0
  58. package/dist/extractor/typescript-contract.js +67 -0
  59. package/dist/extractor/typescript-contract.js.map +1 -0
  60. package/dist/extractor/upward-classifier.d.ts +25 -0
  61. package/dist/extractor/upward-classifier.d.ts.map +1 -0
  62. package/dist/extractor/upward-classifier.js +48 -0
  63. package/dist/extractor/upward-classifier.js.map +1 -0
  64. package/dist/index.d.ts +4 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +4 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/status/index.d.ts +20 -0
  69. package/dist/status/index.d.ts.map +1 -0
  70. package/dist/status/index.js +46 -0
  71. package/dist/status/index.js.map +1 -0
  72. package/dist/store/sqlite.d.ts +1 -1
  73. package/dist/store/sqlite.d.ts.map +1 -1
  74. package/dist/store/sqlite.js +37 -32
  75. package/dist/store/sqlite.js.map +1 -1
  76. package/dist/store/types.d.ts +6 -2
  77. package/dist/store/types.d.ts.map +1 -1
  78. package/package.json +3 -2
  79. package/src/config.ts +3 -0
  80. package/src/contract.test.ts +99 -0
  81. package/src/contract.ts +38 -0
  82. package/src/extractor/__fixtures__/cross-file-id.fixture.ts +9 -0
  83. package/src/extractor/__fixtures__/cross-file-unresolved.fixture.ts +9 -0
  84. package/src/extractor/__fixtures__/empty.fixture.ts +4 -0
  85. package/src/extractor/__fixtures__/external-no-id.fixture.ts +7 -0
  86. package/src/extractor/__fixtures__/external-with-id.fixture.ts +8 -0
  87. package/src/extractor/__fixtures__/mixed.fixture.ts +17 -0
  88. package/src/extractor/__fixtures__/one-contract.fixture.ts +10 -0
  89. package/src/extractor/__fixtures__/optional-fields.fixture.ts +10 -0
  90. package/src/extractor/__fixtures__/same-file-consumes.fixture.ts +12 -0
  91. package/src/extractor/__fixtures__/three-unresolved.fixture.ts +24 -0
  92. package/src/extractor/__fixtures__/throws-on-import.fixture.ts +3 -0
  93. package/src/extractor/frontmatter.test.ts +74 -0
  94. package/src/extractor/frontmatter.ts +11 -1
  95. package/src/extractor/typescript-contract.test.ts +143 -0
  96. package/src/extractor/typescript-contract.ts +76 -0
  97. package/src/extractor/upward-classifier.test.ts +188 -0
  98. package/src/extractor/upward-classifier.ts +68 -0
  99. package/src/index.ts +4 -0
  100. package/src/status/index.ts +68 -0
  101. package/src/store/sqlite.test.ts +135 -79
  102. package/src/store/sqlite.ts +45 -92
  103. package/src/store/types.ts +7 -6
package/dist/config.d.ts CHANGED
@@ -10,6 +10,9 @@ export interface FerretConfig {
10
10
  include: string[];
11
11
  watchNodes?: string[];
12
12
  };
13
+ contractParsers?: {
14
+ typescript?: boolean;
15
+ };
13
16
  }
14
17
  export declare const DEFAULT_CONFIG: FerretConfig;
15
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,iBAAiB,CAAC,EAAE;QAClB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH;AAED,eAAO,MAAM,cAAc,EAAE,YAQ5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,IAAI,YAAY,CAezC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,iBAAiB,CAAC,EAAE;QAClB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,eAAe,CAAC,EAAE;QAChB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;CACH;AAED,eAAO,MAAM,cAAc,EAAE,YAQ5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,IAAI,YAAY,CAezC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAgBnD,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,OAAO,EAAE,YAAY;IACrB,WAAW,EAAE,kBAAkB;IAC/B,QAAQ,EAAE,CAAC,kBAAkB,CAAC;IAC9B,KAAK,EAAE,QAAQ;IACf,iBAAiB,EAAE;QACjB,OAAO,EAAE,IAAI;KACd;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAEzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAmBnD,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,OAAO,EAAE,YAAY;IACrB,WAAW,EAAE,kBAAkB;IAC/B,QAAQ,EAAE,CAAC,kBAAkB,CAAC;IAC9B,KAAK,EAAE,QAAQ;IACf,iBAAiB,EAAE;QACjB,OAAO,EAAE,IAAI;KACd;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAEzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+ export interface Contract<T extends Record<string, z.ZodTypeAny> = Record<string, z.ZodTypeAny>> {
3
+ id?: string;
4
+ value: string;
5
+ output: T;
6
+ invariants?: Array<(r: z.infer<z.ZodObject<T>>) => boolean>;
7
+ consumes?: Contract[];
8
+ forbids?: string[];
9
+ status?: 'complete' | 'active' | 'pending';
10
+ closedBy?: string;
11
+ closedWhen?: string;
12
+ dependsOn?: Contract[];
13
+ }
14
+ export declare function defineContract<T extends Record<string, z.ZodTypeAny>>(contract: Contract<T>): Contract<T>;
15
+ export declare function isContract(value: unknown): value is Contract;
16
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,QAAQ,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC;IAErE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,CAAC,CAAC;IACV,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC5D,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,EACnE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GACpB,QAAQ,CAAC,CAAC,CAAC,CAKb;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAW5D"}
@@ -0,0 +1,17 @@
1
+ export function defineContract(contract) {
2
+ if ('id' in contract && contract.id !== undefined && contract.id.trim() === '') {
3
+ throw new Error('defineContract: id must be a non-empty string if provided');
4
+ }
5
+ return contract;
6
+ }
7
+ export function isContract(value) {
8
+ return (typeof value === 'object' &&
9
+ value !== null &&
10
+ 'value' in value &&
11
+ typeof value.value === 'string' &&
12
+ 'output' in value &&
13
+ typeof value.output === 'object' &&
14
+ value.output !== null &&
15
+ !Array.isArray(value.output));
16
+ }
17
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,cAAc,CAC5B,QAAqB;IAErB,IAAI,IAAI,IAAI,QAAQ,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/E,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAO,IAAI,KAAK;QAChB,OAAQ,KAAiC,CAAC,KAAK,KAAK,QAAQ;QAC5D,QAAQ,IAAI,KAAK;QACjB,OAAQ,KAAiC,CAAC,MAAM,KAAK,QAAQ;QAC5D,KAAiC,CAAC,MAAM,KAAK,IAAI;QAClD,CAAC,KAAK,CAAC,OAAO,CAAE,KAAiC,CAAC,MAAM,CAAC,CAC1D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ export declare const myContract: {
3
+ value: string;
4
+ output: {
5
+ result: z.ZodString;
6
+ };
7
+ consumes: {
8
+ value: string;
9
+ output: {
10
+ data: z.ZodString;
11
+ };
12
+ id: string;
13
+ }[];
14
+ };
15
+ //# sourceMappingURL=cross-file-id.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-file-id.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/cross-file-id.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,UAAU;;;;;;;;;;;;CAItB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import { externalWithId } from './external-with-id.fixture.js';
3
+ // Consumes an external contract that has an explicit id — resolves via c.id
4
+ export const myContract = {
5
+ value: 'Contract consuming known external',
6
+ output: { result: z.string() },
7
+ consumes: [externalWithId],
8
+ };
9
+ //# sourceMappingURL=cross-file-id.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-file-id.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/cross-file-id.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,mCAAmC;IAC1C,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC9B,QAAQ,EAAE,CAAC,cAAc,CAAC;CAC3B,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ export declare const myContract: {
3
+ value: string;
4
+ output: {
5
+ result: z.ZodString;
6
+ };
7
+ consumes: {
8
+ value: string;
9
+ output: {
10
+ data: z.ZodString;
11
+ };
12
+ }[];
13
+ };
14
+ //# sourceMappingURL=cross-file-unresolved.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-file-unresolved.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/cross-file-unresolved.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,UAAU;;;;;;;;;;;CAItB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import { externalNoId } from './external-no-id.fixture.js';
3
+ // Consumes an external contract with no id — triggers exactly one warning
4
+ export const myContract = {
5
+ value: 'Contract consuming unresolvable external',
6
+ output: { result: z.string() },
7
+ consumes: [externalNoId],
8
+ };
9
+ //# sourceMappingURL=cross-file-unresolved.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-file-unresolved.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/cross-file-unresolved.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,0CAA0C;IACjD,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC9B,QAAQ,EAAE,CAAC,YAAY,CAAC;CACzB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const version = "1.0.0";
2
+ export declare const count = 42;
3
+ export declare const config: {
4
+ debug: boolean;
5
+ };
6
+ //# sourceMappingURL=empty.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/empty.fixture.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,KAAK,KAAK,CAAC;AACxB,eAAO,MAAM,MAAM;;CAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // No ferret contracts here — only primitives and non-contract objects
2
+ export const version = '1.0.0';
3
+ export const count = 42;
4
+ export const config = { debug: true };
5
+ //# sourceMappingURL=empty.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/empty.fixture.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAC/B,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ export declare const externalNoId: {
3
+ value: string;
4
+ output: {
5
+ data: z.ZodString;
6
+ };
7
+ };
8
+ //# sourceMappingURL=external-no-id.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-no-id.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/external-no-id.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,YAAY;;;;;CAGxB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ // External contract with no id — cross-file refs to this will be unresolvable
3
+ export const externalNoId = {
4
+ value: 'External contract without id',
5
+ output: { data: z.string() },
6
+ };
7
+ //# sourceMappingURL=external-no-id.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-no-id.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/external-no-id.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,8BAA8B;IACrC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;CAC7B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export declare const externalWithId: {
3
+ value: string;
4
+ output: {
5
+ data: z.ZodString;
6
+ };
7
+ id: string;
8
+ };
9
+ //# sourceMappingURL=external-with-id.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-with-id.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/external-with-id.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,cAAc;;;;;;CAI1B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ // External contract with an explicit id — cross-file refs resolve via c.id
3
+ export const externalWithId = {
4
+ value: 'External contract with explicit id',
5
+ output: { data: z.string() },
6
+ id: 'external.known.id',
7
+ };
8
+ //# sourceMappingURL=external-with-id.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-with-id.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/external-with-id.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,oCAAoC;IAC3C,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC5B,EAAE,EAAE,mBAAmB;CACxB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ export declare const validContract: {
3
+ value: string;
4
+ output: {
5
+ name: z.ZodString;
6
+ };
7
+ };
8
+ export declare const anotherValid: {
9
+ value: string;
10
+ output: {
11
+ count: z.ZodNumber;
12
+ };
13
+ };
14
+ export declare const notAContract = 42;
15
+ export declare const alsoNotAContract = "just a string";
16
+ export declare const missingOutput: {
17
+ value: string;
18
+ };
19
+ export declare const missingValue: {
20
+ output: {
21
+ x: z.ZodString;
22
+ };
23
+ };
24
+ //# sourceMappingURL=mixed.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mixed.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/mixed.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa;;;;;CAGzB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;CAGxB,CAAC;AAGF,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAChD,eAAO,MAAM,aAAa;;CAAoB,CAAC;AAC/C,eAAO,MAAM,YAAY;;;;CAAgC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ export const validContract = {
3
+ value: 'valid',
4
+ output: { name: z.string() },
5
+ };
6
+ export const anotherValid = {
7
+ value: 'another valid',
8
+ output: { count: z.number() },
9
+ };
10
+ // These should be skipped by isContract
11
+ export const notAContract = 42;
12
+ export const alsoNotAContract = 'just a string';
13
+ export const missingOutput = { value: 'oops' };
14
+ export const missingValue = { output: { x: z.string() } };
15
+ //# sourceMappingURL=mixed.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mixed.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/mixed.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;CAC9B,CAAC;AAEF,wCAAwC;AACxC,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC;AAC/B,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAChD,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export declare const userContract: {
3
+ value: string;
4
+ output: {
5
+ id: z.ZodString;
6
+ name: z.ZodString;
7
+ email: z.ZodString;
8
+ };
9
+ };
10
+ //# sourceMappingURL=one-contract.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"one-contract.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/one-contract.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;;;;CAOxB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export const userContract = {
3
+ value: 'User shape contract',
4
+ output: {
5
+ id: z.string().uuid(),
6
+ name: z.string(),
7
+ email: z.string().email(),
8
+ },
9
+ };
10
+ //# sourceMappingURL=one-contract.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"one-contract.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/one-contract.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,qBAAqB;IAC5B,MAAM,EAAE;QACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;QACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;KAC1B;CACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export declare const optionalFieldsContract: {
3
+ value: string;
4
+ output: {
5
+ required_field: z.ZodString;
6
+ optional_field: z.ZodOptional<z.ZodString>;
7
+ optional_number: z.ZodOptional<z.ZodNumber>;
8
+ };
9
+ };
10
+ //# sourceMappingURL=optional-fields.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-fields.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/optional-fields.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,sBAAsB;;;;;;;CAOlC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export const optionalFieldsContract = {
3
+ value: 'Contract with optional fields',
4
+ output: {
5
+ required_field: z.string(),
6
+ optional_field: z.string().optional(),
7
+ optional_number: z.number().optional(),
8
+ },
9
+ };
10
+ //# sourceMappingURL=optional-fields.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-fields.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/optional-fields.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,KAAK,EAAE,+BAA+B;IACtC,MAAM,EAAE;QACN,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;QAC1B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACvC;CACF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ export declare const baseContract: {
3
+ value: string;
4
+ output: {
5
+ token: z.ZodString;
6
+ };
7
+ };
8
+ export declare const dependentContract: {
9
+ value: string;
10
+ output: {
11
+ result: z.ZodString;
12
+ };
13
+ consumes: {
14
+ value: string;
15
+ output: {
16
+ token: z.ZodString;
17
+ };
18
+ }[];
19
+ };
20
+ //# sourceMappingURL=same-file-consumes.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"same-file-consumes.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/same-file-consumes.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;;CAGxB,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;CAI7B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ export const baseContract = {
3
+ value: 'Base contract',
4
+ output: { token: z.string() },
5
+ };
6
+ export const dependentContract = {
7
+ value: 'Dependent contract that consumes baseContract',
8
+ output: { result: z.string() },
9
+ consumes: [baseContract],
10
+ };
11
+ //# sourceMappingURL=same-file-consumes.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"same-file-consumes.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/same-file-consumes.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;CAC9B,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,KAAK,EAAE,+CAA+C;IACtD,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC9B,QAAQ,EAAE,CAAC,YAAY,CAAC;CACzB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ export declare const contractA: {
3
+ value: string;
4
+ output: {
5
+ x: z.ZodString;
6
+ };
7
+ consumes: {
8
+ value: string;
9
+ output: {
10
+ a: z.ZodString;
11
+ };
12
+ }[];
13
+ };
14
+ export declare const contractB: {
15
+ value: string;
16
+ output: {
17
+ y: z.ZodString;
18
+ };
19
+ consumes: {
20
+ value: string;
21
+ output: {
22
+ b: z.ZodString;
23
+ };
24
+ }[];
25
+ };
26
+ export declare const contractC: {
27
+ value: string;
28
+ output: {
29
+ zField: z.ZodString;
30
+ };
31
+ consumes: {
32
+ value: string;
33
+ output: {
34
+ c: z.ZodString;
35
+ };
36
+ }[];
37
+ };
38
+ //# sourceMappingURL=three-unresolved.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"three-unresolved.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/three-unresolved.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,SAAS;;;;;;;;;;;CAIrB,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;;;;;;;CAIrB,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;;;;;;;CAIrB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ // Three separate unresolvable external references (not exported, no id)
3
+ const ext1 = { value: 'ext1', output: { a: z.string() } };
4
+ const ext2 = { value: 'ext2', output: { b: z.string() } };
5
+ const ext3 = { value: 'ext3', output: { c: z.string() } };
6
+ export const contractA = {
7
+ value: 'Contract A',
8
+ output: { x: z.string() },
9
+ consumes: [ext1],
10
+ };
11
+ export const contractB = {
12
+ value: 'Contract B',
13
+ output: { y: z.string() },
14
+ consumes: [ext2],
15
+ };
16
+ export const contractC = {
17
+ value: 'Contract C',
18
+ output: { zField: z.string() },
19
+ consumes: [ext3],
20
+ };
21
+ //# sourceMappingURL=three-unresolved.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"three-unresolved.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/three-unresolved.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wEAAwE;AACxE,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;AAC1D,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;AAC1D,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;AAE1D,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IACzB,QAAQ,EAAE,CAAC,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IACzB,QAAQ,EAAE,CAAC,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC9B,QAAQ,EAAE,CAAC,IAAI,CAAC;CACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=throws-on-import.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throws-on-import.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/throws-on-import.fixture.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ // Fixture: throws synchronously at module top-level.
2
+ // Used to verify that extractFromContractFile() does not swallow import errors.
3
+ throw new Error('intentional module-level throw');
4
+ export {};
5
+ //# sourceMappingURL=throws-on-import.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throws-on-import.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/throws-on-import.fixture.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,gFAAgF;AAChF,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC"}
@@ -8,8 +8,12 @@ export interface ExtractionResult {
8
8
  shape: object;
9
9
  shape_hash: string;
10
10
  imports: string[];
11
+ /** Path to the TypeScript source file (code-first contracts only). */
12
+ sourceFile?: string;
13
+ /** TypeScript symbol name (code-first contracts only). */
14
+ sourceSymbol?: string;
11
15
  }>;
12
- extractedBy: 'gray-matter' | 'tree-sitter';
16
+ extractedBy: 'gray-matter' | 'tree-sitter' | 'typescript';
13
17
  extractedAt: number;
14
18
  warning?: 'no-frontmatter';
15
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;IACH,WAAW,EAAE,aAAa,GAAG,aAAa,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CA4C3F"}
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,sEAAsE;QACtE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,0DAA0D;QAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,WAAW,EAAE,aAAa,GAAG,aAAa,GAAG,YAAY,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAkD3F"}
@@ -36,6 +36,9 @@ export function extractFromSpecFile(filePath, fileContent) {
36
36
  // validateFerretSchema never throws — only warns on unsupported keywords
37
37
  const validation = validateFerretSchema(ferret.shape, filePath);
38
38
  validation.warnings.forEach((w) => process.stderr.write(w + '\n'));
39
+ const source = ferret.source;
40
+ const sourceFile = typeof source?.file === 'string' ? source.file : undefined;
41
+ const sourceSymbol = typeof source?.symbol === 'string' ? source.symbol : undefined;
39
42
  return {
40
43
  filePath,
41
44
  fileType: 'spec',
@@ -46,6 +49,8 @@ export function extractFromSpecFile(filePath, fileContent) {
46
49
  shape: ferret.shape,
47
50
  shape_hash: hashSchema(ferret.shape),
48
51
  imports: Array.isArray(ferret.imports) ? ferret.imports : [],
52
+ ...(sourceFile !== undefined && { sourceFile }),
53
+ ...(sourceSymbol !== undefined && { sourceSymbol }),
49
54
  },
50
55
  ],
51
56
  extractedBy: 'gray-matter',
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kFAAkF;AAElF,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAkBvC;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAmB;IACvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;IAE5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,KAAK,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,cAAc,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,yEAAyE;IACzE,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAChE,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE;YACT;gBACE,EAAE,EAAE,MAAM,CAAC,EAAY;gBACvB,IAAI,EAAE,cAAc,CAAC,KAAK;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAe;gBAC7B,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,OAAoB,CAAC,CAAC,CAAC,EAAE;aAC3E;SACF;QACD,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kFAAkF;AAElF,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAsBvC;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAmB;IACvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;IAE5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,KAAK,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,cAAc,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,yEAAyE;IACzE,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAChE,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,MAAM,CAAC,MAA0D,CAAC;IACjF,MAAM,UAAU,GAAG,OAAO,MAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,YAAY,GAAG,OAAO,MAAM,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpF,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE;YACT;gBACE,EAAE,EAAE,MAAM,CAAC,EAAY;gBACvB,IAAI,EAAE,cAAc,CAAC,KAAK;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAe;gBAC7B,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,OAAoB,CAAC,CAAC,CAAC,EAAE;gBAC1E,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;gBAC/C,GAAG,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,CAAC;aACpD;SACF;QACD,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ExtractionResult } from './frontmatter.js';
2
+ export declare function extractFromContractFile(filePath: string): Promise<ExtractionResult>;
3
+ //# sourceMappingURL=typescript-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-contract.d.ts","sourceRoot":"","sources":["../../src/extractor/typescript-contract.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkEzF"}
@@ -0,0 +1,67 @@
1
+ // Extractor layer — turns a .contract.ts file into an ExtractionResult.
2
+ // Uses Bun's native import() — no ts-morph, no AST, no compile step.
3
+ import { z } from 'zod';
4
+ import { zodToJsonSchema } from 'zod-to-json-schema';
5
+ import { isContract } from '../contract.js';
6
+ import { hashSchema } from './hash.js';
7
+ export async function extractFromContractFile(filePath) {
8
+ const mod = (await import(filePath));
9
+ // Pass 1: build Map<contract object reference → export name> for same-file resolution
10
+ const exportNameMap = new Map();
11
+ for (const [exportName, exportValue] of Object.entries(mod)) {
12
+ if (isContract(exportValue)) {
13
+ exportNameMap.set(exportValue, exportName);
14
+ }
15
+ }
16
+ if (exportNameMap.size === 0) {
17
+ return {
18
+ filePath,
19
+ fileType: 'code',
20
+ contracts: [],
21
+ extractedBy: 'typescript',
22
+ extractedAt: Date.now(),
23
+ warning: 'no-frontmatter',
24
+ };
25
+ }
26
+ const contracts = [];
27
+ for (const [exportName, exportValue] of Object.entries(mod)) {
28
+ if (!isContract(exportValue))
29
+ continue;
30
+ const shape = zodToJsonSchema(z.object(exportValue.output), { $refStrategy: 'none' });
31
+ const shape_hash = hashSchema(shape);
32
+ // Pass 2: resolve consumes → import IDs
33
+ const imports = [];
34
+ if (exportValue.consumes) {
35
+ for (const consumed of exportValue.consumes) {
36
+ const samefile = exportNameMap.get(consumed);
37
+ if (samefile !== undefined) {
38
+ imports.push(samefile);
39
+ }
40
+ else if (consumed.id !== undefined) {
41
+ imports.push(consumed.id);
42
+ }
43
+ else {
44
+ process.stderr.write(`[specferret] warning: unresolvable consumes reference in '${filePath}' — export '${exportName}' references a contract with no id and no matching same-file export\n`);
45
+ imports.push('[unresolved]');
46
+ }
47
+ }
48
+ }
49
+ contracts.push({
50
+ id: exportName,
51
+ type: 'type',
52
+ shape,
53
+ shape_hash,
54
+ imports,
55
+ sourceFile: filePath,
56
+ sourceSymbol: exportName,
57
+ });
58
+ }
59
+ return {
60
+ filePath,
61
+ fileType: 'code',
62
+ contracts,
63
+ extractedBy: 'typescript',
64
+ extractedAt: Date.now(),
65
+ };
66
+ }
67
+ //# sourceMappingURL=typescript-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-contract.js","sourceRoot":"","sources":["../../src/extractor/typescript-contract.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,qEAAqE;AAErE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,QAAgB;IAC5D,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAA4B,CAAC;IAEhE,sFAAsF;IACtF,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,KAAK,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,YAAY;YACzB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAkC,EAAE,CAAC;IAEpD,KAAK,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,SAAS;QAEvC,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QACtF,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAErC,wCAAwC;QACxC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,KAAK,MAAM,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;gBAC5C,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC;qBAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;oBACrC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC5B,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6DAA6D,QAAQ,eAAe,UAAU,uEAAuE,CACtK,CAAC;oBACF,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;QAED,SAAS,CAAC,IAAI,CAAC;YACb,EAAE,EAAE,UAAU;YACd,IAAI,EAAE,MAAM;YACZ,KAAK;YACL,UAAU;YACV,OAAO;YACP,UAAU,EAAE,QAAQ;YACpB,YAAY,EAAE,UAAU;SACzB,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,MAAM;QAChB,SAAS;QACT,WAAW,EAAE,YAAY;QACzB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;AACJ,CAAC"}