@igoruehara/canvas-flow 0.1.0 → 0.1.2

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
@@ -12,22 +12,22 @@ Canvas Flow roda frontend e backend juntos a partir de um pacote npm.
12
12
  Este caminho sobe MongoDB local automaticamente e abre o navegador.
13
13
 
14
14
  ```bash
15
- npx canvas-flow@latest --with-docker --open
15
+ npx @igoruehara/canvas-flow@latest --with-docker --open
16
16
  ```
17
17
 
18
18
  Para RAG local com Milvus, MinIO e etcd:
19
19
 
20
20
  ```bash
21
- npx canvas-flow@latest infra up --full
22
- npx canvas-flow@latest --open
21
+ npx @igoruehara/canvas-flow@latest infra up --full
22
+ npx @igoruehara/canvas-flow@latest --open
23
23
  ```
24
24
 
25
25
  Comandos uteis:
26
26
 
27
27
  ```bash
28
- npx canvas-flow@latest infra status
29
- npx canvas-flow@latest infra logs
30
- npx canvas-flow@latest infra down
28
+ npx @igoruehara/canvas-flow@latest infra status
29
+ npx @igoruehara/canvas-flow@latest infra logs
30
+ npx @igoruehara/canvas-flow@latest infra down
31
31
  ```
32
32
 
33
33
  `infra down` para os containers, mas mantem os volumes Docker.
@@ -37,7 +37,7 @@ npx canvas-flow@latest infra down
37
37
  Use este caminho quando voce ja tem MongoDB local, Atlas ou outro Mongo remoto.
38
38
 
39
39
  ```bash
40
- npx canvas-flow@latest --open
40
+ npx @igoruehara/canvas-flow@latest --open
41
41
  ```
42
42
 
43
43
  Mongo local padrao:
@@ -49,7 +49,7 @@ mongodb://127.0.0.1:27017/canvas_flow
49
49
  Para usar outro Mongo, edite a config:
50
50
 
51
51
  ```bash
52
- npx canvas-flow@latest config --edit
52
+ npx @igoruehara/canvas-flow@latest config --edit
53
53
  ```
54
54
 
55
55
  ```json
@@ -77,13 +77,13 @@ C:\Users\<usuario>\.canvas-flow\config.json
77
77
  Abrir a config:
78
78
 
79
79
  ```bash
80
- npx canvas-flow@latest config --edit
80
+ npx @igoruehara/canvas-flow@latest config --edit
81
81
  ```
82
82
 
83
83
  Ver o caminho da config:
84
84
 
85
85
  ```bash
86
- npx canvas-flow@latest config
86
+ npx @igoruehara/canvas-flow@latest config
87
87
  ```
88
88
 
89
89
  Exemplo com OpenAI:
@@ -112,7 +112,7 @@ Exemplo com porta customizada:
112
112
  Tambem da para usar outro arquivo:
113
113
 
114
114
  ```bash
115
- npx canvas-flow@latest --config C:\canvas-flow\config.json --open
115
+ npx @igoruehara/canvas-flow@latest --config C:\canvas-flow\config.json --open
116
116
  ```
117
117
 
118
118
  Nao publique `config.json`: ele contem tokens e secrets gerados.
@@ -120,13 +120,13 @@ Nao publique `config.json`: ele contem tokens e secrets gerados.
120
120
  ## Validar
121
121
 
122
122
  ```bash
123
- npx canvas-flow@latest doctor
123
+ npx @igoruehara/canvas-flow@latest doctor
124
124
  ```
125
125
 
126
126
  Sem checar rede/Mongo:
127
127
 
128
128
  ```bash
129
- npx canvas-flow@latest doctor --offline
129
+ npx @igoruehara/canvas-flow@latest doctor --offline
130
130
  ```
131
131
 
132
132
  ## Instalar globalmente
@@ -134,7 +134,7 @@ npx canvas-flow@latest doctor --offline
134
134
  Opcional:
135
135
 
136
136
  ```bash
137
- npm i -g canvas-flow
137
+ npm i -g @igoruehara/canvas-flow
138
138
  canvas-flow --with-docker --open
