swagger-parser-mcp-server 2.0.4 → 2.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 (131) hide show
  1. package/README.md +131 -100
  2. package/dist/application/snapshot/createSnapshotRuntime.d.ts +2 -0
  3. package/dist/application/snapshot/createSnapshotRuntime.d.ts.map +1 -0
  4. package/dist/application/snapshot/createSnapshotRuntime.js +2 -0
  5. package/dist/application/snapshot/createSnapshotRuntime.js.map +1 -0
  6. package/dist/application/snapshot/snapshotCaptureService.d.ts +90 -0
  7. package/dist/application/snapshot/snapshotCaptureService.d.ts.map +1 -0
  8. package/dist/application/snapshot/snapshotCaptureService.js +394 -0
  9. package/dist/application/snapshot/snapshotCaptureService.js.map +1 -0
  10. package/dist/application/snapshot/snapshotRepository.d.ts +77 -0
  11. package/dist/application/snapshot/snapshotRepository.d.ts.map +1 -0
  12. package/dist/application/snapshot/snapshotRepository.js +2 -0
  13. package/dist/application/snapshot/snapshotRepository.js.map +1 -0
  14. package/dist/domain/canonical/canonicalSnapshot.d.ts +61 -0
  15. package/dist/domain/canonical/canonicalSnapshot.d.ts.map +1 -0
  16. package/dist/domain/canonical/canonicalSnapshot.js +300 -0
  17. package/dist/domain/canonical/canonicalSnapshot.js.map +1 -0
  18. package/dist/domain/contracts/runtimeEnvironmentContract.d.ts +21 -0
  19. package/dist/domain/contracts/runtimeEnvironmentContract.d.ts.map +1 -0
  20. package/dist/domain/contracts/runtimeEnvironmentContract.js +50 -0
  21. package/dist/domain/contracts/runtimeEnvironmentContract.js.map +1 -0
  22. package/dist/domain/contracts/snapshotDiffContract.d.ts +270 -0
  23. package/dist/domain/contracts/snapshotDiffContract.d.ts.map +1 -0
  24. package/dist/domain/contracts/snapshotDiffContract.js +99 -0
  25. package/dist/domain/contracts/snapshotDiffContract.js.map +1 -0
  26. package/dist/domain/diff/endpointDiffClassifier.d.ts +78 -0
  27. package/dist/domain/diff/endpointDiffClassifier.d.ts.map +1 -0
  28. package/dist/domain/diff/endpointDiffClassifier.js +317 -0
  29. package/dist/domain/diff/endpointDiffClassifier.js.map +1 -0
  30. package/dist/http.d.ts +3 -0
  31. package/dist/http.d.ts.map +1 -0
  32. package/dist/http.js +52 -0
  33. package/dist/http.js.map +1 -0
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +88 -266
  37. package/dist/index.js.map +1 -1
  38. package/dist/infrastructure/postgres/migrationRunner.d.ts +14 -0
  39. package/dist/infrastructure/postgres/migrationRunner.d.ts.map +1 -0
  40. package/dist/infrastructure/postgres/migrationRunner.js +161 -0
  41. package/dist/infrastructure/postgres/migrationRunner.js.map +1 -0
  42. package/dist/infrastructure/postgres/migrations/001_snapshot_schema.sql +29 -0
  43. package/dist/infrastructure/postgres/migrations/002_snapshot_change_history.sql +32 -0
  44. package/dist/infrastructure/postgres/postgresSnapshotRepository.d.ts +25 -0
  45. package/dist/infrastructure/postgres/postgresSnapshotRepository.d.ts.map +1 -0
  46. package/dist/infrastructure/postgres/postgresSnapshotRepository.js +323 -0
  47. package/dist/infrastructure/postgres/postgresSnapshotRepository.js.map +1 -0
  48. package/dist/infrastructure/postgres/runMigrations.d.ts +3 -0
  49. package/dist/infrastructure/postgres/runMigrations.d.ts.map +1 -0
  50. package/dist/infrastructure/postgres/runMigrations.js +33 -0
  51. package/dist/infrastructure/postgres/runMigrations.js.map +1 -0
  52. package/dist/infrastructure/runtime/createSnapshotRuntime.d.ts +17 -0
  53. package/dist/infrastructure/runtime/createSnapshotRuntime.d.ts.map +1 -0
  54. package/dist/infrastructure/runtime/createSnapshotRuntime.js +38 -0
  55. package/dist/infrastructure/runtime/createSnapshotRuntime.js.map +1 -0
  56. package/dist/schemas.d.ts +284 -3
  57. package/dist/schemas.d.ts.map +1 -1
  58. package/dist/schemas.js +110 -1
  59. package/dist/schemas.js.map +1 -1
  60. package/dist/tests/canonicalSnapshot.test.d.ts +2 -0
  61. package/dist/tests/canonicalSnapshot.test.d.ts.map +1 -0
  62. package/dist/tests/canonicalSnapshot.test.js +425 -0
  63. package/dist/tests/canonicalSnapshot.test.js.map +1 -0
  64. package/dist/tests/endpointDiffClassifier.test.d.ts +2 -0
  65. package/dist/tests/endpointDiffClassifier.test.d.ts.map +1 -0
  66. package/dist/tests/endpointDiffClassifier.test.js +633 -0
  67. package/dist/tests/endpointDiffClassifier.test.js.map +1 -0
  68. package/dist/tests/httpSnapshotTransport.test.d.ts +2 -0
  69. package/dist/tests/httpSnapshotTransport.test.d.ts.map +1 -0
  70. package/dist/tests/httpSnapshotTransport.test.js +356 -0
  71. package/dist/tests/httpSnapshotTransport.test.js.map +1 -0
  72. package/dist/tests/indexLifecycle.test.d.ts +2 -0
  73. package/dist/tests/indexLifecycle.test.d.ts.map +1 -0
  74. package/dist/tests/indexLifecycle.test.js +23 -0
  75. package/dist/tests/indexLifecycle.test.js.map +1 -0
  76. package/dist/tests/mcpSnapshotTools.test.d.ts +2 -0
  77. package/dist/tests/mcpSnapshotTools.test.d.ts.map +1 -0
  78. package/dist/tests/mcpSnapshotTools.test.js +316 -0
  79. package/dist/tests/mcpSnapshotTools.test.js.map +1 -0
  80. package/dist/tests/postgresMigrationSmoke.test.d.ts +2 -0
  81. package/dist/tests/postgresMigrationSmoke.test.d.ts.map +1 -0
  82. package/dist/tests/postgresMigrationSmoke.test.js +187 -0
  83. package/dist/tests/postgresMigrationSmoke.test.js.map +1 -0
  84. package/dist/tests/realPostgresTestSchema.d.ts +10 -0
  85. package/dist/tests/realPostgresTestSchema.d.ts.map +1 -0
  86. package/dist/tests/realPostgresTestSchema.js +73 -0
  87. package/dist/tests/realPostgresTestSchema.js.map +1 -0
  88. package/dist/tests/snapshotCapturePipeline.test.d.ts +2 -0
  89. package/dist/tests/snapshotCapturePipeline.test.d.ts.map +1 -0
  90. package/dist/tests/snapshotCapturePipeline.test.js +475 -0
  91. package/dist/tests/snapshotCapturePipeline.test.js.map +1 -0
  92. package/dist/tests/snapshotDiffContract.test.d.ts +2 -0
  93. package/dist/tests/snapshotDiffContract.test.d.ts.map +1 -0
  94. package/dist/tests/snapshotDiffContract.test.js +156 -0
  95. package/dist/tests/snapshotDiffContract.test.js.map +1 -0
  96. package/dist/tests/snapshotPersistence.real.test.d.ts +2 -0
  97. package/dist/tests/snapshotPersistence.real.test.d.ts.map +1 -0
  98. package/dist/tests/snapshotPersistence.real.test.js +310 -0
  99. package/dist/tests/snapshotPersistence.real.test.js.map +1 -0
  100. package/dist/tests/webServerRuntime.test.d.ts +2 -0
  101. package/dist/tests/webServerRuntime.test.d.ts.map +1 -0
  102. package/dist/tests/webServerRuntime.test.js +123 -0
  103. package/dist/tests/webServerRuntime.test.js.map +1 -0
  104. package/dist/transport/createSnapshotToolRuntime.d.ts +7 -0
  105. package/dist/transport/createSnapshotToolRuntime.d.ts.map +1 -0
  106. package/dist/transport/createSnapshotToolRuntime.js +40 -0
  107. package/dist/transport/createSnapshotToolRuntime.js.map +1 -0
  108. package/dist/transport/httpSnapshotServer.d.ts +11 -0
  109. package/dist/transport/httpSnapshotServer.d.ts.map +1 -0
  110. package/dist/transport/httpSnapshotServer.js +216 -0
  111. package/dist/transport/httpSnapshotServer.js.map +1 -0
  112. package/dist/transport/mcpToolRouter.d.ts +81 -0
  113. package/dist/transport/mcpToolRouter.d.ts.map +1 -0
  114. package/dist/transport/mcpToolRouter.js +416 -0
  115. package/dist/transport/mcpToolRouter.js.map +1 -0
  116. package/dist/transport/webServerRuntime.d.ts +17 -0
  117. package/dist/transport/webServerRuntime.d.ts.map +1 -0
  118. package/dist/transport/webServerRuntime.js +73 -0
  119. package/dist/transport/webServerRuntime.js.map +1 -0
  120. package/dist/utils/swaggerCache.d.ts +4 -0
  121. package/dist/utils/swaggerCache.d.ts.map +1 -1
  122. package/dist/utils/swaggerCache.js +8 -0
  123. package/dist/utils/swaggerCache.js.map +1 -1
  124. package/dist/utils/types.d.ts +2 -1
  125. package/dist/utils/types.d.ts.map +1 -1
  126. package/dist/utils/types.js +2 -0
  127. package/dist/utils/types.js.map +1 -1
  128. package/dist/web/dashboard.css +411 -0
  129. package/dist/web/dashboard.html +141 -0
  130. package/dist/web/dashboard.js +540 -0
  131. package/package.json +27 -17
