@feltdb/core 0.11.0 → 0.11.1

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.
@@ -9,7 +9,7 @@ import { createRequire } from 'node:module';
9
9
  import { spawn, spawnSync } from 'child_process';
10
10
  import { randomBytes } from 'crypto';
11
11
  import { createInterface } from 'node:readline/promises';
12
- import { createFeltDB, diffFlowSpec, formatFlowSpec, InvestigationLifecycleManager, listFeltDBModules, parseFlowSpec, planFlowSpecMigration, renderConvergenceDiagnostic, renderProposalDiagnostic, resolveFeltDBModule, resolveModuleIntent, startLocalDevelopmentAuthority, validateFlowSpec, verifyProposalConvergence } from '@feltdb/core';
12
+ import { createFeltDB, diffFlowSpec, emptyFlowSpec, formatFlowSpec, InvestigationLifecycleManager, listFeltDBModules, parseFlowSpec, planFlowSpecMigration, renderConvergenceDiagnostic, renderProposalDiagnostic, resolveFeltDBModule, resolveModuleIntent, startLocalDevelopmentAuthority, validateFlowSpec, verifyProposalConvergence } from '@feltdb/core';
13
13
  import { collectApplicationUnderstanding } from '@feltdb/core';
14
14
  import { collectRepositoryEvidence } from './repository-evidence.js';
15
15
  import { discoverWorkspace, ensureWorkspaceGitIgnored, generatePairingToken, persistPairingToken, displayWorkspaceStatus, initializeWorkspace, startPairingDiscoveryServer } from './workspace-integration.js';
@@ -902,9 +902,40 @@ async function promptSecret(message) {
902
902
  input.on('keypress', onKeypress);
903
903
  });
904
904
  }
905
+ export function ensureManagedProjectContract(projectDir) {
906
+ const projectName = path.basename(projectDir);
907
+ const flowApp = projectName.replace(/[^A-Za-z0-9_]/g, '_').replace(/^[^A-Za-z_]/, '_$&');
908
+ const configPath = path.join(projectDir, 'feltdb.config.json');
909
+ const flowPath = path.join(projectDir, 'feltdb.flow');
910
+ const created = { config: false, flow: false };
911
+ if (!fs.existsSync(configPath)) {
912
+ fs.writeFileSync(configPath, `${JSON.stringify({
913
+ namespace: projectName,
914
+ mode: 'remote',
915
+ runtime: 'managed',
916
+ storage: 'managed',
917
+ application: { lifecycle: 'managed' },
918
+ }, null, 2)}\n`);
919
+ created.config = true;
920
+ }
921
+ if (!fs.existsSync(flowPath)) {
922
+ const draft = formatFlowSpec(emptyFlowSpec(flowApp)).replace(/\n\napp /, '\n\n// Recovery draft: define the application contract before publishing.\napp ');
923
+ fs.writeFileSync(flowPath, draft);
924
+ created.flow = true;
925
+ }
926
+ return { ...created, configPath, flowPath };
927
+ }
905
928
  async function handleInitManaged(args) {
906
929
  loadProjectEnvironment();
907
930
  const projectDir = process.cwd();
931
+ const initialized = ensureManagedProjectContract(projectDir);
932
+ if (initialized.config)
933
+ console.log('✓ Created feltdb.config.json');
934
+ if (initialized.flow) {
935
+ console.log('⚠️ feltdb.flow was missing; created an empty recovery draft.');
936
+ console.log(' FeltDB cannot infer the application authority from source code.');
937
+ console.log(' Review and complete feltdb.flow before publishing.\n');
938
+ }
908
939
  // Check if already managed
909
940
  const managedState = readManagedProjectState(projectDir);
910
941
  if (managedState.applicationId) {
@@ -915,7 +946,8 @@ async function handleInitManaged(args) {
915
946
  if (managedState.revisionId) {
916
947
  console.log(`Revision: ${managedState.revisionId}`);
917
948
  }
918
- console.log('\nTo update credentials, manually edit .env.local and .feltdb/managed.json\n');
949
+ console.log('\nTo publish the local authority contract, run:');
950
+ console.log(' feltdb publish --approve-destructive-changes --yes\n');
919
951
  return;
920
952
  }
921
953
  // Prompt for credentials
@@ -930,9 +962,7 @@ async function handleInitManaged(args) {
930
962
  prompt.close();
931
963
  console.log('\nProvisioning managed account...\n');
932
964
  try {
933
- const projectConfig = fs.existsSync(path.join(projectDir, 'feltdb.config.json'))
934
- ? JSON.parse(fs.readFileSync(path.join(projectDir, 'feltdb.config.json'), 'utf8'))
935
- : {};
965
+ const projectConfig = JSON.parse(fs.readFileSync(initialized.configPath, 'utf8'));
936
966
  const namespace = projectConfig.namespace || path.basename(projectDir);
937
967
  const applicationName = projectConfig.name || path.basename(projectDir);
938
968
  const managed = await configureManagedAccount({
@@ -945,22 +975,24 @@ async function handleInitManaged(args) {
945
975
  console.log(`✓ Managed application: ${managed.application.name}`);
946
976
  console.log(`✓ Namespace: ${managed.application.namespace || namespace}`);
947
977
  console.log(`✓ Environment configured in .env.local\n`);
978
+ if (initialized.flow) {
979
+ console.log('✅ Managed connection setup complete.');
980
+ console.log('Automatic publication was skipped because feltdb.flow had to be recovered.');
981
+ console.log('Review feltdb.flow, then run:');
982
+ console.log(' feltdb validate');
983
+ console.log(' feltdb publish --approve-destructive-changes --yes\n');
984
+ return;
985
+ }
948
986
  // Ask if user wants to publish the initial revision
949
987
  const publishPrompt = await import('node:readline/promises').then(m => m.createInterface({ input: process.stdin, output: process.stdout }));
950
988
  const shouldPublish = await publishPrompt.question('Publish initial application revision now? [Y/n] ');
951
989
  publishPrompt.close();
952
990
  if (!/^(n|no)$/i.test(shouldPublish.trim())) {
953
991
  console.log('\n🔨 Building and publishing initial revision...\n');
954
- const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
955
- // Run publish
956
- await new Promise((resolve, reject) => {
957
- const child = spawn(npm, ['run', 'feltdb:publish'], {
958
- cwd: projectDir,
959
- stdio: 'inherit',
960
- env: process.env,
961
- });
962
- child.once('error', reject);
963
- child.once('exit', code => code === 0 ? resolve() : reject(new Error(`feltdb publish exited with status ${code ?? 'unknown'}`)));
992
+ await publishApplication({
993
+ cwd: projectDir,
994
+ yes: true,
995
+ approveDestructive: true,
964
996
  });
965
997
  console.log('\n✓ Initial revision published\n');
966
998
  // Finalize and verify
@@ -976,7 +1008,7 @@ async function handleInitManaged(args) {
976
1008
  else {
977
1009
  console.log('\n✅ Managed setup complete!\n');
978
1010
  console.log('Next steps:');
979
- console.log(' 1. npm run feltdb:publish (to publish your initial revision)');
1011
+ console.log(' 1. feltdb publish --approve-destructive-changes --yes (to publish your initial revision)');
980
1012
  console.log(' 2. npm run dev (to start development)\n');
981
1013
  }
982
1014
  }
@@ -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.11.0';
3
+ export const FELTDB_PACKAGE_VERSION = '0.11.1';
4
4
  export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feltdb/core",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "FeltDB Core - Application-facing database with Browser, Local, and Server runtimes. Durable state, reactive APIs.",
5
5
  "license": "MIT",
6
6
  "type": "module",