d1s 0.2.6 → 0.2.8
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 +3 -1
- package/dist/.next/.next/BUILD_ID +1 -1
- package/dist/.next/.next/app-build-manifest.json +34 -27
- package/dist/.next/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/.next/build-manifest.json +2 -2
- package/dist/.next/.next/cache/.rscinfo +1 -1
- package/dist/.next/.next/cache/.tsbuildinfo +1 -1
- package/dist/.next/.next/cache/webpack/client-development/0.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/1.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/2.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/3.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/4.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/index.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/index.pack.gz.old +0 -0
- package/dist/.next/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/10.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/11.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/12.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/13.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/14.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/2.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/3.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/4.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/5.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/6.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/7.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/8.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/9.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/dist/.next/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-development/0.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/1.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/2.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/3.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/4.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/index.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/index.pack.gz.old +0 -0
- package/dist/.next/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/10.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/11.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/12.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/13.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/2.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/3.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/4.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/5.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/6.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/7.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/8.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/9.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/dist/.next/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/.next/.next/next-server.js.nft.json +1 -1
- package/dist/.next/.next/prerender-manifest.json +1 -1
- package/dist/.next/.next/server/app/_not-found/page.js +1 -1
- package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/_not-found.html +1 -1
- package/dist/.next/.next/server/app/_not-found.rsc +2 -2
- package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/.next/server/app/api/cloudflare/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/.next/server/app/api/databases/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync/route.js +3 -3
- package/dist/.next/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +2 -2
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js +2 -2
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/query/route.js +2 -2
- package/dist/.next/.next/server/app/api/query/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/tables/[name]/route.js +4 -4
- package/dist/.next/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/.next/server/app/api/tables/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/update/route.js +5 -0
- package/dist/.next/.next/server/app/api/update/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/update/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/index.html +3 -3
- package/dist/.next/.next/server/app/index.rsc +3 -3
- package/dist/.next/.next/server/app/page.js +14 -12
- package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app-paths-manifest.json +4 -3
- package/dist/.next/.next/server/chunks/336.js +1 -1
- package/dist/.next/.next/server/chunks/391.js +23 -0
- package/dist/.next/.next/server/chunks/452.js +1 -0
- package/dist/.next/.next/server/chunks/627.js +3 -3
- package/dist/.next/.next/server/chunks/638.js +3 -3
- package/dist/.next/.next/server/chunks/801.js +55 -0
- package/dist/.next/.next/server/chunks/992.js +3 -3
- package/dist/.next/.next/server/pages/404.html +1 -1
- package/dist/.next/.next/server/pages/500.html +1 -1
- package/dist/.next/.next/server/pages/_app.js +1 -1
- package/dist/.next/.next/server/pages/_document.js +1 -1
- package/dist/.next/.next/server/pages/_error.js +1 -1
- package/dist/.next/.next/server/pages-manifest.json +1 -1
- package/dist/.next/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/.next/static/JrwgdSDcipr0Zh7k19Cj_/_buildManifest.js +1 -0
- package/dist/.next/.next/static/chunks/958-98887928efebfdf7.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/cloudflare/route-5133155a604f2719.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/databases/route-63a31080b565794e.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-d97667565b4a59b6.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-7089bcbfeb6b5260.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-9143e6e4c3f05162.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-c963d143a51aed66.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-072132c0a6cb3df3.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-ca6bf35aa72661ee.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/query/route-1466f6b7ffd8b6c0.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-898d3f85fc8544c4.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/route-91650359fc3735cb.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/update/route-504d663df9124f97.js +1 -0
- package/dist/.next/.next/static/chunks/app/page-2c28a255a4ecd8d4.js +1 -0
- package/dist/.next/.next/static/chunks/app/page-3db7feef57019055.js +1 -0
- package/dist/.next/.next/static/css/4957328384ed5c42.css +3 -0
- package/dist/.next/.next/static/gc8l1G6KXOeLLOM7VJip6/_buildManifest.js +1 -0
- package/dist/.next/.next/static/kYsJoni86CJWDuTkc1xU6/_buildManifest.js +1 -0
- package/dist/.next/.next/static/kYsJoni86CJWDuTkc1xU6/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/scC5qwQC9H7rR1groM0Q-/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/tEHOI_-t-iqfJClNzuo9m/_buildManifest.js +1 -0
- package/dist/.next/.next/static/tEHOI_-t-iqfJClNzuo9m/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/vin2VQs5pM_dH2e2_I7AN/_buildManifest.js +1 -0
- package/dist/.next/.next/static/vin2VQs5pM_dH2e2_I7AN/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/wHKwQhaxin5_i06GFVDHb/_buildManifest.js +1 -0
- package/dist/.next/.next/static/wHKwQhaxin5_i06GFVDHb/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/xW4MspD8XibrhXDi_q2IO/_ssgManifest.js +1 -0
- package/dist/.next/.next/trace +3 -3
- package/dist/.next/.next/types/app/api/update/route.ts +347 -0
- package/dist/.next/BUILD_ID +1 -1
- package/dist/.next/app-build-manifest.json +17 -17
- package/dist/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/build-manifest.json +2 -2
- package/dist/.next/cache/.rscinfo +1 -1
- package/dist/.next/cache/.tsbuildinfo +1 -1
- package/dist/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/cache/webpack/server-production/index.pack +0 -0
- 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 +1 -1
- package/dist/.next/server/app/_not-found.html +1 -1
- package/dist/.next/server/app/_not-found.rsc +1 -1
- package/dist/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/server/app/api/migrations/sync/route.js +3 -3
- package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route.js +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/pull-remote/confirm/route.js +1 -1
- package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/pull-remote/preview/route.js +1 -1
- package/dist/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/push-remote/confirm/route.js +2 -2
- package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/push-remote/preview/route.js +2 -2
- package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/query/route.js +2 -2
- package/dist/.next/server/app/api/query/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/tables/[name]/route.js +4 -4
- package/dist/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/server/app/index.html +1 -1
- package/dist/.next/server/app/index.rsc +1 -1
- package/dist/.next/server/app-paths-manifest.json +6 -6
- package/dist/.next/server/chunks/801.js +55 -0
- package/dist/.next/server/pages/404.html +1 -1
- package/dist/.next/server/pages/500.html +1 -1
- package/dist/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/static/ZwNOdZJ0LOtE0AJMNWwzY/_buildManifest.js +1 -0
- package/dist/.next/static/ZwNOdZJ0LOtE0AJMNWwzY/_ssgManifest.js +1 -0
- package/dist/.next/trace +14 -14
- package/dist/app/api/cloudflare/route.js +5 -1
- package/dist/app/api/databases/route.js +3 -4
- package/dist/app/api/migrations/sync/route.js +5 -3
- package/dist/app/api/pull-remote/confirm/route.js +24 -23
- package/dist/app/api/pull-remote/preview/route.js +4 -3
- package/dist/app/api/push-remote/preview/route.js +3 -2
- package/dist/app/api/query/route.js +11 -3
- package/dist/app/api/tables/[name]/route.js +3 -2
- package/dist/app/api/tables/route.js +6 -2
- package/dist/app/app/api/cloudflare/route.js +5 -1
- package/dist/app/app/api/databases/route.js +3 -4
- package/dist/app/app/api/migrations/sync/route.js +5 -3
- package/dist/app/app/api/pull-remote/confirm/route.js +24 -23
- package/dist/app/app/api/pull-remote/preview/route.js +4 -3
- package/dist/app/app/api/push-remote/preview/route.js +3 -2
- package/dist/app/app/api/query/route.js +11 -3
- package/dist/app/app/api/tables/[name]/route.js +3 -2
- package/dist/app/app/api/tables/route.js +6 -2
- package/dist/app/app/api/update/route.js +11 -0
- package/dist/app/app/page.jsx +7 -1
- package/dist/d1-studio.js +94 -58
- package/dist/lib/database-queue.js +34 -30
- package/dist/lib/find-wrangler-config.js +14 -8
- package/dist/lib/logger.js +11 -2
- package/dist/lib/migrations.js +4 -4
- package/dist/lib/schema-operations.js +4 -1
- package/dist/lib/sql-operations.js +8 -1
- package/package.json +3 -1
- package/scripts/studio.js +94 -58
- package/scripts/test.js +280 -82
- package/src/app/api/cloudflare/route.js +5 -1
- package/src/app/api/databases/route.js +3 -4
- package/src/app/api/migrations/sync/route.js +5 -3
- package/src/app/api/pull-remote/confirm/route.js +24 -23
- package/src/app/api/pull-remote/preview/route.js +4 -3
- package/src/app/api/push-remote/preview/route.js +3 -2
- package/src/app/api/query/route.js +11 -3
- package/src/app/api/tables/[name]/route.js +3 -2
- package/src/app/api/tables/route.js +6 -2
- package/src/app/api/update/route.js +11 -0
- package/src/app/page.jsx +7 -1
- package/src/components/update-banner.jsx +64 -0
- package/src/lib/database-queue.js +34 -30
- package/src/lib/find-wrangler-config.js +14 -8
- package/src/lib/logger.js +11 -2
- package/src/lib/migrations.js +4 -4
- package/src/lib/schema-operations.js +4 -1
- package/src/lib/sql-operations.js +8 -1
- package/dist/.next/.next/server/chunks/603.js +0 -55
- package/dist/.next/server/chunks/603.js +0 -55
- /package/dist/.next/.next/static/{HsZ8OanS5v86DqC9rErO- → IWRJZhjf8U8mjzz4h0VNE}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{HsZ8OanS5v86DqC9rErO- → IWRJZhjf8U8mjzz4h0VNE}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{q6WmQmyONe88bMN0_jrC2 → JrwgdSDcipr0Zh7k19Cj_}/_ssgManifest.js +0 -0
- /package/dist/.next/{static/Tk1fnz_CXLavm23ZEeChG → .next/static/gc8l1G6KXOeLLOM7VJip6}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{q6WmQmyONe88bMN0_jrC2 → scC5qwQC9H7rR1groM0Q-}/_buildManifest.js +0 -0
- /package/dist/.next/{static/Tk1fnz_CXLavm23ZEeChG → .next/static/xW4MspD8XibrhXDi_q2IO}/_buildManifest.js +0 -0
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from '@/lib/sql-operations';
|
|
13
13
|
import { getCurrentSchema, analyzeDependencies } from '@/lib/schema-operations';
|
|
14
14
|
import { initMigrationsTable, recordMigration, getRemoteMigrations } from '@/lib/migrations.js';
|
|
15
|
+
import logger from '@/lib/logger';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Applies the pull migrations by:
|
|
@@ -52,33 +53,33 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
52
53
|
await Promise.all(stagedFilesList.map(file => unlink(path.join(stagingDir, file))));
|
|
53
54
|
|
|
54
55
|
// --- STEP 1: Fetch remote migration metadata ---
|
|
55
|
-
|
|
56
|
+
logger.debug('Fetching remote migration metadata...');
|
|
56
57
|
const remoteMigrations = await getRemoteMigrations(projectDir, databaseName, env);
|
|
57
|
-
|
|
58
|
+
logger.debug('Remote migration metadata:', remoteMigrations);
|
|
58
59
|
|
|
59
60
|
// --- STEP 2: For each remote migration, fetch its file content ---
|
|
60
|
-
|
|
61
|
+
logger.debug('Fetching migration file content from remote...');
|
|
61
62
|
const stagedFiles = new Map();
|
|
62
63
|
for (const migration of remoteMigrations) {
|
|
63
64
|
try {
|
|
64
65
|
const migrationFileName = migration.name; // Use the remote migration's name.
|
|
65
66
|
const content = await getMigrationFileContent(projectDir, databaseName, migrationFileName, env);
|
|
66
67
|
stagedFiles.set(migrationFileName, content);
|
|
67
|
-
|
|
68
|
+
logger.debug(`Staged migration file: ${migrationFileName}`);
|
|
68
69
|
await writeFile(path.join(stagingDir, migrationFileName), content, 'utf8');
|
|
69
70
|
} catch (fileError) {
|
|
70
|
-
|
|
71
|
+
logger.error(`Error fetching content for migration ${migration.name}:`, fileError);
|
|
71
72
|
throw new Error(`Failed to fetch migration file content for ${migration.name}`);
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
// --- STEP 3: Fetch local schema for destructive update ---
|
|
76
|
-
|
|
77
|
+
logger.debug('Fetching local schema for destructive update...');
|
|
77
78
|
const currentSchema = await getCurrentSchema(projectDir, databaseName, env, false);
|
|
78
79
|
const tableSchema = currentSchema.filter(obj =>
|
|
79
80
|
obj.type === 'table' && obj.name && obj.name.toLowerCase() !== 'if'
|
|
80
81
|
);
|
|
81
|
-
|
|
82
|
+
logger.debug('Local table schema:', tableSchema);
|
|
82
83
|
const dropOrder = tableSchema.length > 0
|
|
83
84
|
? analyzeDependencies(
|
|
84
85
|
tableSchema.map(obj => ({
|
|
@@ -88,18 +89,18 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
88
89
|
}))
|
|
89
90
|
)
|
|
90
91
|
: [];
|
|
91
|
-
|
|
92
|
+
logger.debug('Computed drop order:', dropOrder);
|
|
92
93
|
|
|
93
94
|
// --- STEP 4: Destructive update (all-or-nothing) ---
|
|
94
|
-
|
|
95
|
+
logger.debug('Beginning destructive update...');
|
|
95
96
|
try {
|
|
96
|
-
|
|
97
|
+
logger.debug('Disabling foreign keys...');
|
|
97
98
|
await executeSQL(projectDir, databaseName, 'PRAGMA foreign_keys=OFF;', env, false);
|
|
98
99
|
|
|
99
100
|
// Drop triggers.
|
|
100
101
|
const triggers = currentSchema.filter(obj => obj.type === 'trigger');
|
|
101
102
|
for (const trigger of triggers) {
|
|
102
|
-
|
|
103
|
+
logger.debug(`Dropping trigger: ${trigger.name}`);
|
|
103
104
|
await executeSQL(
|
|
104
105
|
projectDir,
|
|
105
106
|
databaseName,
|
|
@@ -111,7 +112,7 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
111
112
|
// Drop indexes.
|
|
112
113
|
const indexes = currentSchema.filter(obj => obj.type === 'index');
|
|
113
114
|
for (const index of indexes) {
|
|
114
|
-
|
|
115
|
+
logger.debug(`Dropping index: ${index.name}`);
|
|
115
116
|
await executeSQL(
|
|
116
117
|
projectDir,
|
|
117
118
|
databaseName,
|
|
@@ -122,7 +123,7 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
122
123
|
}
|
|
123
124
|
// Drop tables in reverse dependency order.
|
|
124
125
|
for (const tableName of dropOrder.reverse()) {
|
|
125
|
-
|
|
126
|
+
logger.debug(`Dropping table: ${tableName}`);
|
|
126
127
|
await executeSQL(
|
|
127
128
|
projectDir,
|
|
128
129
|
databaseName,
|
|
@@ -131,7 +132,7 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
131
132
|
false
|
|
132
133
|
);
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
logger.debug('Re-enabling foreign keys...');
|
|
135
136
|
await executeSQL(projectDir, databaseName, 'PRAGMA foreign_keys=ON;', env, false);
|
|
136
137
|
} catch (dropError) {
|
|
137
138
|
throw new Error(`Error dropping existing objects: ${dropError.message}`);
|
|
@@ -139,7 +140,7 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
139
140
|
|
|
140
141
|
// --- STEP 5: Reset the local migrations table ---
|
|
141
142
|
try {
|
|
142
|
-
|
|
143
|
+
logger.debug('Resetting local migrations table...');
|
|
143
144
|
await initMigrationsTable(projectDir, databaseName, 'local', true);
|
|
144
145
|
} catch (initError) {
|
|
145
146
|
throw new Error(`Error resetting migrations table: ${initError.message}`);
|
|
@@ -152,7 +153,7 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
152
153
|
try {
|
|
153
154
|
for (const [filename, content] of stagedFiles.entries()) {
|
|
154
155
|
currentFilename = filename;
|
|
155
|
-
|
|
156
|
+
logger.debug(`Applying migration: ${filename}`);
|
|
156
157
|
// Write the migration file to the main migrations folder.
|
|
157
158
|
await writeFile(path.join(migrationsDir, filename), content, 'utf8');
|
|
158
159
|
|
|
@@ -162,7 +163,7 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
162
163
|
.update(content)
|
|
163
164
|
.digest('hex');
|
|
164
165
|
|
|
165
|
-
|
|
166
|
+
logger.debug(`Recording migration: ${filename} with checksum ${checksum}`);
|
|
166
167
|
await recordMigration(
|
|
167
168
|
projectDir,
|
|
168
169
|
databaseName,
|
|
@@ -181,26 +182,26 @@ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
// --- STEP 7: Replace main migrations folder with staged files ---
|
|
184
|
-
|
|
185
|
+
logger.debug('Replacing main migrations folder with staged files...');
|
|
185
186
|
const mainFiles = await readdir(migrationsDir).catch(() => []);
|
|
186
187
|
if (mainFiles.length) {
|
|
187
188
|
for (const file of mainFiles) {
|
|
188
|
-
|
|
189
|
+
logger.debug(`Deleting local migration file: ${file}`);
|
|
189
190
|
await unlink(path.join(migrationsDir, file));
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
for (const [filename, content] of stagedFiles.entries()) {
|
|
193
|
-
|
|
194
|
+
logger.debug(`Copying staged file ${filename} to main migrations folder`);
|
|
194
195
|
await writeFile(path.join(migrationsDir, filename), content, 'utf8');
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
|
|
198
|
+
logger.debug('Pull migration applied successfully.');
|
|
198
199
|
return {
|
|
199
200
|
appliedMigrations: Array.from(stagedFiles.keys()),
|
|
200
201
|
details: appliedPreview
|
|
201
202
|
};
|
|
202
203
|
} catch (error) {
|
|
203
|
-
|
|
204
|
+
logger.error('Pull migration error:', error);
|
|
204
205
|
throw error;
|
|
205
206
|
}
|
|
206
207
|
}
|
|
@@ -251,7 +252,7 @@ export async function POST(req) {
|
|
|
251
252
|
details: result
|
|
252
253
|
});
|
|
253
254
|
} catch (error) {
|
|
254
|
-
|
|
255
|
+
logger.error('Pull remote confirm error:', error);
|
|
255
256
|
return NextResponse.json({
|
|
256
257
|
success: false,
|
|
257
258
|
error: {
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { NextResponse } from 'next/server';
|
|
4
4
|
import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
5
|
-
import { ErrorTypes
|
|
5
|
+
import { ErrorTypes } from '@/lib/sql-operations';
|
|
6
6
|
import { getCurrentSchema, analyzeDependencies } from '@/lib/schema-operations';
|
|
7
7
|
import { getRemoteMigrations } from '@/lib/migrations.js';
|
|
8
|
+
import logger from '@/lib/logger';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Generates a preview for pulling remote migrations.
|
|
@@ -64,7 +65,7 @@ async function generatePullPreview(projectDir, accountId, apiToken, databaseName
|
|
|
64
65
|
|
|
65
66
|
return preview;
|
|
66
67
|
} catch (error) {
|
|
67
|
-
|
|
68
|
+
logger.error('Pull preview generation error:', error);
|
|
68
69
|
throw error;
|
|
69
70
|
}
|
|
70
71
|
}
|
|
@@ -123,7 +124,7 @@ export async function POST(req) {
|
|
|
123
124
|
details: preview
|
|
124
125
|
});
|
|
125
126
|
} catch (error) {
|
|
126
|
-
|
|
127
|
+
logger.error('Pull remote preview error:', error);
|
|
127
128
|
return NextResponse.json({
|
|
128
129
|
success: false,
|
|
129
130
|
error: {
|
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
7
7
|
import { executeSQL, ErrorTypes } from '@/lib/sql-operations';
|
|
8
8
|
import { validateMigrationFile } from '@/lib/migrations.js';
|
|
9
|
+
import logger from '@/lib/logger';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Pushes migration preview to remote.
|
|
@@ -100,7 +101,7 @@ async function pushToRemote(projectDir, accountId, apiToken, databaseName, previ
|
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
logger.debug("Push Preview Result (server):", results);
|
|
104
105
|
return { success: true, preview: true, applied: results.applied.length, skipped: results.skipped.length, details: results };
|
|
105
106
|
} catch (error) {
|
|
106
107
|
throw {
|
|
@@ -157,7 +158,7 @@ export async function POST(req) {
|
|
|
157
158
|
details: result
|
|
158
159
|
});
|
|
159
160
|
} catch (error) {
|
|
160
|
-
|
|
161
|
+
logger.error('Push to remote preview error:', error);
|
|
161
162
|
return NextResponse.json({
|
|
162
163
|
success: false,
|
|
163
164
|
error: {
|
|
@@ -11,15 +11,19 @@ import {
|
|
|
11
11
|
import { handleSchemaChange } from '@/lib/migrations';
|
|
12
12
|
import { isSchemaChange } from '@/lib/sql-operations';
|
|
13
13
|
import { parseSQLError } from '@/lib/parse-sql-error';
|
|
14
|
+
import logger from '@/lib/logger';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* API POST handler to execute SQL queries against the configured D1 database.
|
|
17
18
|
*/
|
|
18
19
|
export async function POST(req) {
|
|
20
|
+
logger.logRequest('POST', '/api/query');
|
|
21
|
+
|
|
19
22
|
try {
|
|
20
23
|
// Ensure that the project directory is set.
|
|
21
24
|
const projectDir = process.env.D1_PROJECT_DIR;
|
|
22
25
|
if (!projectDir) {
|
|
26
|
+
logger.error('Project directory not configured');
|
|
23
27
|
return NextResponse.json(
|
|
24
28
|
{ error: 'Project directory not configured' },
|
|
25
29
|
{ status: 500 }
|
|
@@ -28,7 +32,10 @@ export async function POST(req) {
|
|
|
28
32
|
|
|
29
33
|
// Extract the SQL query from the request body.
|
|
30
34
|
const { query } = await req.json();
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
if (logger.shouldLog('debug')) {
|
|
37
|
+
logger.debug('Received query:', query);
|
|
38
|
+
}
|
|
32
39
|
|
|
33
40
|
if (!query?.trim()) {
|
|
34
41
|
return NextResponse.json(
|
|
@@ -40,6 +47,7 @@ export async function POST(req) {
|
|
|
40
47
|
// Retrieve the Wrangler configuration using the centralized helper.
|
|
41
48
|
const wranglerResult = await findWranglerConfig(projectDir);
|
|
42
49
|
if (!wranglerResult || !wranglerResult.config) {
|
|
50
|
+
logger.error('No Wrangler configuration file found');
|
|
43
51
|
return NextResponse.json(
|
|
44
52
|
{ success: false, error: { message: 'No Wrangler configuration file found' } },
|
|
45
53
|
{ status: 404 }
|
|
@@ -94,7 +102,7 @@ export async function POST(req) {
|
|
|
94
102
|
// Process schema changes and capture migrations.
|
|
95
103
|
// The handleSchemaChange helper is responsible for executing the DDL statements.
|
|
96
104
|
const migrations = await handleSchemaChange(projectDir, databaseName, statements);
|
|
97
|
-
console.log('Schema changes processed:', migrations);
|
|
105
|
+
// console.log('Schema changes processed:', migrations);
|
|
98
106
|
|
|
99
107
|
result = {
|
|
100
108
|
success: true,
|
|
@@ -127,7 +135,7 @@ export async function POST(req) {
|
|
|
127
135
|
return NextResponse.json(result);
|
|
128
136
|
|
|
129
137
|
} catch (error) {
|
|
130
|
-
|
|
138
|
+
logger.logError(error, 'query-route');
|
|
131
139
|
const parsedError = parseSQLError(error);
|
|
132
140
|
|
|
133
141
|
const statusCode =
|
|
@@ -5,6 +5,7 @@ import { promisify } from 'util';
|
|
|
5
5
|
import { exec } from 'child_process';
|
|
6
6
|
import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
7
7
|
import { dbQueue } from '@/lib/database-queue';
|
|
8
|
+
import logger from '@/lib/logger';
|
|
8
9
|
|
|
9
10
|
const execAsync = promisify(exec);
|
|
10
11
|
|
|
@@ -35,7 +36,7 @@ async function executeD1Query(command, projectDir, databaseName) {
|
|
|
35
36
|
const result = JSON.parse(stdout);
|
|
36
37
|
return result[0]?.results || [];
|
|
37
38
|
} catch (error) {
|
|
38
|
-
|
|
39
|
+
logger.error('Query execution error:', error);
|
|
39
40
|
throw error;
|
|
40
41
|
} finally {
|
|
41
42
|
isProcessing = false;
|
|
@@ -145,7 +146,7 @@ export async function GET(request, context) {
|
|
|
145
146
|
});
|
|
146
147
|
|
|
147
148
|
} catch (error) {
|
|
148
|
-
|
|
149
|
+
logger.error('Error handling request:', error);
|
|
149
150
|
return NextResponse.json({
|
|
150
151
|
success: false,
|
|
151
152
|
error: {
|
|
@@ -4,6 +4,7 @@ import { NextResponse } from 'next/server';
|
|
|
4
4
|
import { promisify } from 'util';
|
|
5
5
|
import { exec } from 'child_process';
|
|
6
6
|
import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
7
|
+
import logger from '@/lib/logger';
|
|
7
8
|
|
|
8
9
|
const execAsync = promisify(exec);
|
|
9
10
|
|
|
@@ -75,11 +76,13 @@ async function retryWithTimeout(fn, retries = 3, timeout = 1000) {
|
|
|
75
76
|
* It uses the Wrangler configuration (via findWranglerConfig) to determine the D1 database.
|
|
76
77
|
*/
|
|
77
78
|
export async function GET() {
|
|
79
|
+
logger.logRequest('GET', '/api/tables');
|
|
80
|
+
|
|
78
81
|
try {
|
|
79
82
|
const projectDir = process.env.D1_PROJECT_DIR;
|
|
80
83
|
|
|
81
84
|
if (!projectDir) {
|
|
82
|
-
|
|
85
|
+
logger.error('D1_PROJECT_DIR environment variable is not set');
|
|
83
86
|
return NextResponse.json(
|
|
84
87
|
{ error: 'Project directory not configured' },
|
|
85
88
|
{ status: 500 }
|
|
@@ -89,6 +92,7 @@ export async function GET() {
|
|
|
89
92
|
// Use the centralized helper to get Wrangler configuration
|
|
90
93
|
const wranglerResult = await findWranglerConfig(projectDir);
|
|
91
94
|
if (!wranglerResult || !wranglerResult.config) {
|
|
95
|
+
logger.error('No Wrangler configuration file found');
|
|
92
96
|
return NextResponse.json(
|
|
93
97
|
{ error: 'No Wrangler configuration file found in project directory' },
|
|
94
98
|
{ status: 404 }
|
|
@@ -138,7 +142,7 @@ export async function GET() {
|
|
|
138
142
|
});
|
|
139
143
|
|
|
140
144
|
} catch (error) {
|
|
141
|
-
|
|
145
|
+
logger.logError(error, 'tables-route');
|
|
142
146
|
|
|
143
147
|
// Enhanced error response for troubleshooting
|
|
144
148
|
const errorResponse = {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// app/api/update/route.js
|
|
2
|
+
import { NextResponse } from 'next/server';
|
|
3
|
+
import updateNotifier from 'update-notifier';
|
|
4
|
+
import pkg from '../../../../package.json' assert { type: 'json' };
|
|
5
|
+
|
|
6
|
+
export async function GET() {
|
|
7
|
+
// Check for updates (you might want to cache this result to avoid too many requests)
|
|
8
|
+
const notifier = updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 * 24 });
|
|
9
|
+
const update = notifier.update;
|
|
10
|
+
return NextResponse.json({ update });
|
|
11
|
+
}
|
package/dist/app/app/page.jsx
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// app/page.js
|
|
2
2
|
'use client'
|
|
3
3
|
|
|
4
|
+
import { useState } from 'react';
|
|
4
5
|
import { AppSidebar } from '../components/sidebar';
|
|
5
6
|
import { SQLEditor } from '../components/sql-editor';
|
|
6
7
|
import { TableView } from '../components/table-view';
|
|
7
|
-
import
|
|
8
|
+
import UpdateBanner from '@/components/update-banner';
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
export default function StudioPage() {
|
|
10
12
|
const [currentView, setCurrentView] = useState('sql-editor');
|
|
@@ -17,12 +19,16 @@ export default function StudioPage() {
|
|
|
17
19
|
|
|
18
20
|
return (
|
|
19
21
|
<div className="min-h-screen bg-background">
|
|
22
|
+
{/* notification banner at the top of the page */}
|
|
23
|
+
<UpdateBanner />
|
|
24
|
+
{/* sidebar */}
|
|
20
25
|
<AppSidebar
|
|
21
26
|
className="w-64 border-r"
|
|
22
27
|
currentView={currentView}
|
|
23
28
|
onNavigate={setCurrentView}
|
|
24
29
|
onTableSelect={handleTableSelect}
|
|
25
30
|
/>
|
|
31
|
+
{/* main content */}
|
|
26
32
|
<main className="ml-64 h-screen">
|
|
27
33
|
{currentView === 'sql-editor' && <SQLEditor />}
|
|
28
34
|
{currentView === 'table-view' && selectedTable && (
|
package/dist/d1-studio.js
CHANGED
|
@@ -12,8 +12,13 @@ import { createServer } from 'http';
|
|
|
12
12
|
import next from 'next';
|
|
13
13
|
import { findWranglerConfig } from '../src/lib/find-wrangler-config.js';
|
|
14
14
|
import logger from '../src/lib/logger.js';
|
|
15
|
+
import updateNotifier from 'update-notifier';
|
|
16
|
+
import pkg from '../package.json' assert { type: 'json' };
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
const notifier = updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 * 24 });
|
|
19
|
+
notifier.notify({ defer: false });
|
|
20
|
+
|
|
21
|
+
// Compute the absolute path of this file and its directory
|
|
17
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
23
|
const __dirname = dirname(__filename);
|
|
19
24
|
|
|
@@ -26,6 +31,70 @@ class LicenseError extends Error {
|
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
|
|
34
|
+
class StudioLicenseManager {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.licenseDir = join(homedir(), '.d1studio');
|
|
37
|
+
this.licensePath = join(this.licenseDir, 'license.json');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async checkLicenseFile() {
|
|
41
|
+
try {
|
|
42
|
+
const licenseData = JSON.parse(await readFile(this.licensePath, 'utf8'));
|
|
43
|
+
|
|
44
|
+
// If no end_date or subscription_status, the license is valid (perpetual license)
|
|
45
|
+
if (!licenseData.end_date || !licenseData.subscription_status) {
|
|
46
|
+
return {
|
|
47
|
+
licenseData,
|
|
48
|
+
isValid: true,
|
|
49
|
+
isExpiringSoon: false
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check subscription status first
|
|
54
|
+
if (licenseData.subscription_status !== 'active') {
|
|
55
|
+
return {
|
|
56
|
+
licenseData,
|
|
57
|
+
isValid: false,
|
|
58
|
+
isExpiringSoon: false
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const endDate = new Date(licenseData.end_date);
|
|
63
|
+
const now = new Date();
|
|
64
|
+
|
|
65
|
+
// Check if subscription has ended
|
|
66
|
+
if (endDate < now) {
|
|
67
|
+
return {
|
|
68
|
+
licenseData,
|
|
69
|
+
isValid: false,
|
|
70
|
+
isExpiringSoon: false
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check if subscription ends in next 7 days
|
|
75
|
+
const sevenDaysFromNow = new Date(now.getTime() + (7 * 24 * 60 * 60 * 1000));
|
|
76
|
+
const isExpiringSoon = endDate <= sevenDaysFromNow;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
licenseData,
|
|
80
|
+
isValid: true,
|
|
81
|
+
isExpiringSoon
|
|
82
|
+
};
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async saveLicenseFile(licenseData) {
|
|
89
|
+
try {
|
|
90
|
+
await mkdir(this.licenseDir, { recursive: true });
|
|
91
|
+
await writeFile(this.licensePath, JSON.stringify(licenseData, null, 2));
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new LicenseError('Failed to save license information', 'SAVE_ERROR');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
29
98
|
async function generateHardwareId() {
|
|
30
99
|
const osInfo = {
|
|
31
100
|
platform: process.platform,
|
|
@@ -60,13 +129,6 @@ async function validateLicenseRemote(licenseKey, email, hardwareId) {
|
|
|
60
129
|
);
|
|
61
130
|
}
|
|
62
131
|
|
|
63
|
-
if (result.end_date && new Date(result.end_date) < new Date()) {
|
|
64
|
-
throw new LicenseError(
|
|
65
|
-
'Your subscription has expired. Please renew your license to continue using D1 Studio.',
|
|
66
|
-
'SUBSCRIPTION_EXPIRED'
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
132
|
return result;
|
|
71
133
|
} catch (error) {
|
|
72
134
|
if (error instanceof LicenseError) {
|
|
@@ -87,35 +149,6 @@ async function validateLicenseRemote(licenseKey, email, hardwareId) {
|
|
|
87
149
|
}
|
|
88
150
|
}
|
|
89
151
|
|
|
90
|
-
async function checkLicenseFile() {
|
|
91
|
-
const licenseDir = join(homedir(), '.d1studio');
|
|
92
|
-
const licensePath = join(licenseDir, 'license.json');
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
const licenseData = JSON.parse(await readFile(licensePath, 'utf8'));
|
|
96
|
-
const hardwareId = await generateHardwareId();
|
|
97
|
-
|
|
98
|
-
if (licenseData.hardwareId !== hardwareId) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
return licenseData;
|
|
102
|
-
} catch (error) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function saveLicenseFile(licenseData) {
|
|
108
|
-
const licenseDir = join(homedir(), '.d1studio');
|
|
109
|
-
const licensePath = join(licenseDir, 'license.json');
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
await mkdir(licenseDir, { recursive: true });
|
|
113
|
-
await writeFile(licensePath, JSON.stringify(licenseData, null, 2));
|
|
114
|
-
} catch (error) {
|
|
115
|
-
throw new LicenseError('Failed to save license information', 'SAVE_ERROR');
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
152
|
async function startServer(port, projectDirectory) {
|
|
120
153
|
return new Promise((resolvePromise, rejectPromise) => {
|
|
121
154
|
// Determine Next.js app directory based on environment:
|
|
@@ -170,20 +203,14 @@ async function startStudio() {
|
|
|
170
203
|
try {
|
|
171
204
|
logger.info(chalk.green('Initializing D1 Studio...'));
|
|
172
205
|
|
|
173
|
-
|
|
174
|
-
let licenseData = await checkLicenseFile();
|
|
175
|
-
logger.debug(chalk.blue(`License data found: ${JSON.stringify(licenseData)}`));
|
|
176
|
-
|
|
177
|
-
const TWELVE_HOURS_MS = 43200000; // 12 hours
|
|
178
|
-
let shouldRevalidate = true;
|
|
179
|
-
if (licenseData) {
|
|
180
|
-
const lastCheck = new Date(licenseData.lastValidatedAt || licenseData.activatedAt);
|
|
181
|
-
if (Date.now() - lastCheck.getTime() < TWELVE_HOURS_MS) {
|
|
182
|
-
shouldRevalidate = false;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
206
|
+
const licenseManager = new StudioLicenseManager();
|
|
185
207
|
|
|
186
|
-
|
|
208
|
+
// Check existing license
|
|
209
|
+
const licenseCheck = await licenseManager.checkLicenseFile();
|
|
210
|
+
|
|
211
|
+
// Handle license validation
|
|
212
|
+
if (!licenseCheck || !licenseCheck.isValid) {
|
|
213
|
+
// Prompt for license information if needed
|
|
187
214
|
const { default: inquirer } = await import('inquirer');
|
|
188
215
|
logger.info(chalk.yellow('\nPlease enter your D1 Studio license information:'));
|
|
189
216
|
|
|
@@ -205,9 +232,8 @@ async function startStudio() {
|
|
|
205
232
|
},
|
|
206
233
|
]);
|
|
207
234
|
|
|
208
|
-
logger.debug(chalk.blue(`Entered license information: ${JSON.stringify(answers)}`));
|
|
209
|
-
|
|
210
235
|
const hardwareId = await generateHardwareId();
|
|
236
|
+
|
|
211
237
|
try {
|
|
212
238
|
const validation = await validateLicenseRemote(
|
|
213
239
|
answers.licenseKey,
|
|
@@ -215,19 +241,29 @@ async function startStudio() {
|
|
|
215
241
|
hardwareId
|
|
216
242
|
);
|
|
217
243
|
|
|
218
|
-
|
|
244
|
+
// Save the complete validation response
|
|
245
|
+
await licenseManager.saveLicenseFile({
|
|
219
246
|
licenseKey: answers.licenseKey,
|
|
220
247
|
email: answers.email,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
248
|
+
hardwareId,
|
|
249
|
+
end_date: validation.end_date,
|
|
250
|
+
subscription_status: validation.subscription_status,
|
|
251
|
+
type: validation.licenseType,
|
|
252
|
+
activatedAt: new Date().toISOString()
|
|
253
|
+
});
|
|
224
254
|
|
|
225
|
-
await saveLicenseFile(licenseData);
|
|
226
255
|
logger.info(chalk.green('\nLicense activated successfully!'));
|
|
227
256
|
} catch (error) {
|
|
228
257
|
logger.error(chalk.red(`\nLicense validation failed: ${error.message}`));
|
|
229
258
|
process.exit(1);
|
|
230
259
|
}
|
|
260
|
+
} else if (licenseCheck.isExpiringSoon) {
|
|
261
|
+
// Show warning about expiring subscription
|
|
262
|
+
const endDate = new Date(licenseCheck.licenseData.end_date).toLocaleDateString();
|
|
263
|
+
logger.warn(chalk.yellow(`
|
|
264
|
+
⚠️ Your subscription will expire on ${endDate}
|
|
265
|
+
Please renew your subscription at https://d1-studio.com to continue using D1 Studio.
|
|
266
|
+
`));
|
|
231
267
|
}
|
|
232
268
|
|
|
233
269
|
// Get wrangler configuration
|
|
@@ -317,4 +353,4 @@ process.on('SIGTERM', () => {
|
|
|
317
353
|
startStudio().catch((error) => {
|
|
318
354
|
logger.error(chalk.red(`\nFailed to start D1 Studio: ${error}`));
|
|
319
355
|
process.exit(1);
|
|
320
|
-
});
|
|
356
|
+
});
|
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
// utils/database-queue.js
|
|
2
|
+
|
|
3
|
+
import logger from '@/lib/logger.js';
|
|
4
|
+
|
|
2
5
|
class DatabaseQueue {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
constructor() {
|
|
7
|
+
this.queue = [];
|
|
8
|
+
this.isProcessing = false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async add(operation) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
this.queue.push({ operation, resolve, reject });
|
|
14
|
+
this.processNext();
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async processNext() {
|
|
19
|
+
if (this.isProcessing || this.queue.length === 0) return;
|
|
20
|
+
|
|
21
|
+
this.isProcessing = true;
|
|
22
|
+
const { operation, resolve, reject } = this.queue.shift();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const result = await operation();
|
|
26
|
+
resolve(result);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
logger.error('Error processing database queue operation:', error);
|
|
29
|
+
reject(error);
|
|
30
|
+
} finally {
|
|
31
|
+
this.isProcessing = false;
|
|
32
|
+
this.processNext();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
7
36
|
|
|
8
|
-
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
this.queue.push({ operation, resolve, reject });
|
|
11
|
-
this.processNext();
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async processNext() {
|
|
16
|
-
if (this.isProcessing || this.queue.length === 0) return;
|
|
17
|
-
|
|
18
|
-
this.isProcessing = true;
|
|
19
|
-
const { operation, resolve, reject } = this.queue.shift();
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const result = await operation();
|
|
23
|
-
resolve(result);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
reject(error);
|
|
26
|
-
} finally {
|
|
27
|
-
this.isProcessing = false;
|
|
28
|
-
this.processNext();
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const dbQueue = new DatabaseQueue();
|
|
37
|
+
export const dbQueue = new DatabaseQueue();
|