d1s 0.3.7 → 0.3.11
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/README.md +1 -1
- package/dist/.next/BUILD_ID +1 -1
- package/dist/.next/app-build-manifest.json +125 -125
- package/dist/.next/app-path-routes-manifest.json +23 -1
- package/dist/.next/build-manifest.json +14 -14
- package/dist/.next/export-marker.json +6 -1
- package/dist/.next/images-manifest.json +58 -1
- package/dist/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/.next/next-server.js.nft.json +1 -1
- package/dist/.next/prerender-manifest.json +61 -1
- package/dist/.next/react-loadable-manifest.json +5 -5
- package/dist/.next/required-server-files.json +325 -1
- package/dist/.next/routes-manifest.json +70 -1
- package/dist/.next/server/app/_not-found/page.js +2 -1
- package/dist/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/_not-found.html +1 -1
- package/dist/.next/server/app/_not-found.meta +1 -1
- package/dist/.next/server/app/_not-found.rsc +15 -12
- package/dist/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/server/app/api/cloudflare/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/server/app/api/databases/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/list/route.js +8 -8
- package/dist/.next/server/app/api/migrations/list/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/migrations/list/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/sync/route.js +10 -10
- package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route.js +8 -8
- package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pro/route.js +1 -1
- package/dist/.next/server/app/api/pro/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/pro/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-remote/confirm/route.js +8 -8
- package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-remote/preview/route.js +8 -8
- package/dist/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/push-remote/confirm/route.js +10 -10
- package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/push-remote/preview/route.js +10 -10
- package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/query/route.js +15 -15
- package/dist/.next/server/app/api/query/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/schema/route.js +1 -1
- package/dist/.next/server/app/api/schema/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/schema/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/[name]/import/route.js +1 -1
- package/dist/.next/server/app/api/tables/[name]/import/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/tables/[name]/import/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/server/app/api/tables/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/time-travel/preview/route.js +1 -1
- package/dist/.next/server/app/api/time-travel/preview/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/time-travel/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/time-travel/restore/route.js +1 -1
- package/dist/.next/server/app/api/time-travel/restore/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/time-travel/restore/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/server/app/api/update/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/index.html +3 -3
- package/dist/.next/server/app/index.meta +1 -1
- package/dist/.next/server/app/index.rsc +18 -15
- package/dist/.next/server/app/page.js +15 -14
- package/dist/.next/server/app/page.js.nft.json +1 -1
- package/dist/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/.next/server/app-paths-manifest.json +4 -4
- package/dist/.next/server/chunks/347.js +23 -0
- package/dist/.next/server/chunks/366.js +1 -0
- package/dist/.next/server/chunks/386.js +9 -0
- package/dist/.next/server/chunks/611.js +6 -0
- package/dist/.next/server/chunks/626.js +30 -0
- package/dist/.next/server/chunks/692.js +1 -0
- package/dist/.next/server/chunks/839.js +1 -0
- package/dist/.next/server/chunks/873.js +22 -0
- package/dist/.next/server/functions-config-manifest.json +6 -1
- package/dist/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/.next/server/pages/404.html +1 -1
- package/dist/.next/server/pages/500.html +1 -1
- package/dist/.next/server/pages/_app.js +1 -1
- package/dist/.next/server/pages/_document.js +1 -1
- package/dist/.next/server/pages/_document.js.nft.json +1 -1
- package/dist/.next/server/pages/_error.js +19 -1
- package/dist/.next/server/pages/_error.js.nft.json +1 -1
- package/dist/.next/server/pages-manifest.json +6 -1
- package/dist/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/server/webpack-runtime.js +1 -1
- package/dist/.next/static/chunks/1a258343.234dd786cf6c097e.js +1 -0
- package/dist/.next/static/chunks/255-4f212684648fcab9.js +1 -0
- package/dist/.next/static/chunks/421-55f8ce492f5bd9c3.js +1 -0
- package/dist/.next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
- package/dist/.next/static/chunks/654-f2f8931465d44ae7.js +1 -0
- package/dist/.next/static/chunks/69-00a70b2df83ed9ee.js +1 -0
- package/dist/.next/static/chunks/823-77b9a2d152da81dd.js +1 -0
- package/dist/.next/static/chunks/95.8b08bca2768cb67c.js +1 -0
- package/dist/.next/static/chunks/950.edd33691c78c1807.js +1 -0
- package/dist/.next/static/chunks/app/_not-found/page-255a8a616fa8d3a5.js +1 -0
- package/dist/.next/static/chunks/app/api/cloudflare/{route-d0c1dc2a9e7dce36.js → route-58aca057db1e5530.js} +1 -1
- package/dist/.next/static/chunks/app/api/databases/{route-cd322321212797cf.js → route-58aca057db1e5530.js} +1 -1
- package/dist/.next/static/chunks/app/api/migrations/list/{route-cd710ff75b6bcd02.js → route-58aca057db1e5530.js} +1 -1
- package/dist/.next/static/chunks/app/api/migrations/sync/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/migrations/sync-files/{route-79ee2c26f87d3bc7.js → route-58aca057db1e5530.js} +1 -1
- package/dist/.next/static/chunks/app/api/pro/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-data/confirm/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-remote/preview/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/push-remote/confirm/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/push-remote/preview/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/query/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/schema/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/[name]/import/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/[name]/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/time-travel/preview/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/time-travel/restore/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/api/update/route-58aca057db1e5530.js +1 -0
- package/dist/.next/static/chunks/app/layout-a5219438265f0b6c.js +1 -0
- package/dist/.next/static/chunks/app/page-4170252891367dde.js +1 -0
- package/dist/.next/static/chunks/framework-a6e0b7e30f98059a.js +1 -0
- package/dist/.next/static/chunks/main-0bd218f776705cbf.js +1 -0
- package/dist/.next/static/chunks/main-app-d20e9d5e211da7c8.js +1 -0
- package/dist/.next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
- package/dist/.next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
- package/dist/.next/static/chunks/webpack-d5e8b5757f0fec83.js +1 -0
- package/dist/.next/static/css/262ae258bbcfd289.css +3 -0
- package/dist/.next/static/css/599369d853c61df7.css +31 -0
- package/dist/.next/static/{TqY9pInUBjZNteD9IEnz3 → kGRfd0CDzKPsrYHw9rLTQ}/_buildManifest.js +1 -1
- package/dist/.next/trace +3 -3
- package/dist/app/api/query/route.js +35 -16
- package/dist/app/api/schema/route.js +16 -6
- package/dist/app/api/tables/[name]/route.js +23 -12
- package/dist/app/api/tables/route.js +21 -6
- package/dist/d1-studio.js +1 -0
- package/package.json +6 -2
- package/dist/.next/server/chunks/226.js +0 -30
- package/dist/.next/server/chunks/391.js +0 -23
- package/dist/.next/server/chunks/452.js +0 -1
- package/dist/.next/server/chunks/487.js +0 -1
- package/dist/.next/server/chunks/572.js +0 -1
- package/dist/.next/server/chunks/627.js +0 -6
- package/dist/.next/server/chunks/992.js +0 -3
- package/dist/.next/server/chunks/994.js +0 -13
- package/dist/.next/static/chunks/1a258343.3b3e7ba5ba0bd0d2.js +0 -1
- package/dist/.next/static/chunks/345.8fc37569d5708622.js +0 -1
- package/dist/.next/static/chunks/480-85b6c8ae3f51b156.js +0 -1
- package/dist/.next/static/chunks/4bd1b696-124ea104c06f6cea.js +0 -1
- package/dist/.next/static/chunks/517-c876ce2f00030cd0.js +0 -2
- package/dist/.next/static/chunks/52.2cdc9bdb75e1fc2e.js +0 -1
- package/dist/.next/static/chunks/692-9e59d546afd11ec3.js +0 -1
- package/dist/.next/static/chunks/803-a2fcfbd00e6b3b38.js +0 -1
- package/dist/.next/static/chunks/92-a84bdac2be7c8d7a.js +0 -1
- package/dist/.next/static/chunks/app/_not-found/page-3e24b81707d98126.js +0 -1
- package/dist/.next/static/chunks/app/api/migrations/sync/route-ee522f232b9f0a9c.js +0 -1
- package/dist/.next/static/chunks/app/api/pro/route-c90c1f901fc00d38.js +0 -1
- package/dist/.next/static/chunks/app/api/pull-data/confirm/route-118764086af798f8.js +0 -1
- package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-2b0ade4ebfcea0bc.js +0 -1
- package/dist/.next/static/chunks/app/api/pull-remote/preview/route-342db7ea13e6f447.js +0 -1
- package/dist/.next/static/chunks/app/api/push-remote/confirm/route-b778c053bd515abd.js +0 -1
- package/dist/.next/static/chunks/app/api/push-remote/preview/route-ab090482f299f57f.js +0 -1
- package/dist/.next/static/chunks/app/api/query/route-4d21a8b1d34491f1.js +0 -1
- package/dist/.next/static/chunks/app/api/schema/route-cb17a387d6b557ad.js +0 -1
- package/dist/.next/static/chunks/app/api/tables/[name]/import/route-510472de7a5c29bd.js +0 -1
- package/dist/.next/static/chunks/app/api/tables/[name]/route-6a1fa95c303ce0de.js +0 -1
- package/dist/.next/static/chunks/app/api/tables/route-daa975df4ea8e8f8.js +0 -1
- package/dist/.next/static/chunks/app/api/time-travel/preview/route-5787d7e8f17bd539.js +0 -1
- package/dist/.next/static/chunks/app/api/time-travel/restore/route-84b64a27e831e21c.js +0 -1
- package/dist/.next/static/chunks/app/api/update/route-54ee900537982652.js +0 -1
- package/dist/.next/static/chunks/app/layout-f0ec4d636ee0f763.js +0 -1
- package/dist/.next/static/chunks/app/page-6bcbc40fdbc40128.js +0 -1
- package/dist/.next/static/chunks/framework-d29117d969504448.js +0 -1
- package/dist/.next/static/chunks/main-8d0ab17774ffa031.js +0 -1
- package/dist/.next/static/chunks/main-app-4506e88db72db4b7.js +0 -1
- package/dist/.next/static/chunks/pages/_app-d23763e3e6c904ff.js +0 -1
- package/dist/.next/static/chunks/pages/_error-9b7125ad1a1e68fa.js +0 -1
- package/dist/.next/static/chunks/webpack-024900a94af4f0a7.js +0 -1
- package/dist/.next/static/css/2c165a0ede9b2442.css +0 -3
- package/dist/.next/static/css/32df9a4d493f8b0f.css +0 -31
- /package/dist/.next/static/{TqY9pInUBjZNteD9IEnz3 → kGRfd0CDzKPsrYHw9rLTQ}/_ssgManifest.js +0 -0
|
@@ -8,9 +8,9 @@ import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
|
8
8
|
|
|
9
9
|
const execAsync = promisify(exec);
|
|
10
10
|
|
|
11
|
-
async function runPragma(databaseName, query, projectDir) {
|
|
11
|
+
async function runPragma(databaseName, query, projectDir, source = 'local') {
|
|
12
12
|
const { stdout } = await execAsync(
|
|
13
|
-
`wrangler d1 execute ${databaseName}
|
|
13
|
+
`wrangler d1 execute ${databaseName} --${source} --command="${query.replace(/"/g, '\\"')}" --json`,
|
|
14
14
|
{ cwd: projectDir }
|
|
15
15
|
);
|
|
16
16
|
const result = JSON.parse(stdout);
|
|
@@ -21,10 +21,19 @@ export async function GET(request) {
|
|
|
21
21
|
try {
|
|
22
22
|
const { searchParams } = new URL(request.url);
|
|
23
23
|
const dbParam = searchParams.get('db');
|
|
24
|
+
const sourceParam = searchParams.get('source');
|
|
25
|
+
const source = sourceParam === 'remote' ? 'remote' : 'local';
|
|
24
26
|
|
|
25
27
|
const projectDir = process.env.D1_PROJECT_DIR;
|
|
26
28
|
if (!projectDir) throw new Error('Project directory not configured');
|
|
27
29
|
|
|
30
|
+
if (source === 'remote' && process.env.D1_IS_PRO !== 'true') {
|
|
31
|
+
return NextResponse.json(
|
|
32
|
+
{ success: false, error: 'Pro license required. Run: d1s --license YOUR-KEY' },
|
|
33
|
+
{ status: 402 }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
const wranglerResult = await findWranglerConfig(projectDir);
|
|
29
38
|
if (!wranglerResult?.config) throw new Error('No Wrangler configuration found');
|
|
30
39
|
const config = wranglerResult.config;
|
|
@@ -40,19 +49,20 @@ export async function GET(request) {
|
|
|
40
49
|
const tableRows = await runPragma(
|
|
41
50
|
databaseName,
|
|
42
51
|
`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_cf_%' ORDER BY name;`,
|
|
43
|
-
projectDir
|
|
52
|
+
projectDir,
|
|
53
|
+
source
|
|
44
54
|
);
|
|
45
55
|
const tableNames = tableRows.map(r => r.name);
|
|
46
56
|
|
|
47
57
|
// Run sequentially to avoid SQLITE_BUSY (database locked) errors
|
|
48
58
|
const tables = [];
|
|
49
59
|
for (const name of tableNames) {
|
|
50
|
-
const columns = await runPragma(databaseName, `PRAGMA table_info(${name});`, projectDir);
|
|
51
|
-
const foreignKeys = await runPragma(databaseName, `PRAGMA foreign_key_list(${name});`, projectDir);
|
|
60
|
+
const columns = await runPragma(databaseName, `PRAGMA table_info(${name});`, projectDir, source);
|
|
61
|
+
const foreignKeys = await runPragma(databaseName, `PRAGMA foreign_key_list(${name});`, projectDir, source);
|
|
52
62
|
tables.push({ name, columns, foreignKeys });
|
|
53
63
|
}
|
|
54
64
|
|
|
55
|
-
return NextResponse.json({ success: true, tables });
|
|
65
|
+
return NextResponse.json({ success: true, tables, source });
|
|
56
66
|
} catch (error) {
|
|
57
67
|
return NextResponse.json({ success: false, error: error.message }, { status: 500 });
|
|
58
68
|
}
|
|
@@ -22,12 +22,14 @@ let isProcessing = false;
|
|
|
22
22
|
/**
|
|
23
23
|
* Executes a D1 SQL query, preferring direct SQLite access over the wrangler CLI.
|
|
24
24
|
*/
|
|
25
|
-
async function executeD1Query(sql, projectDir, dbConfig) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
async function executeD1Query(sql, projectDir, dbConfig, source = 'local') {
|
|
26
|
+
if (source === 'local') {
|
|
27
|
+
// Try direct SQLite access first (fast path)
|
|
28
|
+
const localOutput = executeLocalSQL(projectDir, dbConfig, sql);
|
|
29
|
+
if (localOutput !== null) {
|
|
30
|
+
const parsed = JSON.parse(localOutput);
|
|
31
|
+
return parsed[0]?.results || [];
|
|
32
|
+
}
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
// Fall back to wrangler CLI
|
|
@@ -38,7 +40,7 @@ async function executeD1Query(sql, projectDir, dbConfig) {
|
|
|
38
40
|
}
|
|
39
41
|
isProcessing = true;
|
|
40
42
|
const { stdout } = await execAsync(
|
|
41
|
-
`wrangler d1 execute ${databaseName}
|
|
43
|
+
`wrangler d1 execute ${databaseName} --${source} --command="${sql.replace(/"/g, '\\"')}" --json`,
|
|
42
44
|
{ cwd: projectDir }
|
|
43
45
|
);
|
|
44
46
|
const result = JSON.parse(stdout);
|
|
@@ -89,12 +91,21 @@ export async function GET(request, context) {
|
|
|
89
91
|
const offset = (page - 1) * limit;
|
|
90
92
|
const isExport = searchParams.get('export') === 'true';
|
|
91
93
|
const dbParam = searchParams.get('db');
|
|
94
|
+
const sourceParam = searchParams.get('source');
|
|
95
|
+
const source = sourceParam === 'remote' ? 'remote' : 'local';
|
|
92
96
|
|
|
93
97
|
const projectDir = process.env.D1_PROJECT_DIR;
|
|
94
98
|
if (!projectDir) {
|
|
95
99
|
throw new Error('Project directory not configured');
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
if (source === 'remote' && process.env.D1_IS_PRO !== 'true') {
|
|
103
|
+
return NextResponse.json(
|
|
104
|
+
{ success: false, error: { message: 'Pro license required. Run: d1s --license YOUR-KEY' } },
|
|
105
|
+
{ status: 402 }
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
98
109
|
// Use the centralized helper to find Wrangler configuration
|
|
99
110
|
const wranglerResult = await findWranglerConfig(projectDir);
|
|
100
111
|
if (!wranglerResult || !wranglerResult.config) {
|
|
@@ -116,11 +127,11 @@ export async function GET(request, context) {
|
|
|
116
127
|
|
|
117
128
|
// Get table schema using PRAGMA query (PRAGMA is safe from injection when table name is sanitized)
|
|
118
129
|
const schemaQuery = `PRAGMA table_info(${sanitizedTableName});`;
|
|
119
|
-
const schema = await executeD1Query(schemaQuery, projectDir, dbConfig);
|
|
130
|
+
const schema = await executeD1Query(schemaQuery, projectDir, dbConfig, source);
|
|
120
131
|
|
|
121
132
|
// Get the CREATE TABLE statement from sqlite_master
|
|
122
133
|
const createTableQuerySafe = `SELECT sql FROM sqlite_master WHERE type='table' AND name='${name.replace(/'/g, "''")}';`;
|
|
123
|
-
const tableDefinition = await executeD1Query(createTableQuerySafe, projectDir, dbConfig);
|
|
134
|
+
const tableDefinition = await executeD1Query(createTableQuerySafe, projectDir, dbConfig, source);
|
|
124
135
|
const createTableSQL = tableDefinition[0]?.sql || '';
|
|
125
136
|
|
|
126
137
|
// Extract CHECK constraints from the CREATE TABLE statement
|
|
@@ -134,7 +145,7 @@ export async function GET(request, context) {
|
|
|
134
145
|
|
|
135
146
|
// Get total row count for the table (using sanitized table name)
|
|
136
147
|
const countQuery = `SELECT COUNT(*) as total FROM ${sanitizedTableName};`;
|
|
137
|
-
const countResult = await executeD1Query(countQuery, projectDir, dbConfig);
|
|
148
|
+
const countResult = await executeD1Query(countQuery, projectDir, dbConfig, source);
|
|
138
149
|
const totalRows = countResult[0]?.total || 0;
|
|
139
150
|
|
|
140
151
|
// Fetch paginated data using the primary key column for ordering
|
|
@@ -152,7 +163,7 @@ export async function GET(request, context) {
|
|
|
152
163
|
ORDER BY ${sanitizedPrimaryKey} DESC
|
|
153
164
|
LIMIT ${safeLimitNum} OFFSET ${safeOffsetNum};
|
|
154
165
|
`;
|
|
155
|
-
const data = await executeD1Query(dataQuery, projectDir, dbConfig);
|
|
166
|
+
const data = await executeD1Query(dataQuery, projectDir, dbConfig, source);
|
|
156
167
|
|
|
157
168
|
if (isExport) trackEvent('export');
|
|
158
169
|
return NextResponse.json({
|
|
@@ -160,6 +171,7 @@ export async function GET(request, context) {
|
|
|
160
171
|
schema: enhancedSchema,
|
|
161
172
|
data,
|
|
162
173
|
meta: {
|
|
174
|
+
source,
|
|
163
175
|
tableName: name,
|
|
164
176
|
total: totalRows,
|
|
165
177
|
page,
|
|
@@ -194,4 +206,3 @@ export async function OPTIONS() {
|
|
|
194
206
|
},
|
|
195
207
|
});
|
|
196
208
|
}
|
|
197
|
-
|
|
@@ -82,6 +82,8 @@ export async function GET(request) {
|
|
|
82
82
|
try {
|
|
83
83
|
const { searchParams } = new URL(request.url);
|
|
84
84
|
const dbParam = searchParams.get('db');
|
|
85
|
+
const sourceParam = searchParams.get('source');
|
|
86
|
+
const source = sourceParam === 'remote' ? 'remote' : 'local';
|
|
85
87
|
|
|
86
88
|
const projectDir = process.env.D1_PROJECT_DIR;
|
|
87
89
|
|
|
@@ -93,6 +95,13 @@ export async function GET(request) {
|
|
|
93
95
|
);
|
|
94
96
|
}
|
|
95
97
|
|
|
98
|
+
if (source === 'remote' && process.env.D1_IS_PRO !== 'true') {
|
|
99
|
+
return NextResponse.json(
|
|
100
|
+
{ error: 'Pro license required. Run: d1s --license YOUR-KEY' },
|
|
101
|
+
{ status: 402 }
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
96
105
|
// Use the centralized helper to get Wrangler configuration
|
|
97
106
|
const wranglerResult = await findWranglerConfig(projectDir);
|
|
98
107
|
if (!wranglerResult || !wranglerResult.config) {
|
|
@@ -127,16 +136,21 @@ export async function GET(request) {
|
|
|
127
136
|
ORDER BY name;
|
|
128
137
|
`;
|
|
129
138
|
|
|
130
|
-
//
|
|
139
|
+
// For local mode, try direct SQLite access first (fast), then wrangler --local.
|
|
140
|
+
// For remote mode, always use wrangler --remote.
|
|
131
141
|
let result;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
142
|
+
if (source === 'local') {
|
|
143
|
+
const localOutput = executeLocalSQL(projectDir, dbConfig, query.trim());
|
|
144
|
+
if (localOutput !== null) {
|
|
145
|
+
result = JSON.parse(localOutput);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!result) {
|
|
136
150
|
const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
137
151
|
const { stdout } = await retryWithTimeout(async () => {
|
|
138
152
|
return execAsync(
|
|
139
|
-
`${npxCmd} wrangler d1 execute ${databaseName}
|
|
153
|
+
`${npxCmd} wrangler d1 execute ${databaseName} --${source} --json --command="${query.trim().replace(/\n\s*/g, ' ')}"`,
|
|
140
154
|
{ cwd: projectDir, timeout: 10000 }
|
|
141
155
|
);
|
|
142
156
|
});
|
|
@@ -148,6 +162,7 @@ export async function GET(request) {
|
|
|
148
162
|
return NextResponse.json({
|
|
149
163
|
success: true,
|
|
150
164
|
tables,
|
|
165
|
+
source,
|
|
151
166
|
debug: {
|
|
152
167
|
projectDir,
|
|
153
168
|
tableCount: tables.length
|
package/dist/d1-studio.js
CHANGED
|
@@ -92,6 +92,7 @@ if (notifier.update) {
|
|
|
92
92
|
const versionMessages = {
|
|
93
93
|
'0.2.11': 'Fixed table toolbar and table view horizontal/vertical scroll issues',
|
|
94
94
|
'0.3.0': 'Per-db migrations_dir, seed exclusion from push, sidebar UX improvements',
|
|
95
|
+
'0.3.11': 'Global Local/Remote source mode, remote table/schema browsing, and safer read-only remote editing UX',
|
|
95
96
|
};
|
|
96
97
|
|
|
97
98
|
// Create custom message
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "d1s",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The first native studio for Cloudflare D1. Zero setup. No extra dependencies.",
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"test": "node scripts/test.js",
|
|
21
21
|
"test:api": "node tests/run-tests.mjs",
|
|
22
22
|
"test:cli": "d1-studio --version",
|
|
23
|
+
"link:test:setup": "bash scripts/link-test.sh setup",
|
|
24
|
+
"link:test:run": "bash scripts/link-test.sh run",
|
|
25
|
+
"link:test:doctor": "bash scripts/link-test.sh doctor",
|
|
26
|
+
"link:test:clean": "bash scripts/link-test.sh clean",
|
|
23
27
|
"test:all": "npm run test && npm run test:cli",
|
|
24
28
|
"build:all": "npm run build:cli",
|
|
25
29
|
"prepublishOnly": "npm run build:all"
|
|
@@ -75,7 +79,7 @@
|
|
|
75
79
|
"find-up": "^7.0.0",
|
|
76
80
|
"inquirer": "^9.2.14",
|
|
77
81
|
"lucide-react": "^0.474.0",
|
|
78
|
-
"next": "15.
|
|
82
|
+
"next": "^15.5.15",
|
|
79
83
|
"node": "^20.18.3",
|
|
80
84
|
"open": "^8.4.2",
|
|
81
85
|
"react": "^18.2.0",
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
exports.id=226,exports.ids=[226],exports.modules={6487:()=>{},8335:()=>{},5949:(t,e,r)=>{"use strict";r.d(e,{S:()=>c});var s=r(9748),n=r(3873),i=r(3149),a=r(2537),E=r(6789),l=r(1804);let o=null,u=null;async function c(t){try{let e;if(!t||"string"!=typeof t)throw Error("Project path is required and must be a string");if(o&&u===t)return o;let r=null,c=null;for(let e of["wrangler.toml","wrangler.json","wrangler.jsonc"])if(r=await (0,i.dJ)(e,{cwd:t})){c=e;break}if(!r)return l.A.warn(`No Wrangler configuration file found in: ${t}`),null;l.A.info(`Found ${c} at: ${r}`);let T=await (0,s.readFile)(r,"utf-8");c.endsWith(".toml")?e=(0,a.parse)(T):(c.endsWith(".jsonc")&&(T=(0,E.A)(T)),e=JSON.parse(T));let A=(0,n.dirname)(r);return o={config:e,projectPath:A,configPath:r,configFile:c},u=t,o}catch(t){throw l.A.error(`Error reading Wrangler configuration: ${t.message}`),t}}},1804:(t,e,r)=>{"use strict";r.d(e,{A:()=>c});var s=r(6399);let{combine:n,timestamp:i,printf:a,colorize:E}=s.format,l="true"===process.env.DEBUG,o=a(({level:t,message:e,timestamp:r,...s})=>{let n=`${r} ${t}: ${e}`;return Object.keys(s).length>0&&(n+=` ${JSON.stringify(s)}`),n}),u=s.createLogger({level:l?"debug":"warn",format:n(i({format:"YYYY-MM-DD HH:mm:ss"}),E(),o),transports:[new s.transports.Console({level:l?"debug":"warn",silent:!1})]});u.logRequest=(t,e,r={})=>{u.debug(`Request: ${t} ${e}`,r)},u.logError=(t,e="unknown")=>{u.error(`Error in ${e}: ${t.message}`,{error:t.stack||t.message,source:e})},u.shouldLog=t=>{let e=u.level,r={error:0,warn:1,info:2,debug:3};return r[t]<=r[e]};let c=u},4218:(t,e,r)=>{"use strict";r.d(e,{IC:()=>a,ZX:()=>i});var s=r(9421),n=r(1804);async function i(t,e,r={},a=!1){let E=`
|
|
2
|
-
SELECT name, type, sql
|
|
3
|
-
FROM sqlite_master
|
|
4
|
-
WHERE type IN ('table', 'index', 'trigger')
|
|
5
|
-
AND name NOT LIKE 'sqlite_%'
|
|
6
|
-
AND name != 'd1_migrations';
|
|
7
|
-
`;try{let n=await (0,s.KK)(t,e,E,r,a),i=JSON.parse(n);return i[0]?.results||[]}catch(t){throw n.A.error("Failed to get current schema:",t),{type:s.wU.EXECUTION_ERROR,message:"Failed to get current schema",details:{error:t.message,suggestions:["Check database permissions"]}}}}function a(t){let e=new Map;return t.filter(t=>"DATA_MODIFICATION"!==t.type).forEach(t=>{let r=(t.name||t.tableName).toLowerCase();if(e.has(r)||e.set(r,new Set),"CREATE_TABLE"===t.type){let s=t.sql.match(/FOREIGN\s+KEY\s*\([^)]+\)\s+REFERENCES\s+(\w+)/gi);s&&s.forEach(t=>{let s=t.match(/REFERENCES\s+(\w+)/i)[1].toLowerCase();e.get(r).add(s)})}}),function(t){let e=[],r=new Set,s=new Set;for(let n of t.keys())r.has(n)||function n(i){if(s.has(i))throw Error(`Circular dependency detected for table: ${i}`);if(!r.has(i)){for(let e of(s.add(i),t.get(i)||new Set)){if(!t.has(e))throw Error(`Missing table dependency: ${e}`);n(e)}s.delete(i),r.add(i),e.push(i)}}(n);return e}(e)}},9421:(t,e,r)=>{"use strict";r.d(e,{By:()=>c,F9:()=>d,Gq:()=>T,KK:()=>I,Pg:()=>l,QQ:()=>u,bp:()=>m,h3:()=>N,mA:()=>f,tn:()=>g,wU:()=>o,xk:()=>p});var s=r(8354),n=r(9646),i=r(3648),a=r(1804);let E=(0,s.promisify)(n.exec),l={CREATE_TABLE:"CREATE_TABLE",ALTER_TABLE:"ALTER_TABLE",DROP_TABLE:"DROP_TABLE",CREATE_INDEX:"CREATE_INDEX",DROP_INDEX:"DROP_INDEX",DATA_MODIFICATION:"DATA_MODIFICATION"},o={VALIDATION_ERROR:"VALIDATION_ERROR",SYNTAX_ERROR:"SYNTAX_ERROR",EXECUTION_ERROR:"EXECUTION_ERROR",DEPENDENCY_ERROR:"DEPENDENCY_ERROR"};function u(t){return t.type!==l.DATA_MODIFICATION}function c(t){let e=t.trim().replace(/\s+/g," "),r=e.toUpperCase();if(r.startsWith("CREATE TABLE"))return{type:l.CREATE_TABLE,tableName:A(e,"CREATE TABLE"),sql:e,description:"create-table"};if(r.startsWith("ALTER TABLE")){let t=A(e,"ALTER TABLE"),s="";if(r.includes("RENAME")){let t=e.match(/RENAME\s+(?:COLUMN\s+)?([\w$]+)\s+TO\s+([\w$]+)/i);t&&(s=`rename-${t[1]}-to-${t[2]}`)}else if(r.includes("ADD COLUMN")){let t=e.match(/ADD\s+COLUMN\s+([\w$]+)(\s+[\w()]+)?/i);if(t){let e=t[1],r=t[2]?t[2].trim().replace(/\s+/g,"-"):"";s=r?`add-${e}-${r}`:`add-${e}`}}else if(r.includes("DROP COLUMN")){let t=e.match(/DROP\s+COLUMN\s+([\w$]+)/i);t&&(s=`drop-${t[1]}`)}else if(r.includes("MODIFY COLUMN")||r.includes("CHANGE COLUMN")){let t=e.match(/(?:MODIFY|CHANGE)\s+COLUMN\s+([\w$]+)(\s+[\w()]+)?/i);if(t){let e=t[1],r=t[2]?t[2].trim().replace(/\s+/g,"-"):"";s=r?`modify-${e}-to-${r}`:`modify-${e}`}}return{type:l.ALTER_TABLE,tableName:t,sql:e,description:s}}if(r.startsWith("DROP TABLE"))return{type:l.DROP_TABLE,tableName:A(e,"DROP TABLE"),sql:e,description:"drop-table"};if(r.startsWith("CREATE INDEX")||r.startsWith("CREATE UNIQUE INDEX")){let t=R(e),r=e.match(/INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?([\w$]+)/i),s=r?r[1]:"";return{type:l.CREATE_INDEX,tableName:t,sql:e,description:s}}if(r.startsWith("DROP INDEX")){let t=R(e),r=e.match(/DROP\s+INDEX\s+(?:IF\s+EXISTS\s+)?([\w$]+)/i),s=r?r[1]:"";return{type:l.DROP_INDEX,tableName:t,sql:e,description:s?`drop-index-${s}`:"drop-index"}}return{type:l.DATA_MODIFICATION,sql:e,description:"data-modification"}}function T(t){if(t.type!==l.DATA_MODIFICATION&&!t.tableName)throw{type:o.VALIDATION_ERROR,message:`Invalid SQL statement: unable to determine table name for "${t.type}".`,details:{sql:t.sql}};return t}function A(t,e){let r=t.match(RegExp(`${e}\\s+(?:IF\\s+(?:NOT\\s+)?EXISTS\\s+)?([\\w_]+)`,"i"));return r?r[1]:null}function R(t){let e=t.match(/ON\s+([\w_]+)/i);return e?e[1]:null}function m(t){return t.replace(/--[^\r\n]*/g,"").replace(/\/\*[\s\S]*?\*\//g,"").trim()}async function d(t,e,r,s,n=!1){try{(0,i.nZ)(s)}catch(t){return a.A.error("Invalid table name:",s,t.message),!1}let E=`SELECT name FROM sqlite_master WHERE type='table' AND name = '${s.replace(/'/g,"''")}' COLLATE NOCASE;`,l=await I(t,e,E,r,n);try{let t=l.indexOf("[");if(-1!==t){let e=l.substring(t),r=JSON.parse(e);return(r[0]?.results||[]).length>0}return!1}catch(t){return console.error("Error parsing tableExists result:",t),!1}}function f(t){return t.replace(/--.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").trim().split(";").map(t=>t.trim()).filter(t=>t.length>0).map(t=>c(t+";"))}async function I(t,e,s,n={},i=!1,l=null){try{let o=s.replace(/--[^\r\n]*/g,"").replace(/\/\*[\s\S]*?\*\//g,"").trim().replace(/\s+/g," "),u=o.toUpperCase();if((u.startsWith("CREATE INDEX")||u.startsWith("CREATE UNIQUE INDEX"))&&!u.includes("IF NOT EXISTS")&&(o=u.startsWith("CREATE UNIQUE INDEX")?o.replace(/CREATE\s+UNIQUE\s+INDEX/i,"CREATE UNIQUE INDEX IF NOT EXISTS"):o.replace(/CREATE\s+INDEX/i,"CREATE INDEX IF NOT EXISTS")),!e||"string"!=typeof e||!/^[a-zA-Z0-9_-]+$/.test(e))throw Error("Invalid database name for security reasons");if(!i&&l){let{executeLocalSQL:e}=await r.e(487).then(r.bind(r,3868)),s=e(t,l,o);if(null!==s)return s}let c="win32"===process.platform,T=o.replace(/"/g,'\\"').replace(/\$/g,"\\$"),A=`${c?"npx.cmd":"npx"} wrangler d1 execute ${e} ${i?"--remote":"--local"} --command="${T}" --json`;i?console.log(`[executeSQL --remote] ${A}`):a.A.shouldLog("debug")&&a.A.debug("Executing command:",A);let R={cwd:t,env:{...process.env,...n},maxBuffer:0xa00000,shell:!0},{stdout:m,stderr:d}=await E(A,R);if(i&&d&&console.log(`[executeSQL --remote stderr]: ${d.substring(0,800)}`),d&&!d.includes("\uD83C\uDF00"))throw Error(d);try{let t=m.indexOf("[");if(-1!==t)return m.substring(t)}catch(t){console.warn("JSON parse warning:",t)}return m}catch(t){throw a.A.shouldLog("debug")&&a.A.debug("SQL execution error:",t.message||t),{type:o.EXECUTION_ERROR,message:"Failed to execute SQL command",details:{command:t.cmd,stderr:t.stderr,stdout:t.stdout,originalError:t.message,suggestions:["Ensure Node.js and Wrangler are installed","Check npx in PATH","Verify the D1 database exists and is configured","Check Wrangler configuration"]}}}}async function N(t,e,r,s,n,E="id"){let l=(0,i.nZ)(r),o=(0,i.r0)(E),u=Math.max(1,Math.min(parseInt(n)||50,1e3)),c=`SELECT * FROM ${l} ORDER BY ${o} DESC LIMIT ${u};`;try{let r=await I(t,e,c,s,!0),n=r.indexOf("[");if(-1===n)throw Error(`Unexpected result format: ${r}`);let i=r.substring(n),a=JSON.parse(i);return a[0]?.results||[]}catch(t){throw a.A.error(`Error fetching remote data for table ${r}:`,t),t}}function p(t,e){if(!e||0===e.length)return"";let r=(0,i.nZ)(t),s=Object.keys(e[0]),n=s.map(t=>(0,i.r0)(t)).join(", "),a=e.map(t=>{let e=s.map(e=>{let r=t[e];return null==r?"NULL":`'${String(r).replace(/'/g,"''")}'`}).join(", ");return`(${e})`}).join(", ");return`INSERT INTO ${r} (${n}) VALUES ${a};`}function O(t){let e=[],r="",s=0,n=!1,i="";for(let a of t)'"'===a&&"\\"!==i&&(n=!n),!n&&("("===a&&s++,")"===a&&s--),","!==a||0!==s||n?r+=a:(e.push(r.trim()),r=""),i=a;return r.trim()&&e.push(r.trim()),e}function g(t){return t.split(";").map(t=>t.trim()).filter(t=>t.length>0).map(t=>(function(t){let e=t.trim(),r=e.toUpperCase();return r.startsWith("CREATE TABLE")?function(t){let e=t.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s*\(([\s\S]*)\)/i);if(!e)return t;let[,r,s]=e,n=O(s).map(t=>t.trim()).filter(Boolean);return`CREATE TABLE ${r} (
|
|
8
|
-
${n.join(",\n ")}
|
|
9
|
-
);`}(e):r.startsWith("CREATE INDEX")||r.startsWith("CREATE UNIQUE INDEX")?function(t){let e=t.match(/CREATE\s+(UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s+ON\s+(\w+)\s*\((.*)\)/i);if(!e)return t;let[,r,s,n,i]=e,a=i.split(",").map(t=>t.trim()).join(", ");return`CREATE ${r||""}INDEX ${s} ON ${n} (${a});`}(e):r.startsWith("ALTER TABLE")?function(t){let e=t.match(/ALTER\s+TABLE\s+(\w+)\s+(.*)/i);if(!e)return t;let[,r,s]=e,n=O(s);return 1===n.length?`ALTER TABLE ${r} ${n[0]};`:`ALTER TABLE ${r}
|
|
10
|
-
${n.map((t,e)=>` ${t}${e<n.length-1?",":";"}`).join("\n")}`}(e):r.startsWith("DROP TABLE")||r.startsWith("DROP INDEX")?function(t){let e=t.match(/DROP\s+(TABLE|INDEX)\s+(?:IF\s+EXISTS\s+)?(\w+)/i);if(!e)return t;let[,r,s]=e;return`DROP ${r} IF EXISTS ${s};`}(e):r.startsWith("INSERT INTO")?function(t){let e=t.match(/INSERT\s+INTO\s+(\w+)\s*(\([^)]+\))?\s*VALUES\s*(.+)/i);if(!e)return t;let[,r,s,n]=e,i=O(n);return`INSERT INTO ${r}${s?` ${s}`:""}
|
|
11
|
-
VALUES
|
|
12
|
-
`+i.map((t,e)=>` ${t}${e<i.length-1?",":";"}`).join("\n")}(e):r.startsWith("UPDATE")?function(t){let e=t.match(/UPDATE\s+(\w+)\s+SET\s+(.+?)(?:\s+WHERE\s+(.+))?$/i);if(!e)return t;let[,r,s,n]=e,i=O(s),a=`UPDATE ${r}
|
|
13
|
-
SET
|
|
14
|
-
${i.map(t=>` ${t.trim()}`).join(",\n")}`;return n&&(a+=`
|
|
15
|
-
WHERE
|
|
16
|
-
${n.trim()}`),a+";"}(e):r.startsWith("DELETE FROM")?function(t){let e=t.match(/DELETE\s+FROM\s+(\w+)(?:\s+WHERE\s+(.+))?$/i);if(!e)return t;let[,r,s]=e,n=`DELETE FROM ${r}`;return s&&(n+=`
|
|
17
|
-
WHERE
|
|
18
|
-
${s.trim()}`),n+";"}(e):r.startsWith("SELECT")?function(t){let e=t.match(/SELECT\s+(.+?)\s+FROM\s+(.+?)(?:\s+WHERE\s+(.+?))?(?:\s+GROUP\s+BY\s+(.+?))?(?:\s+HAVING\s+(.+?))?(?:\s+ORDER\s+BY\s+(.+?))?(?:\s+LIMIT\s+(.+?))?$/i);if(!e)return t;let[,r,s,n,i,a,E,l]=e,o=`SELECT
|
|
19
|
-
${r.split(",").map(t=>t.trim()).join(",\n ")}
|
|
20
|
-
FROM
|
|
21
|
-
${s.trim()}`;return n&&(o+=`
|
|
22
|
-
WHERE
|
|
23
|
-
${n.trim()}`),i&&(o+=`
|
|
24
|
-
GROUP BY
|
|
25
|
-
${i.trim()}`),a&&(o+=`
|
|
26
|
-
HAVING
|
|
27
|
-
${a.trim()}`),E&&(o+=`
|
|
28
|
-
ORDER BY
|
|
29
|
-
${E.trim()}`),l&&(o+=`
|
|
30
|
-
LIMIT ${l.trim()}`),o+";"}(e):e+";"})(t)).join("\n\n")+"\n"}},3648:(t,e,r)=>{"use strict";function s(t){if(!t||"string"!=typeof t)throw Error("Table name must be a non-empty string");if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw Error(`Invalid table name: ${t}. Must start with letter or underscore and contain only letters, digits, and underscores.`);if(["SELECT","FROM","WHERE","INSERT","UPDATE","DELETE","CREATE","DROP","ALTER","TABLE","INDEX","VIEW","TRIGGER","PRAGMA","VACUUM","REINDEX","EXPLAIN","QUERY","PLAN","TRANSACTION","BEGIN","COMMIT","ROLLBACK"].includes(t.toUpperCase()))throw Error(`Table name cannot be a reserved word: ${t}`);return`"${t}"`}function n(t){if(!t||"string"!=typeof t)throw Error("Column name must be a non-empty string");if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw Error(`Invalid column name: ${t}. Must start with letter or underscore and contain only letters, digits, and underscores.`);return`"${t}"`}r.d(e,{nZ:()=>s,r0:()=>n})}};
|