create-feltdb 0.4.5 → 0.4.9

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 CHANGED
@@ -19,7 +19,8 @@ npx --yes create-feltdb@latest my-app --yes
19
19
 
20
20
  ### Options
21
21
 
22
- - `--runtime <browser|node|self-hosted>`
22
+ - `--runtime <browser|node|self-hosted|managed>`
23
+ - `--managed` — connect the app and Studio to a managed FeltDB endpoint
23
24
  - `--framework <react|vanilla>`
24
25
  - `--no-distributed`
25
26
  - `--no-agents`
package/dist/cli.js CHANGED
@@ -10,6 +10,7 @@ import readline from 'readline';
10
10
  import { spawn } from 'child_process';
11
11
  import { createProject } from './create.js';
12
12
  import { FELTDB_PACKAGE_VERSION } from './package-versions.js';
13
+ import { configureManagedAccount } from './managed-account.js';
13
14
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
15
  function parseArgs(args) {
15
16
  const options = {
@@ -21,6 +22,18 @@ function parseArgs(args) {
21
22
  };
22
23
  for (let i = 0; i < args.length; i++) {
23
24
  switch (args[i]) {
25
+ case '--browser':
26
+ options.runtime = 'browser';
27
+ break;
28
+ case '--server':
29
+ options.runtime = 'node';
30
+ break;
31
+ case '--self-host':
32
+ options.runtime = 'self-hosted';
33
+ break;
34
+ case '--managed':
35
+ options.runtime = 'managed';
36
+ break;
24
37
  case '--runtime':
25
38
  options.runtime = args[++i];
26
39
  break;
@@ -49,6 +62,38 @@ function run(command, args, cwd) {
49
62
  : reject(new Error(`${command} exited with status ${code ?? 'unknown'}`)));
50
63
  });
51
64
  }
65
+ async function prompt(message) {
66
+ const interface_ = readline.createInterface({ input: process.stdin, output: process.stdout });
67
+ return new Promise(resolve => interface_.question(message, value => { interface_.close(); resolve(value.trim()); }));
68
+ }
69
+ async function promptSecret(message) {
70
+ if (!process.stdin.isTTY || !process.stdout.isTTY)
71
+ return '';
72
+ const input = process.stdin;
73
+ const output = process.stdout;
74
+ const wasRaw = input.isRaw;
75
+ readline.emitKeypressEvents(input);
76
+ input.setRawMode(true);
77
+ input.resume();
78
+ output.write(message);
79
+ return new Promise(resolve => {
80
+ let value = '';
81
+ const finish = () => { input.off('keypress', onKeypress); input.setRawMode(Boolean(wasRaw)); input.pause(); output.write('\n'); resolve(value); };
82
+ const onKeypress = (character, key) => {
83
+ if (key.ctrl && key.name === 'c')
84
+ process.exit(130);
85
+ if (key.name === 'return' || key.name === 'enter')
86
+ return finish();
87
+ if (key.name === 'backspace') {
88
+ value = value.slice(0, -1);
89
+ return;
90
+ }
91
+ if (!key.ctrl && !key.meta && character)
92
+ value += character;
93
+ };
94
+ input.on('keypress', onKeypress);
95
+ });
96
+ }
52
97
  async function select(message, choices, initialValue) {
53
98
  let selected = Math.max(0, choices.findIndex(choice => choice.value === initialValue));
54
99
  const input = process.stdin;
@@ -108,6 +153,7 @@ async function promptForOptions(defaults) {
108
153
  { label: 'Browser', value: 'browser', description: 'local-first with durable browser storage' },
109
154
  { label: 'Node.js', value: 'node', description: 'application server or worker' },
110
155
  { label: 'Self-hosted', value: 'self-hosted', description: 'dedicated FeltDB server' },
156
+ { label: 'Managed', value: 'managed', description: 'FeltDB-hosted persistence, sync, and workloads' },
111
157
  ], defaults.runtime),
112
158
  framework: await select('Choose an application framework:', [
113
159
  { label: 'React', value: 'react' },
@@ -125,7 +171,59 @@ async function promptForOptions(defaults) {
125
171
  async function main() {
126
172
  const args = process.argv.slice(2);
127
173
  if (args.includes('--help') || args.includes('-h')) {
128
- console.log(`create-feltdb ${FELTDB_PACKAGE_VERSION}\n\nUsage: create-feltdb [project-name] [options]\n\nOptions:\n --runtime <browser|node|self-hosted>\n --framework <react|vanilla>\n --no-distributed\n --no-agents\n --capabilities <list>\n --no-install\n --no-start\n -y, --yes\n -h, --help\n --version`);
174
+ console.log(`create-feltdb ${FELTDB_PACKAGE_VERSION}
175
+
176
+ Create a new FeltDB application with one command.
177
+
178
+ Usage:
179
+ create-feltdb [project-name] [options]
180
+
181
+ Examples:
182
+ create-feltdb my-app
183
+ create-feltdb my-app --browser
184
+ create-feltdb my-app --server
185
+ create-feltdb my-app --self-host
186
+ create-feltdb my-app --managed
187
+ create-feltdb my-app --framework react --yes
188
+
189
+ Deployment Target (Explicit):
190
+ --browser Local-first with durable browser storage (IndexedDB)
191
+ Best for: Client-side apps, offline-first experiences
192
+ No server required, full offline capability
193
+
194
+ --server Node.js server runtime with server-side FeltDB authority
195
+ Best for: Server-side applications, API servers
196
+ Requires production FeltDB instance or self-host
197
+
198
+ --self-host Dedicated FeltDB server with Docker Compose
199
+ Best for: Production deployments, multi-user systems
200
+ Generates Docker Compose with persistent /data volume
201
+
202
+ --managed Managed FeltDB runtime
203
+ Best for: Production without operating servers
204
+ Requires VITE_FELTDB_URL and VITE_FELTDB_API_KEY
205
+
206
+ Options:
207
+ --browser Explicit: Browser runtime with IndexedDB
208
+ --server Explicit: Node.js server runtime
209
+ --self-host Explicit: Self-hosted with Docker Compose
210
+ --managed Explicit: Managed FeltDB service
211
+ --runtime <runtime> Alternative: Set runtime (browser, node, self-hosted, managed)
212
+ --framework <framework> Choose framework: react or vanilla (default: react)
213
+ --no-distributed Disable distributed operation
214
+ --no-agents Exclude agent examples
215
+ --capabilities <list> Choose capabilities: search, vector, or search,vector
216
+ --no-install Skip npm install
217
+ --no-start Skip npm run dev
218
+ -y, --yes Use all defaults (non-interactive mode)
219
+ -h, --help Show this help message
220
+ --version Show version number
221
+
222
+ Environment Variables:
223
+ FELTDB_IMAGE Override the default self-hosted container image
224
+ NODE_ENV Set to 'development' or 'production'
225
+
226
+ Learn more: https://github.com/rkendel1/feltdb`);
129
227
  return;
130
228
  }
131
229
  if (args.includes('--version')) {
@@ -149,16 +247,31 @@ async function main() {
149
247
  const shouldInstall = !args.includes('--no-install');
150
248
  const shouldStart = !args.includes('--no-start');
151
249
  let options = parseArgs(args);
250
+ const runtimeDescriptions = {
251
+ 'browser': 'Browser with IndexedDB (local-first, no server)',
252
+ 'node': 'Node.js server (server-side authority)',
253
+ 'self-hosted': 'Self-hosted with Docker Compose (production)',
254
+ 'managed': 'Managed FeltDB service (hosted persistence, sync, and workloads)',
255
+ };
256
+ if (!runtimeDescriptions[options.runtime]) {
257
+ throw new Error(`Unsupported runtime "${options.runtime}". Choose browser, node, self-hosted, or managed.`);
258
+ }
152
259
  console.log('\n✨ Creating FeltDB Application\n');
153
260
  if (!shouldAutoYes) {
154
261
  options = await promptForOptions(options);
155
- console.log('\nConfiguration:');
156
- console.log(` Runtime: ${options.runtime}`);
157
- console.log(` Framework: ${options.framework}`);
158
- console.log(` Distributed: ${options.distributed ? 'yes' : 'no'}`);
159
- console.log(` Agents: ${options.agents ? 'yes' : 'no'}`);
160
- console.log(` Capabilities: ${options.capabilities}\n`);
161
262
  }
263
+ // Display the deployment target explicitly
264
+ console.log('\n═══════════════════════════════════════════════');
265
+ console.log('📦 DEPLOYMENT TARGET');
266
+ console.log('═══════════════════════════════════════════════');
267
+ console.log(`\nRuntime: ${options.runtime.toUpperCase()}`);
268
+ console.log(`Description: ${runtimeDescriptions[options.runtime]}`);
269
+ console.log(`Framework: ${options.framework}`);
270
+ console.log(`Distributed: ${options.distributed ? 'yes' : 'no'}`);
271
+ console.log(`Agents: ${options.agents ? 'yes' : 'no'}`);
272
+ console.log(`Capabilities: ${options.capabilities}`);
273
+ console.log('\n═══════════════════════════════════════════════\n');
274
+ const projectDir = path.resolve(process.cwd(), projectName);
162
275
  try {
163
276
  await createProject({
164
277
  projectName,
@@ -170,8 +283,18 @@ async function main() {
170
283
  agents: options.agents,
171
284
  capabilities: options.capabilities,
172
285
  });
286
+ if (options.runtime === 'managed') {
287
+ console.log('\n☁️ Setting up your managed FeltDB account...\n');
288
+ const email = process.env.FELTDB_MANAGED_EMAIL || (shouldAutoYes ? '' : await prompt('Email: '));
289
+ const password = process.env.FELTDB_MANAGED_PASSWORD || (shouldAutoYes ? '' : await promptSecret('Password (8+ characters): '));
290
+ if (!email || password.length < 8) {
291
+ throw new Error('Managed setup needs an email and an 8+ character password. In non-interactive mode set FELTDB_MANAGED_EMAIL and FELTDB_MANAGED_PASSWORD.');
292
+ }
293
+ const managed = await configureManagedAccount({ projectDir, applicationName: projectName, namespace: projectName, email, password });
294
+ console.log(`✓ Managed application: ${managed.application.name}`);
295
+ console.log(`✓ Managed environment written to ${projectName}/.env.local`);
296
+ }
173
297
  console.log('\n✅ FeltDB application created successfully!\n');
174
- const projectDir = path.resolve(process.cwd(), projectName);
175
298
  const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
176
299
  if (shouldInstall) {
177
300
  console.log('📦 Installing application, Studio, and local AI dependencies...\n');