@specferret/core 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ export declare const tables_dataSource: {
3
+ id: string;
4
+ value: string;
5
+ output: {
6
+ data: z.ZodString;
7
+ };
8
+ };
9
+ export declare const tables_ingestionRun: {
10
+ id: string;
11
+ value: string;
12
+ output: {
13
+ runId: z.ZodString;
14
+ };
15
+ consumes: {
16
+ id: string;
17
+ value: string;
18
+ output: {
19
+ data: z.ZodString;
20
+ };
21
+ }[];
22
+ };
23
+ //# sourceMappingURL=same-file-dotted-id-consumes.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"same-file-dotted-id-consumes.fixture.d.ts","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/same-file-dotted-id-consumes.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,iBAAiB;;;;;;CAI7B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;CAK/B,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ // Export name uses underscores; .id uses dot notation — the standard convention.
3
+ export const tables_dataSource = {
4
+ id: 'tables.dataSource',
5
+ value: 'tables data source',
6
+ output: { data: z.string() },
7
+ };
8
+ export const tables_ingestionRun = {
9
+ id: 'tables.ingestionRun',
10
+ value: 'tables ingestion run',
11
+ output: { runId: z.string() },
12
+ consumes: [tables_dataSource],
13
+ };
14
+ //# sourceMappingURL=same-file-dotted-id-consumes.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"same-file-dotted-id-consumes.fixture.js","sourceRoot":"","sources":["../../../src/extractor/__fixtures__/same-file-dotted-id-consumes.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,iFAAiF;AACjF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,EAAE,EAAE,mBAAmB;IACvB,KAAK,EAAE,oBAAoB;IAC3B,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,EAAE,EAAE,qBAAqB;IACzB,KAAK,EAAE,sBAAsB;IAC7B,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC7B,QAAQ,EAAE,CAAC,iBAAiB,CAAC;CAC9B,CAAC"}
@@ -36,7 +36,7 @@ export async function extractFromContractFile(filePath) {
36
36
  for (const consumed of exportValue.consumes) {
37
37
  const samefile = exportNameMap.get(consumed);
38
38
  if (samefile !== undefined) {
39
- imports.push(samefile);
39
+ imports.push(consumed.id ?? samefile);
40
40
  }
41
41
  else if (consumed.id !== undefined) {
42
42
  imports.push(consumed.id);
@@ -48,7 +48,7 @@ export async function extractFromContractFile(filePath) {
48
48
  }
49
49
  }
50
50
  contracts.push({
51
- id: exportName,
51
+ id: exportValue.id ?? exportName,
52
52
  type: 'type',
53
53
  shape,
54
54
  shape_hash,
@@ -1 +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,iGAAiG;QACjG,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAQ,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7F,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"}
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,iGAAiG;QACjG,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAQ,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7F,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,EAAE,IAAI,QAAQ,CAAC,CAAC;gBACxC,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,WAAW,CAAC,EAAE,IAAI,UAAU;YAChC,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specferret/core",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "SpecFerret core engine — spec drift detection.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+
3
+ // Export name uses underscores; .id uses dot notation — the standard convention.
4
+ export const tables_dataSource = {
5
+ id: 'tables.dataSource',
6
+ value: 'tables data source',
7
+ output: { data: z.string() },
8
+ };
9
+
10
+ export const tables_ingestionRun = {
11
+ id: 'tables.ingestionRun',
12
+ value: 'tables ingestion run',
13
+ output: { runId: z.string() },
14
+ consumes: [tables_dataSource],
15
+ };
@@ -61,9 +61,7 @@ describe('extractFromContractFile', () => {
61
61
  });
62
62
 
63
63
  it('zod schema with optional fields extracts without throwing', async () => {
64
- await assert.doesNotReject(() =>
65
- extractFromContractFile(fixtures('optional-fields.fixture.ts')),
66
- );
64
+ await assert.doesNotReject(() => extractFromContractFile(fixtures('optional-fields.fixture.ts')));
67
65
 
68
66
  const result = await extractFromContractFile(fixtures('optional-fields.fixture.ts'));
69
67
  assert.equal(result.contracts.length, 1);
@@ -134,10 +132,25 @@ describe('extractFromContractFile', () => {
134
132
  assert.equal(result.contracts[0].sourceSymbol, 'userContract');
135
133
  });
136
134
 
135
+ it('stored contract id uses .id field when present, not export name', async () => {
136
+ const result = await extractFromContractFile(fixtures('same-file-dotted-id-consumes.fixture.ts'));
137
+
138
+ const ids = result.contracts.map((c) => c.id);
139
+ assert.ok(ids.includes('tables.dataSource'), 'expected tables.dataSource stored id');
140
+ assert.ok(ids.includes('tables.ingestionRun'), 'expected tables.ingestionRun stored id');
141
+ assert.ok(!ids.includes('tables_dataSource'), 'export name must not be used as stored id when .id is present');
142
+ assert.ok(!ids.includes('tables_ingestionRun'), 'export name must not be used as stored id when .id is present');
143
+ });
144
+
145
+ it('same-file consumes with dotted .id resolves to .id, not export name', async () => {
146
+ const result = await extractFromContractFile(fixtures('same-file-dotted-id-consumes.fixture.ts'));
147
+
148
+ const ingestionRun = result.contracts.find((c) => c.id === 'tables.ingestionRun');
149
+ assert.ok(ingestionRun, 'tables.ingestionRun not found');
150
+ assert.deepEqual(ingestionRun.imports, ['tables.dataSource']);
151
+ });
152
+
137
153
  it('module that throws at top-level causes extractFromContractFile to reject', async () => {
138
- await assert.rejects(
139
- () => extractFromContractFile(fixtures('throws-on-import.fixture.ts')),
140
- /intentional module-level throw/,
141
- );
154
+ await assert.rejects(() => extractFromContractFile(fixtures('throws-on-import.fixture.ts')), /intentional module-level throw/);
142
155
  });
143
156
  });
@@ -44,7 +44,7 @@ export async function extractFromContractFile(filePath: string): Promise<Extract
44
44
  for (const consumed of exportValue.consumes) {
45
45
  const samefile = exportNameMap.get(consumed);
46
46
  if (samefile !== undefined) {
47
- imports.push(samefile);
47
+ imports.push(consumed.id ?? samefile);
48
48
  } else if (consumed.id !== undefined) {
49
49
  imports.push(consumed.id);
50
50
  } else {
@@ -57,7 +57,7 @@ export async function extractFromContractFile(filePath: string): Promise<Extract
57
57
  }
58
58
 
59
59
  contracts.push({
60
- id: exportName,
60
+ id: exportValue.id ?? exportName,
61
61
  type: 'type',
62
62
  shape,
63
63
  shape_hash,