@secondlayer/shared 4.3.4 → 5.0.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 (64) hide show
  1. package/dist/src/crypto/hmac.js +3 -3
  2. package/dist/src/crypto/hmac.js.map +3 -3
  3. package/dist/src/crypto/secrets.js.map +2 -2
  4. package/dist/src/db/index.js.map +2 -2
  5. package/dist/src/db/queries/account-usage.js +137 -29
  6. package/dist/src/db/queries/account-usage.js.map +3 -3
  7. package/dist/src/db/queries/subscriptions.js +3 -3
  8. package/dist/src/db/queries/subscriptions.js.map +5 -5
  9. package/dist/src/db/queries/tenants.js.map +2 -2
  10. package/dist/src/errors.d.ts +1 -2
  11. package/dist/src/errors.js +3 -2
  12. package/dist/src/errors.js.map +3 -3
  13. package/dist/src/index.d.ts +51 -3
  14. package/dist/src/index.js +351 -4
  15. package/dist/src/index.js.map +9 -8
  16. package/dist/src/logger.js.map +2 -2
  17. package/dist/src/node/archive-client.js.map +2 -2
  18. package/dist/src/node/hiro-client.js +27 -23
  19. package/dist/src/node/hiro-client.js.map +4 -4
  20. package/dist/src/node/hiro-pg-client.js +2 -2
  21. package/dist/src/node/hiro-pg-client.js.map +3 -3
  22. package/dist/src/node/local-client.js.map +2 -2
  23. package/dist/src/pricing.d.ts +51 -7
  24. package/dist/src/pricing.js +143 -28
  25. package/dist/src/pricing.js.map +3 -3
  26. package/dist/src/schemas/filters.js.map +2 -2
  27. package/dist/src/schemas/index.d.ts +9 -0
  28. package/dist/src/schemas/index.js.map +3 -3
  29. package/dist/src/schemas/subgraphs.d.ts +9 -0
  30. package/dist/src/schemas/subgraphs.js.map +1 -1
  31. package/dist/src/subgraphs/spec.d.ts +104 -0
  32. package/dist/src/subgraphs/spec.js +366 -0
  33. package/dist/src/subgraphs/spec.js.map +10 -0
  34. package/migrations/0001_initial.ts +2 -0
  35. package/migrations/0002_api_keys.ts +2 -0
  36. package/migrations/0003_tenant_isolation.ts +5 -3
  37. package/migrations/0004_accounts_and_usage.ts +2 -0
  38. package/migrations/0005_sessions.ts +2 -0
  39. package/migrations/0006_tx_index.ts +2 -0
  40. package/migrations/0007_contracts.ts +2 -0
  41. package/migrations/0008_drop_contracts.ts +2 -0
  42. package/migrations/0009_waitlist.ts +2 -0
  43. package/migrations/0010_waitlist_status.ts +2 -0
  44. package/migrations/0011_account_insights.ts +2 -0
  45. package/migrations/0012_view_health_snapshots.ts +2 -0
  46. package/migrations/0013_view_processing_stats.ts +2 -0
  47. package/migrations/0014_view_table_snapshots.ts +2 -0
  48. package/migrations/0015_rename_views_to_subgraphs.ts +2 -0
  49. package/migrations/0016_rename_webhook_to_endpoint.ts +2 -0
  50. package/migrations/0017_security_hardening.ts +2 -0
  51. package/migrations/0018_subgraph_gaps.ts +2 -0
  52. package/migrations/0021_tx_function_args_result.ts +3 -4
  53. package/migrations/0022_marketplace.ts +4 -5
  54. package/migrations/0023_projects.ts +3 -1
  55. package/migrations/0024_chat_sessions.ts +3 -1
  56. package/migrations/0025_chat_session_summary.ts +3 -4
  57. package/migrations/0026_workflows.ts +4 -5
  58. package/migrations/0027_workflow_cursors.ts +3 -1
  59. package/migrations/0028_subgraph_account_scoping.ts +7 -2
  60. package/migrations/0029_subgraph_handler_code.ts +3 -4
  61. package/migrations/0030_workflow_source_code.ts +2 -0
  62. package/migrations/0031_subgraph_source_code.ts +2 -0
  63. package/migrations/0032_drop_streams_tables.ts +9 -9
  64. package/package.json +6 -2
