@feltdb/core 0.4.13 → 0.4.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands.js +38 -24
- package/dist/cli/index.js +1 -1
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +11 -5
- package/dist/create/cli.js +23 -3
- package/dist/create/create.js +4 -6
- package/dist/create/docker-compose-generator.js +23 -5
- package/dist/create/package-versions.js +1 -1
- package/dist/feltdb.d.ts +1 -1
- package/dist/feltdb.d.ts.map +1 -1
- package/dist/indexeddb-db.d.ts +20 -1
- package/dist/indexeddb-db.d.ts.map +1 -1
- package/dist/indexeddb-db.js +167 -26
- package/dist/studio/components/ConflictExplorer.d.ts.map +1 -1
- package/dist/studio/components/index.js +1 -1
- package/dist/studio/{components-bHTARBin.js → components-9kDSWiGL.js} +7 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio-app/assets/{feltdb_wasm-Bb1Pg6qz.js → feltdb_wasm-CJEJryDx.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-BJxQXtoo.wasm +0 -0
- package/dist/studio-app/assets/{index-BqKquLuU.js → index-D_p8T7nO.js} +2 -2
- package/dist/studio-app/index.html +1 -1
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-2_wVudcZ.wasm +0 -0
package/dist/cli/commands.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import http from 'http';
|
|
7
|
+
import net from 'net';
|
|
7
8
|
import { createRequire } from 'module';
|
|
8
9
|
import { spawn, spawnSync } from 'child_process';
|
|
9
10
|
import { createFeltDB, diffFlowSpec, formatFlowSpec, parseFlowSpec, planFlowSpecMigration, validateFlowSpec } from '@feltdb/core';
|
|
10
|
-
const RELEASE_VERSION = '0.4.13';
|
|
11
11
|
function loadProjectEnvironment(file = path.resolve('.env.local')) {
|
|
12
12
|
if (!fs.existsSync(file))
|
|
13
13
|
return;
|
|
@@ -24,6 +24,19 @@ function loadProjectEnvironment(file = path.resolve('.env.local')) {
|
|
|
24
24
|
process.env[key] = value;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
async function availablePort(preferred, host = '127.0.0.1') {
|
|
28
|
+
for (let port = preferred; port < preferred + 100; port += 1) {
|
|
29
|
+
const available = await new Promise(resolve => {
|
|
30
|
+
const server = net.createServer();
|
|
31
|
+
server.unref();
|
|
32
|
+
server.once('error', () => resolve(false));
|
|
33
|
+
server.listen(port, host, () => server.close(() => resolve(true)));
|
|
34
|
+
});
|
|
35
|
+
if (available)
|
|
36
|
+
return port;
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`No available port found between ${preferred} and ${preferred + 99}`);
|
|
39
|
+
}
|
|
27
40
|
export async function handleCommand(command, args) {
|
|
28
41
|
switch (command) {
|
|
29
42
|
case 'studio':
|
|
@@ -387,35 +400,36 @@ async function handleDev(args) {
|
|
|
387
400
|
const runtimeNamespace = config.runtime === 'managed'
|
|
388
401
|
? process.env.VITE_FELTDB_MANAGED_NAMESPACE || config.namespace
|
|
389
402
|
: config.namespace;
|
|
390
|
-
const
|
|
391
|
-
const
|
|
392
|
-
|
|
403
|
+
const requestedAppPort = Number(args.includes('--port') ? args[args.indexOf('--port') + 1] || '5173' : '5173');
|
|
404
|
+
const requestedStudioPort = Number(args.includes('--studio-port') ? args[args.indexOf('--studio-port') + 1] || '3000' : '3000');
|
|
405
|
+
const appPort = String(await availablePort(requestedAppPort));
|
|
406
|
+
const studioPort = String(await availablePort(requestedStudioPort));
|
|
407
|
+
if (appPort !== String(requestedAppPort))
|
|
408
|
+
console.log(`Port ${requestedAppPort} is busy; using ${appPort} for the application.`);
|
|
409
|
+
if (studioPort !== String(requestedStudioPort))
|
|
410
|
+
console.log(`Port ${requestedStudioPort} is busy; using ${studioPort} for Studio.`);
|
|
411
|
+
process.env.APP_PORT = appPort;
|
|
412
|
+
process.env.STUDIO_PORT = studioPort;
|
|
413
|
+
let selfHostedStarted = false;
|
|
393
414
|
const stopSelfHosted = () => {
|
|
394
|
-
if (
|
|
395
|
-
|
|
415
|
+
if (selfHostedStarted) {
|
|
416
|
+
spawnSync('docker', ['compose', 'stop', 'feltdb'], { cwd: process.cwd(), stdio: 'ignore' });
|
|
417
|
+
selfHostedStarted = false;
|
|
418
|
+
}
|
|
396
419
|
};
|
|
397
420
|
if (config.runtime === 'self-hosted') {
|
|
398
421
|
const docker = spawnSync('docker', ['version'], { stdio: 'ignore' });
|
|
399
422
|
if (docker.status !== 0) {
|
|
400
423
|
throw new Error('Self-hosted development requires Docker Desktop or Docker Engine. Install Docker, start it, and rerun npm run dev.');
|
|
401
424
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
'-v', `${containerName}-data:/data`,
|
|
411
|
-
image,
|
|
412
|
-
'--allow-origin', `http://127.0.0.1:${appPort}`,
|
|
413
|
-
'--allow-origin', `http://127.0.0.1:${studioPort}`,
|
|
414
|
-
], { stdio: 'inherit' });
|
|
415
|
-
selfHosted.once('exit', code => {
|
|
416
|
-
if (code && code !== 0)
|
|
417
|
-
console.error(`Self-hosted FeltDB server exited with status ${code}`);
|
|
418
|
-
});
|
|
425
|
+
if (!fs.existsSync(path.join(process.cwd(), 'docker-compose.yml'))) {
|
|
426
|
+
throw new Error('Self-hosted project is missing docker-compose.yml. Regenerate the project with create-feltdb.');
|
|
427
|
+
}
|
|
428
|
+
console.log('Building and starting the generated self-hosted FeltDB service...');
|
|
429
|
+
const compose = spawnSync('docker', ['compose', 'up', '--build', '--detach', 'feltdb'], { cwd: process.cwd(), stdio: 'inherit' });
|
|
430
|
+
if (compose.status !== 0)
|
|
431
|
+
throw new Error(`docker compose failed with status ${compose.status ?? 'unknown'}`);
|
|
432
|
+
selfHostedStarted = true;
|
|
419
433
|
(_c = process.env).VITE_FELTDB_URL || (_c.VITE_FELTDB_URL = 'http://127.0.0.1:7700');
|
|
420
434
|
}
|
|
421
435
|
console.log('FeltDB Dev Server');
|
|
@@ -426,7 +440,7 @@ async function handleDev(args) {
|
|
|
426
440
|
const open = !args.includes('--no-open');
|
|
427
441
|
console.log(`Application: http://127.0.0.1:${appPort}`);
|
|
428
442
|
console.log(`Studio: http://127.0.0.1:${studioPort}\n`);
|
|
429
|
-
const viteArgs = ['--host', '127.0.0.1', '--port', appPort, ...(open ? ['--open'] : [])];
|
|
443
|
+
const viteArgs = ['--host', '127.0.0.1', '--port', appPort, '--strictPort', ...(open ? ['--open'] : [])];
|
|
430
444
|
const vite = runLocalVite(viteArgs, false);
|
|
431
445
|
let shuttingDown = false;
|
|
432
446
|
const stopVite = () => { if (!vite.killed)
|
package/dist/cli/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import * as path from 'path';
|
|
|
23
23
|
import * as readline from 'readline';
|
|
24
24
|
import { getClient } from './api-client.js';
|
|
25
25
|
import { loadFeltDBConfig, createDefaultConfig, validateModel, } from './config.js';
|
|
26
|
-
const VERSION = '0.4.
|
|
26
|
+
const VERSION = '0.4.15';
|
|
27
27
|
function prompt(question) {
|
|
28
28
|
const rl = readline.createInterface({
|
|
29
29
|
input: process.stdin,
|
package/dist/collection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAIxC,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAEhE,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;AAChD,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC;AAEjD;;;;;GAKG;AACH,qBAAa,UAAU,CAAC,CAAC;IACvB,OAAO,CAAC,EAAE,CAAO;IACjB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IAmBpF;;OAEG;YACW,oBAAoB;IAalC;;;OAGG;IACG,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAKzB,0DAA0D;IACpD,IAAI,CAAC,KAAK,GAAE,OAAO,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQhD;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAWtC;;OAEG;IACH,WAAW,IAAI,WAAW,EAAE;IAI5B;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAYrC;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAazC;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAajD;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IAO7C;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BrE;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BrE;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BhD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAK9B;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKnD;;;OAGG;IACH,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI;
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
|
package/dist/collection.js
CHANGED
|
@@ -258,10 +258,16 @@ export class Collection {
|
|
|
258
258
|
}
|
|
259
259
|
// Subscribe to changes via reactive dependency graph
|
|
260
260
|
if (!this.graphUnsubscribe) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
let refreshInFlight = null;
|
|
262
|
+
const notify = () => {
|
|
263
|
+
if (refreshInFlight)
|
|
264
|
+
return refreshInFlight;
|
|
265
|
+
refreshInFlight = (async () => {
|
|
266
|
+
await this.refresh();
|
|
267
|
+
for (const sub of this.subscribers)
|
|
268
|
+
sub([...this.cache]);
|
|
269
|
+
})().finally(() => { refreshInFlight = null; });
|
|
270
|
+
return refreshInFlight;
|
|
265
271
|
};
|
|
266
272
|
const graph = getReactiveDependencyGraph();
|
|
267
273
|
this.graphUnsubscribe = graph.subscribe(this.name, notify);
|
|
@@ -269,7 +275,7 @@ export class Collection {
|
|
|
269
275
|
this.runtimeUnsubscribe = this.db.subscribe_changes(collection => {
|
|
270
276
|
if (collection === this.name)
|
|
271
277
|
void notify();
|
|
272
|
-
});
|
|
278
|
+
}, this.name);
|
|
273
279
|
}
|
|
274
280
|
}
|
|
275
281
|
// Return unsubscribe function
|
package/dist/create/cli.js
CHANGED
|
@@ -73,6 +73,14 @@ async function prompt(message) {
|
|
|
73
73
|
const interface_ = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
74
74
|
return new Promise(resolve => interface_.question(message, value => { interface_.close(); resolve(value.trim()); }));
|
|
75
75
|
}
|
|
76
|
+
async function promptForProjectName(defaultName = 'feltdb-app') {
|
|
77
|
+
while (true) {
|
|
78
|
+
const value = (await prompt(`What should we name your FeltDB app? (${defaultName}): `)) || defaultName;
|
|
79
|
+
if (/^[a-z0-9][a-z0-9-]*$/.test(value))
|
|
80
|
+
return value;
|
|
81
|
+
console.log('Use lowercase letters, numbers, and dashes (for example: customer-portal).');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
76
84
|
async function promptSecret(message) {
|
|
77
85
|
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
78
86
|
return '';
|
|
@@ -207,7 +215,7 @@ Deployment Target (Explicit):
|
|
|
207
215
|
Requires production FeltDB instance or self-host
|
|
208
216
|
|
|
209
217
|
--self-host Dedicated FeltDB server with Docker Compose
|
|
210
|
-
Best for:
|
|
218
|
+
Best for: Staging first, then explicit production promotion
|
|
211
219
|
Generates Docker Compose with persistent /data volume
|
|
212
220
|
|
|
213
221
|
--managed Managed FeltDB runtime
|
|
@@ -245,10 +253,12 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
245
253
|
}
|
|
246
254
|
// Find project name (first non-flag argument)
|
|
247
255
|
let projectName = 'feltdb-app';
|
|
256
|
+
let projectNameProvided = false;
|
|
248
257
|
for (let i = 0; i < args.length; i++) {
|
|
249
258
|
const arg = args[i];
|
|
250
259
|
if (!arg.startsWith('-')) {
|
|
251
260
|
projectName = arg;
|
|
261
|
+
projectNameProvided = true;
|
|
252
262
|
break;
|
|
253
263
|
}
|
|
254
264
|
// Skip next arg if current arg is a flag that takes a value
|
|
@@ -260,10 +270,16 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
260
270
|
const shouldInstall = !args.includes('--no-install');
|
|
261
271
|
const shouldStart = !args.includes('--no-start');
|
|
262
272
|
let options = parseArgs(args);
|
|
273
|
+
if (!projectNameProvided && !shouldAutoYes && process.stdin.isTTY && process.stdout.isTTY) {
|
|
274
|
+
projectName = await promptForProjectName(projectName);
|
|
275
|
+
}
|
|
276
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(projectName)) {
|
|
277
|
+
throw new Error('Application names must use lowercase letters, numbers, and dashes.');
|
|
278
|
+
}
|
|
263
279
|
const runtimeDescriptions = {
|
|
264
280
|
'browser': 'Browser with IndexedDB (local-first, no server)',
|
|
265
281
|
'node': 'Node.js server (server-side authority)',
|
|
266
|
-
'self-hosted': 'Self-hosted with Docker Compose (
|
|
282
|
+
'self-hosted': 'Self-hosted with Docker Compose (staging)',
|
|
267
283
|
'managed': 'Managed FeltDB service (hosted persistence, sync, and workloads)',
|
|
268
284
|
};
|
|
269
285
|
if (!runtimeDescriptions[options.runtime]) {
|
|
@@ -286,6 +302,7 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
286
302
|
console.log(`Capabilities: ${options.capabilities}`);
|
|
287
303
|
console.log('\n═══════════════════════════════════════════════\n');
|
|
288
304
|
const projectDir = path.resolve(process.cwd(), projectName);
|
|
305
|
+
let projectCreated = false;
|
|
289
306
|
try {
|
|
290
307
|
await createProject({
|
|
291
308
|
projectName,
|
|
@@ -298,6 +315,7 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
298
315
|
webllm: options.webllm,
|
|
299
316
|
capabilities: options.capabilities,
|
|
300
317
|
});
|
|
318
|
+
projectCreated = true;
|
|
301
319
|
if (options.runtime === 'managed') {
|
|
302
320
|
console.log('\n☁️ Setting up your managed FeltDB account...\n');
|
|
303
321
|
const email = process.env.FELTDB_MANAGED_EMAIL || (shouldAutoYes ? '' : await prompt('Email: '));
|
|
@@ -341,7 +359,9 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
341
359
|
}
|
|
342
360
|
}
|
|
343
361
|
catch (error) {
|
|
344
|
-
console.error(
|
|
362
|
+
console.error(projectCreated
|
|
363
|
+
? `❌ The project was created at ${projectDir}, but setup or startup failed:`
|
|
364
|
+
: '❌ Failed to create project:', error);
|
|
345
365
|
process.exit(1);
|
|
346
366
|
}
|
|
347
367
|
}
|
package/dist/create/create.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
6
|
import { randomBytes } from 'crypto';
|
|
8
7
|
import { feltdbPackageRange } from './package-versions.js';
|
|
9
8
|
import { generateDockerCompose, generateDockerfile, generateDockerIgnore, generateDotEnvLocal, generateFeltDBDockerfile, generateStudioDockerfile, } from './docker-compose-generator.js';
|
|
@@ -1218,7 +1217,8 @@ VITE_FELTDB_MANAGED_NAMESPACE=
|
|
|
1218
1217
|
VITE_FELTDB_MANAGED_ENVIRONMENT=production
|
|
1219
1218
|
|
|
1220
1219
|
# Override the default self-hosted container image
|
|
1221
|
-
#
|
|
1220
|
+
# By default the server image is built locally from the bundled source.
|
|
1221
|
+
# Example override: your-registry.example/feltdb:staging
|
|
1222
1222
|
FELTDB_IMAGE=
|
|
1223
1223
|
|
|
1224
1224
|
# Node environment
|
|
@@ -1239,11 +1239,8 @@ NODE_ENV=development
|
|
|
1239
1239
|
fs.writeFileSync(path.join(projectDir, 'Dockerfile'), generateDockerfile(dockerConfig, framework));
|
|
1240
1240
|
fs.writeFileSync(path.join(projectDir, 'Dockerfile.feltdb'), generateFeltDBDockerfile(dockerConfig));
|
|
1241
1241
|
fs.writeFileSync(path.join(projectDir, 'Dockerfile.studio'), generateStudioDockerfile(dockerConfig));
|
|
1242
|
-
const serverSource = fileURLToPath(new URL('./server-source', import.meta.url));
|
|
1243
|
-
fs.cpSync(serverSource, path.join(projectDir, '.feltdb', 'server-source'), { recursive: true });
|
|
1244
1242
|
fs.writeFileSync(path.join(projectDir, '.dockerignore'), generateDockerIgnore());
|
|
1245
1243
|
const dockerEnvironment = generateDotEnvLocal(dockerConfig, randomBytes(32).toString('hex'));
|
|
1246
|
-
fs.writeFileSync(path.join(projectDir, '.env.docker'), dockerEnvironment);
|
|
1247
1244
|
// Docker Compose loads .env automatically; it is already excluded from git.
|
|
1248
1245
|
fs.writeFileSync(path.join(projectDir, '.env'), dockerEnvironment);
|
|
1249
1246
|
}
|
|
@@ -1497,7 +1494,8 @@ Verify vector database connection and that embeddings are enabled in capabilitie
|
|
|
1497
1494
|
- Check out example projects in the templates
|
|
1498
1495
|
- Join the community Discord for support
|
|
1499
1496
|
`;
|
|
1500
|
-
|
|
1497
|
+
// Keep generated projects focused; the runtime guide lives in FeltDB's docs.
|
|
1498
|
+
void runtimeGuide;
|
|
1501
1499
|
// Create .gitignore
|
|
1502
1500
|
const gitignore = `node_modules/
|
|
1503
1501
|
dist/
|
|
@@ -14,16 +14,33 @@ export function generateDockerCompose(config) {
|
|
|
14
14
|
build:
|
|
15
15
|
context: .
|
|
16
16
|
dockerfile: Dockerfile.feltdb
|
|
17
|
+
args:
|
|
18
|
+
FELTDB_VERSION: ${config.version}
|
|
17
19
|
container_name: \${COMPOSE_PROJECT_NAME}-feltdb
|
|
18
20
|
environment:
|
|
19
21
|
FELTDB_APP_NAME: \${FELTDB_APP_NAME:-${config.appName}}
|
|
20
22
|
FELTDB_APP_ID: \${FELTDB_APP_ID:-${config.appId}}
|
|
21
23
|
FELTDB_VERSION: \${FELTDB_VERSION:-${config.version}}
|
|
24
|
+
FELTDB_ENVIRONMENT: \${FELTDB_ENVIRONMENT:-staging}
|
|
22
25
|
FELTDB_PEERS: \${FELTDB_PEERS:-}
|
|
23
26
|
FELTDB_MASTER_KEY: \${FELTDB_MASTER_KEY}
|
|
24
27
|
NODE_ENV: \${NODE_ENV:-production}
|
|
25
28
|
ports:
|
|
26
29
|
- "\${FELTDB_API_PORT:-${config.port}}:7700"
|
|
30
|
+
command:
|
|
31
|
+
- feltdb-server
|
|
32
|
+
- --host
|
|
33
|
+
- 0.0.0.0
|
|
34
|
+
- --port
|
|
35
|
+
- "7700"
|
|
36
|
+
- --namespace
|
|
37
|
+
- \${FELTDB_APP_ID:-${config.appId}}
|
|
38
|
+
- --data
|
|
39
|
+
- /data/feltdb.log
|
|
40
|
+
- --allow-origin
|
|
41
|
+
- http://127.0.0.1:\${APP_PORT:-5173}
|
|
42
|
+
- --allow-origin
|
|
43
|
+
- http://127.0.0.1:\${STUDIO_PORT:-${config.studioPort}}
|
|
27
44
|
volumes:
|
|
28
45
|
- feltdb_data:/data
|
|
29
46
|
- ./feltdb.flow:/app/feltdb.flow:ro
|
|
@@ -106,11 +123,13 @@ volumes:
|
|
|
106
123
|
`;
|
|
107
124
|
}
|
|
108
125
|
export function generateFeltDBDockerfile(config) {
|
|
109
|
-
return `# FeltDB server
|
|
126
|
+
return `# Build the matching FeltDB server without adding engine source to the application.
|
|
110
127
|
FROM rust:1.96-alpine AS builder
|
|
111
|
-
RUN apk add --no-cache pkgconf openssl-dev musl-dev
|
|
128
|
+
RUN apk add --no-cache nodejs npm pkgconf openssl-dev musl-dev
|
|
112
129
|
WORKDIR /source
|
|
113
|
-
|
|
130
|
+
ARG FELTDB_VERSION=${config.version}
|
|
131
|
+
RUN npm install --global "create-feltdb@\${FELTDB_VERSION}" \
|
|
132
|
+
&& cp -R "\$(npm root --global)/create-feltdb/dist/server-source/." /source/
|
|
114
133
|
RUN cargo build -p feltdb-server --release --locked
|
|
115
134
|
|
|
116
135
|
FROM alpine:3.22
|
|
@@ -191,6 +210,7 @@ COMPOSE_PROJECT_NAME=${config.appName.toLowerCase().replace(/[^a-z0-9]/g, '-')}
|
|
|
191
210
|
FELTDB_APP_NAME=${config.appName}
|
|
192
211
|
FELTDB_APP_ID=${config.appId}
|
|
193
212
|
FELTDB_VERSION=${config.version}
|
|
213
|
+
FELTDB_ENVIRONMENT=staging
|
|
194
214
|
FELTDB_API_PORT=${config.port}
|
|
195
215
|
FELTDB_REPLICATION_PORT=${config.replicationPort}
|
|
196
216
|
FELTDB_PEERS=
|
|
@@ -203,8 +223,6 @@ FELTDB_API_URL=http://feltdb:7700
|
|
|
203
223
|
# Studio Configuration
|
|
204
224
|
STUDIO_PORT=${config.studioPort}
|
|
205
225
|
|
|
206
|
-
# Runtime
|
|
207
|
-
NODE_ENV=production
|
|
208
226
|
`;
|
|
209
227
|
}
|
|
210
228
|
export function generateHealthCheckScript() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// One release train keeps generated applications installable. The repository
|
|
2
2
|
// validation script checks these values against every workspace manifest.
|
|
3
|
-
export const FELTDB_PACKAGE_VERSION = '0.4.
|
|
3
|
+
export const FELTDB_PACKAGE_VERSION = '0.4.15';
|
|
4
4
|
export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
|
package/dist/feltdb.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export interface JsDb {
|
|
|
52
52
|
/** Delete a record when supported by the runtime. */
|
|
53
53
|
delete?(key: string): any | Promise<any>;
|
|
54
54
|
/** Subscribe to runtime-originated changes, including remote mutations. */
|
|
55
|
-
subscribe_changes?(callback: (collection: string) => void): () => void;
|
|
55
|
+
subscribe_changes?(callback: (collection: string) => void, collection?: string): () => void;
|
|
56
56
|
close?(): void | Promise<void>;
|
|
57
57
|
/**
|
|
58
58
|
* Get capability records
|
package/dist/feltdb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feltdb.d.ts","sourceRoot":"","sources":["../src/feltdb.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG,CAAC;IAEhC;;OAEG;IACH,SAAS,IAAI,GAAG,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAE/B;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAEpC;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAEvC;;OAEG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnE;;OAEG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC;IAEpE;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAErC;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEvD,6DAA6D;IAC7D,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAExD,qDAAqD;IACrD,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC,2EAA2E;IAC3E,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"feltdb.d.ts","sourceRoot":"","sources":["../src/feltdb.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG,CAAC;IAEhC;;OAEG;IACH,SAAS,IAAI,GAAG,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAE/B;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAEpC;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAEvC;;OAEG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnE;;OAEG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC;IAEpE;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAErC;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEvD,6DAA6D;IAC7D,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAExD,qDAAqD;IACrD,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC,2EAA2E;IAC3E,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC5F,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/B;;OAEG;IACH,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC;IAEhD;;OAEG;IACH,WAAW,IAAI,MAAM,CAAC;IAEtB;;OAEG;IACH,YAAY,IAAI,MAAM,CAAC;IAEvB,0EAA0E;IAC1E,YAAY,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpC,6DAA6D;IAC7D,iBAAiB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/D,uBAAuB,CAAC,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACjE;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB"}
|
package/dist/indexeddb-db.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ interface ChangeRecord {
|
|
|
14
14
|
origin: string;
|
|
15
15
|
value?: unknown;
|
|
16
16
|
}
|
|
17
|
+
type ChangeListener = (collection: string) => void;
|
|
17
18
|
/** Durable browser runtime. Every mutation resolves only after its IndexedDB transaction commits. */
|
|
18
19
|
export declare class IndexedDbJsDb implements JsDb {
|
|
19
20
|
private readonly database;
|
|
@@ -21,6 +22,15 @@ export declare class IndexedDbJsDb implements JsDb {
|
|
|
21
22
|
private sequence;
|
|
22
23
|
private readonly origin;
|
|
23
24
|
private readonly peers;
|
|
25
|
+
private readonly changeListeners;
|
|
26
|
+
private changeCursor;
|
|
27
|
+
private changePollGeneration;
|
|
28
|
+
private changePollRunning;
|
|
29
|
+
private changePollTimer?;
|
|
30
|
+
private changeChannelListening;
|
|
31
|
+
private changeCoordinatorReady;
|
|
32
|
+
private pendingChangeAnnouncements;
|
|
33
|
+
private readonly announcedChangeSequences;
|
|
24
34
|
constructor(namespace: string);
|
|
25
35
|
private open;
|
|
26
36
|
private splitKey;
|
|
@@ -31,7 +41,16 @@ export declare class IndexedDbJsDb implements JsDb {
|
|
|
31
41
|
get(key: string): Promise<JsResult>;
|
|
32
42
|
query(collection: string): Promise<JsResult>;
|
|
33
43
|
private request;
|
|
34
|
-
subscribe_changes(callback:
|
|
44
|
+
subscribe_changes(callback: ChangeListener, collection?: string): () => void;
|
|
45
|
+
private readonly receiveChangeMessage;
|
|
46
|
+
private deliverChangeAnnouncement;
|
|
47
|
+
private announceLocalChange;
|
|
48
|
+
private rememberAnnouncedSequence;
|
|
49
|
+
private notifyChangeListeners;
|
|
50
|
+
private startChangeCoordinator;
|
|
51
|
+
private latestChangeSequence;
|
|
52
|
+
private pollChanges;
|
|
53
|
+
private stopChangeCoordinator;
|
|
35
54
|
close(): void;
|
|
36
55
|
get_capability_records(capability: string): Promise<JsResult>;
|
|
37
56
|
execute_op(): JsResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexeddb-db.d.ts","sourceRoot":"","sources":["../src/indexeddb-db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,UAAU,QAAQ;IAAG,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AACtE,UAAU,YAAY;IAAG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"indexeddb-db.d.ts","sourceRoot":"","sources":["../src/indexeddb-db.ts"],"names":[],"mappings":"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"}
|