@objectstack/runtime 10.0.0 → 10.2.0

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/index.js CHANGED
@@ -963,6 +963,36 @@ var init_app_plugin = __esm({
963
963
  error: err?.message ?? String(err)
964
964
  });
965
965
  }
966
+ try {
967
+ const dsDefs = this.bundle.datasources;
968
+ const dsList = Array.isArray(dsDefs) ? dsDefs : dsDefs && typeof dsDefs === "object" ? Object.entries(dsDefs).map(([name, def]) => ({ name, ...def })) : [];
969
+ if (dsList.length > 0) {
970
+ let connection;
971
+ try {
972
+ connection = ctx.getService("datasource-connection");
973
+ } catch {
974
+ connection = void 0;
975
+ }
976
+ if (typeof connection?.connectDeclared === "function") {
977
+ const objects = Array.isArray(this.bundle.objects) ? this.bundle.objects : [];
978
+ const results = await connection.connectDeclared({ datasources: dsList, objects });
979
+ const connected = results.filter((r) => r.status === "connected");
980
+ if (connected.length > 0) {
981
+ ctx.logger.info("Auto-connected declared datasources", {
982
+ appId,
983
+ connected: connected.map((r) => r.name)
984
+ });
985
+ }
986
+ } else {
987
+ ctx.logger.debug("No datasource-connection service \u2014 declared datasources stay metadata-only", { appId });
988
+ }
989
+ }
990
+ } catch (err) {
991
+ ctx.logger.error(
992
+ `[AppPlugin] declared-datasource auto-connect failed for app '${appId}': ${err?.message ?? String(err)}`
993
+ );
994
+ throw err;
995
+ }
966
996
  try {
967
997
  const metadata = ctx.getService("metadata");
968
998
  if (typeof metadata?.registerInMemory === "function") {
@@ -1530,55 +1560,55 @@ async function createStandaloneStack(config) {
1530
1560
  const explicitDriver = cfg.databaseDriver ?? process.env.OS_DATABASE_DRIVER?.trim();
1531
1561
  const dbDriver = explicitDriver ?? detectDriverFromUrl(dbUrl);
1532
1562
  let driverPlugin;
1533
- if (dbDriver === "memory") {
1534
- const { InMemoryDriver } = await import("@objectstack/driver-memory");
1535
- driverPlugin = new DriverPlugin2(new InMemoryDriver());
1536
- } else if (dbDriver === "postgres") {
1537
- const { SqlDriver } = await import("@objectstack/driver-sql");
1538
- driverPlugin = new DriverPlugin2(
1539
- new SqlDriver({
1540
- client: "pg",
1541
- connection: dbUrl,
1542
- pool: { min: 0, max: 5 }
1543
- })
1544
- );
1545
- } else if (dbDriver === "mongodb") {
1546
- let MongoDBDriver;
1547
- try {
1548
- ({ MongoDBDriver } = await import("@objectstack/driver-mongodb"));
1549
- } catch (err) {
1550
- throw new Error(
1551
- `[StandaloneStack] mongodb URL detected but @objectstack/driver-mongodb is not installed. Add it as a dependency or pass an explicit driverPlugin. (${err?.message ?? err})`
1552
- );
1553
- }
1554
- driverPlugin = new DriverPlugin2(new MongoDBDriver({ url: dbUrl }));
1555
- } else if (dbDriver === "sqlite-wasm") {
1563
+ if (dbDriver === "sqlite-wasm") {
1556
1564
  const { SqliteWasmDriver } = await import("@objectstack/driver-sqlite-wasm");
1557
- const filename = dbUrl.replace(/^wasm-sqlite:(\/\/)?/i, "").replace(/^file:(\/\/)?/i, "");
1558
- if (filename && filename !== ":memory:") {
1565
+ const filename = dbUrl.replace(/^wasm-sqlite:(\/\/)?/i, "").replace(/^file:(\/\/)?/i, "") || ":memory:";
1566
+ if (filename !== ":memory:") {
1559
1567
  mkdirSync2(resolvePath2(filename, ".."), { recursive: true });
1560
1568
  }
1561
1569
  driverPlugin = new DriverPlugin2(
1562
1570
  new SqliteWasmDriver({
1563
- filename: filename || ":memory:",
1564
- persist: filename && filename !== ":memory:" ? "on-write" : void 0
1571
+ filename,
1572
+ persist: filename !== ":memory:" ? "on-write" : void 0
1565
1573
  })
1566
1574
  );
1567
1575
  } else {
1568
- const { SqlDriver } = await import("@objectstack/driver-sql");
1569
- const filename = dbUrl.replace(/^file:(\/\/)?/, "");
1570
- if (!filename || /^[a-z][a-z0-9+.-]*:\/\//i.test(filename)) {
1571
- throw new Error(
1572
- `[StandaloneStack] sqlite driver was selected but the URL does not look like a file path: "${dbUrl}". Use file:/path/to/db.sqlite, or set OS_DATABASE_DRIVER explicitly.`
1573
- );
1576
+ const { createDefaultDatasourceDriverFactory } = await import("@objectstack/service-datasource");
1577
+ let driverId;
1578
+ let driverConfig;
1579
+ if (dbDriver === "memory") {
1580
+ driverId = "memory";
1581
+ driverConfig = {};
1582
+ } else if (dbDriver === "postgres") {
1583
+ driverId = "postgres";
1584
+ driverConfig = { url: dbUrl };
1585
+ } else if (dbDriver === "mongodb") {
1586
+ driverId = "mongodb";
1587
+ driverConfig = { url: dbUrl };
1588
+ } else {
1589
+ driverId = "sqlite";
1590
+ const filename = dbUrl.replace(/^file:(\/\/)?/, "");
1591
+ if (!filename || /^[a-z][a-z0-9+.-]*:\/\//i.test(filename)) {
1592
+ throw new Error(
1593
+ `[StandaloneStack] sqlite driver was selected but the URL does not look like a file path: "${dbUrl}". Use file:/path/to/db.sqlite, or set OS_DATABASE_DRIVER explicitly.`
1594
+ );
1595
+ }
1596
+ mkdirSync2(resolvePath2(filename, ".."), { recursive: true });
1597
+ driverConfig = { filename };
1598
+ }
1599
+ let driverHandle;
1600
+ try {
1601
+ driverHandle = await createDefaultDatasourceDriverFactory().create({ driver: driverId, config: driverConfig });
1602
+ } catch (err) {
1603
+ if (dbDriver === "mongodb") {
1604
+ throw new Error(
1605
+ `[StandaloneStack] mongodb URL detected but @objectstack/driver-mongodb is not installed. Add it as a dependency or pass an explicit driverPlugin. (${err?.message ?? err})`
1606
+ );
1607
+ }
1608
+ throw err;
1574
1609
  }
1575
- mkdirSync2(resolvePath2(filename, ".."), { recursive: true });
1576
1610
  driverPlugin = new DriverPlugin2(
1577
- new SqlDriver({
1578
- client: "better-sqlite3",
1579
- connection: { filename },
1580
- useNullAsDefault: true
1581
- })
1611
+ driverHandle?.driver ?? driverHandle
1582
1612
  );
1583
1613
  }
1584
1614
  const artifactBundle = await loadArtifactBundle(artifactPath, {
@@ -2702,7 +2732,7 @@ var _HttpDispatcher = class _HttpDispatcher {
2702
2732
  */
2703
2733
  async enforceProjectMembership(context, path) {
2704
2734
  if (!this.enforceMembership) return null;
2705
- const skipPaths = ["/auth", "/cloud", "/health", "/discovery"];
2735
+ const skipPaths = ["/auth", "/cloud", "/health", "/ready", "/discovery"];
2706
2736
  if (skipPaths.some((p) => path.startsWith(p))) return null;
2707
2737
  if (/(^|\/)share-links\/[^/]+\/(resolve|messages)$/.test(path)) return null;
2708
2738
  const environmentId = context.environmentId;
@@ -4519,6 +4549,10 @@ var _HttpDispatcher = class _HttpDispatcher {
4519
4549
  })
4520
4550
  };
4521
4551
  }
4552
+ if (cleanPath === "/ready" && method === "GET") {
4553
+ const state = typeof this.kernel?.getState === "function" ? this.kernel.getState() : "running";
4554
+ return state === "running" ? { handled: true, response: this.success({ status: "ready", state }) } : { handled: true, response: this.error("Service not ready", 503, { state }) };
4555
+ }
4522
4556
  if (cleanPath.startsWith("/auth")) {
4523
4557
  return this.handleAuth(cleanPath.substring(5), method, body, context);
4524
4558
  }