openvibers/openvibe.sdk Commits

v0.21.3: createTestDb returns url and directUrl for a spawned service process; sqlfix's envelope rewrite is idempotent.

OP OpenVibers committed 28 Sept 2026 · 59b99c545e · 9 files, +21 −9


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 185e672..e295940 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -8,6 +8,11 @@ release may change an API and says so here.
++## 0.21.3 (2026-09-28)
++
++- `openvibe-sdk/testing` `createTestDb`: on the containers it also returns `url` and `directUrl`, the `DATABASE_URL` and `DATABASE_DIRECT_URL` of its schema, for a test that spawns a process of the service (OpenRe's transport workers); `null` on PGlite.
++- `tools/asyncify/sqlfix.py`: the outbox-envelope rewrite no longer nests on a second run.
++
## 0.21.2 (2026-09-28)
- `openvibe-sdk/events` outboxes (SQLite and PostgreSQL): a `flush()` called while a relay pass runs now gets the next pass, which starts when that one ends. It used to share the running pass, so it could return before the rows committed after that pass claimed were published (a caller's "flush, then assert both went out" saw one). Calls made during a pass share that next pass; `stop()` waits for both.
ddiff --git a/STATUS.json b/STATUS.json
iindex 9781ffa..86b3f4f 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -3,7 +3,7 @@
"stage": "alpha",
"code": true,
"wave": "W2",
-- "version": "0.21.2",
++ "version": "0.21.3",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §3.2; roadmap §30",
"deployed": false,
"deployment": "none: a package released as git tags; services and apps pin a tag",
ddiff --git a/browser/openvibe-sdk.mjs b/browser/openvibe-sdk.mjs
iindex d8cac64..2c836f9 100644
---- a/browser/openvibe-sdk.mjs
++++ b/browser/openvibe-sdk.mjs
@@@ -1,4 +1,4 @@
--// Generated by scripts/browser-bundle.js from browser.js (openvibe-sdk 0.21.2, MIT). Do not edit.
++// Generated by scripts/browser-bundle.js from browser.js (openvibe-sdk 0.21.3, MIT). Do not edit.
// One self-contained ES module: core at the top level plus the browser-safe subpaths as namespaces
// (auth, registry, modules, realtime, media, community, search, chat, ai, jobs, tools, projects, geo). No server-only code: no service tokens, JWT verification, events, identity.
/* eslint-disable */
@@@ -41,7 +41,7 @@ const { paginate, offsetPager } = __load(7);
const semver = __load(6);
/** The package version (test/version.test.js keeps it equal to package.json). */
--const SDK_VERSION = '0.21.2';
++const SDK_VERSION = '0.21.3';
module.exports = {
createClient,
ddiff --git a/package-lock.json b/package-lock.json
iindex 958fea4..5e14d46 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-sdk",
-- "version": "0.21.2",
++ "version": "0.21.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-sdk",
-- "version": "0.21.2",
++ "version": "0.21.3",
"license": "MIT",
"devDependencies": {
"@electric-sql/pglite": "^0.5.8",
ddiff --git a/package.json b/package.json
iindex b27fe0f..ffa2997 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-sdk",
-- "version": "0.21.2",
++ "version": "0.21.3",
"description": "Supported browser and server clients for the OpenVibe platform: auth (incl. developer apps), registry discovery, identity, user modules, events, realtime, media, community, search, chat, AI runs, Tools (registry, run API and jobs), VIP memberships and developer projects, the async PostgreSQL data layer (db) and the Valkey cache, limits store, queue and pub/sub, with deadlines, safe retries, problem errors and trace propagation.",
"main": "index.js",
"types": "types/index.d.ts",
ddiff --git a/src/core/index.js b/src/core/index.js
iindex d0c2a21..2665d9a 100644
---- a/src/core/index.js
++++ b/src/core/index.js
@@@ -8,7 +8,7 @@ const { paginate, offsetPager } = require('./paginate');
const semver = require('./semver');
/** The package version (test/version.test.js keeps it equal to package.json). */
--const SDK_VERSION = '0.21.2';
++const SDK_VERSION = '0.21.3';
module.exports = {
createClient,
ddiff --git a/src/testing/db.js b/src/testing/db.js
iindex 3a38ba8..4aff4e8 100644
---- a/src/testing/db.js
++++ b/src/testing/db.js
@@@ -28,7 +28,7 @@ async function createTestDb({ migrations, store = process.env.OV_TEST_STORE || '
if (store !== 'pg') {
const db = createDb({ pglite: true, service: `${service}-test`, log });
if (migrations) await db.migrate({ dir: migrations, log });
-- return { db, store: 'pglite', open: null, close: () => db.close().catch(() => {}) };
++ return { db, store: 'pglite', url: null, directUrl: null, open: null, close: () => db.close().catch(() => {}) };
}
if (!pgAvailable()) throw new Error('store pg needs OV_TEST_PG_URL and OV_TEST_PG_DIRECT_URL (openvibe-sdk scripts/test-services.sh up)');
const safe = String(service).replace(/[^a-z0-9]/g, '').slice(0, 12) || 'svc';
@@@ -74,6 +74,9 @@ async function createTestDb({ migrations, store = process.env.OV_TEST_STORE || '
} catch (e) { await drop().catch(() => {}); throw e; } // a failed setup leaves nothing behind
return {
db, store: 'postgresql', schema: name,
++ // For a process of its own (a worker the test spawns): DATABASE_URL (through PgBouncer, the service role) and
++ // DATABASE_DIRECT_URL (the owner, for its boot's migrate, which finds everything applied).
++ url: as(process.env.OV_TEST_PG_URL, name), directUrl: as(process.env.OV_TEST_PG_DIRECT_URL, owner),
open: (o = {}) => createDb({ url: as(process.env.OV_TEST_PG_URL, name), service: `${service}-test`, max, log, ...o }),
async close() { await db.close().catch(() => {}); await drop(); },
};
ddiff --git a/tools/asyncify/sqlfix.py b/tools/asyncify/sqlfix.py
iindex e0518e7..613fbbe 100644
---- a/tools/asyncify/sqlfix.py
++++ b/tools/asyncify/sqlfix.py
@@@ -81,7 +81,7 @@ for p in files:
# assert.throws(() => db.prepare(…).run(…), re): the statement rejects now.
s = re.sub(r"assert\.throws\(\(\) => ((?:t\.)?[\w.]*db\.prepare\((?:[^()]|\([^()]*\))*\)\.(?:run|get|all)\((?:[^()]|\([^()]*\))*\)), ", r"await assert.rejects(\1, ", s)
# A jsonb column (the SDK outbox's envelope) comes back as an object.
-- s = re.sub(r"JSON\.parse\((\w+)\.envelope\)", r"(typeof \1.envelope === 'string' ? JSON.parse(\1.envelope) : \1.envelope)", s)
++ s = re.sub(r"(?<!\? )JSON\.parse\((\w+)\.envelope\)", r"(typeof \1.envelope === 'string' ? JSON.parse(\1.envelope) : \1.envelope)", s)
# db.transaction(fn)() → db.tx(fn) (balanced parentheses; the codemod then awaits it and makes fn async).
out, i = [], 0
while True:
ddiff --git a/types/testing.d.ts b/types/testing.d.ts
iindex 9e96e2b..3fb6bde 100644
---- a/types/testing.d.ts
++++ b/types/testing.d.ts
@@@ -156,6 +156,10 @@ export interface TestDb {
schema?: string;
/** Another pooled handle on the same database (a second process); null on PGlite. */
open: ((o?: object) => Db) | null;
++ /** DATABASE_URL for a spawned process (the service role through PgBouncer); null on PGlite. */
++ url: string | null;
++ /** DATABASE_DIRECT_URL for a spawned process (the owner, direct: its boot's migrate); null on PGlite. */
++ directUrl: string | null;
close(): Promise<void>;
}
/** A migrated database for one test run: PGlite, or (store 'pg') roles and a schema of its own on the containers. */