139
139
  ```
140
140
 
@@ -50,6 +50,7 @@ Options:
50
50
  --edit Open config file with "init" or "config"
51
51
  --force Overwrite config on init
52
52
  --offline Skip network checks with "doctor"
53
+ --skip-mongo-check Start without preflight MongoDB connection check
53
54
  --strict Treat doctor warnings as failures
54
55
  --help Show this help
55
56
 
@@ -810,6 +811,48 @@ async function checkMongoReachability(uri) {
810
811
  };
811
812
  }
812
813
 
814
+ function sleep(ms) {
815
+ return new Promise((resolve) => setTimeout(resolve, ms));
816
+ }
817
+
818
+ function mongoConnectionOptions(config) {
819
+ return {
820
+ serverSelectionTimeoutMS: Number(config.database?.mongoServerSelectionTimeoutMs || 8000),
821
+ connectTimeoutMS: Number(config.database?.mongoConnectTimeoutMs || 8000),
822
+ };
823
+ }
824
+
825
+ async function checkMongoConnection(uri, options = {}) {
826
+ let connection;
827
+ try {
828
+ const mongoose = require('mongoose');
829
+ connection = mongoose.createConnection(uri, options);
830
+ await connection.asPromise();
831
+ return { ok: true, message: 'connected' };
832
+ } catch (error) {
833
+ return { ok: false, message: error && error.message ? error.message : String(error) };
834
+ } finally {
835
+ if (connection) {
836
+ await connection.close().catch(() => undefined);
837
+ }
838
+ }
839
+ }
840
+
841
+ function isLocalMongoUri(uri) {
842
+ return mongoTargetsFromUri(uri).some((target) => (
843
+ target.host === '127.0.0.1' ||
844
+ target.host === 'localhost' ||
845
+ target.host === '::1'
846
+ ));
847
+ }
848
+
849
+ function mongoConnectionHint(uri) {
850
+ if (isLocalMongoUri(uri)) {
851
+ return 'Start local Mongo with "canvas-flow infra up", or run with "canvas-flow --with-docker --open".';
852
+ }
853
+ return 'Check database.mongoUrl credentials, network access, and the MongoDB Atlas IP access list.';
854
+ }
855
+
813
856
  function dockerComposeBaseArgs() {
814
857
  return [
815
858
  'compose',
@@ -936,6 +979,7 @@ function createDoctorReporter(strict) {
936
979
 
937
980
  async function doctor(flags) {
938
981
  const reporter = createDoctorReporter(flags.strict === true);
982
+ addSourceDependencyFallback();
939
983
  const paths = resolvePaths(flags);
940
984
  ensureDir(paths.homeDir);
941
985
 
@@ -975,11 +1019,11 @@ async function doctor(flags) {
975
1019
  if (config.database.mongoUrl) {
976
1020
  reporter.pass('Mongo config', 'MONGO_DB_CONNECTION_STRING is set');
977
1021
  if (flags.offline === true) {
978
- reporter.warn('Mongo reachability', 'skipped because --offline was used');
1022
+ reporter.warn('Mongo connection', 'skipped because --offline was used');
979
1023
  } else {
980
- const mongoCheck = await checkMongoReachability(config.database.mongoUrl);
981
- if (mongoCheck.ok) reporter.pass('Mongo reachability', mongoCheck.message);
982
- else reporter.fail('Mongo reachability', `${mongoCheck.message}; run "canvas-flow infra up" to start local Mongo with Docker`);
1024
+ const mongoCheck = await checkMongoConnection(config.database.mongoUrl, mongoConnectionOptions(config));
1025
+ if (mongoCheck.ok) reporter.pass('Mongo connection', mongoCheck.message);
1026
+ else reporter.fail('Mongo connection', `${mongoCheck.message}; ${mongoConnectionHint(config.database.mongoUrl)}`);
983
1027
  }
984
1028
  } else {
985
1029
  reporter.fail('Mongo config', 'database.mongoUrl is required');
@@ -1044,7 +1088,41 @@ async function doctor(flags) {
1044
1088
  reporter.finish();
1045
1089
  }
1046
1090
 
1047
- function start(flags) {
1091
+ async function waitForMongo(config, flags, paths) {
1092
+ if (flags['skip-mongo-check'] === true) return;
1093
+ if (!config.database.mongoUrl) {
1094
+ throw new Error(`database.mongoUrl is required. Edit the config with: canvas-flow config --edit`);
1095
+ }
1096
+
1097
+ const attempts = (flags['with-docker'] === true || flags.infra === true) && isLocalMongoUri(config.database.mongoUrl)
1098
+ ? 20
1099
+ : 1;
1100
+ const options = mongoConnectionOptions(config);
1101
+ let lastMessage = '';
1102
+
1103
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
1104
+ const result = await checkMongoConnection(config.database.mongoUrl, options);
1105
+ if (result.ok) {
1106
+ console.log('MongoDB preflight: connected');
1107
+ return;
1108
+ }
1109
+
1110
+ lastMessage = result.message;
1111
+ if (attempt < attempts) {
1112
+ console.log(`MongoDB preflight waiting (${attempt}/${attempts}): ${result.message}`);
1113
+ await sleep(1500);
1114
+ }
1115
+ }
1116
+
1117
+ throw new Error([
1118
+ `MongoDB preflight failed: ${lastMessage}`,
1119
+ mongoConnectionHint(config.database.mongoUrl),
1120
+ `Config file: ${paths.configPath}`,
1121
+ 'Use "canvas-flow doctor" for a detailed readiness check.',
1122
+ ].join('\n'));
1123
+ }
1124
+
1125
+ async function start(flags) {
1048
1126
  assertBundleExists();
1049
1127
  addSourceDependencyFallback();
1050
1128
  if (flags['with-docker'] === true || flags.infra === true) {
@@ -1055,6 +1133,7 @@ function start(flags) {
1055
1133
  const configExisted = fs.existsSync(paths.configPath);
1056
1134
  const config = loadConfig(paths.configPath);
1057
1135
  const runtime = applyEnvironment(config, paths, flags);
1136
+ await waitForMongo(config, flags, paths);
1058
1137
 
1059
1138
  process.chdir(paths.homeDir);
1060
1139
 
@@ -1117,7 +1196,7 @@ async function main() {
1117
1196
  }
1118
1197
 
1119
1198
  if (args.command === 'start' || args.command === 'run') {
1120
- start(args.flags);
1199
+ await start(args.flags);
1121
1200
  return;
1122
1201
  }
1123
1202
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "@igoruehara/canvas-flow",
3
- "version": "0.1.0",
2
+ "name": "@igoruehara/canvas-flow",
3
+ "version": "0.1.2",
4
4
  "description": "Standalone npm launcher for Canvas Flow multi-agent GenAI workflows.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -65,4 +65,4 @@
65
65
  "overrides": {
66
66
  "uuid": "^11.1.1"
67
67
  }
68
- }
68
+ }
@@ -12,13 +12,17 @@ exports.databaseProviders = [
12
12
  const uri = configService.get('MONGO_DB_CONNECTION_STRING') ||
13
13
  'mongodb://127.0.0.1:27017/canvas_flow';
14
14
  mongoose.set('bufferCommands', false);
15
- await mongoose
16
- .connect(uri, {
17
- serverSelectionTimeoutMS: Number(configService.get('MONGO_SERVER_SELECTION_TIMEOUT_MS') || 8000),
18
- connectTimeoutMS: Number(configService.get('MONGO_CONNECT_TIMEOUT_MS') || 8000),
19
- })
20
- .then(() => console.log('MongoDB connected'))
21
- .catch((error) => console.warn(`MongoDB connection skipped: ${error?.message || String(error)}`));
15
+ try {
16
+ await mongoose.connect(uri, {
17
+ serverSelectionTimeoutMS: Number(configService.get('MONGO_SERVER_SELECTION_TIMEOUT_MS') || 8000),
18
+ connectTimeoutMS: Number(configService.get('MONGO_CONNECT_TIMEOUT_MS') || 8000),
19
+ });
20
+ console.log('MongoDB connected');
21
+ }
22
+ catch (error) {
23
+ console.error(`MongoDB connection failed: ${error?.message || String(error)}`);
24
+ throw error;
25
+ }
22
26
  return mongoose;
23
27
  },
24
28
  },
@@ -1 +1 @@
1
- {"version":3,"file":"database.providers.js","sourceRoot":"","sources":["../../src/database/database.providers.ts"],"names":[],"mappings":";;;AAAA,qCAAqC;AACrC,2CAA+C;AAC/C,4DAAuE;AAE1D,QAAA,iBAAiB,GAAG;IAC/B;QACE,OAAO,EAAE,iDAA8B;QACvC,MAAM,EAAE,CAAC,sBAAa,CAAC;QACvB,UAAU,EAAE,KAAK,EAAE,aAA4B,EAA4B,EAAE;YAC3E,MAAM,GAAG,GACP,aAAa,CAAC,GAAG,CAAS,4BAA4B,CAAC;gBACvD,uCAAuC,CAAC;YAC1C,QAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;YACtC,MAAM,QAAQ;iBACX,OAAO,CAAC,GAAG,EAAE;gBACZ,wBAAwB,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,mCAAmC,CAAC,IAAI,IAAI,CAAC;gBAChG,gBAAgB,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,IAAI,CAAC;aAChF,CAAC;iBACD,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;iBAC5C,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,+BAA+B,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACpG,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"database.providers.js","sourceRoot":"","sources":["../../src/database/database.providers.ts"],"names":[],"mappings":";;;AAAA,qCAAqC;AACrC,2CAA+C;AAC/C,4DAAuE;AAE1D,QAAA,iBAAiB,GAAG;IAC/B;QACE,OAAO,EAAE,iDAA8B;QACvC,MAAM,EAAE,CAAC,sBAAa,CAAC;QACvB,UAAU,EAAE,KAAK,EAAE,aAA4B,EAA4B,EAAE;YAC3E,MAAM,GAAG,GACP,aAAa,CAAC,GAAG,CAAS,4BAA4B,CAAC;gBACvD,uCAAuC,CAAC;YAC1C,QAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE;oBAC1B,wBAAwB,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,mCAAmC,CAAC,IAAI,IAAI,CAAC;oBAChG,gBAAgB,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,IAAI,CAAC;iBAChF,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACnC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC/E,MAAM,KAAK,CAAC;YACd,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF;CACF,CAAC"}