create-cloud-db 1.0.2 → 1.0.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,4 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- ### [1.0.2](https://github.com/vtempest/Svelte-Starter-DOCS/compare/v1.0.1...v1.0.2) (2025-12-22)
6
-
7
- ### [1.0.1](https://github.com/vtempest/Svelte-Starter-DOCS/compare/v0.9.2...v1.0.1) (2025-12-22)
5
+ ### [1.0.3](https://github.com/vtempest/Svelte-Starter-DOCS/compare/v1.0.2...v1.0.3) (2025-12-22)
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # create-cloud-db
2
+
3
+ `create-cloud-db` is a small CLI that creates a Turso database and manages the `TURSO_DATABASE_URL` and `TURSO_AUTH_TOKEN` values in your local `.env` file.
4
+
5
+ It is designed for quick local setup so you can be ready to connect from Node, frameworks, or serverless environments with minimal manual configuration.
6
+
7
+ ## Installation
8
+
9
+ You must first login to turso with:
10
+
11
+ ```bash
12
+ bun i -g turso
13
+ turso auth login
14
+
15
+ # or
16
+ bun x turso auth login
17
+ ```
18
+
19
+ Then run:
20
+
21
+ ```bash
22
+ # will ask for name
23
+ npx create-cloud-db
24
+
25
+ npx create-cloud-db [myapp-db]
26
+ ```
27
+
28
+ Or install globally:
29
+
30
+ ```bash
31
+ npm install -g create-cloud-db
32
+ create-cloud-db myapp-db
33
+ ```
34
+
35
+ ## What it does
36
+
37
+ When you run the command, the CLI:
38
+
39
+ 1. Ensures you are logged into Turso via `turso auth login`.
40
+ 2. Creates a Turso database if it does not already exist.
41
+ 3. Generates a database URL and an auth token via the Turso CLI.
42
+ 4. Overwrites (not appends) the `TURSO_DATABASE_URL` and `TURSO_AUTH_TOKEN` entries in your local `.env` file.
43
+
44
+ After running, your `.env` file will contain something like:
45
+
46
+ ```env
47
+ TURSO_DATABASE_URL=libsql://your-db-name.region.turso.io
48
+ TURSO_AUTH_TOKEN=eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...
49
+ ```
50
+
51
+ ## Add to package.json
52
+
53
+ ```json
54
+ "db:create": "create-cloud-db",
55
+ "db:generate": "drizzle-kit generate",
56
+ "db:push": "drizzle-kit push",
57
+ "db:studio": "drizzle-kit studio",
58
+ ```
59
+
60
+ ## Environment file behavior
61
+
62
+ - The CLI reads your existing `.env` file if present.
63
+ - It updates or inserts `TURSO_DATABASE_URL` and `TURSO_AUTH_TOKEN` keys.
64
+ - The `.env` file is rewritten, so old placeholder values are removed and replaced with valid values.
65
+
66
+ ### Example with Drizzle
67
+
68
+ ```ts
69
+ // drizzle.config.ts
70
+
71
+ import { defineConfig } from 'drizzle-kit';
72
+
73
+ export default defineConfig({
74
+ dialect: 'turso',
75
+ schema: './src/lib/db/schema.ts',
76
+ out: './drizzle',
77
+ dbCredentials: {
78
+ url: process.env.TURSO_DATABASE_URL || 'file:./localdb.sqlite',
79
+ authToken: process.env.TURSO_AUTH_TOKEN,
80
+ },
81
+ });
82
+ ```
83
+
84
+ ## 📝 License
85
+
86
+ MIT License - Star this repo so it can grow features! 🌟
@@ -53,38 +53,69 @@ async function ensureLogin() {
53
53
  }
54
54
  }
55
55
 
56
- // Parse env file into plain object
56
+ // Parse env file into array of line objects to preserve comments/whitespace
57
57
  function readEnvFile(filePath) {
58
- if (!fs.existsSync(filePath)) return {};
58
+ if (!fs.existsSync(filePath)) return [];
59
59
  const content = fs.readFileSync(filePath, "utf8");
60
60
  const lines = content.split(/\r?\n/);
61
61
 
62
- const env = {};
63
- for (const line of lines) {
62
+ return lines.map((line) => {
64
63
  const trimmed = line.trim();
65
- if (!trimmed || trimmed.startsWith("#")) continue;
64
+
65
+ // Blank line
66
+ if (!trimmed) {
67
+ return { type: 'blank', line };
68
+ }
69
+
70
+ // Comment line
71
+ if (trimmed.startsWith("#")) {
72
+ return { type: 'comment', line };
73
+ }
74
+
75
+ // Key-value pair
66
76
  const idx = trimmed.indexOf("=");
67
- if (idx === -1) continue;
77
+ if (idx === -1) {
78
+ return { type: 'other', line };
79
+ }
80
+
68
81
  const key = trimmed.slice(0, idx).trim();
69
82
  let value = trimmed.slice(idx + 1).trim();
83
+
84
+ // Remove quotes from value if present
70
85
  if (
71
86
  (value.startsWith('"') && value.endsWith('"')) ||
72
87
  (value.startsWith("'") && value.endsWith("'"))
73
88
  ) {
74
89
  value = value.slice(1, -1);
75
90
  }
76
- env[key] = value;
77
- }
78
- return env;
91
+
92
+ return { type: 'keyvalue', key, value, line };
93
+ });
79
94
  }
