openvibers/openvibe.sdk Commits
openvibe-sdk 0.37.1: the mock Events' pull carries latest_cursor (#30)
Changes
@@@ -3,6 +3,12 @@All notable changes to `openvibe-sdk`. The package follows semver; while it is `0.x`, a minorrelease may change an API and says so here.++## 0.37.1 (2026-10-10)++++- `openvibe-sdk/testing`'s mock Events answers a pull with `latest_cursor` (the head as an opaque cursor), as++ OpenVibe.Events does since Events#45. A consumer that starts at "now" stores it and reads on with `after=`,++ never needing the numeric `latest_seq`. `events.pull()` documents it. Additive.++## 0.37.0 (2026-10-08)- **`openvibe-sdk/account-data`: `startSubscriptions()`**, the boot-time half every adopter had copied. It creates any@@@ -3,7 +3,7 @@"stage": "alpha","code": true,"wave": "W2",-- "version": "0.37.0",++ "version": "0.37.1","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",@@@ -1,4 +1,4 @@--// Generated by scripts/browser-bundle.js from browser.js (openvibe-sdk 0.37.0, MIT). Do not edit.++// Generated by scripts/browser-bundle.js from browser.js (openvibe-sdk 0.37.1, 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, bot, search, chat, ai, jobs, tools, projects, geo). No server-only code: no service tokens, JWT verification, events, identity./* eslint-disable */@@@ -42,7 +42,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.37.0';++const SDK_VERSION = '0.37.1';module.exports = {createClient,@@@ -1,12 +1,12 @@{"name": "openvibe-sdk",-- "version": "0.37.0",++ "version": "0.37.1","lockfileVersion": 3,"requires": true,"packages": {"": {"name": "openvibe-sdk",-- "version": "0.37.0",++ "version": "0.37.1","license": "MIT","devDependencies": {"@electric-sql/pglite": "^0.5.8",@@@ -1,6 +1,6 @@{"name": "openvibe-sdk",-- "version": "0.37.0",++ "version": "0.37.1","description": "Supported browser and server clients for the OpenVibe platform: auth (incl. developer apps), registry discovery, identity, user modules, events, realtime, media, community, Bot robots, 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",@@@ -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.37.0';++const SDK_VERSION = '0.37.1';module.exports = {createClient,@@@ -182,9 +182,10 @@ function createEventsClient(client, { source, baseUrl } = {}) {}/**-- * One page: { events: [{ seq, cursor, event }], next_cursor, next_after_seq, latest_seq, gap? }.-- * Pass `after` — a page's opaque `next_cursor` — to resume exactly where the previous page ended;-- * `afterSeq`, the numeric position, remains for one release.++ * One page: { events: [{ seq, cursor, event }], next_cursor, next_after_seq, latest_seq, latest_cursor, gap? }.++ * Pass `after` — a page's opaque `next_cursor` — to resume exactly where the previous page ended, or++ * `latest_cursor` to start at the head without history; `afterSeq`, the numeric position, remains for++ * one release.*/function pull({ topic = '*', after, afterSeq = 0, limit } = {}) {return call({ path: '/api/v1/events', query: {@@@ -480,7 +480,7 @@ function createMockPlatform(opts = {}) {if (pats.some(([x, re]) => re.test(e.event.event_type) && readable(who.principal, e, x))) out.push({ seq: e.seq, cursor: eventCursor(e.seq), event: e.event });}if (out.length < limit) cursor = Math.max(cursor, lastSeq);-- return json(200, { ...page, events: out, next_after_seq: cursor, next_cursor: eventCursor(cursor), latest_seq: lastSeq });++ return json(200, { ...page, events: out, next_after_seq: cursor, next_cursor: eventCursor(cursor), latest_seq: lastSeq, latest_cursor: eventCursor(lastSeq) });}if ((r = path.match(/^\/api\/v1\/events\/([^/]+)$/)) && req.method === 'GET') {const who = eventsPrincipal(req, 'events.event.read', 'events.app.read');@@@ -72,6 +72,8 @@ run([assert.equal(page.next_after_seq, 3);assert.equal(page.latest_seq, 5);assert.match(page.next_cursor, /^c1\./, 'the page carries an opaque next_cursor');++ assert.match(page.latest_cursor, /^c1\./, 'and the head as an opaque latest_cursor');++ assert.deepStrictEqual((await events.pull({ topic: 'media.vod.*', after: page.latest_cursor })).events, [], 'nothing after the head');assert.match(page.events[0].cursor, /^c1\./, 'each event carries its cursor');// The opaque cursor round-trips: `after` resumes exactly where the page ended.const rest = await events.pull({ topic: 'media.vod.*', after: page.next_cursor, limit: 2 });
@@ -3,6 +3,12 @@
@@ -3,6 +3,12 @@
All notable changes to `openvibe-sdk`. The package follows semver; while it is `0.x`, a minor
All notable changes to `openvibe-sdk`. The package follows semver; while it is `0.x`, a minor
release may change an API and says so here.
release may change an API and says so here.
+## 0.37.1 (2026-10-10)
+
+- `openvibe-sdk/testing`'s mock Events answers a pull with `latest_cursor` (the head as an opaque cursor), as
+ OpenVibe.Events does since Events#45. A consumer that starts at "now" stores it and reads on with `after=`,
+ never needing the numeric `latest_seq`. `events.pull()` documents it. Additive.
+
## 0.37.0 (2026-10-08)
## 0.37.0 (2026-10-08)
- **`openvibe-sdk/account-data`: `startSubscriptions()`**, the boot-time half every adopter had copied. It creates any
- **`openvibe-sdk/account-data`: `startSubscriptions()`**, the boot-time half every adopter had copied. It creates any
@@ -3,7 +3,7 @@
@@ -3,7 +3,7 @@
"stage": "alpha",
"stage": "alpha",
"code": true,
"code": true,
"wave": "W2",
"wave": "W2",
- "version": "0.37.0",
+ "version": "0.37.1",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §3.2; roadmap §30",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §3.2; roadmap §30",
"deployed": false,
"deployed": false,
"deployment": "none: a package released as git tags; services and apps pin a tag",
"deployment": "none: a package released as git tags; services and apps pin a tag",
@@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
-// Generated by scripts/browser-bundle.js from browser.js (openvibe-sdk 0.37.0, MIT). Do not edit.
+// Generated by scripts/browser-bundle.js from browser.js (openvibe-sdk 0.37.1, MIT). Do not edit.
// One self-contained ES module: core at the top level plus the browser-safe subpaths as namespaces
// One self-contained ES module: core at the top level plus the browser-safe subpaths as namespaces
// (auth, registry, modules, realtime, media, community, bot, search, chat, ai, jobs, tools, projects, geo). No server-only code: no service tokens, JWT verification, events, identity.
// (auth, registry, modules, realtime, media, community, bot, search, chat, ai, jobs, tools, projects, geo). No server-only code: no service tokens, JWT verification, events, identity.
/* eslint-disable */
/* eslint-disable */
@@ -42,7 +42,7 @@ const { paginate, offsetPager } = __load(7);
@@ -42,7 +42,7 @@ const { paginate, offsetPager } = __load(7);
const semver = __load(6);
const semver = __load(6);
/** The package version (test/version.test.js keeps it equal to package.json). */
/** The package version (test/version.test.js keeps it equal to package.json). */
-const SDK_VERSION = '0.37.0';
+const SDK_VERSION = '0.37.1';
module.exports = {
module.exports = {
createClient,
createClient,
@@ -1,12 +1,12 @@
@@ -1,12 +1,12 @@
{
{
"name": "openvibe-sdk",
"name": "openvibe-sdk",
- "version": "0.37.0",
+ "version": "0.37.1",
"lockfileVersion": 3,
"lockfileVersion": 3,
"requires": true,
"requires": true,
"packages": {
"packages": {
"": {
"": {
"name": "openvibe-sdk",
"name": "openvibe-sdk",
- "version": "0.37.0",
+ "version": "0.37.1",
"license": "MIT",
"license": "MIT",
"devDependencies": {
"devDependencies": {
"@electric-sql/pglite": "^0.5.8",
"@electric-sql/pglite": "^0.5.8",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-sdk",
"name": "openvibe-sdk",
- "version": "0.37.0",
+ "version": "0.37.1",
"description": "Supported browser and server clients for the OpenVibe platform: auth (incl. developer apps), registry discovery, identity, user modules, events, realtime, media, community, Bot robots, 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.",
"description": "Supported browser and server clients for the OpenVibe platform: auth (incl. developer apps), registry discovery, identity, user modules, events, realtime, media, community, Bot robots, 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",
"main": "index.js",
"types": "types/index.d.ts",
"types": "types/index.d.ts",
@@ -8,7 +8,7 @@ const { paginate, offsetPager } = require('./paginate');
@@ -8,7 +8,7 @@ const { paginate, offsetPager } = require('./paginate');
const semver = require('./semver');
const semver = require('./semver');
/** The package version (test/version.test.js keeps it equal to package.json). */
/** The package version (test/version.test.js keeps it equal to package.json). */
-const SDK_VERSION = '0.37.0';
+const SDK_VERSION = '0.37.1';
module.exports = {
module.exports = {
createClient,
createClient,
@@ -182,9 +182,10 @@ function createEventsClient(client, { source, baseUrl } = {}) {
@@ -182,9 +182,10 @@ function createEventsClient(client, { source, baseUrl } = {}) {
}
}
/**
/**
- * One page: { events: [{ seq, cursor, event }], next_cursor, next_after_seq, latest_seq, gap? }.
- * Pass `after` — a page's opaque `next_cursor` — to resume exactly where the previous page ended;
- * `afterSeq`, the numeric position, remains for one release.
+ * One page: { events: [{ seq, cursor, event }], next_cursor, next_after_seq, latest_seq, latest_cursor, gap? }.
+ * Pass `after` — a page's opaque `next_cursor` — to resume exactly where the previous page ended, or
+ * `latest_cursor` to start at the head without history; `afterSeq`, the numeric position, remains for
+ * one release.
*/
*/
function pull({ topic = '*', after, afterSeq = 0, limit } = {}) {
function pull({ topic = '*', after, afterSeq = 0, limit } = {}) {
return call({ path: '/api/v1/events', query: {
return call({ path: '/api/v1/events', query: {
@@ -480,7 +480,7 @@ function createMockPlatform(opts = {}) {
@@ -480,7 +480,7 @@ function createMockPlatform(opts = {}) {
if (pats.some(([x, re]) => re.test(e.event.event_type) && readable(who.principal, e, x))) out.push({ seq: e.seq, cursor: eventCursor(e.seq), event: e.event });
if (pats.some(([x, re]) => re.test(e.event.event_type) && readable(who.principal, e, x))) out.push({ seq: e.seq, cursor: eventCursor(e.seq), event: e.event });
}
}
if (out.length < limit) cursor = Math.max(cursor, lastSeq);
if (out.length < limit) cursor = Math.max(cursor, lastSeq);
- return json(200, { ...page, events: out, next_after_seq: cursor, next_cursor: eventCursor(cursor), latest_seq: lastSeq });
+ return json(200, { ...page, events: out, next_after_seq: cursor, next_cursor: eventCursor(cursor), latest_seq: lastSeq, latest_cursor: eventCursor(lastSeq) });
}
}
if ((r = path.match(/^\/api\/v1\/events\/([^/]+)$/)) && req.method === 'GET') {
if ((r = path.match(/^\/api\/v1\/events\/([^/]+)$/)) && req.method === 'GET') {
const who = eventsPrincipal(req, 'events.event.read', 'events.app.read');
const who = eventsPrincipal(req, 'events.event.read', 'events.app.read');
@@ -72,6 +72,8 @@ run([
@@ -72,6 +72,8 @@ run([
assert.equal(page.next_after_seq, 3);
assert.equal(page.next_after_seq, 3);
assert.equal(page.latest_seq, 5);
assert.equal(page.latest_seq, 5);
assert.match(page.next_cursor, /^c1\./, 'the page carries an opaque next_cursor');
assert.match(page.next_cursor, /^c1\./, 'the page carries an opaque next_cursor');
+ assert.match(page.latest_cursor, /^c1\./, 'and the head as an opaque latest_cursor');
+ assert.deepStrictEqual((await events.pull({ topic: 'media.vod.*', after: page.latest_cursor })).events, [], 'nothing after the head');
assert.match(page.events[0].cursor, /^c1\./, 'each event carries its cursor');
assert.match(page.events[0].cursor, /^c1\./, 'each event carries its cursor');
// The opaque cursor round-trips: `after` resumes exactly where the page ended.
// The opaque cursor round-trips: `after` resumes exactly where the page ended.
const rest = await events.pull({ topic: 'media.vod.*', after: page.next_cursor, limit: 2 });
const rest = await events.pull({ topic: 'media.vod.*', after: page.next_cursor, limit: 2 });