@feltdb/core 0.6.12 → 0.6.14
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/agent-registry.js +1 -3
- package/dist/agent-runtime.js +8 -7
- package/dist/analytics-backend.js +3 -1
- package/dist/application-contract.js +1 -0
- package/dist/application-manifest.js +1 -0
- package/dist/artifact.js +2 -0
- package/dist/authorization.js +2 -0
- package/dist/bundle.js +2 -0
- package/dist/capability.js +1 -3
- package/dist/cell.js +9 -4
- package/dist/cli/application.js +1 -1
- package/dist/cli/browser-opening.js +35 -0
- package/dist/cli/commands.js +50 -17
- package/dist/cli/index.js +1 -1
- package/dist/collection.js +39 -31
- package/dist/create/cli.js +7 -5
- package/dist/create/create.js +9 -7
- package/dist/create/development-handoff.js +4 -0
- package/dist/create/docker-compose-generator.js +4 -4
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +497 -27
- package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +452 -0
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +208 -0
- package/dist/create/server-source/crates/feltdb/src/convergence.rs +16 -0
- package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +402 -0
- package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +765 -24
- package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +418 -0
- package/dist/create/server-source/crates/feltdb/src/lib.rs +4 -0
- package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +661 -0
- package/dist/db.js +19 -13
- package/dist/development-runtime-bridge.js +1 -1
- package/dist/distributed-indexing.js +7 -5
- package/dist/file-db.js +8 -3
- package/dist/flowspec.js +2 -1
- package/dist/http-client.js +2 -0
- package/dist/http-db.js +16 -1
- package/dist/identity.js +1 -0
- package/dist/index-analytics.js +6 -7
- package/dist/index-backend.js +3 -3
- package/dist/index-dashboard.js +10 -13
- package/dist/index-manager.js +12 -11
- package/dist/index-monitoring.js +9 -4
- package/dist/index-store.js +2 -0
- package/dist/indexeddb-db.js +27 -23
- package/dist/memory-db.js +7 -4
- package/dist/observe.js +2 -0
- package/dist/provider.js +2 -0
- package/dist/query-planner.js +2 -4
- package/dist/reactive-graph.js +6 -8
- package/dist/release.js +2 -0
- package/dist/sharding.js +11 -6
- package/dist/state-contract.js +3 -3
- package/dist/studio-app/assets/{feltdb_wasm-CJv3wHzi.js → feltdb_wasm-C9xpYtna.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-BsXHw7eX.wasm +0 -0
- package/dist/studio-app/assets/{index-DospFFYE.js → index-D4RZ44qs.js} +4 -4
- package/dist/studio-app/index.html +1 -1
- package/dist/sync-contract.js +9 -2
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +32 -12
- package/dist/transaction.js +4 -2
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/worker.js +2 -0
- package/dist/workload.js +2 -0
- package/dist/workspace/development-node.js +11 -10
- package/dist/workspace/investigation-lifecycle-manager.js +2 -0
- package/dist/workspace/investigation-supervisor.js +5 -3
- package/dist/workspace/workspace-connection.js +14 -5
- package/package.json +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-C8TG8r2n.wasm +0 -0
package/dist/agent-registry.js
CHANGED
package/dist/agent-runtime.js
CHANGED
|
@@ -9,10 +9,8 @@ import { AgentExecutionStatus, generateExecutionId } from './agent.js';
|
|
|
9
9
|
* Agent ownership manager for distributed execution
|
|
10
10
|
*/
|
|
11
11
|
export class AgentOwnershipManager {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.locks = new Map();
|
|
15
|
-
}
|
|
12
|
+
ownership = new Map(); // executionId -> peerId
|
|
13
|
+
locks = new Map();
|
|
16
14
|
/**
|
|
17
15
|
* Claim ownership of an execution
|
|
18
16
|
*/
|
|
@@ -86,10 +84,13 @@ export class AgentOwnershipManager {
|
|
|
86
84
|
* Manages agent lifecycle and execution across the distributed fabric.
|
|
87
85
|
*/
|
|
88
86
|
export class AgentRuntime {
|
|
87
|
+
config;
|
|
88
|
+
registry;
|
|
89
|
+
handlers = new Map();
|
|
90
|
+
executions = new Map();
|
|
91
|
+
ownership;
|
|
92
|
+
triggers = new Map();
|
|
89
93
|
constructor(registry, config) {
|
|
90
|
-
this.handlers = new Map();
|
|
91
|
-
this.executions = new Map();
|
|
92
|
-
this.triggers = new Map();
|
|
93
94
|
this.registry = registry;
|
|
94
95
|
this.config = config;
|
|
95
96
|
this.ownership = new AgentOwnershipManager();
|
|
@@ -10,8 +10,9 @@ import { IndexAnalytics as TypeScriptIndexAnalytics } from './index-analytics.js
|
|
|
10
10
|
* Analytics backend selector with dynamic WASM loading
|
|
11
11
|
*/
|
|
12
12
|
export class AnalyticsBackend {
|
|
13
|
+
backend;
|
|
14
|
+
wasmLoaded = false;
|
|
13
15
|
constructor() {
|
|
14
|
-
this.wasmLoaded = false;
|
|
15
16
|
// Start with TypeScript backend, attempt WASM load async
|
|
16
17
|
// Create a wrapper that implements the interface
|
|
17
18
|
const tsBackend = new TypeScriptIndexAnalytics();
|
|
@@ -76,6 +77,7 @@ export class AnalyticsBackend {
|
|
|
76
77
|
* Adapter to bridge WASM analytics to TypeScript interface
|
|
77
78
|
*/
|
|
78
79
|
class WasmAnalyticsAdapter {
|
|
80
|
+
wasm;
|
|
79
81
|
constructor(wasm) {
|
|
80
82
|
this.wasm = wasm;
|
|
81
83
|
}
|
package/dist/artifact.js
CHANGED
package/dist/authorization.js
CHANGED
package/dist/bundle.js
CHANGED
package/dist/capability.js
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
* Capabilities are distributed, pluggable features like search, vector embeddings, etc.
|
|
5
5
|
*/
|
|
6
6
|
export class CapabilityRegistry {
|
|
7
|
-
|
|
8
|
-
this.capabilities = new Map();
|
|
9
|
-
}
|
|
7
|
+
capabilities = new Map();
|
|
10
8
|
register(capability) {
|
|
11
9
|
this.capabilities.set(capability.id, capability);
|
|
12
10
|
}
|
package/dist/cell.js
CHANGED
|
@@ -16,11 +16,16 @@ export const AUTHORITY_CONFLICT = Symbol('FELTDB_AUTHORITY_CONFLICT');
|
|
|
16
16
|
* A replica is read-only: replication transfers knowledge, not authority.
|
|
17
17
|
*/
|
|
18
18
|
export class CellImpl {
|
|
19
|
+
id;
|
|
20
|
+
jsDb;
|
|
21
|
+
cellCollection;
|
|
22
|
+
replicaCollection;
|
|
23
|
+
failureObservationCollection;
|
|
24
|
+
mutationQueue = [];
|
|
25
|
+
isLocked = false;
|
|
26
|
+
changeHandlers = [];
|
|
27
|
+
isReplica = false;
|
|
19
28
|
constructor(jsDb, cellId) {
|
|
20
|
-
this.mutationQueue = [];
|
|
21
|
-
this.isLocked = false;
|
|
22
|
-
this.changeHandlers = [];
|
|
23
|
-
this.isReplica = false;
|
|
24
29
|
this.id = cellId;
|
|
25
30
|
this.jsDb = jsDb;
|
|
26
31
|
this.cellCollection = new Collection(jsDb, '_cells', undefined, undefined, false);
|
package/dist/cli/application.js
CHANGED
|
@@ -71,7 +71,7 @@ export function applicationUrlCandidate(project, environment = process.env) {
|
|
|
71
71
|
if (project.configuredUrl)
|
|
72
72
|
return project.configuredUrl;
|
|
73
73
|
if (project.configuredPort)
|
|
74
|
-
return `http://
|
|
74
|
+
return `http://localhost:${project.configuredPort}/`;
|
|
75
75
|
return undefined;
|
|
76
76
|
}
|
|
77
77
|
export function applicationIsRunning(url, timeoutMs = 750) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
function defaultSpawn(command, args) {
|
|
3
|
+
return spawn(command, [...args], { detached: true, stdio: 'ignore' });
|
|
4
|
+
}
|
|
5
|
+
export function browserCommand(url, platform = process.platform) {
|
|
6
|
+
if (platform === 'darwin')
|
|
7
|
+
return ['open', [url]];
|
|
8
|
+
if (platform === 'win32')
|
|
9
|
+
return ['cmd', ['/c', 'start', '', url]];
|
|
10
|
+
if (platform === 'linux')
|
|
11
|
+
return ['xdg-open', [url]];
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
export function openBrowser(url, spawnBrowser = defaultSpawn) {
|
|
15
|
+
const command = browserCommand(url);
|
|
16
|
+
if (!command || !process.stdout.isTTY || process.env.CI)
|
|
17
|
+
return false;
|
|
18
|
+
try {
|
|
19
|
+
const child = spawnBrowser(command[0], command[1]);
|
|
20
|
+
child.once('error', () => undefined);
|
|
21
|
+
child.unref();
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function openApplication(url) {
|
|
29
|
+
console.log(`🌐 Application: ${url}`);
|
|
30
|
+
return openBrowser(url);
|
|
31
|
+
}
|
|
32
|
+
export function openStudio(url) {
|
|
33
|
+
console.log(`🛠️ Studio: ${url}`);
|
|
34
|
+
return openBrowser(url);
|
|
35
|
+
}
|
package/dist/cli/commands.js
CHANGED
|
@@ -13,6 +13,7 @@ import { discoverWorkspace, ensureWorkspaceGitIgnored, generatePairingToken, per
|
|
|
13
13
|
import { applicationUrlCandidate, detectApplication, discoverApplicationUrl } from './application.js';
|
|
14
14
|
import { resolveApplicationLifecycle, startManagedApplication, waitForManagedApplication } from './application-lifecycle.js';
|
|
15
15
|
import { createDevelopmentSession, developmentSessionEnvironment, developmentSessionSummary, transitionDevelopmentSession } from './development-session.js';
|
|
16
|
+
import { openApplication, openStudio } from './browser-opening.js';
|
|
16
17
|
function loadProjectEnvironment(file = path.resolve('.env.local')) {
|
|
17
18
|
if (!fs.existsSync(file))
|
|
18
19
|
return;
|
|
@@ -511,7 +512,7 @@ async function handleDev(args) {
|
|
|
511
512
|
if (args.includes('--help')) {
|
|
512
513
|
console.log('Usage: feltdb dev [--app-url URL] [--studio-port 7701] [--authority-port 7700] [--discovery-port 7799] [--no-open]');
|
|
513
514
|
console.log('\nOptions:');
|
|
514
|
-
console.log(' --app-url <url> Application URL (e.g., http://
|
|
515
|
+
console.log(' --app-url <url> Application URL (e.g., http://localhost:3000/)');
|
|
515
516
|
console.log(' --studio-port <port> FeltDB Studio port (default: 7701)');
|
|
516
517
|
console.log(' --authority-port <port> Authority port (default: 7700)');
|
|
517
518
|
console.log(' --discovery-port <port> Pairing discovery port (default: 7799)');
|
|
@@ -628,7 +629,7 @@ async function handleDev(args) {
|
|
|
628
629
|
console.log(`Attaching existing FeltDB application (${detectedApplication.feltDBSignals.join(', ')})\n`);
|
|
629
630
|
}
|
|
630
631
|
const requestedStudioPort = Number(args.includes('--studio-port') ? args[args.indexOf('--studio-port') + 1] || '7701' : '7701');
|
|
631
|
-
const studioPort = String(await availablePort(requestedStudioPort));
|
|
632
|
+
const studioPort = String(await availablePort(requestedStudioPort, 'localhost'));
|
|
632
633
|
if (studioPort !== String(requestedStudioPort))
|
|
633
634
|
console.log(`⚠ Port ${requestedStudioPort} is busy; using ${studioPort} for Studio.\n`);
|
|
634
635
|
process.env.STUDIO_PORT = studioPort;
|
|
@@ -678,7 +679,7 @@ async function handleDev(args) {
|
|
|
678
679
|
storage: config.storage,
|
|
679
680
|
lifecycle: applicationLifecycle,
|
|
680
681
|
authorityUrl,
|
|
681
|
-
studioUrl: `http://
|
|
682
|
+
studioUrl: `http://localhost:${studioPort}/`,
|
|
682
683
|
pairingUrl: `http://127.0.0.1:${discoveryPort}`,
|
|
683
684
|
applicationUrl: appUrl,
|
|
684
685
|
});
|
|
@@ -718,7 +719,14 @@ async function handleDev(args) {
|
|
|
718
719
|
throw error;
|
|
719
720
|
}
|
|
720
721
|
let stopping = null;
|
|
722
|
+
// The development session runs until something stops it — a signal, a managed
|
|
723
|
+
// application exiting, or a failure. Its lifetime belongs to this command, so
|
|
724
|
+
// it is represented explicitly rather than borrowed from whichever service
|
|
725
|
+
// happens to be long-running.
|
|
726
|
+
let releaseSession = () => { };
|
|
727
|
+
const sessionStopped = new Promise(resolve => { releaseSession = resolve; });
|
|
721
728
|
const stopAll = () => stopping ?? (stopping = (async () => {
|
|
729
|
+
releaseSession();
|
|
722
730
|
if (developmentSession && developmentSession.state !== 'STOPPING' && developmentSession.state !== 'STOPPED') {
|
|
723
731
|
transitionDevelopmentSession(developmentSession, 'STOPPING');
|
|
724
732
|
}
|
|
@@ -791,7 +799,7 @@ async function handleDev(args) {
|
|
|
791
799
|
else {
|
|
792
800
|
console.log('❌ No application URL is configured.\n');
|
|
793
801
|
console.log('Start your application, then run:\n');
|
|
794
|
-
console.log(' feltdb dev --app-url http://
|
|
802
|
+
console.log(' feltdb dev --app-url http://localhost:<port>/\n');
|
|
795
803
|
console.log('Or set applicationUrl in feltdb.config.json\n');
|
|
796
804
|
console.log('FeltDB workspace is ready at:');
|
|
797
805
|
console.log('Authority: ' + developmentSession.authorityUrl);
|
|
@@ -812,19 +820,47 @@ async function handleDev(args) {
|
|
|
812
820
|
'--lifecycle', developmentSession.lifecycle,
|
|
813
821
|
...(developmentSession.applicationUrl ? ['--app-url', developmentSession.applicationUrl] : []),
|
|
814
822
|
...((developmentSession.runtime === 'self-hosted' || developmentSession.runtime === 'managed') ? ['--connect', developmentSession.authorityUrl] : []),
|
|
815
|
-
|
|
816
|
-
],
|
|
823
|
+
'--no-open',
|
|
824
|
+
], studioUrl => {
|
|
825
|
+
developmentSession.studioUrl = studioUrl;
|
|
817
826
|
transitionDevelopmentSession(developmentSession, 'READY');
|
|
818
827
|
console.log(`\n${developmentSessionSummary(developmentSession)}\n`);
|
|
828
|
+
if (open) {
|
|
829
|
+
if (developmentSession.applicationUrl)
|
|
830
|
+
openApplication(developmentSession.applicationUrl);
|
|
831
|
+
openStudio(developmentSession.studioUrl);
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
if (developmentSession.applicationUrl)
|
|
835
|
+
console.log(`🌐 Application: ${developmentSession.applicationUrl}`);
|
|
836
|
+
console.log(`🛠️ Studio: ${developmentSession.studioUrl}`);
|
|
837
|
+
}
|
|
819
838
|
transitionDevelopmentSession(developmentSession, 'RUNNING');
|
|
820
839
|
});
|
|
840
|
+
// Studio is one service in the session, not the session itself.
|
|
841
|
+
// `handleStudio` returns immediately when Studio's static assets are absent,
|
|
842
|
+
// and awaiting it as the session's lifetime meant a missing optional
|
|
843
|
+
// artifact tore down the authority, the pairing discovery server, and the
|
|
844
|
+
// workspace transport: the process printed "workspace is ready" and then
|
|
845
|
+
// exited, so anything reaching for the discovery endpoint afterwards got a
|
|
846
|
+
// connection failure. The session now outlives Studio either way.
|
|
847
|
+
void studio.then(() => {
|
|
848
|
+
if (!developmentSession || developmentSession.state === 'RUNNING')
|
|
849
|
+
return;
|
|
850
|
+
console.log('\u26a0\ufe0f Studio is unavailable for this session. The authority, pairing discovery, and workspace transport are unaffected.');
|
|
851
|
+
transitionDevelopmentSession(developmentSession, 'READY');
|
|
852
|
+
console.log(`\n${developmentSessionSummary(developmentSession)}\n`);
|
|
853
|
+
transitionDevelopmentSession(developmentSession, 'RUNNING');
|
|
854
|
+
}).catch(error => {
|
|
855
|
+
console.error(`Studio failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
856
|
+
});
|
|
821
857
|
if (managedApplication) {
|
|
822
|
-
await Promise.race([
|
|
858
|
+
await Promise.race([sessionStopped, managedApplication.exited.then(exit => {
|
|
823
859
|
throw new Error(`Managed application stopped during the development session (command: ${managedApplication.command}; exit: ${exit.code ?? exit.signal})`);
|
|
824
860
|
})]);
|
|
825
861
|
}
|
|
826
862
|
else
|
|
827
|
-
await
|
|
863
|
+
await sessionStopped;
|
|
828
864
|
}
|
|
829
865
|
finally {
|
|
830
866
|
await stopAll();
|
|
@@ -1092,8 +1128,8 @@ async function handleStudio(args, onReady) {
|
|
|
1092
1128
|
? args[args.indexOf('--port') + 1] || '7701'
|
|
1093
1129
|
: '7701';
|
|
1094
1130
|
const host = args.includes('--host')
|
|
1095
|
-
? args[args.indexOf('--host') + 1] || '
|
|
1096
|
-
: '
|
|
1131
|
+
? args[args.indexOf('--host') + 1] || 'localhost'
|
|
1132
|
+
: 'localhost';
|
|
1097
1133
|
const open = !args.includes('--no-open');
|
|
1098
1134
|
const namespace = args.includes('--namespace')
|
|
1099
1135
|
? args[args.indexOf('--namespace') + 1] || 'default'
|
|
@@ -1223,15 +1259,12 @@ async function handleStudio(args, onReady) {
|
|
|
1223
1259
|
if (session.pairingUrl)
|
|
1224
1260
|
parameters.set('pairing', session.pairingUrl);
|
|
1225
1261
|
const query = `?${parameters.toString()}`;
|
|
1226
|
-
const studioUrl = `http://
|
|
1262
|
+
const studioUrl = `http://localhost:${port}/${query}`;
|
|
1227
1263
|
console.log(`FeltDB Studio ready at ${studioUrl}`);
|
|
1228
|
-
onReady?.();
|
|
1264
|
+
onReady?.(studioUrl);
|
|
1229
1265
|
console.log('Use Ctrl+C to stop the server.');
|
|
1230
|
-
if (open)
|
|
1231
|
-
|
|
1232
|
-
const child = spawn(command[0], command.slice(1), { detached: true, stdio: 'ignore' });
|
|
1233
|
-
child.unref();
|
|
1234
|
-
}
|
|
1266
|
+
if (open)
|
|
1267
|
+
openStudio(studioUrl);
|
|
1235
1268
|
await new Promise(() => { });
|
|
1236
1269
|
}
|
|
1237
1270
|
function handleHelp() {
|
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.6.
|
|
26
|
+
const VERSION = '0.6.14';
|
|
27
27
|
function prompt(question) {
|
|
28
28
|
const rl = readline.createInterface({
|
|
29
29
|
input: process.stdin,
|
package/dist/collection.js
CHANGED
|
@@ -18,38 +18,42 @@ import { IndexStore } from './index-store.js';
|
|
|
18
18
|
* Uses reactive dependency graph instead of polling for efficient updates.
|
|
19
19
|
*/
|
|
20
20
|
export class Collection {
|
|
21
|
+
db;
|
|
22
|
+
name;
|
|
23
|
+
collectionId; // Unique ID for this collection instance
|
|
24
|
+
predicate = null;
|
|
25
|
+
cache = [];
|
|
26
|
+
subscribers = new Set();
|
|
27
|
+
parent = null;
|
|
28
|
+
parentId = null;
|
|
29
|
+
isInitialized = false;
|
|
30
|
+
unsubscribeFunctions = new Set();
|
|
31
|
+
graphUnsubscribe = null;
|
|
32
|
+
runtimeUnsubscribe = null;
|
|
33
|
+
indexBackend = new IndexBackend();
|
|
34
|
+
indexStore;
|
|
35
|
+
indexesLoaded = false;
|
|
36
|
+
/** Incremented whenever `cache` is replaced, so the index can tell it is stale. */
|
|
37
|
+
cacheGeneration = 0;
|
|
38
|
+
/** The cache generation the index entries currently reflect, or -1 for none. */
|
|
39
|
+
indexedGeneration = -1;
|
|
40
|
+
lastPlan = null;
|
|
41
|
+
/** Cache records addressed by id, valid for `indexedGeneration`. */
|
|
42
|
+
recordsById = null;
|
|
43
|
+
/** Raw payload the cache was parsed from, used to detect that nothing changed. */
|
|
44
|
+
lastRawSnapshot = null;
|
|
45
|
+
/**
|
|
46
|
+
* The runtime revision the cache was built from, when the runtime offers one.
|
|
47
|
+
*
|
|
48
|
+
* Captured *before* the query that produced the cache, never after. A write
|
|
49
|
+
* landing between the two then makes this older than the data it labels,
|
|
50
|
+
* which costs one unnecessary refresh. Capturing it after would make it
|
|
51
|
+
* newer than the data, and the cache would look current forever.
|
|
52
|
+
*/
|
|
53
|
+
cachedRevision = null;
|
|
54
|
+
/** How the last refresh decided the cache was usable. Reporting only. */
|
|
55
|
+
lastFreshness = null;
|
|
21
56
|
constructor(db, name, predicate, parent, loadIndexes = true) {
|
|
22
|
-
this.predicate = null;
|
|
23
|
-
this.cache = [];
|
|
24
|
-
this.subscribers = new Set();
|
|
25
|
-
this.parent = null;
|
|
26
|
-
this.parentId = null;
|
|
27
|
-
this.isInitialized = false;
|
|
28
|
-
this.unsubscribeFunctions = new Set();
|
|
29
|
-
this.graphUnsubscribe = null;
|
|
30
|
-
this.runtimeUnsubscribe = null;
|
|
31
|
-
this.indexBackend = new IndexBackend();
|
|
32
|
-
this.indexesLoaded = false;
|
|
33
|
-
/** Incremented whenever `cache` is replaced, so the index can tell it is stale. */
|
|
34
|
-
this.cacheGeneration = 0;
|
|
35
|
-
/** The cache generation the index entries currently reflect, or -1 for none. */
|
|
36
|
-
this.indexedGeneration = -1;
|
|
37
|
-
this.lastPlan = null;
|
|
38
|
-
/** Cache records addressed by id, valid for `indexedGeneration`. */
|
|
39
|
-
this.recordsById = null;
|
|
40
|
-
/** Raw payload the cache was parsed from, used to detect that nothing changed. */
|
|
41
|
-
this.lastRawSnapshot = null;
|
|
42
|
-
/**
|
|
43
|
-
* The runtime revision the cache was built from, when the runtime offers one.
|
|
44
|
-
*
|
|
45
|
-
* Captured *before* the query that produced the cache, never after. A write
|
|
46
|
-
* landing between the two then makes this older than the data it labels,
|
|
47
|
-
* which costs one unnecessary refresh. Capturing it after would make it
|
|
48
|
-
* newer than the data, and the cache would look current forever.
|
|
49
|
-
*/
|
|
50
|
-
this.cachedRevision = null;
|
|
51
|
-
/** How the last refresh decided the cache was usable. Reporting only. */
|
|
52
|
-
this.lastFreshness = null;
|
|
53
57
|
this.db = db;
|
|
54
58
|
this.name = name;
|
|
55
59
|
this.collectionId = `${name}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -690,6 +694,10 @@ export class Collection {
|
|
|
690
694
|
* Relationship helper for loading related data.
|
|
691
695
|
*/
|
|
692
696
|
export class Relationship {
|
|
697
|
+
parentDb;
|
|
698
|
+
childDb;
|
|
699
|
+
childCollection;
|
|
700
|
+
foreignKey;
|
|
693
701
|
constructor(parentDb, childDb, childCollection, foreignKey) {
|
|
694
702
|
this.parentDb = parentDb;
|
|
695
703
|
this.childDb = childDb;
|
package/dist/create/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import { spawn, spawnSync } from 'child_process';
|
|
|
11
11
|
import { createProject } from './create.js';
|
|
12
12
|
import { FELTDB_PACKAGE_VERSION } from './package-versions.js';
|
|
13
13
|
import { configureManagedAccount } from './managed-account.js';
|
|
14
|
+
import { localFeltdbExecutable } from './development-handoff.js';
|
|
14
15
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
function parseArgs(args) {
|
|
16
17
|
const options = {
|
|
@@ -235,7 +236,7 @@ Options:
|
|
|
235
236
|
--no-webllm Do not install WebLLM or generate the AI builder
|
|
236
237
|
--capabilities <list> Choose capabilities: search, vector, or search,vector
|
|
237
238
|
--no-install Skip npm install
|
|
238
|
-
--no-start Skip
|
|
239
|
+
--no-start Skip automatic feltdb dev startup
|
|
239
240
|
-y, --yes Use all defaults (non-interactive mode)
|
|
240
241
|
-h, --help Show this help message
|
|
241
242
|
--version Show version number
|
|
@@ -314,6 +315,7 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
314
315
|
agents: options.agents,
|
|
315
316
|
webllm: options.webllm,
|
|
316
317
|
capabilities: options.capabilities,
|
|
318
|
+
showNextSteps: false,
|
|
317
319
|
});
|
|
318
320
|
projectCreated = true;
|
|
319
321
|
if (options.runtime === 'managed') {
|
|
@@ -335,18 +337,18 @@ Learn more: https://github.com/rkendel1/feltdb`);
|
|
|
335
337
|
}
|
|
336
338
|
if (shouldStart) {
|
|
337
339
|
if (!shouldInstall) {
|
|
338
|
-
console.log(`Start after installing dependencies:\n cd ${projectName}\n npm install\n npm run dev\n`);
|
|
340
|
+
console.log(`Start after installing dependencies:\n cd ${projectName}\n npm install\n npm run feltdb:dev\n`);
|
|
339
341
|
}
|
|
340
342
|
else {
|
|
341
343
|
if (options.runtime === 'self-hosted' && spawnSync('docker', ['version'], { stdio: 'ignore' }).status !== 0) {
|
|
342
344
|
console.log('\n✅ Project and Docker image definition are ready.');
|
|
343
345
|
console.log('Docker is not currently running, so startup was skipped.');
|
|
344
|
-
console.log(`Start Docker Desktop, then run:\n cd ${projectName}\n npm run dev`);
|
|
346
|
+
console.log(`Start Docker Desktop, then run:\n cd ${projectName}\n npm run feltdb:dev`);
|
|
345
347
|
console.log('Build the production application image with: docker compose build app');
|
|
346
348
|
}
|
|
347
349
|
else {
|
|
348
|
-
console.log('\n🚀 Starting
|
|
349
|
-
await run(
|
|
350
|
+
console.log('\n🚀 Starting your FeltDB development session...\n');
|
|
351
|
+
await run(localFeltdbExecutable(projectDir), ['dev'], projectDir);
|
|
350
352
|
}
|
|
351
353
|
}
|
|
352
354
|
}
|
package/dist/create/create.js
CHANGED
|
@@ -87,7 +87,7 @@ export async function createProject(options) {
|
|
|
87
87
|
application: {
|
|
88
88
|
lifecycle: 'managed',
|
|
89
89
|
},
|
|
90
|
-
applicationUrl: 'http://
|
|
90
|
+
applicationUrl: 'http://localhost:5173/',
|
|
91
91
|
capabilities: {},
|
|
92
92
|
};
|
|
93
93
|
if (capabilities.includes('search')) {
|
|
@@ -1657,7 +1657,7 @@ Configuration is in \`feltdb.config.json\`:
|
|
|
1657
1657
|
"application": {
|
|
1658
1658
|
"lifecycle": "managed"
|
|
1659
1659
|
},
|
|
1660
|
-
"applicationUrl": "http://
|
|
1660
|
+
"applicationUrl": "http://localhost:5173/",
|
|
1661
1661
|
"capabilities": ["${capabilities}"]
|
|
1662
1662
|
}
|
|
1663
1663
|
\`\`\`
|
|
@@ -1810,9 +1810,11 @@ MIT
|
|
|
1810
1810
|
console.log(`\n✓ Development Workspace initialized`);
|
|
1811
1811
|
console.log(` Workspace ID: ${workspaceDiscovery.workspaceId}`);
|
|
1812
1812
|
console.log(` Location: ${path.join(projectName, '.feltdb/workspace.json')}`);
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1813
|
+
if (options.showNextSteps !== false) {
|
|
1814
|
+
console.log(`\nNext steps:`);
|
|
1815
|
+
console.log(` cd ${projectName}`);
|
|
1816
|
+
console.log(` npm install`);
|
|
1817
|
+
console.log(` npm run feltdb:dev`);
|
|
1818
|
+
console.log(`\nYour Development Workspace is ready for use!`);
|
|
1819
|
+
}
|
|
1818
1820
|
}
|
|
@@ -38,9 +38,9 @@ export function generateDockerCompose(config) {
|
|
|
38
38
|
- --data
|
|
39
39
|
- /data/feltdb.log
|
|
40
40
|
- --allow-origin
|
|
41
|
-
- http://
|
|
41
|
+
- http://localhost:\${APP_PORT:-5173}
|
|
42
42
|
- --allow-origin
|
|
43
|
-
- http://
|
|
43
|
+
- http://localhost:\${STUDIO_PORT:-${config.studioPort}}
|
|
44
44
|
volumes:
|
|
45
45
|
- feltdb_data:/data
|
|
46
46
|
- ./feltdb.flow:/app/feltdb.flow:ro
|
|
@@ -97,7 +97,7 @@ export function generateDockerCompose(config) {
|
|
|
97
97
|
container_name: \${COMPOSE_PROJECT_NAME}-studio
|
|
98
98
|
environment:
|
|
99
99
|
FELTDB_API_URL: \${FELTDB_PUBLIC_URL:-http://127.0.0.1:${config.port}}
|
|
100
|
-
APP_URL: \${APP_PUBLIC_URL:-http://
|
|
100
|
+
APP_URL: \${APP_PUBLIC_URL:-http://localhost:5173/}
|
|
101
101
|
FELTDB_NAMESPACE: \${FELTDB_APP_ID:-${config.appId}}
|
|
102
102
|
ports:
|
|
103
103
|
- "\${STUDIO_PORT:-${config.studioPort}}:8000"
|
|
@@ -140,7 +140,7 @@ USER feltdb
|
|
|
140
140
|
EXPOSE 7700
|
|
141
141
|
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=3 CMD curl -fsS http://127.0.0.1:7700/health || exit 1
|
|
142
142
|
ENTRYPOINT ["/sbin/tini", "--"]
|
|
143
|
-
CMD ["feltdb-server", "--host", "0.0.0.0", "--port", "7700", "--namespace", "${config.appId}", "--data", "/data/feltdb.log", "--allow-origin", "http://
|
|
143
|
+
CMD ["feltdb-server", "--host", "0.0.0.0", "--port", "7700", "--namespace", "${config.appId}", "--data", "/data/feltdb.log", "--allow-origin", "http://localhost:5173", "--allow-origin", "http://localhost:${config.studioPort}"]
|
|
144
144
|
`;
|
|
145
145
|
}
|
|
146
146
|
export function generateStudioDockerfile(config) {
|
|
@@ -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.6.
|
|
3
|
+
export const FELTDB_PACKAGE_VERSION = '0.6.14';
|
|
4
4
|
export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
|