80
95
 
81
- // Write env object back to file, overwriting file completely
82
- function writeEnvFile(filePath, envObj) {
83
- const lines = [];
84
- for (const [key, value] of Object.entries(envObj)) {
85
- lines.push(`${key}=${value}`);
96
+ // Write env array back to file, preserving comments and blank lines
97
+ function writeEnvFile(filePath, lineArray, updates) {
98
+ const updatedLines = lineArray.map((item) => {
99
+ // If this is a key-value pair and we have an update for it
100
+ if (item.type === 'keyvalue' && updates[item.key] !== undefined) {
101
+ return `${item.key}=${updates[item.key]}`;
102
+ }
103
+ // Otherwise, preserve the original line
104
+ return item.line;
105
+ });
106
+
107
+ // Add any new keys that weren't in the original file
108
+ const existingKeys = new Set(
109
+ lineArray.filter(item => item.type === 'keyvalue').map(item => item.key)
110
+ );
111
+
112
+ for (const [key, value] of Object.entries(updates)) {
113
+ if (!existingKeys.has(key)) {
114
+ updatedLines.push(`${key}=${value}`);
115
+ }
86
116
  }
87
- fs.writeFileSync(filePath, lines.join("\n") + "\n");
117
+
118
+ fs.writeFileSync(filePath, updatedLines.join("\n") + "\n");
88
119
  }
89
120
 
90
121
  async function main() {
@@ -100,9 +131,17 @@ async function main() {
100
131
  process.exit(1);
101
132
  }
102
133
 
103
- // Load existing .env into object
134
+ // Load existing .env into line array
104
135
  const envPath = path.join(process.cwd(), ".env");
105
- const envObj = readEnvFile(envPath);
136
+ const envLines = readEnvFile(envPath);
137
+
138
+ // Extract current values from line array
139
+ const envObj = {};
140
+ envLines.forEach(item => {
141
+ if (item.type === 'keyvalue') {
142
+ envObj[item.key] = item.value;
143
+ }
144
+ });
106
145
 
107
146
  const existingUrl = envObj.TURSO_DATABASE_URL || process.env.TURSO_DATABASE_URL;
108
147
  const existingToken = envObj.TURSO_AUTH_TOKEN || process.env.TURSO_AUTH_TOKEN;
@@ -137,8 +176,8 @@ async function main() {
137
176
  process.env.TURSO_DATABASE_URL = dbUrl;
138
177
  process.env.TURSO_AUTH_TOKEN = authToken;
139
178
 
140
- // Overwrite .env with updated values (no duplicates, no stale not logged in values)
141
- writeEnvFile(envPath, envObj);
179
+ // Overwrite .env with updated values (no duplicates, no stale "not logged in" values)
180
+ writeEnvFile(envPath, envLines, envObj);
142
181
 
143
182
  console.log("\nUpdated Turso environment variables (overwritten in .env):");
144
183
  console.log(`TURSO_DATABASE_URL=${process.env.TURSO_DATABASE_URL}`);
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "create-cloud-db",
3
- "description": "CLI to create a Turso database and manage TURSO_* env vars",
3
+ "description": "CLI to create a Turso database and write TURSO_* env vars to .env file",
4
4
  "type": "module",
5
5
  "author": "vtempest",
6
- "version": "1.0.2",
6
+ "version": "1.0.3",
7
7
  "main": "create-cloud-db.js",
8
8
  "bin": {
9
9
  "create-cloud-db": "./create-cloud-db.js"
package/.env DELETED
@@ -1,6 +0,0 @@
1
-
2
- TURSO_DATABASE_URL=You are not logged in, please login with turso auth login before running other commands.
3
- TURSO_AUTH_TOKEN=You are not logged in, please login with turso auth login before running other commands.
4
-
5
- TURSO_DATABASE_URL=libsql://lol-xfreestar10.aws-us-west-2.turso.io
6
- TURSO_AUTH_TOKEN=eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjYzNzYwNjEsImlkIjoiNDUyY2M2NzUtODk2Ny00Njc5LTk4MTItNTA2MGY1YmEyMDljIiwicmlkIjoiZjdkMWFhZTMtYzEzZC00OTEyLWFjYTAtNWRkY2Y5MTZkOWI5In0.loooOtvg-8fYzl_bi032Y32KGdDjOZhbKXdGFQLfrzt7Jbu9vDLY9I8KrUtOPprRFRrCHExXkfQtIg6xmt_XCg