kempo 4.2.40 → 4.4.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/README.md +7 -0
- package/app-public/default.template.html +1 -1
- package/dist/admin/nav.fragment.html +5 -0
- package/dist/admin/realtime/index.page.html +81 -0
- package/dist/kempo/api/realtime/WS.js +2 -0
- package/dist/kempo/api/realtime/WS.js.map +1 -0
- package/dist/kempo/api/realtime/connections/GET.js +2 -0
- package/dist/kempo/api/realtime/connections/GET.js.map +1 -0
- package/dist/kempo/icons/credit_card.svg +1 -0
- package/dist/kempo/icons/sensors.svg +1 -0
- package/dist/kempo/realtime.js +2 -0
- package/dist/kempo/realtime.js.map +1 -0
- package/dist/kempo/sdk.js +1 -1
- package/dist/kempo/sdk.js.map +1 -1
- package/middleware/kempo.js +30 -15
- package/package.json +2 -2
- package/scripts/init-db.js +4 -1
- package/server/db/schema.js +30 -1
- package/server/sdk.js +5 -0
- package/server/utils/extensions/contentDirs.js +27 -0
- package/server/utils/realtime/Hub.js +695 -0
- package/server/utils/realtime/channels.js +247 -0
- package/server/utils/realtime/closeConnection.js +4 -0
- package/server/utils/realtime/constants.js +20 -0
- package/server/utils/realtime/duration.js +18 -0
- package/server/utils/realtime/getHub.js +15 -0
- package/server/utils/realtime/index.js +15 -0
- package/server/utils/realtime/listConnections.js +4 -0
- package/server/utils/realtime/listSubscribers.js +4 -0
- package/server/utils/realtime/pruneMessages.js +45 -0
- package/server/utils/realtime/publish.js +86 -0
- package/server/utils/realtime/sendToConnection.js +4 -0
- package/server/utils/realtime/unregisterChannel.js +19 -0
- package/server/utils/routing/serveUnmatched.js +8 -1
package/server/db/schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pgTable, text, timestamp, boolean, index, jsonb } from 'drizzle-orm/pg-core';
|
|
1
|
+
import { pgTable, text, timestamp, boolean, index, jsonb, bigserial, bigint } from 'drizzle-orm/pg-core';
|
|
2
2
|
|
|
3
3
|
/*
|
|
4
4
|
Auth Tables
|
|
@@ -114,6 +114,35 @@ export const extension = pgTable('extension', {
|
|
|
114
114
|
updatedAt: timestamp('updatedAt').notNull(),
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
+
/*
|
|
118
|
+
Realtime System
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
A published message, kept only for channels that opt in to persistence. `id` is what a client
|
|
123
|
+
hands back as `since` to replay what it missed, so it must be ordered within a channel: publish
|
|
124
|
+
takes a per-channel lock, otherwise two rows could commit out of id order and a replay from the
|
|
125
|
+
earlier id would skip the later-committing one for good.
|
|
126
|
+
*/
|
|
127
|
+
export const realtimeMessage = pgTable('realtimeMessage', {
|
|
128
|
+
id: bigserial('id', { mode: 'number' }).primaryKey(),
|
|
129
|
+
channel: text('channel').notNull(),
|
|
130
|
+
data: jsonb('data').notNull(),
|
|
131
|
+
createdAt: timestamp('createdAt').notNull(),
|
|
132
|
+
}, table => [
|
|
133
|
+
index('realtimeMessage_channel_id_idx').on(table.channel, table.id),
|
|
134
|
+
index('realtimeMessage_createdAt_idx').on(table.createdAt),
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
/*
|
|
138
|
+
How far a channel has been pruned. Ids are shared across channels, so a gap cannot be inferred from
|
|
139
|
+
id arithmetic; a client whose `since` is below this watermark has provably missed messages.
|
|
140
|
+
*/
|
|
141
|
+
export const realtimeChannel = pgTable('realtimeChannel', {
|
|
142
|
+
channel: text('channel').primaryKey(),
|
|
143
|
+
prunedThrough: bigint('prunedThrough', { mode: 'number' }).notNull().default(0),
|
|
144
|
+
});
|
|
145
|
+
|
|
117
146
|
/*
|
|
118
147
|
Triggers to prevent deletion of system resources
|
|
119
148
|
*/
|
package/server/sdk.js
CHANGED
|
@@ -196,3 +196,8 @@ export { default as listExtensions } from './utils/extensions/listExtensions.js'
|
|
|
196
196
|
export { default as uninstallExtension } from './utils/extensions/uninstallExtension.js';
|
|
197
197
|
export { default as updateExtension } from './utils/extensions/updateExtension.js';
|
|
198
198
|
|
|
199
|
+
/*
|
|
200
|
+
Realtime
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
export * as realtime from './utils/realtime/index.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { getEnabledExtensions } from './scopeCache.js';
|
|
3
|
+
|
|
4
|
+
const NODE_MODULES = join(process.cwd(), 'node_modules');
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
The directories an enabled extension may contribute *.global.html and *.fragment.html from, split
|
|
8
|
+
by which half of the site is rendering: `admin/` for the admin portal, `public/` for the live site.
|
|
9
|
+
|
|
10
|
+
Each is read straight from the package at render time, the same way an extension's pages and
|
|
11
|
+
routes are resolved, so nothing is copied anywhere on install: enabling, disabling, upgrading or
|
|
12
|
+
removing an extension takes effect immediately, and there is nothing left behind to clean up.
|
|
13
|
+
|
|
14
|
+
That is also the whole of the on/off switch for this content — a disabled extension drops out of
|
|
15
|
+
these lists and its files are simply never read. There is no `enabled` flag on a packaged file the
|
|
16
|
+
way there is on admin-authored global content, because there is no stored row to carry one.
|
|
17
|
+
|
|
18
|
+
Lives here rather than in middleware/kempo.js so that server utils can reach it too — the 404 page
|
|
19
|
+
is rendered from server/utils/routing/serveUnmatched.js, and importing the middleware from there
|
|
20
|
+
would be circular.
|
|
21
|
+
*/
|
|
22
|
+
const extensionDirs = async sub =>
|
|
23
|
+
(await getEnabledExtensions()).map(ext => join(NODE_MODULES, ext.name, sub));
|
|
24
|
+
|
|
25
|
+
export const extensionAdminDirs = () => extensionDirs('admin');
|
|
26
|
+
|
|
27
|
+
export const extensionPublicDirs = () => extensionDirs('public');
|