@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.
- package/dist/src/crypto/hmac.js +3 -3
- package/dist/src/crypto/hmac.js.map +3 -3
- package/dist/src/crypto/secrets.js.map +2 -2
- package/dist/src/db/index.js.map +2 -2
- package/dist/src/db/queries/account-usage.js +137 -29
- package/dist/src/db/queries/account-usage.js.map +3 -3
- package/dist/src/db/queries/subscriptions.js +3 -3
- package/dist/src/db/queries/subscriptions.js.map +5 -5
- package/dist/src/db/queries/tenants.js.map +2 -2
- package/dist/src/errors.d.ts +1 -2
- package/dist/src/errors.js +3 -2
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +51 -3
- package/dist/src/index.js +351 -4
- package/dist/src/index.js.map +9 -8
- package/dist/src/logger.js.map +2 -2
- package/dist/src/node/archive-client.js.map +2 -2
- package/dist/src/node/hiro-client.js +27 -23
- package/dist/src/node/hiro-client.js.map +4 -4
- package/dist/src/node/hiro-pg-client.js +2 -2
- package/dist/src/node/hiro-pg-client.js.map +3 -3
- package/dist/src/node/local-client.js.map +2 -2
- package/dist/src/pricing.d.ts +51 -7
- package/dist/src/pricing.js +143 -28
- package/dist/src/pricing.js.map +3 -3
- package/dist/src/schemas/filters.js.map +2 -2
- package/dist/src/schemas/index.d.ts +9 -0
- package/dist/src/schemas/index.js.map +3 -3
- package/dist/src/schemas/subgraphs.d.ts +9 -0
- package/dist/src/schemas/subgraphs.js.map +1 -1
- package/dist/src/subgraphs/spec.d.ts +104 -0
- package/dist/src/subgraphs/spec.js +366 -0
- package/dist/src/subgraphs/spec.js.map +10 -0
- package/migrations/0001_initial.ts +2 -0
- package/migrations/0002_api_keys.ts +2 -0
- package/migrations/0003_tenant_isolation.ts +5 -3
- package/migrations/0004_accounts_and_usage.ts +2 -0
- package/migrations/0005_sessions.ts +2 -0
- package/migrations/0006_tx_index.ts +2 -0
- package/migrations/0007_contracts.ts +2 -0
- package/migrations/0008_drop_contracts.ts +2 -0
- package/migrations/0009_waitlist.ts +2 -0
- package/migrations/0010_waitlist_status.ts +2 -0
- package/migrations/0011_account_insights.ts +2 -0
- package/migrations/0012_view_health_snapshots.ts +2 -0
- package/migrations/0013_view_processing_stats.ts +2 -0
- package/migrations/0014_view_table_snapshots.ts +2 -0
- package/migrations/0015_rename_views_to_subgraphs.ts +2 -0
- package/migrations/0016_rename_webhook_to_endpoint.ts +2 -0
- package/migrations/0017_security_hardening.ts +2 -0
- package/migrations/0018_subgraph_gaps.ts +2 -0
- package/migrations/0021_tx_function_args_result.ts +3 -4
- package/migrations/0022_marketplace.ts +4 -5
- package/migrations/0023_projects.ts +3 -1
- package/migrations/0024_chat_sessions.ts +3 -1
- package/migrations/0025_chat_session_summary.ts +3 -4
- package/migrations/0026_workflows.ts +4 -5
- package/migrations/0027_workflow_cursors.ts +3 -1
- package/migrations/0028_subgraph_account_scoping.ts +7 -2
- package/migrations/0029_subgraph_handler_code.ts +3 -4
- package/migrations/0030_workflow_source_code.ts +2 -0
- package/migrations/0031_subgraph_source_code.ts +2 -0
- package/migrations/0032_drop_streams_tables.ts +9 -9
- 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(
|
|
83
|
+
.raw("ALTER TABLE views DROP CONSTRAINT IF EXISTS views_name_key")
|
|
83
84
|
.execute(db);
|
|
84
85
|
await sql
|
|
85
|
-
.raw(
|
|
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(
|
|
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
|
|