@@ -0,0 +1,32 @@
1
+ CREATE TABLE IF NOT EXISTS snapshot_transitions (
2
+ id BIGSERIAL PRIMARY KEY,
3
+ source_id BIGINT NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
4
+ baseline_snapshot_id BIGINT NOT NULL REFERENCES snapshots(id) ON DELETE CASCADE,
5
+ target_snapshot_id BIGINT NOT NULL UNIQUE REFERENCES snapshots(id) ON DELETE CASCADE,
6
+ captured_at TIMESTAMPTZ NOT NULL,
7
+ counts JSONB NOT NULL,
8
+ warnings JSONB NOT NULL
9
+ );
10
+
11
+ CREATE INDEX IF NOT EXISTS idx_snapshot_transitions_source_captured_desc
12
+ ON snapshot_transitions (source_id, captured_at DESC, id DESC);
13
+
14
+ CREATE TABLE IF NOT EXISTS endpoint_change_history (
15
+ id BIGSERIAL PRIMARY KEY,
16
+ transition_id BIGINT NOT NULL REFERENCES snapshot_transitions(id) ON DELETE CASCADE,
17
+ source_id BIGINT NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
18
+ path TEXT NOT NULL,
19
+ method TEXT NOT NULL,
20
+ classification TEXT NOT NULL,
21
+ change_reason TEXT NOT NULL,
22
+ baseline_snapshot_id BIGINT NOT NULL REFERENCES snapshots(id) ON DELETE CASCADE,
23
+ target_snapshot_id BIGINT NOT NULL REFERENCES snapshots(id) ON DELETE CASCADE,
24
+ changed_at TIMESTAMPTZ NOT NULL,
25
+ UNIQUE (transition_id, path, method)
26
+ );
27
+
28
+ CREATE INDEX IF NOT EXISTS idx_endpoint_change_history_source_changed_desc
29
+ ON endpoint_change_history (source_id, changed_at DESC, id DESC);
30
+
31
+ CREATE INDEX IF NOT EXISTS idx_endpoint_change_history_source_path_method_changed_desc
32
+ ON endpoint_change_history (source_id, path, method, changed_at DESC, id DESC);
@@ -0,0 +1,25 @@
1
+ import type { Pool, PoolClient } from 'pg';
2
+ import { EndpointChangeHistoryRecord, ListEndpointChangeHistoryInput, SaveSnapshotInput, SaveSnapshotResult, SnapshotProjectRecord, SnapshotRecord, SnapshotRepository, SnapshotSourceIdentityRecord, SnapshotSourceRecord } from '../../application/snapshot/snapshotRepository.js';
3
+ import { MigrationRunOptions } from './migrationRunner.js';
4
+ type Queryable = Pick<Pool, 'query'> | Pick<Pool, 'query' | 'connect'> | Pick<PoolClient, 'query'>;
5
+ interface PostgresSnapshotRepositoryOptions {
6
+ migrationRunOptions?: MigrationRunOptions;
7
+ }
8
+ export declare class PostgresSnapshotRepository implements SnapshotRepository {
9
+ private readonly db;
10
+ private readonly options;
11
+ constructor(db: Queryable, options?: PostgresSnapshotRepositoryOptions);
12
+ initializeSchema(): Promise<void>;
13
+ ensureProject(projectKey: string): Promise<SnapshotProjectRecord>;
14
+ ensureSource(projectId: string, swaggerUrl: string): Promise<SnapshotSourceRecord>;
15
+ getSourceIdentityById(sourceId: string): Promise<SnapshotSourceIdentityRecord | null>;
16
+ getLatestSnapshot(sourceId: string): Promise<SnapshotRecord | null>;
17
+ private acquireTransactionSession;
18
+ private insertSnapshotTransition;
19
+ saveSnapshot(input: SaveSnapshotInput): Promise<SaveSnapshotResult>;
20
+ getSnapshotById(snapshotId: string): Promise<SnapshotRecord | null>;
21
+ listSnapshotsBySource(sourceId: string, limit?: number): Promise<SnapshotRecord[]>;
22
+ listEndpointChangeHistory(input: ListEndpointChangeHistoryInput): Promise<EndpointChangeHistoryRecord[]>;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=postgresSnapshotRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresSnapshotRepository.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/postgres/postgresSnapshotRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC3C,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAE9B,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,4BAA4B,EAC5B,oBAAoB,EACrB,MAAM,kDAAkD,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAyB,MAAM,sBAAsB,CAAC;AAElF,KAAK,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAGnG,UAAU,iCAAiC;IACzC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C;AAyKD,qBAAa,0BAA2B,YAAW,kBAAkB;IAEjE,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,EAAE,EAAE,SAAS,EACb,OAAO,GAAE,iCAAsC;IAG5D,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAejE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAelF,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC;IAuBrF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YAmB3D,yBAAyB;YAQzB,wBAAwB;IAuEhC,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmEnE,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAkBnE,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAgB9E,yBAAyB,CAAC,KAAK,EAAE,8BAA8B,GAAG,OAAO,CAAC,2BAA2B,EAAE,CAAC;CA+B/G"}
@@ -0,0 +1,323 @@
1
+ import { runPostgresMigrations } from './migrationRunner.js';
2
+ function toIsoTimestamp(value) {
3
+ if (value instanceof Date) {
4
+ return value.toISOString();
5
+ }
6
+ return new Date(value).toISOString();
7
+ }
8
+ function isRecord(value) {
9
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
10
+ }
11
+ function requireString(value, fieldName) {
12
+ if (typeof value !== 'string' || value.length === 0) {
13
+ throw new Error(`Invalid repository row: ${fieldName} must be a non-empty string.`);
14
+ }
15
+ return value;
16
+ }
17
+ function requireId(value, fieldName) {
18
+ if (typeof value !== 'string' && typeof value !== 'number') {
19
+ throw new Error(`Invalid repository row: ${fieldName} must be string or number.`);
20
+ }
21
+ return String(value);
22
+ }
23
+ function requireTimestamp(value, fieldName) {
24
+ if (typeof value !== 'string' && !(value instanceof Date)) {
25
+ throw new Error(`Invalid repository row: ${fieldName} must be a timestamp.`);
26
+ }
27
+ return toIsoTimestamp(value);
28
+ }
29
+ function requireSingleRow(rows, context) {
30
+ if (rows.length === 0) {
31
+ throw new Error(`Repository query returned no rows for ${context}.`);
32
+ }
33
+ return rows[0];
34
+ }
35
+ function parseCanonicalSnapshot(raw) {
36
+ let parsed = raw;
37
+ if (typeof raw === 'string') {
38
+ try {
39
+ parsed = JSON.parse(raw);
40
+ }
41
+ catch {
42
+ throw new Error('Invalid repository row: canonical_snapshot is not valid JSON.');
43
+ }
44
+ }
45
+ if (!isRecord(parsed)) {
46
+ throw new Error('Invalid repository row: canonical_snapshot must be an object.');
47
+ }
48
+ if (typeof parsed.sourceUrl !== 'string' || typeof parsed.documentFingerprint !== 'string') {
49
+ throw new Error('Invalid repository row: canonical_snapshot is missing sourceUrl/documentFingerprint.');
50
+ }
51
+ if (!Array.isArray(parsed.endpoints)) {
52
+ throw new Error('Invalid repository row: canonical_snapshot.endpoints must be an array.');
53
+ }
54
+ if (!isRecord(parsed.versionSignal)) {
55
+ throw new Error('Invalid repository row: canonical_snapshot.versionSignal must be an object.');
56
+ }
57
+ return parsed;
58
+ }
59
+ function mapProjectRow(row) {
60
+ return {
61
+ id: requireId(row.id, 'projects.id'),
62
+ projectKey: requireString(row.project_key, 'projects.project_key'),
63
+ createdAt: requireTimestamp(row.created_at, 'projects.created_at'),
64
+ };
65
+ }
66
+ function mapSourceRow(row) {
67
+ return {
68
+ id: requireId(row.id, 'sources.id'),
69
+ projectId: requireId(row.project_id, 'sources.project_id'),
70
+ swaggerUrl: requireString(row.swagger_url, 'sources.swagger_url'),
71
+ createdAt: requireTimestamp(row.created_at, 'sources.created_at'),
72
+ };
73
+ }
74
+ function mapSnapshotRow(row) {
75
+ return {
76
+ id: requireId(row.id, 'snapshots.id'),
77
+ sourceId: requireId(row.source_id, 'snapshots.source_id'),
78
+ specHash: requireString(row.spec_hash, 'snapshots.spec_hash'),
79
+ documentFingerprint: requireString(row.document_fingerprint, 'snapshots.document_fingerprint'),
80
+ canonicalSnapshot: parseCanonicalSnapshot(row.canonical_snapshot),
81
+ capturedAt: requireTimestamp(row.captured_at, 'snapshots.captured_at'),
82
+ };
83
+ }
84
+ function mapSourceIdentityRow(row) {
85
+ return {
86
+ sourceId: requireId(row.source_id, 'sources.id'),
87
+ projectId: requireId(row.project_id, 'sources.project_id'),
88
+ projectKey: requireString(row.project_key, 'projects.project_key'),
89
+ swaggerUrl: requireString(row.swagger_url, 'sources.swagger_url'),
90
+ };
91
+ }
92
+ function mapEndpointChangeHistoryRow(row) {
93
+ return {
94
+ baselineSnapshotId: requireId(row.baseline_snapshot_id, 'endpoint_change_history.baseline_snapshot_id'),
95
+ targetSnapshotId: requireId(row.target_snapshot_id, 'endpoint_change_history.target_snapshot_id'),
96
+ path: requireString(row.path, 'endpoint_change_history.path'),
97
+ method: requireString(row.method, 'endpoint_change_history.method'),
98
+ classification: requireString(row.classification, 'endpoint_change_history.classification'),
99
+ changeReason: requireString(row.change_reason, 'endpoint_change_history.change_reason'),
100
+ changedAt: requireTimestamp(row.changed_at, 'endpoint_change_history.changed_at'),
101
+ };
102
+ }
103
+ export class PostgresSnapshotRepository {
104
+ db;
105
+ options;
106
+ constructor(db, options = {}) {
107
+ this.db = db;
108
+ this.options = options;
109
+ }
110
+ async initializeSchema() {
111
+ await runPostgresMigrations(this.db, this.options.migrationRunOptions);
112
+ }
113
+ async ensureProject(projectKey) {
114
+ const result = await this.db.query(`
115
+ INSERT INTO projects (project_key)
116
+ VALUES ($1)
117
+ ON CONFLICT (project_key)
118
+ DO UPDATE SET project_key = EXCLUDED.project_key
119
+ RETURNING id, project_key, created_at;
120
+ `, [projectKey]);
121
+ return mapProjectRow(requireSingleRow(result.rows, 'ensure project'));
122
+ }
123
+ async ensureSource(projectId, swaggerUrl) {
124
+ const result = await this.db.query(`
125
+ INSERT INTO sources (project_id, swagger_url)
126
+ VALUES ($1, $2)
127
+ ON CONFLICT (project_id, swagger_url)
128
+ DO UPDATE SET swagger_url = EXCLUDED.swagger_url
129
+ RETURNING id, project_id, swagger_url, created_at;
130
+ `, [projectId, swaggerUrl]);
131
+ return mapSourceRow(requireSingleRow(result.rows, 'ensure source'));
132
+ }
133
+ async getSourceIdentityById(sourceId) {
134
+ const result = await this.db.query(`
135
+ SELECT
136
+ s.id AS source_id,
137
+ s.project_id,
138
+ p.project_key,
139
+ s.swagger_url
140
+ FROM sources s
141
+ INNER JOIN projects p ON p.id = s.project_id
142
+ WHERE s.id = $1
143
+ LIMIT 1;
144
+ `, [sourceId]);
145
+ if (result.rows.length === 0) {
146
+ return null;
147
+ }
148
+ return mapSourceIdentityRow(result.rows[0]);
149
+ }
150
+ async getLatestSnapshot(sourceId) {
151
+ const result = await this.db.query(`
152
+ SELECT id, source_id, spec_hash, document_fingerprint, canonical_snapshot, captured_at
153
+ FROM snapshots
154
+ WHERE source_id = $1
155
+ ORDER BY captured_at DESC, id DESC
156
+ LIMIT 1;
157
+ `, [sourceId]);
158
+ if (result.rows.length === 0) {
159
+ return null;
160
+ }
161
+ return mapSnapshotRow(result.rows[0]);
162
+ }
163
+ async acquireTransactionSession() {
164
+ if ('connect' in this.db && typeof this.db.connect === 'function') {
165
+ return this.db.connect();
166
+ }
167
+ return this.db;
168
+ }
169
+ async insertSnapshotTransition(session, sourceId, snapshot, transition) {
170
+ const transitionResult = await session.query(`
171
+ INSERT INTO snapshot_transitions (
172
+ source_id,
173
+ baseline_snapshot_id,
174
+ target_snapshot_id,
175
+ captured_at,
176
+ counts,
177
+ warnings
178
+ )
179
+ VALUES ($1, $2, $3, $4, $5, $6)
180
+ ON CONFLICT (target_snapshot_id) DO NOTHING
181
+ RETURNING id;
182
+ `, [
183
+ sourceId,
184
+ transition.baselineSnapshotId,
185
+ snapshot.id,
186
+ snapshot.capturedAt,
187
+ JSON.stringify(transition.counts),
188
+ JSON.stringify(transition.warnings),
189
+ ]);
190
+ if (transitionResult.rows.length === 0) {
191
+ return;
192
+ }
193
+ const transitionId = requireId(requireSingleRow(transitionResult.rows, 'insert snapshot transition').id, 'snapshot_transitions.id');
194
+ for (const event of transition.events) {
195
+ await session.query(`
196
+ INSERT INTO endpoint_change_history (
197
+ transition_id,
198
+ source_id,
199
+ path,
200
+ method,
201
+ classification,
202
+ change_reason,
203
+ baseline_snapshot_id,
204
+ target_snapshot_id,
205
+ changed_at
206
+ )
207
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
208
+ ON CONFLICT (transition_id, path, method) DO NOTHING;
209
+ `, [
210
+ transitionId,
211
+ sourceId,
212
+ event.path,
213
+ event.method,
214
+ event.classification,
215
+ event.changeReason,
216
+ transition.baselineSnapshotId,
217
+ snapshot.id,
218
+ snapshot.capturedAt,
219
+ ]);
220
+ }
221
+ }
222
+ async saveSnapshot(input) {
223
+ const session = await this.acquireTransactionSession();
224
+ try {
225
+ await session.query('BEGIN');
226
+ const result = await session.query(`
227
+ WITH inserted AS (
228
+ INSERT INTO snapshots (source_id, spec_hash, document_fingerprint, canonical_snapshot)
229
+ VALUES ($1, $2, $3, $4)
230
+ ON CONFLICT (source_id, spec_hash) DO NOTHING
231
+ RETURNING id, source_id, spec_hash, document_fingerprint, canonical_snapshot, captured_at
232
+ ),
233
+ selected AS (
234
+ SELECT TRUE AS created, id, source_id, spec_hash, document_fingerprint, canonical_snapshot, captured_at
235
+ FROM inserted
236
+ UNION ALL
237
+ SELECT FALSE AS created, s.id, s.source_id, s.spec_hash, s.document_fingerprint, s.canonical_snapshot, s.captured_at
238
+ FROM snapshots s
239
+ WHERE s.source_id = $1
240
+ AND s.spec_hash = $2
241
+ AND NOT EXISTS (SELECT 1 FROM inserted)
242
+ )
243
+ SELECT created, id, source_id, spec_hash, document_fingerprint, canonical_snapshot, captured_at
244
+ FROM selected
245
+ LIMIT 1;
246
+ `, [input.sourceId, input.specHash, input.documentFingerprint, JSON.stringify(input.canonicalSnapshot)]);
247
+ const row = requireSingleRow(result.rows, 'save snapshot');
248
+ const snapshot = mapSnapshotRow(row);
249
+ const created = row.created === true;
250
+ if (created && input.transition) {
251
+ await this.insertSnapshotTransition(session, input.sourceId, snapshot, input.transition);
252
+ }
253
+ await session.query('COMMIT');
254
+ return {
255
+ snapshot,
256
+ created,
257
+ };
258
+ }
259
+ catch (error) {
260
+ await session.query('ROLLBACK').catch(() => undefined);
261
+ const message = error instanceof Error ? error.message : 'Unknown repository error.';
262
+ if (message.includes('no unique or exclusion constraint')) {
263
+ throw new Error('Missing snapshots unique constraint on (source_id, spec_hash). Run postgres migrations before capture.');
264
+ }
265
+ if (message.includes('relation "snapshots" does not exist') ||
266
+ message.includes('relation "snapshot_transitions" does not exist') ||
267
+ message.includes('relation "endpoint_change_history" does not exist')) {
268
+ throw new Error('Snapshot history tables are missing. Run postgres migrations before capture.');
269
+ }
270
+ throw error;
271
+ }
272
+ finally {
273
+ session.release?.();
274
+ }
275
+ }
276
+ async getSnapshotById(snapshotId) {
277
+ const result = await this.db.query(`
278
+ SELECT id, source_id, spec_hash, document_fingerprint, canonical_snapshot, captured_at
279
+ FROM snapshots
280
+ WHERE id = $1
281
+ LIMIT 1;
282
+ `, [snapshotId]);
283
+ if (result.rows.length === 0) {
284
+ return null;
285
+ }
286
+ return mapSnapshotRow(result.rows[0]);
287
+ }
288
+ async listSnapshotsBySource(sourceId, limit = 50) {
289
+ const normalizedLimit = Math.max(1, Math.min(limit, 200));
290
+ const result = await this.db.query(`
291
+ SELECT id, source_id, spec_hash, document_fingerprint, canonical_snapshot, captured_at
292
+ FROM snapshots
293
+ WHERE source_id = $1
294
+ ORDER BY captured_at DESC, id DESC
295
+ LIMIT $2;
296
+ `, [sourceId, normalizedLimit]);
297
+ return result.rows.map(mapSnapshotRow);
298
+ }
299
+ async listEndpointChangeHistory(input) {
300
+ const normalizedLimit = Math.max(1, Math.min(input.limit ?? 50, 200));
301
+ const queryParams = [input.sourceId];
302
+ const filters = ['source_id = $1'];
303
+ let parameterIndex = 2;
304
+ if (input.path && input.method) {
305
+ filters.push(`path = $${parameterIndex}`);
306
+ queryParams.push(input.path);
307
+ parameterIndex += 1;
308
+ filters.push(`method = $${parameterIndex}`);
309
+ queryParams.push(input.method);
310
+ parameterIndex += 1;
311
+ }
312
+ queryParams.push(normalizedLimit);
313
+ const result = await this.db.query(`
314
+ SELECT baseline_snapshot_id, target_snapshot_id, path, method, classification, change_reason, changed_at
315
+ FROM endpoint_change_history
316
+ WHERE ${filters.join(' AND ')}
317
+ ORDER BY changed_at DESC, id DESC
318
+ LIMIT $${parameterIndex};
319
+ `, queryParams);
320
+ return result.rows.map(mapEndpointChangeHistoryRow);
321
+ }
322
+ }
323
+ //# sourceMappingURL=postgresSnapshotRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresSnapshotRepository.js","sourceRoot":"","sources":["../../../src/infrastructure/postgres/postgresSnapshotRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare function runCli(): Promise<void>;
2
+ export { runCli as runPostgresMigrationsCli };
3
+ //# sourceMappingURL=runMigrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runMigrations.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/postgres/runMigrations.ts"],"names":[],"mappings":"AAYA,iBAAe,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAYrC;AAaD,OAAO,EAAE,MAAM,IAAI,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { Pool } from 'pg';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { runPostgresMigrations } from './migrationRunner.js';
4
+ function readDatabaseUrlFromEnvironment(env) {
5
+ const databaseUrl = env.DATABASE_URL?.trim();
6
+ if (!databaseUrl) {
7
+ throw new Error('DATABASE_URL is required to run postgres migrations.');
8
+ }
9
+ return databaseUrl;
10
+ }
11
+ async function runCli() {
12
+ const databaseUrl = readDatabaseUrlFromEnvironment(process.env);
13
+ const pool = new Pool({
14
+ connectionString: databaseUrl,
15
+ });
16
+ try {
17
+ const summary = await runPostgresMigrations(pool);
18
+ console.log(JSON.stringify(summary, null, 2));
19
+ }
20
+ finally {
21
+ await pool.end();
22
+ }
23
+ }
24
+ const isDirectExecution = typeof process.argv[1] === 'string' && pathToFileURL(process.argv[1]).href === import.meta.url;
25
+ if (isDirectExecution) {
26
+ runCli().catch(error => {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ console.error(`Failed to run migrations: ${message}`);
29
+ process.exit(1);
30
+ });
31
+ }
32
+ export { runCli as runPostgresMigrationsCli };
33
+ //# sourceMappingURL=runMigrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runMigrations.js","sourceRoot":"","sources":["../../../src/infrastructure/postgres/runMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,SAAS,8BAA8B,CAAC,GAAsB;IAC5D,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,MAAM;IACnB,MAAM,WAAW,GAAG,8BAA8B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QACpB,gBAAgB,EAAE,WAAW;KAC9B,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,iBAAiB,GACrB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;AAEjG,IAAI,iBAAiB,EAAE,CAAC;IACtB,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QACrB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,MAAM,IAAI,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { Pool } from 'pg';
2
+ import { SnapshotCaptureService, SnapshotDocumentLoader } from '../../application/snapshot/snapshotCaptureService.js';
3
+ import { SnapshotRepository } from '../../application/snapshot/snapshotRepository.js';
4
+ import { RuntimeEnvironment } from '../../domain/contracts/runtimeEnvironmentContract.js';
5
+ export interface SnapshotRuntime {
6
+ environment: RuntimeEnvironment;
7
+ service: SnapshotCaptureService;
8
+ dispose(): Promise<void>;
9
+ }
10
+ export interface SnapshotRuntimeDependencies {
11
+ pool: Pick<Pool, 'end'>;
12
+ repository: SnapshotRepository;
13
+ loader: SnapshotDocumentLoader;
14
+ }
15
+ export type SnapshotRuntimeDependencyFactory = (environment: RuntimeEnvironment) => Promise<SnapshotRuntimeDependencies> | SnapshotRuntimeDependencies;
16
+ export declare function createSnapshotRuntime(env: NodeJS.ProcessEnv, dependencyFactory?: SnapshotRuntimeDependencyFactory): Promise<SnapshotRuntime>;
17
+ //# sourceMappingURL=createSnapshotRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSnapshotRuntime.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/runtime/createSnapshotRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AACtH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kDAAkD,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAuB,MAAM,sDAAsD,CAAC;AAI/G,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,kBAAkB,CAAC;IAChC,OAAO,EAAE,sBAAsB,CAAC;IAChC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,MAAM,MAAM,gCAAgC,GAAG,CAC7C,WAAW,EAAE,kBAAkB,KAC5B,OAAO,CAAC,2BAA2B,CAAC,GAAG,2BAA2B,CAAC;AAcxE,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,iBAAiB,GAAE,gCAA4D,GAC9E,OAAO,CAAC,eAAe,CAAC,CAsB1B"}
@@ -0,0 +1,38 @@
1
+ import { Pool } from 'pg';
2
+ import { SnapshotCaptureService } from '../../application/snapshot/snapshotCaptureService.js';
3
+ import { validateEnvironment } from '../../domain/contracts/runtimeEnvironmentContract.js';
4
+ import { PostgresSnapshotRepository } from '../postgres/postgresSnapshotRepository.js';
5
+ import { SwaggerCache } from '../../utils/swaggerCache.js';
6
+ function createDefaultDependencies(environment) {
7
+ const pool = new Pool({
8
+ connectionString: environment.DATABASE_URL,
9
+ });
10
+ return {
11
+ pool,
12
+ repository: new PostgresSnapshotRepository(pool),
13
+ loader: new SwaggerCache(),
14
+ };
15
+ }
16
+ export async function createSnapshotRuntime(env, dependencyFactory = createDefaultDependencies) {
17
+ const environment = validateEnvironment(env);
18
+ let dependencies = null;
19
+ try {
20
+ dependencies = await dependencyFactory(environment);
21
+ const service = new SnapshotCaptureService(dependencies.repository, dependencies.loader);
22
+ await service.bootstrap(environment);
23
+ return {
24
+ environment,
25
+ service,
26
+ async dispose() {
27
+ await dependencies.pool.end();
28
+ },
29
+ };
30
+ }
31
+ catch (error) {
32
+ if (dependencies) {
33
+ await dependencies.pool.end().catch(() => undefined);
34
+ }
35
+ throw error;
36
+ }
37
+ }
38
+ //# sourceMappingURL=createSnapshotRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSnapshotRuntime.js","sourceRoot":"","sources":["../../../src/infrastructure/runtime/createSnapshotRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAA0B,MAAM,sDAAsD,CAAC;AAEtH,OAAO,EAAsB,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAC/G,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAkB3D,SAAS,yBAAyB,CAAC,WAA+B;IAChE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QACpB,gBAAgB,EAAE,WAAW,CAAC,YAAY;KAC3C,CAAC,CAAC;IAEH,OAAO;QACL,IAAI;QACJ,UAAU,EAAE,IAAI,0BAA0B,CAAC,IAAI,CAAC;QAChD,MAAM,EAAE,IAAI,YAAY,EAAE;KAC3B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAsB,EACtB,oBAAsD,yBAAyB;IAE/E,MAAM,WAAW,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,YAAY,GAAuC,IAAI,CAAC;IAE5D,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACzF,MAAM,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAErC,OAAO;YACL,WAAW;YACX,OAAO;YACP,KAAK,CAAC,OAAO;gBACX,MAAM,YAAa,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}