@dbos-inc/dbos-sdk 3.0.43-preview → 3.0.45-preview

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 (60) hide show
  1. package/dbos-config.schema.json +50 -15
  2. package/dist/dbos-config.schema.json +50 -15
  3. package/dist/src/client.d.ts.map +1 -1
  4. package/dist/src/client.js +5 -11
  5. package/dist/src/client.js.map +1 -1
  6. package/dist/src/dbos-executor.d.ts +10 -10
  7. package/dist/src/dbos-executor.d.ts.map +1 -1
  8. package/dist/src/dbos-executor.js +8 -9
  9. package/dist/src/dbos-executor.js.map +1 -1
  10. package/dist/src/dbos-runtime/cli.d.ts +1 -15
  11. package/dist/src/dbos-runtime/cli.d.ts.map +1 -1
  12. package/dist/src/dbos-runtime/cli.js +74 -106
  13. package/dist/src/dbos-runtime/cli.js.map +1 -1
  14. package/dist/src/dbos-runtime/config.d.ts +29 -74
  15. package/dist/src/dbos-runtime/config.d.ts.map +1 -1
  16. package/dist/src/dbos-runtime/config.js +163 -462
  17. package/dist/src/dbos-runtime/config.js.map +1 -1
  18. package/dist/src/dbos-runtime/debug.d.ts.map +1 -1
  19. package/dist/src/dbos-runtime/debug.js +2 -1
  20. package/dist/src/dbos-runtime/debug.js.map +1 -1
  21. package/dist/src/dbos-runtime/migrate.d.ts +1 -3
  22. package/dist/src/dbos-runtime/migrate.d.ts.map +1 -1
  23. package/dist/src/dbos-runtime/migrate.js +16 -36
  24. package/dist/src/dbos-runtime/migrate.js.map +1 -1
  25. package/dist/src/dbos-runtime/reset.d.ts +2 -2
  26. package/dist/src/dbos-runtime/reset.d.ts.map +1 -1
  27. package/dist/src/dbos-runtime/reset.js +5 -2
  28. package/dist/src/dbos-runtime/reset.js.map +1 -1
  29. package/dist/src/dbos-runtime/runtime.js +1 -1
  30. package/dist/src/dbos-runtime/runtime.js.map +1 -1
  31. package/dist/src/dbos.d.ts +1 -7
  32. package/dist/src/dbos.d.ts.map +1 -1
  33. package/dist/src/dbos.js +17 -39
  34. package/dist/src/dbos.js.map +1 -1
  35. package/dist/src/index.d.ts +1 -1
  36. package/dist/src/index.d.ts.map +1 -1
  37. package/dist/src/index.js +3 -2
  38. package/dist/src/index.js.map +1 -1
  39. package/dist/src/system_database.d.ts +5 -6
  40. package/dist/src/system_database.d.ts.map +1 -1
  41. package/dist/src/system_database.js +24 -25
  42. package/dist/src/system_database.js.map +1 -1
  43. package/dist/src/telemetry/exporters.d.ts +2 -2
  44. package/dist/src/telemetry/exporters.d.ts.map +1 -1
  45. package/dist/src/telemetry/exporters.js +12 -15
  46. package/dist/src/telemetry/exporters.js.map +1 -1
  47. package/dist/src/user_database.d.ts +1 -1
  48. package/dist/src/user_database.d.ts.map +1 -1
  49. package/dist/src/user_database.js +11 -14
  50. package/dist/src/user_database.js.map +1 -1
  51. package/dist/src/utils.d.ts +2 -1
  52. package/dist/src/utils.d.ts.map +1 -1
  53. package/dist/src/utils.js +20 -4
  54. package/dist/src/utils.js.map +1 -1
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +3 -3
  57. package/dist/src/dbos-runtime/configure.d.ts +0 -2
  58. package/dist/src/dbos-runtime/configure.d.ts.map +0 -1
  59. package/dist/src/dbos-runtime/configure.js +0 -42
  60. package/dist/src/dbos-runtime/configure.js.map +0 -1
@@ -3,8 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.overwrite_config = exports.translatePublicDBOSconfig = exports.processConfigFile = exports.parseConfigFile = exports.parseSSLConfig = exports.constructPoolConfig = exports.writeConfigFile = exports.loadConfigFile = exports.readConfigFile = exports.substituteEnvVars = exports.dbosConfigFilePath = void 0;
7
- const error_1 = require("../error");
6
+ exports.overwriteConfigForDBOSCloud = exports.translateRuntimeConfig = exports.getRuntimeConfig = exports.translateDbosConfig = exports.getDbosConfig = exports.getDatabaseUrl = exports.getSystemDatabaseUrl = exports.writeConfigFile = exports.readConfigFile = exports.substituteEnvVars = exports.dbosConfigFilePath = void 0;
8
7
  const utils_1 = require("../utils");
9
8
  const yaml_1 = __importDefault(require("yaml"));
10
9
  const runtime_1 = require("./runtime");
@@ -12,9 +11,9 @@ const user_database_1 = require("../user_database");
12
11
  const fs_1 = require("fs");
13
12
  const ajv_1 = __importDefault(require("ajv"));