@@ -0,0 +1,104 @@
1
+ interface SubgraphGapRange {
2
+ start: number;
3
+ end: number;
4
+ size: number;
5
+ reason: string;
6
+ }
7
+ interface SubgraphSyncInfo {
8
+ status: "synced" | "catching_up" | "reindexing" | "error";
9
+ mode?: "sync" | "reindex";
10
+ startBlock: number;
11
+ lastProcessedBlock: number;
12
+ /**
13
+ * Backward-compatible denominator for progress displays. During reindexing,
14
+ * this is the reindex target block rather than the live source chain tip.
15
+ */
16
+ chainTip: number;
17
+ sourceChainTip?: number;
18
+ targetBlock?: number;
19
+ blocksRemaining: number;
20
+ processedBlocks?: number;
21
+ totalBlocks?: number;
22
+ progress: number;
23
+ gaps: {
24
+ count: number
25
+ totalMissingBlocks: number
26
+ ranges: SubgraphGapRange[]
27
+ };
28
+ integrity: "complete" | "gaps_detected";
29
+ }
30
+ interface SubgraphDetail {
31
+ name: string;
32
+ version: string;
33
+ schemaHash?: string;
34
+ status: string;
35
+ lastProcessedBlock: number;
36
+ description?: string;
37
+ sources?: Record<string, unknown>;
38
+ definition?: Record<string, unknown>;
39
+ health: {
40
+ totalProcessed: number
41
+ totalErrors: number
42
+ errorRate: number
43
+ lastError: string | null
44
+ lastErrorAt: string | null
45
+ };
46
+ sync: SubgraphSyncInfo;
47
+ tables: Record<string, {
48
+ endpoint: string
49
+ columns: Record<string, {
50
+ type: string
51
+ nullable?: boolean
52
+ indexed?: boolean
53
+ searchable?: boolean
54
+ default?: string | number | boolean
55
+ }>
56
+ rowCount: number
57
+ example: string
58
+ indexes?: string[][]
59
+ uniqueKeys?: string[][]
60
+ }>;
61
+ createdAt: string;
62
+ updatedAt: string;
63
+ }
64
+ type SubgraphSpecFormat = "openapi" | "agent" | "markdown";
65
+ interface SubgraphSpecOptions {
66
+ serverUrl?: string;
67
+ generatedAt?: string;
68
+ }
69
+ interface SubgraphAgentSchema {
70
+ name: string;
71
+ version: string;
72
+ description?: string;
73
+ schemaHash?: string;
74
+ generatedAt: string;
75
+ serverUrl: string;
76
+ sources?: Record<string, unknown>;
77
+ tables: Record<string, {
78
+ endpoint: string
79
+ countEndpoint: string
80
+ rowCount: number
81
+ columns: SubgraphDetail["tables"][string]["columns"]
82
+ indexes?: string[][]
83
+ uniqueKeys?: string[][]
84
+ query: {
85
+ parameters: string[]
86
+ sortable: string[]
87
+ selectable: string[]
88
+ searchable: string[]
89
+ filters: string[]
90
+ }
91
+ examples: {
92
+ list: Record<string, unknown>
93
+ count: {
94
+ count: number
95
+ }
96
+ curl: string
97
+ }
98
+ }>;
99
+ }
100
+ declare function generateSubgraphAgentSchema(detail: SubgraphDetail, options?: SubgraphSpecOptions): SubgraphAgentSchema;
101
+ declare function generateSubgraphOpenApi(detail: SubgraphDetail, options?: SubgraphSpecOptions): Record<string, unknown>;
102
+ declare function generateSubgraphMarkdown(detail: SubgraphDetail, options?: SubgraphSpecOptions): string;
103
+ declare function generateSubgraphSpec(detail: SubgraphDetail, format: SubgraphSpecFormat, options?: SubgraphSpecOptions): Record<string, unknown> | SubgraphAgentSchema | string;
104
+ export { generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphAgentSchema };
@@ -0,0 +1,366 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
17
+ // src/subgraphs/spec.ts
18
+ var SYSTEM_COLUMNS = ["_id", "_block_height", "_tx_id", "_created_at"];
19
+ var BASE_QUERY_PARAMS = ["_limit", "_offset", "_sort", "_order", "_fields"];
20
+ var COMPARISON_OPS = ["neq", "gt", "gte", "lt", "lte"];
21
+ function generatedAt(options) {
22
+ return options.generatedAt ?? new Date().toISOString();
23
+ }
24
+ function normalizeServerUrl(serverUrl) {
25
+ return (serverUrl ?? "https://api.secondlayer.tools").replace(/\/+$/, "");
26
+ }
27
+ function tablePath(subgraphName, tableName) {
28
+ return `/api/subgraphs/${subgraphName}/${tableName}`;
29
+ }
30
+ function countPath(subgraphName, tableName) {
31
+ return `${tablePath(subgraphName, tableName)}/count`;
32
+ }
33
+ function isTextLike(type) {
34
+ return type === "text" || type === "principal" || type === "timestamp";
35
+ }
36
+ function isComparable(type) {
37
+ return type === "uint" || type === "int" || type === "bigint" || type === "serial" || type === "timestamp";
38
+ }
39
+ function exampleForColumn(type) {
40
+ switch (type) {
41
+ case "uint":
42
+ case "int":
43
+ case "bigint":
44
+ return "1000";
45
+ case "serial":
46
+ return 1;
47
+ case "principal":
48
+ return "SP000000000000000000002Q6VF78";
49
+ case "timestamp":
50
+ return "2026-01-01T00:00:00.000Z";
51
+ case "boolean":
52
+ return true;
53
+ case "jsonb":
54
+ return { example: true };
55
+ default:
56
+ return "example";
57
+ }
58
+ }
59
+ function openApiSchemaForColumn(col) {
60
+ let schema;
61
+ switch (col.type) {
62
+ case "uint":
63
+ case "int":
64
+ case "bigint":
65
+ schema = { type: "string", pattern: "^-?\\d+(\\.\\d+)?$" };
66
+ break;
67
+ case "serial":
68
+ schema = { type: "integer" };
69
+ break;
70
+ case "principal":
71
+ case "text":
72
+ schema = { type: "string" };
73
+ break;
74
+ case "timestamp":
75
+ schema = { type: "string", format: "date-time" };
76
+ break;
77
+ case "boolean":
78
+ schema = { type: "boolean" };
79
+ break;
80
+ case "jsonb":
81
+ schema = { type: "object", additionalProperties: true };
82
+ break;
83
+ default:
84
+ schema = {};
85
+ break;
86
+ }
87
+ if (col.nullable) {
88
+ const type = schema.type;
89
+ if (typeof type === "string")
90
+ schema.type = [type, "null"];
91
+ }
92
+ return schema;
93
+ }
94
+ function columnEntries(table) {
95
+ return Object.entries(table.columns);
96
+ }
97
+ function selectableColumns(table) {
98
+ return columnEntries(table).map(([name]) => name);
99
+ }
100
+ function searchableColumns(table) {
101
+ return columnEntries(table).filter(([, col]) => col.searchable).map(([name]) => name);
102
+ }
103
+ function filterNames(table) {
104
+ const result = [];
105
+ for (const [name, col] of columnEntries(table)) {
106
+ result.push(name);
107
+ result.push(`${name}.neq`);
108
+ if (isComparable(col.type)) {
109
+ for (const op of COMPARISON_OPS.filter((op2) => op2 !== "neq")) {
110
+ result.push(`${name}.${op}`);
111
+ }
112
+ }
113
+ if (isTextLike(col.type))
114
+ result.push(`${name}.like`);
115
+ }
116
+ return result;
117
+ }
118
+ function queryParameters(table) {
119
+ const params = [...BASE_QUERY_PARAMS];
120
+ if (searchableColumns(table).length > 0)
121
+ params.push("_search");
122
+ return params;
123
+ }
124
+ function rowExample(table) {
125
+ const row = {};
126
+ for (const [name, col] of columnEntries(table)) {
127
+ row[name] = exampleForColumn(col.type);
128
+ }
129
+ return row;
130
+ }
131
+ function openApiParameter(name, description, schema = { type: "string" }) {
132
+ return {
133
+ name,
134
+ in: "query",
135
+ required: false,
136
+ description,
137
+ schema
138
+ };
139
+ }
140
+ function tableParameters(table) {
141
+ const parameters = [
142
+ openApiParameter("_limit", "Maximum rows to return.", {
143
+ type: "integer",
144
+ default: 50,
145
+ minimum: 1,
146
+ maximum: 1000
147
+ }),
148
+ openApiParameter("_offset", "Rows to skip for pagination.", {
149
+ type: "integer",
150
+ default: 0,
151
+ minimum: 0
152
+ }),
153
+ openApiParameter("_sort", "Column to sort by.", {
154
+ type: "string",
155
+ enum: selectableColumns(table)
156
+ }),
157
+ openApiParameter("_order", "Sort direction.", {
158
+ type: "string",
159
+ enum: ["asc", "desc"],
160
+ default: "asc"
161
+ }),
162
+ openApiParameter("_fields", "Comma-separated columns to include.", {
163
+ type: "string"
164
+ })
165
+ ];
166
+ if (searchableColumns(table).length > 0) {
167
+ parameters.push(openApiParameter("_search", "Search across searchable columns.", {
168
+ type: "string"
169
+ }));
170
+ }
171
+ for (const [name, col] of columnEntries(table)) {
172
+ parameters.push(openApiParameter(name, `Filter ${name} by equality.`, {
173
+ type: "string"
174
+ }));
175
+ parameters.push(openApiParameter(`${name}.neq`, `Filter ${name} by inequality.`, {
176
+ type: "string"
177
+ }));
178
+ if (isComparable(col.type)) {
179
+ for (const op of ["gt", "gte", "lt", "lte"]) {
180
+ parameters.push(openApiParameter(`${name}.${op}`, `Filter ${name} with ${op}.`, {
181
+ type: "string"
182
+ }));
183
+ }
184
+ }
185
+ if (isTextLike(col.type)) {
186
+ parameters.push(openApiParameter(`${name}.like`, `Case-insensitive contains filter for ${name}.`, {
187
+ type: "string"
188
+ }));
189
+ }
190
+ }
191
+ return parameters;
192
+ }
193
+ function generateSubgraphAgentSchema(detail, options = {}) {
194
+ const serverUrl = normalizeServerUrl(options.serverUrl);
195
+ const tables = {};
196
+ for (const [tableName, table] of Object.entries(detail.tables)) {
197
+ const path = tablePath(detail.name, tableName);
198
+ tables[tableName] = {
199
+ endpoint: `${serverUrl}${path}`,
200
+ countEndpoint: `${serverUrl}${countPath(detail.name, tableName)}`,
201
+ rowCount: table.rowCount,
202
+ columns: table.columns,
203
+ ...table.indexes ? { indexes: table.indexes } : {},
204
+ ...table.uniqueKeys ? { uniqueKeys: table.uniqueKeys } : {},
205
+ query: {
206
+ parameters: queryParameters(table),
207
+ sortable: selectableColumns(table),
208
+ selectable: selectableColumns(table),
209
+ searchable: searchableColumns(table),
210
+ filters: filterNames(table)
211
+ },
212
+ examples: {
213
+ list: rowExample(table),
214
+ count: { count: table.rowCount },
215
+ curl: `curl '${serverUrl}${path}?_limit=10&_sort=_block_height&_order=desc'`
216
+ }
217
+ };
218
+ }
219
+ return {
220
+ name: detail.name,
221
+ version: detail.version,
222
+ ...detail.description ? { description: detail.description } : {},
223
+ ...detail.schemaHash ? { schemaHash: detail.schemaHash } : {},
224
+ generatedAt: generatedAt(options),
225
+ serverUrl,
226
+ ...detail.sources ? { sources: detail.sources } : {},
227
+ tables
228
+ };
229
+ }
230
+ function generateSubgraphOpenApi(detail, options = {}) {
231
+ const serverUrl = normalizeServerUrl(options.serverUrl);
232
+ const paths = {};
233
+ const schemas = {};
234
+ for (const [tableName, table] of Object.entries(detail.tables)) {
235
+ const schemaName = `${tableName}Row`;
236
+ const properties = {};
237
+ const required = [];
238
+ for (const [columnName, column] of columnEntries(table)) {
239
+ properties[columnName] = openApiSchemaForColumn(column);
240
+ if (!column.nullable)
241
+ required.push(columnName);
242
+ }
243
+ schemas[schemaName] = {
244
+ type: "object",
245
+ properties,
246
+ required,
247
+ example: rowExample(table)
248
+ };
249
+ paths[tablePath(detail.name, tableName)] = {
250
+ get: {
251
+ summary: `Query ${detail.name}.${tableName}`,
252
+ operationId: `query_${detail.name.replace(/-/g, "_")}_${tableName}`,
253
+ parameters: tableParameters(table),
254
+ responses: {
255
+ "200": {
256
+ description: "Rows returned from the subgraph table.",
257
+ content: {
258
+ "application/json": {
259
+ schema: {
260
+ type: "object",
261
+ properties: {
262
+ data: {
263
+ type: "array",
264
+ items: { $ref: `#/components/schemas/${schemaName}` }
265
+ },
266
+ meta: {
267
+ type: "object",
268
+ properties: {
269
+ total: { type: "integer" },
270
+ limit: { type: "integer" },
271
+ offset: { type: "integer" }
272
+ }
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+ };
282
+ paths[countPath(detail.name, tableName)] = {
283
+ get: {
284
+ summary: `Count ${detail.name}.${tableName}`,
285
+ operationId: `count_${detail.name.replace(/-/g, "_")}_${tableName}`,
286
+ parameters: tableParameters(table),
287
+ responses: {
288
+ "200": {
289
+ description: "Row count for the filtered table query.",
290
+ content: {
291
+ "application/json": {
292
+ schema: {
293
+ type: "object",
294
+ properties: { count: { type: "integer" } },
295
+ required: ["count"],
296
+ example: { count: table.rowCount }
297
+ }
298
+ }
299
+ }
300
+ }
301
+ }
302
+ }
303
+ };
304
+ }
305
+ return {
306
+ openapi: "3.1.0",
307
+ info: {
308
+ title: `${detail.name} Subgraph API`,
309
+ version: detail.version,
310
+ ...detail.description ? { description: detail.description } : {}
311
+ },
312
+ servers: [{ url: serverUrl }],
313
+ paths,
314
+ components: { schemas },
315
+ "x-secondlayer-subgraph": detail.name,
316
+ "x-secondlayer-version": detail.version,
317
+ "x-secondlayer-schema-hash": detail.schemaHash,
318
+ "x-secondlayer-generated-at": generatedAt(options),
319
+ "x-secondlayer-sources": detail.sources ?? {},
320
+ "x-secondlayer-tables": Object.keys(detail.tables)
321
+ };
322
+ }
323
+ function generateSubgraphMarkdown(detail, options = {}) {
324
+ const agent = generateSubgraphAgentSchema(detail, options);
325
+ const lines = [
326
+ `# ${detail.name} Subgraph API`,
327
+ "",
328
+ `Version: ${detail.version}`,
329
+ detail.schemaHash ? `Schema hash: ${detail.schemaHash}` : undefined,
330
+ `Server: ${agent.serverUrl}`,
331
+ "",
332
+ detail.description
333
+ ].filter((line) => line !== undefined && line !== "");
334
+ for (const [tableName, table] of Object.entries(agent.tables)) {
335
+ lines.push("", `## ${tableName}`, "", `GET ${table.endpoint}`, `GET ${table.countEndpoint}`, "", `Rows: ${table.rowCount}`, "", "### Columns", "", "| Column | Type | Attributes |", "| --- | --- | --- |");
336
+ for (const [columnName, col] of Object.entries(table.columns)) {
337
+ const attrs = [
338
+ SYSTEM_COLUMNS.includes(columnName) ? "system" : undefined,
339
+ col.nullable ? "nullable" : undefined,
340
+ col.indexed ? "indexed" : undefined,
341
+ col.searchable ? "searchable" : undefined
342
+ ].filter(Boolean).join(", ");
343
+ lines.push(`| \`${columnName}\` | \`${col.type}\` | ${attrs || "-"} |`);
344
+ }
345
+ lines.push("", "### Query", "", `Parameters: ${table.query.parameters.map((p) => `\`${p}\``).join(", ")}`, `Filters: ${table.query.filters.map((p) => `\`${p}\``).join(", ")}`, "", "### Example", "", "```bash", table.examples.curl, "```");
346
+ }
347
+ return `${lines.join(`
348
+ `)}
349
+ `;
350
+ }
351
+ function generateSubgraphSpec(detail, format, options = {}) {
352
+ if (format === "openapi")
353
+ return generateSubgraphOpenApi(detail, options);
354
+ if (format === "agent")
355
+ return generateSubgraphAgentSchema(detail, options);
356
+ return generateSubgraphMarkdown(detail, options);
357
+ }
358
+ export {
359
+ generateSubgraphSpec,
360
+ generateSubgraphOpenApi,
361
+ generateSubgraphMarkdown,
362
+ generateSubgraphAgentSchema
363
+ };
364
+
365
+ //# debugId=A3421FBB41B33DFB64756E2164756E21
366
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/subgraphs/spec.ts"],
4
+ "sourcesContent": [
5
+ "import type { SubgraphDetail } from \"../schemas/subgraphs.ts\";\n\nexport type SubgraphSpecFormat = \"openapi\" | \"agent\" | \"markdown\";\n\nexport interface SubgraphSpecOptions {\n\tserverUrl?: string;\n\tgeneratedAt?: string;\n}\n\nexport interface SubgraphAgentSchema {\n\tname: string;\n\tversion: string;\n\tdescription?: string;\n\tschemaHash?: string;\n\tgeneratedAt: string;\n\tserverUrl: string;\n\tsources?: Record<string, unknown>;\n\ttables: Record<\n\t\tstring,\n\t\t{\n\t\t\tendpoint: string;\n\t\t\tcountEndpoint: string;\n\t\t\trowCount: number;\n\t\t\tcolumns: SubgraphDetail[\"tables\"][string][\"columns\"];\n\t\t\tindexes?: string[][];\n\t\t\tuniqueKeys?: string[][];\n\t\t\tquery: {\n\t\t\t\tparameters: string[];\n\t\t\t\tsortable: string[];\n\t\t\t\tselectable: string[];\n\t\t\t\tsearchable: string[];\n\t\t\t\tfilters: string[];\n\t\t\t};\n\t\t\texamples: {\n\t\t\t\tlist: Record<string, unknown>;\n\t\t\t\tcount: { count: number };\n\t\t\t\tcurl: string;\n\t\t\t};\n\t\t}\n\t>;\n}\n\ntype ColumnMeta = SubgraphDetail[\"tables\"][string][\"columns\"][string];\n\nconst SYSTEM_COLUMNS = [\"_id\", \"_block_height\", \"_tx_id\", \"_created_at\"];\nconst BASE_QUERY_PARAMS = [\"_limit\", \"_offset\", \"_sort\", \"_order\", \"_fields\"];\nconst COMPARISON_OPS = [\"neq\", \"gt\", \"gte\", \"lt\", \"lte\"];\n\nfunction generatedAt(options: SubgraphSpecOptions): string {\n\treturn options.generatedAt ?? new Date().toISOString();\n}\n\nfunction normalizeServerUrl(serverUrl?: string): string {\n\treturn (serverUrl ?? \"https://api.secondlayer.tools\").replace(/\\/+$/, \"\");\n}\n\nfunction tablePath(subgraphName: string, tableName: string): string {\n\treturn `/api/subgraphs/${subgraphName}/${tableName}`;\n}\n\nfunction countPath(subgraphName: string, tableName: string): string {\n\treturn `${tablePath(subgraphName, tableName)}/count`;\n}\n\nfunction isTextLike(type: string): boolean {\n\treturn type === \"text\" || type === \"principal\" || type === \"timestamp\";\n}\n\nfunction isComparable(type: string): boolean {\n\treturn (\n\t\ttype === \"uint\" ||\n\t\ttype === \"int\" ||\n\t\ttype === \"bigint\" ||\n\t\ttype === \"serial\" ||\n\t\ttype === \"timestamp\"\n\t);\n}\n\nfunction exampleForColumn(type: string): unknown {\n\tswitch (type) {\n\t\tcase \"uint\":\n\t\tcase \"int\":\n\t\tcase \"bigint\":\n\t\t\treturn \"1000\";\n\t\tcase \"serial\":\n\t\t\treturn 1;\n\t\tcase \"principal\":\n\t\t\treturn \"SP000000000000000000002Q6VF78\";\n\t\tcase \"timestamp\":\n\t\t\treturn \"2026-01-01T00:00:00.000Z\";\n\t\tcase \"boolean\":\n\t\t\treturn true;\n\t\tcase \"jsonb\":\n\t\t\treturn { example: true };\n\t\tdefault:\n\t\t\treturn \"example\";\n\t}\n}\n\nfunction openApiSchemaForColumn(col: ColumnMeta): Record<string, unknown> {\n\tlet schema: Record<string, unknown>;\n\tswitch (col.type) {\n\t\tcase \"uint\":\n\t\tcase \"int\":\n\t\tcase \"bigint\":\n\t\t\tschema = { type: \"string\", pattern: \"^-?\\\\d+(\\\\.\\\\d+)?$\" };\n\t\t\tbreak;\n\t\tcase \"serial\":\n\t\t\tschema = { type: \"integer\" };\n\t\t\tbreak;\n\t\tcase \"principal\":\n\t\tcase \"text\":\n\t\t\tschema = { type: \"string\" };\n\t\t\tbreak;\n\t\tcase \"timestamp\":\n\t\t\tschema = { type: \"string\", format: \"date-time\" };\n\t\t\tbreak;\n\t\tcase \"boolean\":\n\t\t\tschema = { type: \"boolean\" };\n\t\t\tbreak;\n\t\tcase \"jsonb\":\n\t\t\tschema = { type: \"object\", additionalProperties: true };\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tschema = {};\n\t\t\tbreak;\n\t}\n\tif (col.nullable) {\n\t\tconst type = schema.type;\n\t\tif (typeof type === \"string\") schema.type = [type, \"null\"];\n\t}\n\treturn schema;\n}\n\nfunction columnEntries(table: SubgraphDetail[\"tables\"][string]) {\n\treturn Object.entries(table.columns);\n}\n\nfunction selectableColumns(table: SubgraphDetail[\"tables\"][string]): string[] {\n\treturn columnEntries(table).map(([name]) => name);\n}\n\nfunction searchableColumns(table: SubgraphDetail[\"tables\"][string]): string[] {\n\treturn columnEntries(table)\n\t\t.filter(([, col]) => col.searchable)\n\t\t.map(([name]) => name);\n}\n\nfunction filterNames(table: SubgraphDetail[\"tables\"][string]): string[] {\n\tconst result: string[] = [];\n\tfor (const [name, col] of columnEntries(table)) {\n\t\tresult.push(name);\n\t\tresult.push(`${name}.neq`);\n\t\tif (isComparable(col.type)) {\n\t\t\tfor (const op of COMPARISON_OPS.filter((op) => op !== \"neq\")) {\n\t\t\t\tresult.push(`${name}.${op}`);\n\t\t\t}\n\t\t}\n\t\tif (isTextLike(col.type)) result.push(`${name}.like`);\n\t}\n\treturn result;\n}\n\nfunction queryParameters(table: SubgraphDetail[\"tables\"][string]): string[] {\n\tconst params = [...BASE_QUERY_PARAMS];\n\tif (searchableColumns(table).length > 0) params.push(\"_search\");\n\treturn params;\n}\n\nfunction rowExample(table: SubgraphDetail[\"tables\"][string]) {\n\tconst row: Record<string, unknown> = {};\n\tfor (const [name, col] of columnEntries(table)) {\n\t\trow[name] = exampleForColumn(col.type);\n\t}\n\treturn row;\n}\n\nfunction openApiParameter(\n\tname: string,\n\tdescription: string,\n\tschema: Record<string, unknown> = { type: \"string\" },\n) {\n\treturn {\n\t\tname,\n\t\tin: \"query\",\n\t\trequired: false,\n\t\tdescription,\n\t\tschema,\n\t};\n}\n\nfunction tableParameters(table: SubgraphDetail[\"tables\"][string]) {\n\tconst parameters = [\n\t\topenApiParameter(\"_limit\", \"Maximum rows to return.\", {\n\t\t\ttype: \"integer\",\n\t\t\tdefault: 50,\n\t\t\tminimum: 1,\n\t\t\tmaximum: 1000,\n\t\t}),\n\t\topenApiParameter(\"_offset\", \"Rows to skip for pagination.\", {\n\t\t\ttype: \"integer\",\n\t\t\tdefault: 0,\n\t\t\tminimum: 0,\n\t\t}),\n\t\topenApiParameter(\"_sort\", \"Column to sort by.\", {\n\t\t\ttype: \"string\",\n\t\t\tenum: selectableColumns(table),\n\t\t}),\n\t\topenApiParameter(\"_order\", \"Sort direction.\", {\n\t\t\ttype: \"string\",\n\t\t\tenum: [\"asc\", \"desc\"],\n\t\t\tdefault: \"asc\",\n\t\t}),\n\t\topenApiParameter(\"_fields\", \"Comma-separated columns to include.\", {\n\t\t\ttype: \"string\",\n\t\t}),\n\t];\n\tif (searchableColumns(table).length > 0) {\n\t\tparameters.push(\n\t\t\topenApiParameter(\"_search\", \"Search across searchable columns.\", {\n\t\t\t\ttype: \"string\",\n\t\t\t}),\n\t\t);\n\t}\n\tfor (const [name, col] of columnEntries(table)) {\n\t\tparameters.push(\n\t\t\topenApiParameter(name, `Filter ${name} by equality.`, {\n\t\t\t\ttype: \"string\",\n\t\t\t}),\n\t\t);\n\t\tparameters.push(\n\t\t\topenApiParameter(`${name}.neq`, `Filter ${name} by inequality.`, {\n\t\t\t\ttype: \"string\",\n\t\t\t}),\n\t\t);\n\t\tif (isComparable(col.type)) {\n\t\t\tfor (const op of [\"gt\", \"gte\", \"lt\", \"lte\"]) {\n\t\t\t\tparameters.push(\n\t\t\t\t\topenApiParameter(`${name}.${op}`, `Filter ${name} with ${op}.`, {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (isTextLike(col.type)) {\n\t\t\tparameters.push(\n\t\t\t\topenApiParameter(\n\t\t\t\t\t`${name}.like`,\n\t\t\t\t\t`Case-insensitive contains filter for ${name}.`,\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn parameters;\n}\n\nexport function generateSubgraphAgentSchema(\n\tdetail: SubgraphDetail,\n\toptions: SubgraphSpecOptions = {},\n): SubgraphAgentSchema {\n\tconst serverUrl = normalizeServerUrl(options.serverUrl);\n\tconst tables: SubgraphAgentSchema[\"tables\"] = {};\n\tfor (const [tableName, table] of Object.entries(detail.tables)) {\n\t\tconst path = tablePath(detail.name, tableName);\n\t\ttables[tableName] = {\n\t\t\tendpoint: `${serverUrl}${path}`,\n\t\t\tcountEndpoint: `${serverUrl}${countPath(detail.name, tableName)}`,\n\t\t\trowCount: table.rowCount,\n\t\t\tcolumns: table.columns,\n\t\t\t...(table.indexes ? { indexes: table.indexes } : {}),\n\t\t\t...(table.uniqueKeys ? { uniqueKeys: table.uniqueKeys } : {}),\n\t\t\tquery: {\n\t\t\t\tparameters: queryParameters(table),\n\t\t\t\tsortable: selectableColumns(table),\n\t\t\t\tselectable: selectableColumns(table),\n\t\t\t\tsearchable: searchableColumns(table),\n\t\t\t\tfilters: filterNames(table),\n\t\t\t},\n\t\t\texamples: {\n\t\t\t\tlist: rowExample(table),\n\t\t\t\tcount: { count: table.rowCount },\n\t\t\t\tcurl: `curl '${serverUrl}${path}?_limit=10&_sort=_block_height&_order=desc'`,\n\t\t\t},\n\t\t};\n\t}\n\treturn {\n\t\tname: detail.name,\n\t\tversion: detail.version,\n\t\t...(detail.description ? { description: detail.description } : {}),\n\t\t...(detail.schemaHash ? { schemaHash: detail.schemaHash } : {}),\n\t\tgeneratedAt: generatedAt(options),\n\t\tserverUrl,\n\t\t...(detail.sources ? { sources: detail.sources } : {}),\n\t\ttables,\n\t};\n}\n\nexport function generateSubgraphOpenApi(\n\tdetail: SubgraphDetail,\n\toptions: SubgraphSpecOptions = {},\n): Record<string, unknown> {\n\tconst serverUrl = normalizeServerUrl(options.serverUrl);\n\tconst paths: Record<string, unknown> = {};\n\tconst schemas: Record<string, unknown> = {};\n\n\tfor (const [tableName, table] of Object.entries(detail.tables)) {\n\t\tconst schemaName = `${tableName}Row`;\n\t\tconst properties: Record<string, unknown> = {};\n\t\tconst required: string[] = [];\n\t\tfor (const [columnName, column] of columnEntries(table)) {\n\t\t\tproperties[columnName] = openApiSchemaForColumn(column);\n\t\t\tif (!column.nullable) required.push(columnName);\n\t\t}\n\t\tschemas[schemaName] = {\n\t\t\ttype: \"object\",\n\t\t\tproperties,\n\t\t\trequired,\n\t\t\texample: rowExample(table),\n\t\t};\n\n\t\tpaths[tablePath(detail.name, tableName)] = {\n\t\t\tget: {\n\t\t\t\tsummary: `Query ${detail.name}.${tableName}`,\n\t\t\t\toperationId: `query_${detail.name.replace(/-/g, \"_\")}_${tableName}`,\n\t\t\t\tparameters: tableParameters(table),\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Rows returned from the subgraph table.\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\titems: { $ref: `#/components/schemas/${schemaName}` },\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\ttotal: { type: \"integer\" },\n\t\t\t\t\t\t\t\t\t\t\t\tlimit: { type: \"integer\" },\n\t\t\t\t\t\t\t\t\t\t\t\toffset: { type: \"integer\" },\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tpaths[countPath(detail.name, tableName)] = {\n\t\t\tget: {\n\t\t\t\tsummary: `Count ${detail.name}.${tableName}`,\n\t\t\t\toperationId: `count_${detail.name.replace(/-/g, \"_\")}_${tableName}`,\n\t\t\t\tparameters: tableParameters(table),\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Row count for the filtered table query.\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: { count: { type: \"integer\" } },\n\t\t\t\t\t\t\t\t\trequired: [\"count\"],\n\t\t\t\t\t\t\t\t\texample: { count: table.rowCount },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\topenapi: \"3.1.0\",\n\t\tinfo: {\n\t\t\ttitle: `${detail.name} Subgraph API`,\n\t\t\tversion: detail.version,\n\t\t\t...(detail.description ? { description: detail.description } : {}),\n\t\t},\n\t\tservers: [{ url: serverUrl }],\n\t\tpaths,\n\t\tcomponents: { schemas },\n\t\t\"x-secondlayer-subgraph\": detail.name,\n\t\t\"x-secondlayer-version\": detail.version,\n\t\t\"x-secondlayer-schema-hash\": detail.schemaHash,\n\t\t\"x-secondlayer-generated-at\": generatedAt(options),\n\t\t\"x-secondlayer-sources\": detail.sources ?? {},\n\t\t\"x-secondlayer-tables\": Object.keys(detail.tables),\n\t};\n}\n\nexport function generateSubgraphMarkdown(\n\tdetail: SubgraphDetail,\n\toptions: SubgraphSpecOptions = {},\n): string {\n\tconst agent = generateSubgraphAgentSchema(detail, options);\n\tconst lines = [\n\t\t`# ${detail.name} Subgraph API`,\n\t\t\"\",\n\t\t`Version: ${detail.version}`,\n\t\tdetail.schemaHash ? `Schema hash: ${detail.schemaHash}` : undefined,\n\t\t`Server: ${agent.serverUrl}`,\n\t\t\"\",\n\t\tdetail.description,\n\t].filter((line): line is string => line !== undefined && line !== \"\");\n\n\tfor (const [tableName, table] of Object.entries(agent.tables)) {\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t`## ${tableName}`,\n\t\t\t\"\",\n\t\t\t`GET ${table.endpoint}`,\n\t\t\t`GET ${table.countEndpoint}`,\n\t\t\t\"\",\n\t\t\t`Rows: ${table.rowCount}`,\n\t\t\t\"\",\n\t\t\t\"### Columns\",\n\t\t\t\"\",\n\t\t\t\"| Column | Type | Attributes |\",\n\t\t\t\"| --- | --- | --- |\",\n\t\t);\n\t\tfor (const [columnName, col] of Object.entries(table.columns)) {\n\t\t\tconst attrs = [\n\t\t\t\tSYSTEM_COLUMNS.includes(columnName) ? \"system\" : undefined,\n\t\t\t\tcol.nullable ? \"nullable\" : undefined,\n\t\t\t\tcol.indexed ? \"indexed\" : undefined,\n\t\t\t\tcol.searchable ? \"searchable\" : undefined,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\", \");\n\t\t\tlines.push(`| \\`${columnName}\\` | \\`${col.type}\\` | ${attrs || \"-\"} |`);\n\t\t}\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t\"### Query\",\n\t\t\t\"\",\n\t\t\t`Parameters: ${table.query.parameters.map((p) => `\\`${p}\\``).join(\", \")}`,\n\t\t\t`Filters: ${table.query.filters.map((p) => `\\`${p}\\``).join(\", \")}`,\n\t\t\t\"\",\n\t\t\t\"### Example\",\n\t\t\t\"\",\n\t\t\t\"```bash\",\n\t\t\ttable.examples.curl,\n\t\t\t\"```\",\n\t\t);\n\t}\n\treturn `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function generateSubgraphSpec(\n\tdetail: SubgraphDetail,\n\tformat: SubgraphSpecFormat,\n\toptions: SubgraphSpecOptions = {},\n): Record<string, unknown> | SubgraphAgentSchema | string {\n\tif (format === \"openapi\") return generateSubgraphOpenApi(detail, options);\n\tif (format === \"agent\") return generateSubgraphAgentSchema(detail, options);\n\treturn generateSubgraphMarkdown(detail, options);\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "A3421FBB41B33DFB64756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,5 +1,6 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  // ── blocks ──────────────────────────────────────────────────────────
5
6
  await db.schema
@@ -298,6 +299,7 @@ export async function up(db: Kysely<any>): Promise<void> {
298
299
  `.execute(db);
299
300
  }
300
301
 
302
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
301
303
  export async function down(db: Kysely<any>): Promise<void> {
302
304
  await sql`DROP TRIGGER IF EXISTS views_notify_trigger ON "views"`.execute(db);
303
305
  await sql`DROP FUNCTION IF EXISTS notify_view_changes()`.execute(db);
@@ -1,5 +1,6 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  await db.schema
5
6
  .createTable("api_keys")
@@ -47,6 +48,7 @@ export async function up(db: Kysely<any>): Promise<void> {
47
48
  .execute();
48
49
  }
49
50
 
51
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
50
52
  export async function down(db: Kysely<any>): Promise<void> {
51
53
  await db.schema.alterTable("views").dropColumn("api_key_id").execute();
52
54
  await db.schema.alterTable("streams").dropColumn("api_key_id").execute();
@@ -1,5 +1,6 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  // 1. Drop PG schemas for views with null api_key_id (orphaned pre-product data)
5
6
  const orphanedViews = await db
@@ -79,10 +80,10 @@ export async function up(db: Kysely<any>): Promise<void> {
79
80
  // 4. Drop unique constraint on views(name), replace with views(name, api_key_id)
80
81
  // The original unique constraint is from the initial migration on "name"
81
82
  await sql
82
- .raw(`ALTER TABLE views DROP CONSTRAINT IF EXISTS views_name_key`)
83
+ .raw("ALTER TABLE views DROP CONSTRAINT IF EXISTS views_name_key")
83
84
  .execute(db);
84
85
  await sql
85
- .raw(`ALTER TABLE views DROP CONSTRAINT IF EXISTS views_name_unique`)
86
+ .raw("ALTER TABLE views DROP CONSTRAINT IF EXISTS views_name_unique")
86
87
  .execute(db);
87
88
 
88
89
  await db.schema
@@ -106,6 +107,7 @@ export async function up(db: Kysely<any>): Promise<void> {
106
107
  .execute();
107
108
  }
108
109
 
110
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
109
111
  export async function down(db: Kysely<any>): Promise<void> {
110
112
  await db.schema.dropIndex("views_api_key_id_idx").ifExists().execute();
111
113
  await db.schema.dropIndex("streams_api_key_id_idx").ifExists().execute();
@@ -116,7 +118,7 @@ export async function down(db: Kysely<any>): Promise<void> {
116
118
 
117
119
  // Restore original unique constraint on name
118
120
  await sql
119
- .raw(`ALTER TABLE views ADD CONSTRAINT views_name_key UNIQUE (name)`)
121
+ .raw("ALTER TABLE views ADD CONSTRAINT views_name_key UNIQUE (name)")
120
122
  .execute(db);
121
123
 
122
124
  await db.schema.alterTable("views").dropColumn("schema_name").execute();
@@ -1,5 +1,6 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  // 1. Create accounts table
5
6
  await db.schema
@@ -83,6 +84,7 @@ export async function up(db: Kysely<any>): Promise<void> {
83
84
  .execute();
84
85
  }
85
86
 
87
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
86
88
  export async function down(db: Kysely<any>): Promise<void> {
87
89
  await db.schema.dropIndex("api_keys_account_id_idx").ifExists().execute();
88
90
  await sql`ALTER TABLE api_keys ALTER COLUMN account_id DROP NOT NULL`.execute(
@@ -1,5 +1,6 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  await db.schema
5
6
  .createTable("sessions")
@@ -35,6 +36,7 @@ export async function up(db: Kysely<any>): Promise<void> {
35
36
  .execute();
36
37
  }
37
38
 
39
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
38
40
  export async function down(db: Kysely<any>): Promise<void> {
39
41
  await db.schema.dropIndex("sessions_account_id_idx").ifExists().execute();
40
42
  await db.schema.dropIndex("sessions_token_hash_idx").ifExists().execute();
@@ -1,11 +1,13 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  await sql`ALTER TABLE transactions ADD COLUMN IF NOT EXISTS tx_index INTEGER NOT NULL DEFAULT 0`.execute(
5
6
  db,
6
7
  );
7
8
  }
8
9
 
10
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
9
11
  export async function down(db: Kysely<any>): Promise<void> {
10
12
  await sql`ALTER TABLE transactions DROP COLUMN IF EXISTS tx_index`.execute(
11
13
  db,
@@ -1,5 +1,6 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  // Enable pg_trgm for fast ILIKE search
5
6
  await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
@@ -67,6 +68,7 @@ export async function up(db: Kysely<any>): Promise<void> {
67
68
  `.execute(db);
68
69
  }
69
70
 
71
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
70
72
  export async function down(db: Kysely<any>): Promise<void> {
71
73
  await db.schema.dropTable("contracts").ifExists().cascade().execute();
72
74
  }
@@ -1,9 +1,11 @@
1
1
  import { type Kysely, sql } from "kysely";
2
2
 
3
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
3
4
  export async function up(db: Kysely<any>): Promise<void> {
4
5
  await db.schema.dropTable("contracts").ifExists().cascade().execute();
5
6
  }
6
7
 
8
+ // biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety
7
9
  export async function down(db: Kysely<any>): Promise<void> {
8
10
  await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
9
11