@everystack/events 0.3.1 → 0.4.1
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/CHANGELOG.md +47 -0
- package/package.json +15 -6
- package/src/models/descriptors.ts +77 -0
- package/src/models/event-action.ts +3 -0
- package/src/models/index.ts +5 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@everystack/events` are documented here.
|
|
4
|
+
|
|
5
|
+
Format based on [Keep a Changelog](https://keepachangelog.com/).
|
|
6
|
+
|
|
7
|
+
## [0.4.1] - 2026-09-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- auto-generated changelogs from conventional commits
|
|
12
|
+
- automate the version-drift check — a manual note is not a gate
|
|
13
|
+
|
|
14
|
+
## [0.4.0] - 2026-07-19
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- descriptors go live in the verbs — the B3 wiring (read-model-everywhere)
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- pin React to a single 19.2.0 across the monorepo
|
|
23
|
+
- guard npm publish on workspace-dep packages; cli 0.3.8
|
|
24
|
+
|
|
25
|
+
## [0.3.1] - 2026-06-30
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- add @everystack/events package and wire real-time UI
|
|
30
|
+
- data-driven event actions for admin-configurable routing
|
|
31
|
+
- own ops.event_actions as a v3 Model + eventModule
|
|
32
|
+
- wire cache invalidation + event-driven jobs in example app
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- add AWS KVS + SigV4a as direct dependencies
|
|
37
|
+
- pin all dependency versions to lockfile-resolved values
|
|
38
|
+
- revert @aws-sdk/signature-v4a to 3.1031.0, fix KVS SigV4a signing
|
|
39
|
+
- everystack_notify guards NEW.id for composite-key tables
|
|
40
|
+
- extensionless relative imports (repo convention; Metro resolution)
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- migrate all package schemas to everyschema canonical tables
|
|
45
|
+
- drop type module from all packages, switch Jest to CJS mode
|
|
46
|
+
- consolidate Jest configs into shared base
|
|
47
|
+
- route server imports through react-free package doors
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@everystack/events",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "PostgreSQL LISTEN/NOTIFY bridge for serverless — WebSocket fan-out + Lambda invocation",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"author": "Scalable Technology, Inc. <licensing@scalable.technology>",
|
|
@@ -18,44 +18,53 @@
|
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"src",
|
|
21
|
-
"README.md"
|
|
21
|
+
"README.md",
|
|
22
|
+
"CHANGELOG.md"
|
|
22
23
|
],
|
|
23
24
|
"exports": {
|
|
24
25
|
".": {
|
|
26
|
+
"source": "./src/index.ts",
|
|
25
27
|
"types": "./src/index.ts",
|
|
26
28
|
"default": "./src/index.ts"
|
|
27
29
|
},
|
|
28
30
|
"./triggers": {
|
|
31
|
+
"source": "./src/triggers.ts",
|
|
29
32
|
"types": "./src/triggers.ts",
|
|
30
33
|
"default": "./src/triggers.ts"
|
|
31
34
|
},
|
|
32
35
|
"./handler": {
|
|
36
|
+
"source": "./src/handler/index.ts",
|
|
33
37
|
"types": "./src/handler/index.ts",
|
|
34
38
|
"default": "./src/handler/index.ts"
|
|
35
39
|
},
|
|
36
40
|
"./schema": {
|
|
41
|
+
"source": "./src/schema.ts",
|
|
37
42
|
"types": "./src/schema.ts",
|
|
38
43
|
"default": "./src/schema.ts"
|
|
39
44
|
},
|
|
40
45
|
"./models": {
|
|
46
|
+
"source": "./src/models/index.ts",
|
|
41
47
|
"types": "./src/models/index.ts",
|
|
42
48
|
"default": "./src/models/index.ts"
|
|
43
49
|
},
|
|
44
50
|
"./client": {
|
|
51
|
+
"source": "./src/client/index.ts",
|
|
45
52
|
"types": "./src/client/index.ts",
|
|
46
53
|
"default": "./src/client/index.ts"
|
|
47
54
|
},
|
|
48
55
|
"./actions": {
|
|
56
|
+
"source": "./src/actions.ts",
|
|
49
57
|
"types": "./src/actions.ts",
|
|
50
58
|
"default": "./src/actions.ts"
|
|
51
59
|
},
|
|
52
60
|
"./listener": {
|
|
61
|
+
"source": "./src/listener.ts",
|
|
53
62
|
"types": "./src/listener.ts",
|
|
54
63
|
"default": "./src/listener.ts"
|
|
55
64
|
}
|
|
56
65
|
},
|
|
57
66
|
"dependencies": {
|
|
58
|
-
"@everystack/model": "0.
|
|
67
|
+
"@everystack/model": "0.4.18"
|
|
59
68
|
},
|
|
60
69
|
"peerDependencies": {
|
|
61
70
|
"@aws-sdk/client-apigatewaymanagementapi": "3.1053.0",
|
|
@@ -64,7 +73,7 @@
|
|
|
64
73
|
"@aws-sdk/signature-v4a": "3.1031.0",
|
|
65
74
|
"@tanstack/react-query": "5.100.9",
|
|
66
75
|
"drizzle-orm": "0.41.0",
|
|
67
|
-
"react": "19.2.
|
|
76
|
+
"react": "19.2.0"
|
|
68
77
|
},
|
|
69
78
|
"peerDependenciesMeta": {
|
|
70
79
|
"@aws-sdk/client-cloudfront-keyvaluestore": {
|
|
@@ -96,10 +105,10 @@
|
|
|
96
105
|
"@types/react": "19.2.14",
|
|
97
106
|
"drizzle-orm": "0.41.0",
|
|
98
107
|
"jest": "29.7.0",
|
|
99
|
-
"react": "19.2.
|
|
108
|
+
"react": "19.2.0",
|
|
100
109
|
"ts-jest": "29.4.9",
|
|
101
110
|
"typescript": "5.9.3",
|
|
102
|
-
"@everystack/auth": "0.
|
|
111
|
+
"@everystack/auth": "0.4.5"
|
|
103
112
|
},
|
|
104
113
|
"scripts": {
|
|
105
114
|
"test": "jest",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The events package's DECLARED derived layer — the notify functions and the trigger
|
|
3
|
+
* factory, as descriptors (docs/plans/read-model-everywhere.md). Supersedes the raw-SQL
|
|
4
|
+
* generators in `../triggers` (kept, deprecated, for the transition): declared objects
|
|
5
|
+
* are content-hashed, dependency-ordered, drift-checked by db:reconcile, and — because
|
|
6
|
+
* every compiled function revokes EXECUTE from PUBLIC — secure by default.
|
|
7
|
+
*
|
|
8
|
+
* Trigger attachment stays the APP's choice, now with owner consent visible in the
|
|
9
|
+
* model: each emitting table declares `triggers: [eventsTrigger('posts_events')]`
|
|
10
|
+
* itself — a package can offer a trigger, never silently attach one.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { defineFunction, trigger, sql, type TriggerSpec } from '@everystack/model';
|
|
14
|
+
|
|
15
|
+
/** `everystack_notify()` — row-change events onto the `events` NOTIFY channel. */
|
|
16
|
+
export const notifyFunction = defineFunction('everystack_notify', {
|
|
17
|
+
returns: 'trigger',
|
|
18
|
+
language: 'plpgsql',
|
|
19
|
+
body: sql`
|
|
20
|
+
DECLARE
|
|
21
|
+
row_id text;
|
|
22
|
+
BEGIN
|
|
23
|
+
-- A composite-key table (e.g. likes (user_id, post_id)) has no id column, so NEW.id
|
|
24
|
+
-- raises undefined_column — emit a NULL id rather than fail the whole write.
|
|
25
|
+
BEGIN
|
|
26
|
+
row_id := COALESCE(NEW.id, OLD.id);
|
|
27
|
+
EXCEPTION WHEN undefined_column THEN
|
|
28
|
+
row_id := NULL;
|
|
29
|
+
END;
|
|
30
|
+
PERFORM pg_notify(
|
|
31
|
+
'events',
|
|
32
|
+
json_build_object(
|
|
33
|
+
'schema', TG_TABLE_SCHEMA,
|
|
34
|
+
'table', TG_TABLE_NAME,
|
|
35
|
+
'op', lower(TG_OP),
|
|
36
|
+
'id', row_id
|
|
37
|
+
)::text
|
|
38
|
+
);
|
|
39
|
+
RETURN COALESCE(NEW, OLD);
|
|
40
|
+
END`,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The event trigger for one emitting table — declared ON the model
|
|
45
|
+
* (`triggers: [eventsTrigger('posts_events')]`). Convention: `<table>_events`,
|
|
46
|
+
* matching what `generateTriggerSQL` created, so an existing database adopts via
|
|
47
|
+
* `db:reconcile --baseline` instead of rebuilding.
|
|
48
|
+
*/
|
|
49
|
+
export function eventsTrigger(name: string): TriggerSpec {
|
|
50
|
+
return trigger(name, {
|
|
51
|
+
timing: 'after',
|
|
52
|
+
events: ['insert', 'update', 'delete'],
|
|
53
|
+
forEach: 'row',
|
|
54
|
+
execute: notifyFunction,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** `everystack_event_actions_notify()` — the rules table's self-notify (reload signal). */
|
|
59
|
+
export const eventActionsNotifyFunction = defineFunction('everystack_event_actions_notify', {
|
|
60
|
+
returns: 'trigger',
|
|
61
|
+
language: 'plpgsql',
|
|
62
|
+
body: sql`
|
|
63
|
+
BEGIN
|
|
64
|
+
PERFORM pg_notify('_event_actions', '{}');
|
|
65
|
+
RETURN COALESCE(NEW, OLD);
|
|
66
|
+
END`,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/** The self-notify trigger for ops.event_actions — declared on the EventAction model. */
|
|
70
|
+
export function eventActionsTrigger(): TriggerSpec {
|
|
71
|
+
return trigger('event_actions_notify', {
|
|
72
|
+
timing: 'after',
|
|
73
|
+
events: ['insert', 'update', 'delete'],
|
|
74
|
+
forEach: 'row',
|
|
75
|
+
execute: eventActionsNotifyFunction,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -17,11 +17,14 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { defineModel, field, can, index } from '@everystack/model';
|
|
20
|
+
import { eventActionsTrigger } from './descriptors';
|
|
20
21
|
|
|
21
22
|
export const EventAction = defineModel('event_actions', {
|
|
22
23
|
schema: 'ops',
|
|
23
24
|
writtenBy: 'worker',
|
|
24
25
|
private: true,
|
|
26
|
+
// Owner consent, visible in the model: the reload-signal trigger is declared HERE.
|
|
27
|
+
triggers: [eventActionsTrigger()],
|
|
25
28
|
fields: {
|
|
26
29
|
id: field.uuid().primaryKey().defaultRandom(),
|
|
27
30
|
tenantId: field.uuid().nullable(), // NULL = platform-wide, non-NULL = tenant-scoped
|
package/src/models/index.ts
CHANGED
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
import { defineModule } from '@everystack/model';
|
|
11
11
|
import { EventAction } from './event-action';
|
|
12
|
-
import {
|
|
12
|
+
import { eventActionsNotifyFunction, notifyFunction } from './descriptors';
|
|
13
13
|
|
|
14
14
|
export { EventAction } from './event-action';
|
|
15
|
+
export { notifyFunction, eventsTrigger, eventActionsNotifyFunction, eventActionsTrigger } from './descriptors';
|
|
15
16
|
|
|
16
17
|
/** All events-owned models, for the app to spread into its db:generate model list. */
|
|
17
18
|
export const eventModels = [EventAction];
|
|
@@ -22,5 +23,7 @@ export const eventModels = [EventAction];
|
|
|
22
23
|
*/
|
|
23
24
|
export const eventModule = defineModule({
|
|
24
25
|
models: eventModels,
|
|
25
|
-
functions
|
|
26
|
+
// The notify functions are DECLARED now (content-hashed, drift-checked, PUBLIC-revoked);
|
|
27
|
+
// notifyFunction ships here so app models can reference it via eventsTrigger(...).
|
|
28
|
+
derived: [notifyFunction, eventActionsNotifyFunction],
|
|
26
29
|
});
|