14
13
  const path_1 = __importDefault(require("path"));
15
- const validator_1 = __importDefault(require("validator"));
16
- const logs_1 = require("../telemetry/logs");
17
14
  const dbos_config_schema_json_1 = __importDefault(require("../../dbos-config.schema.json"));
15
+ const assert_1 = __importDefault(require("assert"));
16
+ const validator_1 = __importDefault(require("validator"));
18
17
  exports.dbosConfigFilePath = 'dbos-config.yaml';
19
18
  const ajv = new ajv_1.default({ allErrors: true, verbose: true, allowUnionTypes: true });
20
19
  /*
@@ -58,61 +57,14 @@ function readConfigFile(dirPath) {
58
57
  }
59
58
  }
60
59
  exports.readConfigFile = readConfigFile;
61
- /**
62
- * Loads config file as a ConfigFile.
63
- * @param {string} configFilePath - The path to the config file to be loaded.
64
- * @returns
65
- */
66
- function loadConfigFile(configFilePath) {
67
- try {
68
- const configFileContent = (0, utils_1.readFileSync)(configFilePath);
69
- const interpolatedConfig = substituteEnvVars(configFileContent);
70
- const configFile = yaml_1.default.parse(interpolatedConfig);
71
- if (!configFile) {
72
- throw new Error(`${configFilePath} is empty `);
73
- }
74
- const schemaValidator = ajv.compile(dbos_config_schema_json_1.default);
75
- if (!schemaValidator(configFile)) {
76
- const errorMessages = prettyPrintAjvErrors(schemaValidator);
77
- throw new Error(`${configFilePath} failed schema validation. ${errorMessages}`);
78
- }
79
- if (!configFile.database) {
80
- configFile.database = {}; // Create an empty database object if it doesn't exist
81
- }
82
- // Handle strings in the config file and convert them to arrays
83
- if (configFile.telemetry?.OTLPExporter?.logsEndpoint &&
84
- typeof configFile.telemetry.OTLPExporter.logsEndpoint === 'string') {
85
- configFile.telemetry.OTLPExporter.logsEndpoint = [configFile.telemetry.OTLPExporter.logsEndpoint];
86
- }
87
- if (configFile.telemetry?.OTLPExporter?.tracesEndpoint &&
88
- typeof configFile.telemetry.OTLPExporter.tracesEndpoint === 'string') {
89
- configFile.telemetry.OTLPExporter.tracesEndpoint = [configFile.telemetry.OTLPExporter.tracesEndpoint];
90
- }
91
- return configFile;
92
- }
93
- catch (e) {
94
- if (e instanceof Error) {
95
- throw new error_1.DBOSInitializationError(`Failed to load config from ${configFilePath}: ${e.message}`);
96
- }
97
- else {
98
- throw e;
99
- }
100
- }
101
- }
102
- exports.loadConfigFile = loadConfigFile;
103
- /**
104
- * Writes a YAML.Document object to configFilePath.
105
- * @param {YAML.Document} configFile - The config file to be written.
106
- * @param {string} configFilePath - The path to the config file to be written to.
107
- */
108
60
  function writeConfigFile(configFile, configFilePath) {
109
61
  try {
110
- const configFileContent = configFile.toString();
62
+ const configFileContent = yaml_1.default.stringify(configFile);
111
63
  (0, fs_1.writeFileSync)(configFilePath, configFileContent);
112
64
  }
113
65
  catch (e) {
114
66
  if (e instanceof Error) {
115
- throw new error_1.DBOSInitializationError(`Failed to write config to ${configFilePath}: ${e.message}`);
67
+ throw new Error(`Failed to write config to ${configFilePath}: ${e.message}`);
116
68
  }
117
69
  else {
118
70
  throw e;
@@ -120,457 +72,206 @@ function writeConfigFile(configFile, configFilePath) {
120
72
  }
121
73
  }
122
74
  exports.writeConfigFile = writeConfigFile;
123
- function retrieveApplicationName(configFile) {
124
- let appName = configFile.name;
125
- if (appName !== undefined) {
126
- return appName;
127
- }
128
- const packageJson = JSON.parse((0, utils_1.readFileSync)(path_1.default.join(process.cwd(), 'package.json')).toString());
129
- appName = packageJson.name;
130
- if (appName === undefined) {
131
- throw new error_1.DBOSInitializationError('Error: cannot find a valid package.json file. Please run this command in an application root directory.');
132
- }
133
- return appName;
134
- }
135
- /**
136
- * Build a PoolConfig object.
137
- *
138
- * If configFile.database_url is provided, set it directly in poolConfig.connectionString and backfill the other poolConfig options.
139
- * Backfilling allows the rest of the code to access database parameters easily.
140
- * We configure the ORMs with the connection string
141
- * We still need to extract pool size and connectionTimeoutMillis from the config file and give them manually to the ORMs.
142
- *
143
- * If configFile.database_url is not provided, we build the connection string from the configFile.database object.
144
- *
145
- * In debug mode, apply overrides from DBOS_DBHOST, DBOS_DBPORT, DBOS_DBUSER, and DBOS_DBPASSWORD.
146
- *
147
- * Default configuration:
148
- * - Hostname: localhost
149
- * - Port: 5432
150
- * - Username: postgres
151
- * - Password: $PGPASSWORD
152
- * - Database name: transformed application name. The name is either the one provided in the config file or the one found in package.json.
153
- *
154
- * @param configFile - The configuration to be used.
155
- * @param cliOptions - Optional CLI options.
156
- * @returns PoolConfig - The constructed PoolConfig object.
157
- */
158
- function constructPoolConfig(configFile, cliOptions) {
159
- // FIXME: this is not a good place to set the app name
160
- const appName = retrieveApplicationName(configFile);
161
- const isDebugMode = process.env.DBOS_DEBUG_WORKFLOW_ID !== undefined;
162
- if (!cliOptions?.silent) {
163
- const logger = new logs_1.GlobalLogger();
164
- if (isDebugMode) {
165
- logger.info('Loading database connection parameters from debug environment variables');
166
- }
167
- else if (configFile.database_url) {
168
- logger.info('Loading database connection parameters from database_url');
169
- }
170
- else if (configFile.database?.hostname) {
171
- logger.info('Loading database connection parameters from dbos-config.yaml');
172
- }
173
- else {
174
- logger.info('Using default database connection parameters');
175
- }
75
+ function getSystemDatabaseUrl(configFileOrString) {
76
+ if (typeof configFileOrString === 'string') {
77
+ return convertUserDbUrl(configFileOrString);
176
78
  }
177
- let connectionString = undefined;
178
- let databaseName = undefined;
179
- let connectionTimeoutMillis = 10000;
180
- let ssl = false;
181
- // If a database_url is found, parse it to backfill the poolConfig
182
- if (configFile.database_url) {
183
- const url = new URL(configFile.database_url);
184
- // If in debug mode, apply the debug overrides
185
- if (isDebugMode) {
186
- if (process.env.DBOS_DBHOST) {
187
- url.hostname = process.env.DBOS_DBHOST;
188
- }
189
- if (process.env.DBOS_DBPORT) {
190
- url.port = process.env.DBOS_DBPORT;
191
- }
192
- if (process.env.DBOS_DBUSER) {
193
- url.username = process.env.DBOS_DBUSER;
194
- }
195
- if (process.env.DBOS_DBPASSWORD) {
196
- url.password = process.env.DBOS_DBPASSWORD;
197
- }
198
- configFile.database_url = url.toString();
199
- }
200
- connectionString = configFile.database_url;
201
- databaseName = url.pathname.substring(1);
202
- const queryParams = url.searchParams;
203
- if (queryParams.has('connect_timeout')) {
204
- connectionTimeoutMillis = parseInt(queryParams.get('connect_timeout'), 10) * 1000;
205
- }
206
- const sslMode = queryParams.get('sslmode');
207
- const sslRootCert = queryParams.get('sslrootcert');
208
- ssl = getSSLFromParams(sslMode, sslRootCert);
209
- // Validate required fields
210
- const missingFields = [];
211
- if (!url.username)
212
- missingFields.push('username');
213
- if (!url.hostname)
214
- missingFields.push('hostname');
215
- if (!databaseName)
216
- missingFields.push('database name');
217
- if (missingFields.length > 0) {
218
- throw new Error(`Invalid database URL: missing required field(s): ${missingFields.join(', ')}`);
219
- }
220
- // Backfill the poolConfig
221
- configFile.database = {
222
- ...configFile.database,
223
- hostname: url.hostname,
224
- port: url.port ? parseInt(url.port, 10) : 5432,
225
- username: url.username,
226
- password: url.password,
227
- app_db_name: databaseName,
228
- };
229
- if (!cliOptions?.silent) {
230
- const logger = new logs_1.GlobalLogger();
231
- let logConnectionString = `postgresql://${configFile.database.username}:***@${configFile.database.hostname}:${configFile.database.port}/${databaseName}`;
232
- const logQueryParamsArray = Object.entries(url.searchParams.entries()).map(([key, value]) => `${key}=${value}`);
233
- if (logQueryParamsArray.length > 0) {
234
- logConnectionString += `?${logQueryParamsArray.join('&')}`;
235
- }
236
- logger.info(`Using database connection string: ${logConnectionString}`);
237
- }
79
+ if (configFileOrString.system_database_url) {
80
+ return configFileOrString.system_database_url;
238
81
  }
239
- else {
240
- // Else, build the config from configFile.database and apply overrides
241
- configFile.database ??= {};
242
- configFile.database.hostname = process.env.DBOS_DBHOST || configFile.database.hostname || 'localhost';
243
- const dbos_dbport = process.env.DBOS_DBPORT ? parseInt(process.env.DBOS_DBPORT) : undefined;
244
- configFile.database.port = dbos_dbport || configFile.database.port || 5432;
245
- configFile.database.username = process.env.DBOS_DBUSER || configFile.database.username || 'postgres';
246
- configFile.database.password =
247
- process.env.DBOS_DBPASSWORD || configFile.database.password || process.env.PGPASSWORD || 'dbos';
248
- connectionTimeoutMillis = configFile.database.connectionTimeoutMillis || 10000;
249
- databaseName = configFile.database.app_db_name;
250
- // Construct the database name from the application name, if needed
251
- if (databaseName === undefined || databaseName === '') {
252
- databaseName = appName.toLowerCase().replaceAll('-', '_').replaceAll(' ', '_');
253
- if (databaseName.match(/^\d/)) {
254
- databaseName = '_' + databaseName; // Append an underscore if the name starts with a digit
255
- }
256
- }
257
- connectionString = `postgresql://${configFile.database.username}:${configFile.database.password}@${configFile.database.hostname}:${configFile.database.port}/${databaseName}`;
258
- // Build connection string query parameters
259
- const queryParams = [];
260
- queryParams.push(`connect_timeout=${connectionTimeoutMillis / 1000}`);
261
- // SSL configuration
262
- ssl = parseSSLConfig(configFile.database);
263
- if (ssl === false) {
264
- queryParams.push(`sslmode=disable`);
265
- }
266
- else if (ssl && 'ca' in ssl) {
267
- queryParams.push(`sslmode=verify-full`);
268
- queryParams.push(`sslrootcert=${configFile.database.ssl_ca}`);
269
- }
270
- else {
271
- queryParams.push(`sslmode=no-verify`);
272
- }
273
- if (queryParams.length > 0) {
274
- connectionString += `?${queryParams.join('&')}`;
275
- }
276
- if (!cliOptions?.silent) {
277
- const logger = new logs_1.GlobalLogger();
278
- let logConnectionString = `postgresql://${configFile.database.username}:***@${configFile.database.hostname}:${configFile.database.port}/${databaseName}`;
279
- if (queryParams.length > 0) {
280
- logConnectionString += `?${queryParams.join('&')}`;
281
- }
282
- logger.info(`Using database connection string: ${logConnectionString}`);
283
- }
82
+ if (process.env.DBOS_SYSTEM_DATABASE_URL) {
83
+ return process.env.DBOS_SYSTEM_DATABASE_URL;
284
84
  }
285
- // Build the final poolConfig
286
- const poolConfig = {
287
- connectionString,
288
- connectionTimeoutMillis,
289
- ssl,
290
- host: configFile.database.hostname,
291
- port: configFile.database.port,
292
- user: configFile.database.username,
293
- password: configFile.database.password,
294
- database: databaseName,
295
- max: cliOptions?.userDbPoolSize || 20,
296
- };
297
- if (!poolConfig.database) {
298
- throw new error_1.DBOSInitializationError(`DBOS configuration (${exports.dbosConfigFilePath}) does not contain application database name`);
85
+ const databaseUrl = getDatabaseUrl(configFileOrString);
86
+ return convertUserDbUrl(databaseUrl);
87
+ function convertUserDbUrl(databaseUrl) {
88
+ const url = new URL(databaseUrl);
89
+ const database = url.pathname.slice(1);
90
+ url.pathname = `/${database}_dbos_sys`;
91
+ return url.toString();
299
92
  }
300
- return poolConfig;
301
93
  }
302
- exports.constructPoolConfig = constructPoolConfig;
303
- /**
304
- * A helper to backfill TLS configuration from a connection string sslmode/sslrootcert query parameters
305
- *
306
- * @param sslmode
307
- * @param sslrootcert
308
- * @returns
309
- */
310
- function getSSLFromParams(sslmode, sslrootcert) {
311
- if (!sslmode || sslmode === 'disable') {
94
+ exports.getSystemDatabaseUrl = getSystemDatabaseUrl;
95
+ function isValidDBname(dbName) {
96
+ if (dbName.length < 1 || dbName.length > 63) {
312
97
  return false;
313
98
  }
314
- const ssl = {};
315
- if (sslmode === 'require' || sslmode === 'no-verify') {
316
- ssl.rejectUnauthorized = false;
317
- }
318
- else if (sslmode === 'verify-ca' || sslmode === 'verify-full') {
319
- ssl.rejectUnauthorized = sslmode === 'verify-full';
320
- if (sslrootcert) {
321
- try {
322
- ssl.ca = (0, utils_1.readFileSync)(path_1.default.resolve(sslrootcert)).toString();
323
- }
324
- catch (err) {
325
- throw new Error(`Failed to read sslrootcert from "${sslrootcert}": ${err.message}`);
326
- }
327
- }
328
- else {
329
- throw new Error(`sslmode=${sslmode} requires sslrootcert`);
330
- }
331
- }
332
- return ssl;
333
- }
334
- function parseSSLConfig(dbConfig) {
335
- // Details on Postgres SSL/TLS modes: https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION
336
- if (dbConfig.ssl === false) {
337
- // If SSL is set to false, do not use TLS
99
+ if (dbName.match(/^\d/)) {
100
+ // Cannot start with a digit
338
101
  return false;
339
102
  }
340
- if (dbConfig.ssl_ca) {
341
- // If an SSL certificate is provided, connect to Postgres using TLS and verify the server certificate. (equivalent to verify-full)
342
- return { ca: [(0, utils_1.readFileSync)(dbConfig.ssl_ca)], rejectUnauthorized: true };
103
+ return validator_1.default.matches(dbName, '^[a-z0-9_]+$');
104
+ }
105
+ function getDatabaseUrl(configFile) {
106
+ const databaseUrl = configFile.database_url || process.env.DBOS_DATABASE_URL || defaultDatabaseUrl(configFile.name);
107
+ const url = new URL(databaseUrl);
108
+ const dbName = url.pathname.slice(1);
109
+ const missingFields = [];
110
+ if (!url.username)
111
+ missingFields.push('username');
112
+ if (!url.hostname)
113
+ missingFields.push('hostname');
114
+ if (!dbName)
115
+ missingFields.push('database name');
116
+ if (missingFields.length > 0) {
117
+ throw new Error(`Invalid database URL: missing required field(s): ${missingFields.join(', ')}`);
118
+ }
119
+ (0, assert_1.default)(isValidDBname(dbName), `Database name "${dbName}" in database_url is invalid.`);
120
+ if (process.env.DBOS_DEBUG_WORKFLOW_ID !== undefined) {
121
+ // If in debug mode, apply the debug overrides
122
+ url.hostname = process.env.DBOS_DBHOST || url.hostname;
123
+ url.port = process.env.DBOS_DBPORT || url.port;
124
+ url.username = process.env.DBOS_DBUSER || url.username;
125
+ url.password = process.env.DBOS_DBPASSWORD || url.password;
126
+ return url.toString();
343
127
  }
344
- if (dbConfig.ssl === undefined && (dbConfig.hostname === 'localhost' || dbConfig.hostname === '127.0.0.1')) {
345
- // For local development only, do not use TLS unless it is specifically asked for (to support Dockerized Postgres, which does not support SSL connections)
346
- return false;
128
+ else {
129
+ return databaseUrl;
130
+ }
131
+ function defaultDatabaseUrl(appName) {
132
+ (0, assert_1.default)(appName, 'Application name must be defined to construct a valid database URL.');
133
+ const host = process.env.PGHOST || 'localhost';
134
+ const port = process.env.PGPORT || '5432';
135
+ const username = process.env.PGUSER || 'postgres';
136
+ const password = process.env.PGPASSWORD || 'dbos';
137
+ const database = toDbName(appName);
138
+ const timeout = process.env.PGCONNECT_TIMEOUT || '10';
139
+ const sslmode = process.env.PGSSLMODE || (host === 'localhost' ? 'disable' : 'allow');
140
+ return `postgresql://${username}:${password}@${host}:${port}/${database}?connect_timeout=${timeout}&sslmode=${sslmode}`;
141
+ }
142
+ function toDbName(appName) {
143
+ const dbName = appName.toLowerCase().replaceAll('-', '_').replaceAll(' ', '_');
144
+ return dbName.match(/^\d/) ? '_' + dbName : dbName;
347
145
  }
348
- // Otherwise, connect to Postgres using TLS but do not verify the server certificate. (equivalent to require)
349
- return { rejectUnauthorized: false };
350
146
  }
351
- exports.parseSSLConfig = parseSSLConfig;
352
- function prettyPrintAjvErrors(validate) {
353
- return validate
354
- .errors.map((error) => {
355
- let message = `Error: ${error.message}`;
356
- if (error.schemaPath)
357
- message += ` (schema path: ${error.schemaPath})`;
358
- if (error.params && error.keyword === 'additionalProperties') {
359
- message += `; the additional property '${error.params.additionalProperty}' is not allowed`;
360
- }
361
- if (error.data && error.keyword === 'not') {
362
- message += `; the value ${utils_1.DBOSJSON.stringify(error.data)} is not allowed for field ${error.instancePath}`;
363
- }
364
- return message;
365
- })
366
- .join(', ');
147
+ exports.getDatabaseUrl = getDatabaseUrl;
148
+ function getDbosConfig(config, options = {}) {
149
+ (0, assert_1.default)(config.language === undefined || config.language === 'node', `Config file specifies invalid language ${config.language}`);
150
+ const userDbClient = config.database?.app_db_client ?? user_database_1.UserDatabaseName.KNEX;
151
+ (0, assert_1.default)(isValidUserDbClient(userDbClient), `Invalid app_db_client ${userDbClient} in config file`);
152
+ return translateDbosConfig({
153
+ name: config.name,
154
+ databaseUrl: config.database_url,
155
+ systemDatabaseUrl: config.system_database_url,
156
+ userDatabaseClient: userDbClient,
157
+ logLevel: options.logLevel ?? config.telemetry?.logs?.logLevel,
158
+ addContextMetadata: config.telemetry?.logs?.addContextMetadata,
159
+ otlpTracesEndpoints: toArray(config.telemetry?.OTLPExporter?.tracesEndpoint),
160
+ otlpLogsEndpoints: toArray(config.telemetry?.OTLPExporter?.logsEndpoint),
161
+ runAdminServer: config.runtimeConfig?.runAdminServer,
162
+ }, options.forceConsole);
367
163
  }
368
- /*
369
- * Parse `dbosConfigFilePath` and return DBOSConfig and DBOSRuntimeConfig
370
- * Considers DBOSCLIStartOptions if provided, which takes precedence over config file
371
- * */
372
- function parseConfigFile(cliOptions) {
373
- if (cliOptions?.appDir) {
374
- process.chdir(cliOptions.appDir);
375
- }
376
- const configFilePath = cliOptions?.configfile ?? exports.dbosConfigFilePath;
377
- const configFile = loadConfigFile(configFilePath);
378
- if (!configFile) {
379
- throw new error_1.DBOSInitializationError(`DBOS configuration file ${configFilePath} is empty`);
380
- }
381
- return processConfigFile(configFile, cliOptions);
164
+ exports.getDbosConfig = getDbosConfig;
165
+ function toArray(endpoint) {
166
+ return endpoint ? (Array.isArray(endpoint) ? endpoint : [endpoint]) : [];
382
167
  }
383
- exports.parseConfigFile = parseConfigFile;
384
- function processConfigFile(configFile, cliOptions) {
385
- if (configFile.language && configFile.language !== 'node') {
386
- throw new error_1.DBOSInitializationError(`Config file specifies invalid language ${configFile.language}`);
387
- }
388
- /*******************************/
389
- /* Handle user database config */
390
- /*******************************/
391
- const poolConfig = constructPoolConfig(configFile, cliOptions);
392
- if (!isValidDBname(poolConfig.database)) {
393
- throw new error_1.DBOSInitializationError(`Config file specifies invalid app_db_name ${poolConfig.database}. Must be between 3 and 31 characters long and contain only lowercase letters, underscores, and digits (cannot begin with a digit).`);
394
- }
395
- /***************************/
396
- /* Handle telemetry config */
397
- /***************************/
398
- // Consider CLI --loglevel and forceConsole flags
399
- const logs = {
400
- ...configFile.telemetry?.logs,
401
- logLevel: cliOptions?.loglevel ?? configFile.telemetry?.logs?.logLevel ?? 'info',
402
- forceConsole: cliOptions?.forceConsole ?? configFile.telemetry?.logs?.forceConsole,
403
- };
404
- const traceEndpointSet = (0, utils_1.toStringSet)(configFile.telemetry?.OTLPExporter?.tracesEndpoint);
405
- const logEndpointSet = (0, utils_1.toStringSet)(configFile.telemetry?.OTLPExporter?.logsEndpoint);
406
- /************************************/
407
- /* Build final DBOS configuration */
408
- /************************************/
409
- utils_1.globalParams.appVersion = getAppVersion(cliOptions?.appVersion);
410
- const dbosConfig = {
411
- poolConfig: poolConfig,
412
- userDbclient: configFile.database?.app_db_client || user_database_1.UserDatabaseName.KNEX,
413
- databaseUrl: configFile.database_url,
168
+ function isValidUserDbClient(name) {
169
+ return Object.values(user_database_1.UserDatabaseName).includes(name);
170
+ }
171
+ function translateDbosConfig(options, forceConsole = false) {
172
+ const databaseUrl = getDatabaseUrl({ database_url: options.databaseUrl, name: options.name });
173
+ const systemDatabaseUrl = getSystemDatabaseUrl({
174
+ database_url: options.databaseUrl,
175
+ system_database_url: options.systemDatabaseUrl,
176
+ name: options.name,
177
+ });
178
+ return {
179
+ databaseUrl,
180
+ userDbPoolSize: options.userDatabasePoolSize,
181
+ systemDatabaseUrl,
182
+ sysDbPoolSize: options.systemDatabasePoolSize,
183
+ userDbClient: options.userDatabaseClient,
414
184
  telemetry: {
415
- logs,
185
+ logs: {
186
+ logLevel: options.logLevel || 'info',
187
+ addContextMetadata: options.addContextMetadata,
188
+ forceConsole,
189
+ },
416
190
  OTLPExporter: {
417
- tracesEndpoint: Array.from(traceEndpointSet),
418
- logsEndpoint: Array.from(logEndpointSet),
191
+ tracesEndpoint: options.otlpTracesEndpoints,
192
+ logsEndpoint: options.otlpLogsEndpoints,
419
193
  },
420
194
  },
421
- system_database: configFile.database?.sys_db_name ?? `${poolConfig.database}_dbos_sys`,
422
- http: configFile.http,
423
195
  };
424
- /*************************************/
425
- /* Build final runtime Configuration */
426
- /*************************************/
196
+ }
197
+ exports.translateDbosConfig = translateDbosConfig;
198
+ function getRuntimeConfig(config, options = {}) {
199
+ return translateRuntimeConfig(config.runtimeConfig, options.port);
200
+ }
201
+ exports.getRuntimeConfig = getRuntimeConfig;
202
+ function translateRuntimeConfig(config = {}, port) {
427
203
  const entrypoints = new Set();
428
- if (configFile.runtimeConfig?.entrypoints) {
429
- configFile.runtimeConfig.entrypoints.forEach((entry) => entrypoints.add(entry));
430
- }
431
- else {
204
+ config.entrypoints?.forEach((entry) => entrypoints.add(entry));
205
+ if (entrypoints.size === 0) {
432
206
  entrypoints.add(runtime_1.defaultEntryPoint);
433
207
  }
434
- const appPort = Number(cliOptions?.port) || Number(configFile.runtimeConfig?.port) || 3000;
435
- const runtimeConfig = {
208
+ port ??= config.port ?? 3000;
209
+ return {
436
210
  entrypoints: [...entrypoints],
437
- port: appPort,
438
- runAdminServer: true,
439
- admin_port: Number(configFile.runtimeConfig?.admin_port) || appPort + 1,
440
- start: configFile.runtimeConfig?.start || [],
441
- setup: configFile.runtimeConfig?.setup || [],
211
+ port: port,
212
+ runAdminServer: config.runAdminServer ?? true,
213
+ admin_port: config.admin_port ?? port + 1,
214
+ start: config.start ?? [],
215
+ setup: config.setup ?? [],
442
216
  };
443
- return [dbosConfig, runtimeConfig];
444
217
  }
445
- exports.processConfigFile = processConfigFile;
446
- function getAppVersion(appVersion) {
447
- if (typeof appVersion === 'string') {
448
- return appVersion;
218
+ exports.translateRuntimeConfig = translateRuntimeConfig;
219
+ function overwriteConfigForDBOSCloud(providedDBOSConfig, providedRuntimeConfig, configFile) {
220
+ // Load the DBOS configuration file and force the use of:
221
+ // 1. Use the application name from the file. This is a defensive measure to ensure the application name is whatever it was registered with in the cloud
222
+ // 2. use the database URL from environment var
223
+ // 3. OTLP traces endpoints (add the config data to the provided config)
224
+ // 4. Force admin_port and runAdminServer
225
+ const appName = configFile.name ?? providedDBOSConfig.name;
226
+ let databaseUrl = process.env.DBOS_DATABASE_URL;
227
+ if (!databaseUrl) {
228
+ databaseUrl = configFile.database_url;
449
229
  }
450
- if (appVersion === false) {
451
- return '';
230
+ if (!databaseUrl) {
231
+ databaseUrl = providedDBOSConfig.databaseUrl;
452
232
  }
453
- return process.env.DBOS__APPVERSION || '';
454
- }
455
- function isValidDBname(dbName) {
456
- if (dbName.length < 1 || dbName.length > 63) {
457
- return false;
233
+ let systemDatabaseUrl = process.env.DBOS_SYSTEM_DATABASE_URL;
234
+ if (!systemDatabaseUrl && process.env.DBOS_DATABASE_URL) {
235
+ systemDatabaseUrl = getSystemDatabaseUrl(process.env.DBOS_DATABASE_URL);
458
236
  }
459
- if (dbName.match(/^\d/)) {
460
- // Cannot start with a digit
461
- return false;
237
+ if (!systemDatabaseUrl) {
238
+ systemDatabaseUrl = configFile.system_database_url;
462
239
  }
463
- return validator_1.default.matches(dbName, '^[a-z0-9_]+$');
464
- }
465
- /*
466
- This function takes a DBOSConfig and ensure that 'public' fields take precedence over 'internal' fields.
467
- It assumes that the DBOSConfig was passed programmatically and thus does not need to consider CLI options.
468
-
469
- - Application Name: check there is no inconsistency between the provided name and the one in dbos-config.yaml, if any
470
- - Database configuration: Ignore provided poolConfig and reconstructs it from the databaseUrl field and constructPoolConfig()
471
- */
472
- function translatePublicDBOSconfig(config, isDebugging) {
473
- let appName = config.name;
474
- // Opportunistically grab the name from the config file if none was provided
475
- try {
476
- const configFile = loadConfigFile(exports.dbosConfigFilePath);
477
- if (configFile?.name && !appName) {
478
- appName = configFile.name;
479
- }
240
+ if (!systemDatabaseUrl) {
241
+ systemDatabaseUrl = providedDBOSConfig.systemDatabaseUrl;
480
242
  }
481
- catch (e) {
482
- // Ignore file not found errors
483
- if (!e.message.includes('ENOENT: no such file or directory')) {
484
- throw e;
243
+ const logsSet = new Set(providedDBOSConfig.telemetry.OTLPExporter?.logsEndpoint);
244
+ const logsEndpoint = configFile.telemetry?.OTLPExporter?.logsEndpoint;
245
+ if (logsEndpoint) {
246
+ if (Array.isArray(logsEndpoint)) {
247
+ logsEndpoint.forEach((endpoint) => logsSet.add(endpoint));
248
+ }
249
+ else {
250
+ logsSet.add(logsEndpoint);
485
251
  }
486
252
  }
487
- // Resolve database configuration
488
- const poolConfig = constructPoolConfig({
489
- name: appName,
490
- database: {},
491
- database_url: config.databaseUrl,
492
- application: {},
493
- env: {},
494
- }, { silent: true, userDbPoolSize: config.userDbPoolSize });
495
- const translatedConfig = {
496
- name: appName,
497
- poolConfig: poolConfig,
498
- userDbclient: config.userDbclient || user_database_1.UserDatabaseName.KNEX,
499
- databaseUrl: config.databaseUrl,
500
- telemetry: {
501
- logs: {
502
- logLevel: config.logLevel || 'info',
503
- addContextMetadata: config.addContextMetadata,
504
- forceConsole: isDebugging === undefined ? false : isDebugging,
505
- },
506
- OTLPExporter: {
507
- tracesEndpoint: config.otlpTracesEndpoints || [],
508
- logsEndpoint: config.otlpLogsEndpoints || [],
509
- },
510
- },
511
- system_database: config.sysDbName || `${poolConfig.database}_dbos_sys`,
512
- sysDbPoolSize: config.sysDbPoolSize || 20,
513
- };
514
- const runtimeConfig = {
515
- port: 3000,
516
- admin_port: config.adminPort || 3001,
517
- runAdminServer: config.runAdminServer === undefined ? true : config.runAdminServer,
518
- entrypoints: [],
519
- start: [],
520
- setup: [],
521
- };
522
- return [translatedConfig, runtimeConfig];
523
- }
524
- exports.translatePublicDBOSconfig = translatePublicDBOSconfig;
525
- function overwrite_config(providedDBOSConfig, providedRuntimeConfig, configFile) {
526
- if (configFile === undefined) {
527
- try {
528
- configFile = loadConfigFile(exports.dbosConfigFilePath);
253
+ const tracesSet = new Set(providedDBOSConfig.telemetry.OTLPExporter?.tracesEndpoint);
254
+ const tracesEndpoint = configFile.telemetry?.OTLPExporter?.tracesEndpoint;
255
+ if (tracesEndpoint) {
256
+ if (Array.isArray(tracesEndpoint)) {
257
+ tracesEndpoint.forEach((endpoint) => tracesSet.add(endpoint));
529
258
  }
530
- catch (e) {
531
- if (e.message.includes('ENOENT: no such file or directory')) {
532
- return [providedDBOSConfig, providedRuntimeConfig];
533
- }
534
- else {
535
- throw e;
536
- }
259
+ else {
260
+ tracesSet.add(tracesEndpoint);
537
261
  }
538
262
  }
539
- // Load the DBOS configuration file and force the use of:
540
- // 1. Use the application name from the file. This is a defensive measure to ensure the application name is whatever it was registered with in the cloud
541
- // 2. The database connection parameters (sub the file data to the provided config)
542
- // 3. OTLP traces endpoints (add the config data to the provided config)
543
- // 4. Force admin_port and runAdminServer
544
- const appName = configFile.name || providedDBOSConfig.name;
545
- if (configFile.database?.ssl_ca) {
546
- configFile.database_url = `postgresql://${configFile.database.username}:${configFile.database.password}@${configFile.database.hostname}:${configFile.database.port}/${configFile.database.app_db_name}?connect_timeout=10&sslmode=verify-full&sslrootcert=${configFile.database.ssl_ca}`;
547
- }
548
- else {
549
- configFile.database_url = `postgresql://${configFile.database?.username}:${configFile.database?.password}@${configFile.database?.hostname}:${configFile.database?.port}/${configFile.database?.app_db_name}?connect_timeout=10&sslmode=no-verify`;
550
- }
551
- const poolConfig = constructPoolConfig(configFile);
552
- const providedTraceEndpointSet = (0, utils_1.toStringSet)(providedDBOSConfig.telemetry.OTLPExporter?.tracesEndpoint);
553
- const configTraceEndpointSet = (0, utils_1.toStringSet)(configFile.telemetry?.OTLPExporter?.tracesEndpoint);
554
- for (const endpoint of configTraceEndpointSet) {
555
- providedTraceEndpointSet.add(endpoint);
556
- }
557
- const providedLogEndpointSet = (0, utils_1.toStringSet)(providedDBOSConfig.telemetry?.OTLPExporter?.logsEndpoint);
558
- const configLogEndpointSet = (0, utils_1.toStringSet)(configFile.telemetry?.OTLPExporter?.logsEndpoint);
559
- for (const endpoint of configLogEndpointSet) {
560
- providedLogEndpointSet.add(endpoint);
561
- }
562
263
  const overwritenDBOSConfig = {
563
264
  ...providedDBOSConfig,
564
265
  name: appName,
565
- poolConfig: poolConfig,
266
+ databaseUrl,
267
+ systemDatabaseUrl,
566
268
  telemetry: {
567
269
  logs: providedDBOSConfig.telemetry.logs,
568
270
  OTLPExporter: {
569
- tracesEndpoint: Array.from(providedTraceEndpointSet),
570
- logsEndpoint: Array.from(providedLogEndpointSet),
271
+ tracesEndpoint: Array.from(tracesSet),
272
+ logsEndpoint: Array.from(logsSet),
571
273
  },
572
274
  },
573
- system_database: configFile.database?.sys_db_name || poolConfig.database + '_dbos_sys', // Unexpected, but possible
574
275
  };
575
276
  const overwriteDBOSRuntimeConfig = {
576
277
  admin_port: 3001,
@@ -582,5 +283,5 @@ function overwrite_config(providedDBOSConfig, providedRuntimeConfig, configFile)
582
283
  };
583
284
  return [overwritenDBOSConfig, overwriteDBOSRuntimeConfig];
584
285
  }
585
- exports.overwrite_config = overwrite_config;
286
+ exports.overwriteConfigForDBOSCloud = overwriteConfigForDBOSCloud;
586
287
  //# sourceMappingURL=config.js.map