@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.
Files changed (69) hide show
  1. package/dist/agent-registry.js +1 -3
  2. package/dist/agent-runtime.js +8 -7
  3. package/dist/analytics-backend.js +3 -1
  4. package/dist/application-contract.js +1 -0
  5. package/dist/application-manifest.js +1 -0
  6. package/dist/artifact.js +2 -0
  7. package/dist/authorization.js +2 -0
  8. package/dist/bundle.js +2 -0
  9. package/dist/capability.js +1 -3
  10. package/dist/cell.js +9 -4
  11. package/dist/cli/application.js +1 -1
  12. package/dist/cli/browser-opening.js +35 -0
  13. package/dist/cli/commands.js +50 -17
  14. package/dist/cli/index.js +1 -1
  15. package/dist/collection.js +39 -31
  16. package/dist/create/cli.js +7 -5
  17. package/dist/create/create.js +9 -7
  18. package/dist/create/development-handoff.js +4 -0
  19. package/dist/create/docker-compose-generator.js +4 -4
  20. package/dist/create/package-versions.js +1 -1
  21. package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +497 -27
  22. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +452 -0
  23. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +208 -0
  24. package/dist/create/server-source/crates/feltdb/src/convergence.rs +16 -0
  25. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +402 -0
  26. package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +765 -24
  27. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +418 -0
  28. package/dist/create/server-source/crates/feltdb/src/lib.rs +4 -0
  29. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +661 -0
  30. package/dist/db.js +19 -13
  31. package/dist/development-runtime-bridge.js +1 -1
  32. package/dist/distributed-indexing.js +7 -5
  33. package/dist/file-db.js +8 -3
  34. package/dist/flowspec.js +2 -1
  35. package/dist/http-client.js +2 -0
  36. package/dist/http-db.js +16 -1
  37. package/dist/identity.js +1 -0
  38. package/dist/index-analytics.js +6 -7
  39. package/dist/index-backend.js +3 -3
  40. package/dist/index-dashboard.js +10 -13
  41. package/dist/index-manager.js +12 -11
  42. package/dist/index-monitoring.js +9 -4
  43. package/dist/index-store.js +2 -0
  44. package/dist/indexeddb-db.js +27 -23
  45. package/dist/memory-db.js +7 -4
  46. package/dist/observe.js +2 -0
  47. package/dist/provider.js +2 -0
  48. package/dist/query-planner.js +2 -4
  49. package/dist/reactive-graph.js +6 -8
  50. package/dist/release.js +2 -0
  51. package/dist/sharding.js +11 -6
  52. package/dist/state-contract.js +3 -3
  53. package/dist/studio-app/assets/{feltdb_wasm-CJv3wHzi.js → feltdb_wasm-C9xpYtna.js} +1 -1
  54. package/dist/studio-app/assets/feltdb_wasm_bg-BsXHw7eX.wasm +0 -0
  55. package/dist/studio-app/assets/{index-DospFFYE.js → index-D4RZ44qs.js} +4 -4
  56. package/dist/studio-app/index.html +1 -1
  57. package/dist/sync-contract.js +9 -2
  58. package/dist/telemetry.d.ts.map +1 -1
  59. package/dist/telemetry.js +32 -12
  60. package/dist/transaction.js +4 -2
  61. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  62. package/dist/worker.js +2 -0
  63. package/dist/workload.js +2 -0
  64. package/dist/workspace/development-node.js +11 -10
  65. package/dist/workspace/investigation-lifecycle-manager.js +2 -0
  66. package/dist/workspace/investigation-supervisor.js +5 -3
  67. package/dist/workspace/workspace-connection.js +14 -5
  68. package/package.json +1 -1
  69. package/dist/studio-app/assets/feltdb_wasm_bg-C8TG8r2n.wasm +0 -0
@@ -8,9 +8,7 @@
8
8
  * Registry for agent definitions and discovery
9
9
  */
10
10
  export class AgentRegistry {
11
- constructor() {
12
- this.agents = new Map();
13
- }
11
+ agents = new Map();
14
12
  /**
15
13
  * Register an agent definition
16
14
  */
@@ -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
- constructor() {
13
- this.ownership = new Map(); // executionId -> peerId
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
  }
@@ -1,4 +1,5 @@
1
1
  export class ApplicationContractClient {
2
+ request;
2
3
  constructor(request) {
3
4
  this.request = request;
4
5
  }
@@ -1,4 +1,5 @@
1
1
  export class ApplicationManifestClient {
2
+ baseUrl;
2
3
  constructor(baseUrl = '') {
3
4
  this.baseUrl = baseUrl;
4
5
  }
package/dist/artifact.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export class ArtifactClient {
2
+ baseUrl;
3
+ fetcher;
2
4
  constructor(baseUrl = '', fetcher = fetch) {
3
5
  this.baseUrl = baseUrl;
4
6
  this.fetcher = fetcher;
@@ -1,4 +1,6 @@
1
1
  export class AuthorizationClient {
2
+ baseUrl;
3
+ fetcher;
2
4
  constructor(baseUrl = '', fetcher = fetch) {
3
5
  this.baseUrl = baseUrl;
4
6
  this.fetcher = fetcher;
package/dist/bundle.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export class BundleClient {
2
+ baseUrl;
3
+ fetcher;
2
4
  constructor(baseUrl = '', fetcher = fetch) {
3
5
  this.baseUrl = baseUrl;
4
6
  this.fetcher = fetcher;
@@ -4,9 +4,7 @@
4
4
  * Capabilities are distributed, pluggable features like search, vector embeddings, etc.
5
5
  */
6
6
  export class CapabilityRegistry {
7
- constructor() {
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);
@@ -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://127.0.0.1:${project.configuredPort}`;
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
+ }
@@ -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://127.0.0.1:3000)');
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://127.0.0.1:${studioPort}`,
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://127.0.0.1:<port>\n');
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
- ...(open ? [] : ['--no-open']),
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([studio, managedApplication.exited.then(exit => {
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 studio;
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] || '127.0.0.1'
1096
- : '127.0.0.1';
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://127.0.0.1:${port}/${query}`;
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
- const command = process.platform === 'darwin' ? ['open', studioUrl] : process.platform === 'win32' ? ['cmd', '/c', 'start', '', studioUrl] : ['xdg-open', studioUrl];
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.12';
26
+ const VERSION = '0.6.14';
27
27
  function prompt(question) {
28
28
  const rl = readline.createInterface({
29
29
  input: process.stdin,
@@ -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;
@@ -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 npm run dev
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 the application...\n');
349
- await run(npm, ['run', 'dev'], projectDir);
350
+ console.log('\n🚀 Starting your FeltDB development session...\n');
351
+ await run(localFeltdbExecutable(projectDir), ['dev'], projectDir);
350
352
  }
351
353
  }
352
354
  }
@@ -87,7 +87,7 @@ export async function createProject(options) {
87
87
  application: {
88
88
  lifecycle: 'managed',
89
89
  },
90
- applicationUrl: 'http://127.0.0.1:5173',
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://127.0.0.1:5173",
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
- console.log(`\nNext steps:`);
1814
- console.log(` cd ${projectName}`);
1815
- console.log(` npm install`);
1816
- console.log(` npm run dev`);
1817
- console.log(`\nYour Development Workspace is ready for use!`);
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
  }
@@ -0,0 +1,4 @@
1
+ import path from 'path';
2
+ export function localFeltdbExecutable(projectDir, platform = process.platform) {
3
+ return path.join(projectDir, 'node_modules', '.bin', platform === 'win32' ? 'feltdb.cmd' : 'feltdb');
4
+ }
@@ -38,9 +38,9 @@ export function generateDockerCompose(config) {
38
38
  - --data
39
39
  - /data/feltdb.log
40
40
  - --allow-origin
41
- - http://127.0.0.1:\${APP_PORT:-5173}
41
+ - http://localhost:\${APP_PORT:-5173}
42
42
  - --allow-origin
43
- - http://127.0.0.1:\${STUDIO_PORT:-${config.studioPort}}
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://127.0.0.1:5173}
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://127.0.0.1:5173", "--allow-origin", "http://127.0.0.1:${config.studioPort}"]
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.12';
3
+ export const FELTDB_PACKAGE_VERSION = '0.6.14';
4
4
  export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;