@owlmeans/bot-postgres 0.1.18-rc.2 → 0.1.18

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 CHANGED
@@ -1,29 +1,30 @@
1
1
  # @owlmeans/bot-postgres
2
2
 
3
- PostgreSQL storage for `@owlmeans/server-bot`: it registers the four resources the `BotService`
4
- resolves by alias — `bot-connection`, `bot-rule`, `bot-update` (the inbox) and `bot-activity` — with
3
+ PostgreSQL storage for `@owlmeans/server-bot`: it registers the three resources the `BotService`
4
+ resolves by alias — `bot-connection`, `bot-update` (the inbox) and `bot-activity` — with
5
5
  the shared AJV schemas and the indexes the service reads by. A Postgres-backed server (typically a
6
6
  generated target project) adds it next to `appendBot`.
7
7
 
8
8
  ## Installation
9
9
 
10
10
  ```bash
11
- bun add @owlmeans/bot-postgres@^0.1.18-rc.2
11
+ bun add @owlmeans/bot-postgres@^0.1.18
12
12
  ```
13
13
 
14
14
  Peer dependencies: `pg`, `ajv`.
15
15
 
16
16
  ## Concepts
17
17
 
18
- - **Four resources** — `BotConnectionResource`, `BotRuleResource`, `BotUpdateResource` and
19
- `BotActivityResource`, each a `PostgresResource` of the matching `@owlmeans/server-bot` record, at
20
- the aliases `RES_BOT_CONNECTION`, `RES_BOT_RULE`, `RES_BOT_UPDATE`, `RES_BOT_ACTIVITY`.
18
+ - **Three resources** — `BotConnectionResource`, `BotUpdateResource` and `BotActivityResource`, each
19
+ a `PostgresResource` of the matching `@owlmeans/server-bot` record, at the aliases
20
+ `RES_BOT_CONNECTION`, `RES_BOT_UPDATE`, `RES_BOT_ACTIVITY`. An application's keyword groups are its
21
+ own records, stored by its own resources — not here.
21
22
  - **Shared schemas** — `resource.schema` is exactly `server-bot`'s record schema; this package
22
23
  declares no schema of its own.
23
24
  - **Column shapes** — nested objects (`identity`, the inbox `update`, the activity `target`) are one
24
- `jsonb` column each; string lists (`keywords`, `setup`, `credentialsSet`, `handled`) are `text[]`;
25
- timestamps are ISO `text`; the sealed credentials are one `text` column; the rule's `order` is a
26
- quoted `double precision` column.
25
+ `jsonb` column each; string lists (`setup`, `credentialsSet`, `handled`) are `text[]`; timestamps
26
+ are ISO `text`; the sealed credentials are one `text` column; the activity's `ref` (the handler's
27
+ opaque reference) is a nullable `text` column.
27
28
  - **Unique inbox key** — `dedupe` carries a unique index, so a redelivered update is one row even
28
29
  when two deliveries race.
29
30
  - **Ids** — records are created without one; Postgres mints it.
@@ -38,7 +39,7 @@ import { appendPostgresBot } from '@owlmeans/bot-postgres'
38
39
  import { appendBot } from '@owlmeans/server-bot'
39
40
 
40
41
  appendPostgres(context) // the Postgres connection service, cfg.dbs[...]
41
- appendPostgresBot(context) // the four resources
42
+ appendPostgresBot(context) // the three resources
42
43
  appendBot(context) // the service that resolves them by alias
43
44
 
44
45
  await context.configure().init() // resource init reconciles tables and indexes (meta.autoSync, default Full)
@@ -49,7 +50,7 @@ await context.configure().init() // resource init reconciles tables and inde
49
50
  ### Another database, connection service or alias set
50
51
 
51
52
  ```typescript
52
- const resources = { connection: 'chat-connection', rule: 'chat-rule', update: 'chat-update', activity: 'chat-activity' }
53
+ const resources = { connection: 'chat-connection', update: 'chat-update', activity: 'chat-activity' }
53
54
 
54
55
  appendPostgresBot(context, { dbAlias: 'bots', serviceAlias: 'postgres-secondary', resources })
55
56
  appendBot(context, { resources })
@@ -72,15 +73,14 @@ export const makeResource: ResourceMaker<BotConnectionRecord, BotConnectionResou
72
73
  (dbAlias, serviceAlias) => makeBotConnectionResource(dbAlias, RES_BOT_CONNECTION, serviceAlias)
73
74
  ```
74
75
 
75
- `rule.ts`, `update.ts` and `activity.ts` follow the same shape.
76
+ `update.ts` and `activity.ts` follow the same shape.
76
77
 
77
78
  ## API
78
79
 
79
80
  | Symbol | Kind | Purpose |
80
81
  |---|---|---|
81
- | `appendPostgresBot(ctx, opts?)` | function | Registers the four resources, each only if its alias is free |
82
+ | `appendPostgresBot(ctx, opts?)` | function | Registers the three resources, each only if its alias is free |
82
83
  | `makeBotConnectionResource(dbAlias?, alias?, serviceAlias?)` | function | `BotConnectionResource` |
83
- | `makeBotRuleResource(dbAlias?, alias?, serviceAlias?)` | function | `BotRuleResource` |
84
84
  | `makeBotUpdateResource(dbAlias?, alias?, serviceAlias?)` | function | `BotUpdateResource` (the inbox) |
85
85
  | `makeBotActivityResource(dbAlias?, alias?, serviceAlias?)` | function | `BotActivityResource` |
86
86
  | `BotPostgresOptions` | type | `{ dbAlias?, serviceAlias?, resources? }` |
@@ -93,8 +93,6 @@ Named `<table>_<suffix>`:
93
93
  |---|---|---|
94
94
  | `bot_connection` | `scope_created` | `scope`, `createdAt` |
95
95
  | `bot_connection` | `receive` | `enabled`, `status`, `receive` |
96
- | `bot_rule` | `scope` | `scope` |
97
- | `bot_rule` | `scope_connection` | `scope`, `connection` |
98
96
  | `bot_update` | `dedupe` (unique) | `dedupe` |
99
97
  | `bot_update` | `inbox` | `status`, `receivedAt` |
100
98
  | `bot_update` | `lease` | `status`, `claimedAt` |
@@ -106,7 +104,7 @@ Named `<table>_<suffix>`:
106
104
  ## Testing
107
105
 
108
106
  `tests/schema.spec.ts` needs no database: it compiles the shared schemas and asserts the column
109
- types, the quoted `order` column, the declared indexes and idempotent registration.
107
+ types, the activity's `ref` column, the declared indexes and idempotent registration.
110
108
  `tests/conformance.spec.ts` (the `@owlmeans/server-bot/conformance` store suite, every case including
111
109
  the unique one) and `tests/tables.spec.ts` (a second boot plans no DDL; the round trips) are
112
110
  integration suites gated on `POSTGRES_URL`; they skip without one.
@@ -135,7 +133,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
135
133
  your project's skill store (`.agents/skills/`):
136
134
 
137
135
  ```sh
138
- npx @owlmeans/agent-skills@^0.1.18-rc.59
136
+ npx @owlmeans/agent-skills@^0.1.18
139
137
  ```
140
138
 
141
139
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 3,
3
3
  "package": "@owlmeans/bot-postgres",
4
- "version": "0.1.18-rc.2",
5
- "generatedAt": "2026-10-26T22:23:53.840Z",
4
+ "version": "0.1.18",
5
+ "generatedAt": "2026-10-28T00:31:34.725Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bot-postgres
3
- description: How to use @owlmeans/bot-postgres — the Postgres extension that registers the four @owlmeans/server-bot resources (bot-connection, bot-rule, bot-update, bot-activity) for a GENERATED TARGET PROJECT, their table shapes and indexes, the unique inbox dedupe key, and the target's resource seed files. Auto-invoked when wiring bot storage into a target's Postgres backend, writing a target's resources/bot/*.ts, or touching the bot tables' shape or indexes.
3
+ description: How to use @owlmeans/bot-postgres — the Postgres extension that registers the three @owlmeans/server-bot resources (bot-connection, bot-update, bot-activity) for a GENERATED TARGET PROJECT, their table shapes and indexes, the unique inbox dedupe key, and the target's resource seed files. Auto-invoked when wiring bot storage into a target's Postgres backend, writing a target's resources/bot/*.ts, or touching the bot tables' shape or indexes.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,11 +8,11 @@ user-invocable: false
8
8
  # @owlmeans/bot-postgres
9
9
 
10
10
  **Layer:** Infra extension
11
- **Install:** `"@owlmeans/bot-postgres": "^0.1.18-rc.2"` in `dependencies` (peers `pg`, `ajv`)
11
+ **Install:** `"@owlmeans/bot-postgres": "^0.1.18"` in `dependencies` (peers `pg`, `ajv`)
12
12
 
13
- The Postgres store of `@owlmeans/server-bot`: four `@owlmeans/postgres-resource` resources over the
13
+ The Postgres store of `@owlmeans/server-bot`: three `@owlmeans/postgres-resource` resources over the
14
14
  record schemas `server-bot` declares, plus the indexes its reads need. It owns no bot behaviour — the
15
- `BotService` resolves the four by alias on every call, so this package and `appendBot` are registered
15
+ `BotService` resolves the three by alias on every call, so this package and `appendBot` are registered
16
16
  independently, in any order.
17
17
 
18
18
  ## Key Exports
@@ -20,10 +20,9 @@ independently, in any order.
20
20
  | Export | Description |
21
21
  |--------|-------------|
22
22
  | `makeBotConnectionResource(dbAlias?, alias?, serviceAlias?)` | `BotConnectionResource` (`PostgresResource<BotConnectionRecord>`), alias default `RES_BOT_CONNECTION` |
23
- | `makeBotRuleResource(dbAlias?, alias?, serviceAlias?)` | `BotRuleResource`, default `RES_BOT_RULE` |
24
23
  | `makeBotUpdateResource(dbAlias?, alias?, serviceAlias?)` | `BotUpdateResource` — the inbox, default `RES_BOT_UPDATE` |
25
24
  | `makeBotActivityResource(dbAlias?, alias?, serviceAlias?)` | `BotActivityResource`, default `RES_BOT_ACTIVITY` |
26
- | `appendPostgresBot(ctx, opts?)` | Registers the four, each only while its alias is free — idempotent |
25
+ | `appendPostgresBot(ctx, opts?)` | Registers the three, each only while its alias is free — idempotent |
27
26
  | `BotPostgresOptions` | `{ dbAlias?, serviceAlias?, resources?: BotResourceAliases }` |
28
27
 
29
28
  `dbAlias` is the `cfg.dbs` entry (default `postgres`), `serviceAlias` the connection service (default
@@ -32,8 +31,8 @@ independently, in any order.
32
31
 
33
32
  ## The schema is imported, never redeclared
34
33
 
35
- Each maker assigns `BotConnectionRecordSchema` / `BotRuleRecordSchema` / `BotUpdateRecordSchema` /
36
- `BotActivityRecordSchema` from `@owlmeans/server-bot` to `resource.schema` — the same object, never a
34
+ Each maker assigns `BotConnectionRecordSchema` / `BotUpdateRecordSchema` / `BotActivityRecordSchema`
35
+ from `@owlmeans/server-bot` to `resource.schema` — the same object, never a
37
36
  copy, and no `pg:` override. A change to a record is a change to `server-bot`'s schema; this package
38
37
  follows it at the next boot (`PgAutoSync.Full` reconciles the table).
39
38
 
@@ -44,11 +43,11 @@ What `postgres-resource`'s default compiler makes of the shared schemas (`tests/
44
43
  | Values | Column | Properties |
45
44
  |---|---|---|
46
45
  | nested objects | one `jsonb` column each | `identity`, the inbox `update` (open: `raw` is the platform's payload), the activity `target` |
47
- | string lists | native `text[]` | `setup`, `credentialsSet`, `keywords`, `handled` |
46
+ | string lists | native `text[]` | `setup`, `credentialsSet`, `handled` |
48
47
  | timestamps | `text` (ISO, sortable as stored — no `format`, so never `timestamptz`) | `createdAt`, `updatedAt`, `receivedAt`, `claimedAt`, `retryAt`, `processedAt`, `at` |
49
48
  | sealed credentials | ONE `text` column, never split per credential key | `sealed` (`v1.<iv>.<tag>.<ciphertext>`) |
50
- | enums | `text` + `CHECK` | `platform`, `transport`, `status`, `receive`, `mode`, `action` |
51
- | `order` (a reserved word) | `double precision`, quoted wherever the store names it | rule `order` |
49
+ | enums | `text` + `CHECK` | `platform`, `transport`, `status`, `receive`, `action` |
50
+ | the handler's reference | nullable `text` | the activity `ref` (opaque: the id of the app's own record a handler followed) |
52
51
 
53
52
  Records are created without an `id` (Postgres mints `gen_random_uuid()::text`); `update`/`save` with an
54
53
  id REPLACES the whole row. Absent optional fields come back `null`; the service reads `null` as absent.
@@ -62,8 +61,6 @@ schema never collides; a maker run twice declares each index once.
62
61
  |---|---|---|---|
63
62
  | `bot_connection` | `scope_created` | `scope`, `createdAt` | a scope's connections in order |
64
63
  | `bot_connection` | `receive` | `enabled`, `status`, `receive` | the worker's receiver reconciliation |
65
- | `bot_rule` | `scope` | `scope` | a scope's rules |
66
- | `bot_rule` | `scope_connection` | `scope`, `connection` | a connection's own rules, the remove cascade |
67
64
  | `bot_update` | `dedupe` **UNIQUE** | `dedupe` | one row per redelivered update |
68
65
  | `bot_update` | `inbox` | `status`, `receivedAt` | pending rows, oldest first |
69
66
  | `bot_update` | `lease` | `status`, `claimedAt` | expired `processing` claims |
@@ -78,7 +75,7 @@ the conformance suite's `unique` capability.
78
75
 
79
76
  ## Target wiring
80
77
 
81
- **Backs:** chat-bot connections with sealed credentials, keyword rules, the inbound update inbox and the bots' activity log
78
+ **Backs:** chat-bot connections with sealed credentials, the inbound update inbox and the bots' activity log
82
79
 
83
80
  | Sub-project | Packages |
84
81
  |---|---|
@@ -88,7 +85,8 @@ One file per resource under `sources/backend/src/resources/bot/`: the generated
88
85
  file's zero-argument `makeResource` and registers it before `init()` creates the table. The path
89
86
  names the alias (`bot/connection.ts` → `bot-connection`), which is exactly `server-bot`'s default, so
90
87
  `appendBot(context)` needs no `resources` option. The bot service itself, the api trees and the
91
- worker runtime are `server-bot`'s wiring.
88
+ worker runtime are `server-bot`'s wiring. Keyword groups are NOT stored here: they are the target's
89
+ own generated product records, with their own resource file like any other record.
92
90
 
93
91
  ```ts file=sources/backend/src/resources/bot/connection.ts
94
92
  import { makeBotConnectionResource } from '@owlmeans/bot-postgres'
@@ -105,18 +103,6 @@ export const makeResource: ResourceMaker<BotConnectionRecord, BotConnectionResou
105
103
  (dbAlias, serviceAlias) => makeBotConnectionResource(dbAlias, RES_BOT_CONNECTION, serviceAlias)
106
104
  ```
107
105
 
108
- ```ts file=sources/backend/src/resources/bot/rule.ts
109
- import { makeBotRuleResource } from '@owlmeans/bot-postgres'
110
- import type { BotRuleResource } from '@owlmeans/bot-postgres'
111
- import { RES_BOT_RULE } from '@owlmeans/server-bot'
112
- import type { BotRuleRecord } from '@owlmeans/server-bot'
113
- import type { ResourceMaker } from '@owlmeans/resource'
114
-
115
- /** The keyword rules (`bot-rule`) — scope-wide or bound to one connection, kept in `order`. */
116
- export const makeResource: ResourceMaker<BotRuleRecord, BotRuleResource> =
117
- (dbAlias, serviceAlias) => makeBotRuleResource(dbAlias, RES_BOT_RULE, serviceAlias)
118
- ```
119
-
120
106
  ```ts file=sources/backend/src/resources/bot/update.ts
121
107
  import { makeBotUpdateResource } from '@owlmeans/bot-postgres'
122
108
  import type { BotUpdateResource } from '@owlmeans/bot-postgres'
@@ -141,7 +127,7 @@ export const makeResource: ResourceMaker<BotActivityRecord, BotActivityResource>
141
127
  (dbAlias, serviceAlias) => makeBotActivityResource(dbAlias, RES_BOT_ACTIVITY, serviceAlias)
142
128
  ```
143
129
 
144
- All four are required: the service reads and writes every one of them. Never pass a maker to
130
+ All three are required: the service reads and writes every one of them. Never pass a maker to
145
131
  `ResourceMaker` directly (`makeResource = makeBotConnectionResource`) — a caller's `serviceAlias`
146
132
  would land in the resource-alias position.
147
133
 
@@ -153,9 +139,9 @@ import { appendPostgresBot } from '@owlmeans/bot-postgres'
153
139
  import { appendBot } from '@owlmeans/server-bot'
154
140
 
155
141
  appendPostgres(context) // the connection service, cfg.dbs[...]
156
- appendPostgresBot(context) // the four resources
142
+ appendPostgresBot(context) // the three resources
157
143
  appendBot(context) // the service, which resolves them by alias per call
158
- await context.configure().init() // init reconciles the four tables and their indexes
144
+ await context.configure().init() // init reconciles the three tables and their indexes
159
145
  ```
160
146
 
161
147
  Custom aliases go to both sides:
@@ -163,11 +149,11 @@ Custom aliases go to both sides:
163
149
 
164
150
  ## Testing
165
151
 
166
- Category C. `bun test ./tests`: `schema.spec.ts` needs no database (the column types, the quoted
167
- `order`, the declared indexes, the unique dedupe DDL, idempotent registration); `conformance.spec.ts`
152
+ Category C. `bun test ./tests`: `schema.spec.ts` needs no database (the column types, the activity's
153
+ `ref` column, the declared indexes, the unique dedupe DDL, idempotent registration); `conformance.spec.ts`
168
154
  runs `server-bot`'s store suite — `botConformanceCasesFor(['unique'])` over
169
155
  `makeBotConformanceSubject(context)`, every case — and `tables.spec.ts` asserts a second boot plans
170
- no DDL and round-trips the jsonb, `text[]` and `order` columns. Both are gated on `POSTGRES_URL`
156
+ no DDL and round-trips the jsonb, `text[]` and `ref` columns. Both are gated on `POSTGRES_URL`
171
157
  (`gateHelper.postgresGate()`, each spec file its own throwaway schema) and skip cleanly without it.
172
158
  With no database of this checkout's own, run them against a throwaway container
173
159
  (`docker run --rm -d -p 127.0.0.1:<port>:5432 -e POSTGRES_PASSWORD=… postgres:<tag>`) — never another
package/build/helper.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { BasicContext } from '@owlmeans/context';
2
2
  import type { BotPostgresOptions } from './types.js';
3
3
  /**
4
- * Registers the four bot resources, each only while its alias is free — a second call (a context
4
+ * Registers the three bot resources, each only while its alias is free — a second call (a context
5
5
  * composed in two places, a hot reload) leaves the registered ones alone. Registration order against
6
6
  * `appendBot` is free: the service resolves its resources by alias on every call.
7
7
  */
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAMrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEpD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAAS,YAAY,CAAC,GAAG,CAAC,SAAQ,kBAAkB,KAAQ,IAmBzF,CAAA"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEpD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAAS,YAAY,CAAC,GAAG,CAAC,SAAQ,kBAAkB,KAAQ,IAezF,CAAA"}
package/build/helper.js CHANGED
@@ -1,22 +1,18 @@
1
- import { RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE } from '@owlmeans/server-bot';
2
- import { makeBotActivityResource, makeBotConnectionResource, makeBotRuleResource, makeBotUpdateResource, } from './resource.js';
1
+ import { RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_UPDATE } from '@owlmeans/server-bot';
2
+ import { makeBotActivityResource, makeBotConnectionResource, makeBotUpdateResource } from './resource.js';
3
3
  /**
4
- * Registers the four bot resources, each only while its alias is free — a second call (a context
4
+ * Registers the three bot resources, each only while its alias is free — a second call (a context
5
5
  * composed in two places, a hot reload) leaves the registered ones alone. Registration order against
6
6
  * `appendBot` is free: the service resolves its resources by alias on every call.
7
7
  */
8
8
  export const appendPostgresBot = (ctx, opts = {}) => {
9
9
  const { dbAlias, serviceAlias, resources = {} } = opts;
10
10
  const connection = resources.connection ?? RES_BOT_CONNECTION;
11
- const rule = resources.rule ?? RES_BOT_RULE;
12
11
  const update = resources.update ?? RES_BOT_UPDATE;
13
12
  const activity = resources.activity ?? RES_BOT_ACTIVITY;
14
13
  if (!ctx.hasResource(connection)) {
15
14
  ctx.registerResource(makeBotConnectionResource(dbAlias, connection, serviceAlias));
16
15
  }
17
- if (!ctx.hasResource(rule)) {
18
- ctx.registerResource(makeBotRuleResource(dbAlias, rule, serviceAlias));
19
- }
20
16
  if (!ctx.hasResource(update)) {
21
17
  ctx.registerResource(makeBotUpdateResource(dbAlias, update, serviceAlias));
22
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAEzG,OAAO,EACL,uBAAuB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,qBAAqB,GAC/F,MAAM,eAAe,CAAA;AAGtB;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAsB,EAAE,IAAI,GAAuB,EAAE,EAAQ,EAAE;IAC/F,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,IAAI,CAAA;IACtD,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,IAAI,kBAAkB,CAAA;IAC7D,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,YAAY,CAAA;IAC3C,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,cAAc,CAAA;IACjD,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,gBAAgB,CAAA;IAEvD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAA;IACpF,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAA;IACxE,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAA;IAC5E,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,GAAG,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAA;IAChF,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE3F,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAGzG;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAsB,EAAE,IAAI,GAAuB,EAAE,EAAQ,EAAE;IAC/F,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,IAAI,CAAA;IACtD,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,IAAI,kBAAkB,CAAA;IAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,cAAc,CAAA;IACjD,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,gBAAgB,CAAA;IAEvD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAA;IACpF,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAA;IAC5E,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,GAAG,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAA;IAChF,CAAC;AACH,CAAC,CAAA"}
@@ -1,4 +1,4 @@
1
- import type { BotActivityResource, BotConnectionResource, BotRuleResource, BotUpdateResource } from './types.js';
1
+ import type { BotActivityResource, BotConnectionResource, BotUpdateResource } from './types.js';
2
2
  /**
3
3
  * `bot-connection` — the connections of every scope. The schema is `server-bot`'s own, assigned, never
4
4
  * copied: `identity` compiles to one `jsonb` column, `setup` and `credentialsSet` to `text[]`, the
@@ -6,11 +6,6 @@ import type { BotActivityResource, BotConnectionResource, BotRuleResource, BotUp
6
6
  * the worker's reconciliation (enabled, connected, polling or on the gateway).
7
7
  */
8
8
  export declare const makeBotConnectionResource: (dbAlias?: string, alias?: string, serviceAlias?: string) => BotConnectionResource;
9
- /**
10
- * `bot-rule` — keyword rules, scope-wide (`connection` null) or bound to one connection; `keywords` is
11
- * `text[]`, `order` a `double precision` column (quoted wherever the store names it).
12
- */
13
- export declare const makeBotRuleResource: (dbAlias?: string, alias?: string, serviceAlias?: string) => BotRuleResource;
14
9
  /**
15
10
  * `bot-update` — the inbox. `dedupe` is UNIQUE: two concurrent deliveries of one platform update
16
11
  * collide here (`RecordExists`) and the service reads the stored row back. The normalized `update`
@@ -18,6 +13,9 @@ export declare const makeBotRuleResource: (dbAlias?: string, alias?: string, ser
18
13
  * expired leases), a connection's newest update, and the retention purge.
19
14
  */
20
15
  export declare const makeBotUpdateResource: (dbAlias?: string, alias?: string, serviceAlias?: string) => BotUpdateResource;
21
- /** `bot-activity` — what every action did; `target` is one `jsonb` column. Read newest first per scope. */
16
+ /**
17
+ * `bot-activity` — what every action did; `target` is one `jsonb` column, `ref` (the handler's opaque
18
+ * reference) a nullable `text` column. Read newest first per scope.
19
+ */
22
20
  export declare const makeBotActivityResource: (dbAlias?: string, alias?: string, serviceAlias?: string) => BotActivityResource;
23
21
  //# sourceMappingURL=resource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAoBhH;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,aAC1B,MAAM,UAAS,MAAM,iBAAsC,MAAM,KAC1E,qBASF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,aACpB,MAAM,UAAS,MAAM,iBAAgC,MAAM,KACpE,eASF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,aACtB,MAAM,UAAS,MAAM,iBAAkC,MAAM,KACtE,iBAYF,CAAA;AAED,2GAA2G;AAC3G,eAAO,MAAM,uBAAuB,aACxB,MAAM,UAAS,MAAM,iBAAoC,MAAM,KACxE,mBASF,CAAA"}
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAoB/F;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,aAC1B,MAAM,UAAS,MAAM,iBAAsC,MAAM,KAC1E,qBASF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,aACtB,MAAM,UAAS,MAAM,iBAAkC,MAAM,KACtE,iBAYF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,aACxB,MAAM,UAAS,MAAM,iBAAoC,MAAM,KACxE,mBASF,CAAA"}
package/build/resource.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { makePostgresResource, pgDeclarationHelper, pgNameHelper } from '@owlmeans/postgres-resource';
2
- import { BotActivityRecordSchema, BotConnectionRecordSchema, BotRuleRecordSchema, BotUpdateRecordSchema, RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE, } from '@owlmeans/server-bot';
2
+ import { BotActivityRecordSchema, BotConnectionRecordSchema, BotUpdateRecordSchema, RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_UPDATE, } from '@owlmeans/server-bot';
3
3
  /**
4
4
  * Declare the indexes a maker owns, each once. Declarations are kept per alias at module scope, so a
5
5
  * maker that runs twice (a target's file wrapping it, a spec) would otherwise declare every index
@@ -31,19 +31,6 @@ export const makeBotConnectionResource = (dbAlias, alias = RES_BOT_CONNECTION, s
31
31
  ]);
32
32
  return resource;
33
33
  };
34
- /**
35
- * `bot-rule` — keyword rules, scope-wide (`connection` null) or bound to one connection; `keywords` is
36
- * `text[]`, `order` a `double precision` column (quoted wherever the store names it).
37
- */
38
- export const makeBotRuleResource = (dbAlias, alias = RES_BOT_RULE, serviceAlias) => {
39
- const resource = makePostgresResource(alias, dbAlias, serviceAlias);
40
- resource.schema = BotRuleRecordSchema;
41
- declareIndexes(resource, alias, [
42
- ['scope', { columns: ['scope'] }],
43
- ['scope_connection', { columns: ['scope', 'connection'] }],
44
- ]);
45
- return resource;
46
- };
47
34
  /**
48
35
  * `bot-update` — the inbox. `dedupe` is UNIQUE: two concurrent deliveries of one platform update
49
36
  * collide here (`RecordExists`) and the service reads the stored row back. The normalized `update`
@@ -62,7 +49,10 @@ export const makeBotUpdateResource = (dbAlias, alias = RES_BOT_UPDATE, serviceAl
62
49
  ]);
63
50
  return resource;
64
51
  };
65
- /** `bot-activity` — what every action did; `target` is one `jsonb` column. Read newest first per scope. */
52
+ /**
53
+ * `bot-activity` — what every action did; `target` is one `jsonb` column, `ref` (the handler's opaque
54
+ * reference) a nullable `text` column. Read newest first per scope.
55
+ */
66
56
  export const makeBotActivityResource = (dbAlias, alias = RES_BOT_ACTIVITY, serviceAlias) => {
67
57
  const resource = makePostgresResource(alias, dbAlias, serviceAlias);
68
58
  resource.schema = BotActivityRecordSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
package/build/types.d.ts CHANGED
@@ -1,11 +1,8 @@
1
1
  import type { PostgresResource } from '@owlmeans/postgres-resource';
2
- import type { BotActivityRecord, BotConnectionRecord, BotResourceAliases, BotRuleRecord, BotUpdateRecord } from '@owlmeans/server-bot';
2
+ import type { BotActivityRecord, BotConnectionRecord, BotResourceAliases, BotUpdateRecord } from '@owlmeans/server-bot';
3
3
  /** `bot-connection` — one row per connected bot, its credentials sealed in one text column. */
4
4
  export interface BotConnectionResource extends PostgresResource<BotConnectionRecord> {
5
5
  }
6
- /** `bot-rule` — the keyword rules of a scope, scope-wide or bound to one connection. */
7
- export interface BotRuleResource extends PostgresResource<BotRuleRecord> {
8
- }
9
6
  /** `bot-update` — the inbox: one row per inbound platform update, unique by its `dedupe` key. */
10
7
  export interface BotUpdateResource extends PostgresResource<BotUpdateRecord> {
11
8
  }
@@ -13,12 +10,12 @@ export interface BotUpdateResource extends PostgresResource<BotUpdateRecord> {
13
10
  export interface BotActivityResource extends PostgresResource<BotActivityRecord> {
14
11
  }
15
12
  export interface BotPostgresOptions {
16
- /** The `cfg.dbs` entry the four tables live in — default `postgres`. */
13
+ /** The `cfg.dbs` entry the three tables live in — default `postgres`. */
17
14
  dbAlias?: string;
18
15
  /** The Postgres connection service — default `postgres`. */
19
16
  serviceAlias?: string;
20
17
  /**
21
- * The resources' aliases — default `bot-connection`, `bot-rule`, `bot-update`, `bot-activity`.
18
+ * The resources' aliases — default `bot-connection`, `bot-update`, `bot-activity`.
22
19
  * The bot service must be given the same ones (`appendBot(ctx, { resources })`).
23
20
  */
24
21
  resources?: BotResourceAliases;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,KAAK,EACV,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAC3F,MAAM,sBAAsB,CAAA;AAE7B,+FAA+F;AAC/F,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB,CAAC,mBAAmB,CAAC;CAAG;AAEvF,wFAAwF;AACxF,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,CAAC,aAAa,CAAC;CAAG;AAE3E,iGAAiG;AACjG,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB,CAAC,eAAe,CAAC;CAAG;AAE/E,sFAAsF;AACtF,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB,CAAC,iBAAiB,CAAC;CAAG;AAEnF,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEvH,+FAA+F;AAC/F,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB,CAAC,mBAAmB,CAAC;CAAG;AAEvF,iGAAiG;AACjG,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB,CAAC,eAAe,CAAC;CAAG;AAE/E,sFAAsF;AACtF,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB,CAAC,iBAAiB,CAAC;CAAG;AAEnF,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@owlmeans/bot-postgres",
3
- "version": "0.1.18-rc.2",
3
+ "version": "0.1.18",
4
4
  "license": "MIT",
5
- "description": "Postgres-backed resources for @owlmeans/server-bot — the connection, rule, inbox and activity tables of a generated target project, compiled from the shared AJV schemas, with the unique inbox dedupe key.",
5
+ "description": "Postgres-backed resources for @owlmeans/server-bot \u2014 the connection, inbox and activity tables of a generated target project, compiled from the shared AJV schemas, with the unique inbox dedupe key.",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "build": "tsc -b",
@@ -23,23 +23,23 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@owlmeans/context": "^0.1.18-rc.35",
27
- "@owlmeans/postgres-resource": "^0.1.18-rc.50",
28
- "@owlmeans/resource": "^0.1.18-rc.41",
29
- "@owlmeans/server-bot": "^0.1.18-rc.2"
26
+ "@owlmeans/context": "^0.1.18",
27
+ "@owlmeans/postgres-resource": "^0.1.18",
28
+ "@owlmeans/resource": "^0.1.18",
29
+ "@owlmeans/server-bot": "^0.1.18"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "ajv": "*",
33
33
  "pg": "*"
34
34
  },
35
35
  "devDependencies": {
36
- "@owlmeans/bot": "^0.1.18-rc.2",
37
- "@owlmeans/dep-config": "workspace:*",
38
- "@owlmeans/log": "^0.1.18-rc.4",
39
- "@owlmeans/postgres": "^0.1.18-rc.52",
40
- "@owlmeans/server-context": "^0.1.18-rc.45",
41
- "@owlmeans/test": "^0.1.18-rc.39",
42
- "@owlmeans/test-integration": "^0.1.18-rc.37",
36
+ "@owlmeans/bot": "^0.1.18",
37
+ "@owlmeans/dep-config": "^0.1.18",
38
+ "@owlmeans/log": "^0.1.18",
39
+ "@owlmeans/postgres": "^0.1.18",
40
+ "@owlmeans/server-context": "^0.1.18",
41
+ "@owlmeans/test": "^0.1.18",
42
+ "@owlmeans/test-integration": "^0.1.18",
43
43
  "@types/bun": "^1.4.2",
44
44
  "@types/node": "^26.6.4",
45
45
  "@types/pg": "^8.23.1",
package/src/helper.ts CHANGED
@@ -1,29 +1,23 @@
1
1
  import type { BasicContext } from '@owlmeans/context'
2
- import { RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE } from '@owlmeans/server-bot'
2
+ import { RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_UPDATE } from '@owlmeans/server-bot'
3
3
 
4
- import {
5
- makeBotActivityResource, makeBotConnectionResource, makeBotRuleResource, makeBotUpdateResource,
6
- } from './resource.js'
4
+ import { makeBotActivityResource, makeBotConnectionResource, makeBotUpdateResource } from './resource.js'
7
5
  import type { BotPostgresOptions } from './types.js'
8
6
 
9
7
  /**
10
- * Registers the four bot resources, each only while its alias is free — a second call (a context
8
+ * Registers the three bot resources, each only while its alias is free — a second call (a context
11
9
  * composed in two places, a hot reload) leaves the registered ones alone. Registration order against
12
10
  * `appendBot` is free: the service resolves its resources by alias on every call.
13
11
  */
14
12
  export const appendPostgresBot = (ctx: BasicContext<any>, opts: BotPostgresOptions = {}): void => {
15
13
  const { dbAlias, serviceAlias, resources = {} } = opts
16
14
  const connection = resources.connection ?? RES_BOT_CONNECTION
17
- const rule = resources.rule ?? RES_BOT_RULE
18
15
  const update = resources.update ?? RES_BOT_UPDATE
19
16
  const activity = resources.activity ?? RES_BOT_ACTIVITY
20
17
 
21
18
  if (!ctx.hasResource(connection)) {
22
19
  ctx.registerResource(makeBotConnectionResource(dbAlias, connection, serviceAlias))
23
20
  }
24
- if (!ctx.hasResource(rule)) {
25
- ctx.registerResource(makeBotRuleResource(dbAlias, rule, serviceAlias))
26
- }
27
21
  if (!ctx.hasResource(update)) {
28
22
  ctx.registerResource(makeBotUpdateResource(dbAlias, update, serviceAlias))
29
23
  }
package/src/resource.ts CHANGED
@@ -2,12 +2,12 @@ import { makePostgresResource, pgDeclarationHelper, pgNameHelper } from '@owlmea
2
2
  import type { PostgresResource } from '@owlmeans/postgres-resource'
3
3
  import type { ResourceRecord } from '@owlmeans/resource'
4
4
  import {
5
- BotActivityRecordSchema, BotConnectionRecordSchema, BotRuleRecordSchema, BotUpdateRecordSchema,
6
- RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE,
5
+ BotActivityRecordSchema, BotConnectionRecordSchema, BotUpdateRecordSchema, RES_BOT_ACTIVITY, RES_BOT_CONNECTION,
6
+ RES_BOT_UPDATE,
7
7
  } from '@owlmeans/server-bot'
8
- import type { BotActivityRecord, BotConnectionRecord, BotRuleRecord, BotUpdateRecord } from '@owlmeans/server-bot'
8
+ import type { BotActivityRecord, BotConnectionRecord, BotUpdateRecord } from '@owlmeans/server-bot'
9
9
 
10
- import type { BotActivityResource, BotConnectionResource, BotRuleResource, BotUpdateResource } from './types.js'
10
+ import type { BotActivityResource, BotConnectionResource, BotUpdateResource } from './types.js'
11
11
  import type { IndexList } from './types.local.js'
12
12
 
13
13
  /**
@@ -46,23 +46,6 @@ export const makeBotConnectionResource = (
46
46
  return resource
47
47
  }
48
48
 
49
- /**
50
- * `bot-rule` — keyword rules, scope-wide (`connection` null) or bound to one connection; `keywords` is
51
- * `text[]`, `order` a `double precision` column (quoted wherever the store names it).
52
- */
53
- export const makeBotRuleResource = (
54
- dbAlias?: string, alias: string = RES_BOT_RULE, serviceAlias?: string
55
- ): BotRuleResource => {
56
- const resource = makePostgresResource<BotRuleRecord, BotRuleResource>(alias, dbAlias, serviceAlias)
57
- resource.schema = BotRuleRecordSchema
58
- declareIndexes(resource, alias, [
59
- ['scope', { columns: ['scope'] }],
60
- ['scope_connection', { columns: ['scope', 'connection'] }],
61
- ])
62
-
63
- return resource
64
- }
65
-
66
49
  /**
67
50
  * `bot-update` — the inbox. `dedupe` is UNIQUE: two concurrent deliveries of one platform update
68
51
  * collide here (`RecordExists`) and the service reads the stored row back. The normalized `update`
@@ -85,7 +68,10 @@ export const makeBotUpdateResource = (
85
68
  return resource
86
69
  }
87
70
 
88
- /** `bot-activity` — what every action did; `target` is one `jsonb` column. Read newest first per scope. */
71
+ /**
72
+ * `bot-activity` — what every action did; `target` is one `jsonb` column, `ref` (the handler's opaque
73
+ * reference) a nullable `text` column. Read newest first per scope.
74
+ */
89
75
  export const makeBotActivityResource = (
90
76
  dbAlias?: string, alias: string = RES_BOT_ACTIVITY, serviceAlias?: string
91
77
  ): BotActivityResource => {
package/src/types.ts CHANGED
@@ -1,14 +1,9 @@
1
1
  import type { PostgresResource } from '@owlmeans/postgres-resource'
2
- import type {
3
- BotActivityRecord, BotConnectionRecord, BotResourceAliases, BotRuleRecord, BotUpdateRecord,
4
- } from '@owlmeans/server-bot'
2
+ import type { BotActivityRecord, BotConnectionRecord, BotResourceAliases, BotUpdateRecord } from '@owlmeans/server-bot'
5
3
 
6
4
  /** `bot-connection` — one row per connected bot, its credentials sealed in one text column. */
7
5
  export interface BotConnectionResource extends PostgresResource<BotConnectionRecord> {}
8
6
 
9
- /** `bot-rule` — the keyword rules of a scope, scope-wide or bound to one connection. */
10
- export interface BotRuleResource extends PostgresResource<BotRuleRecord> {}
11
-
12
7
  /** `bot-update` — the inbox: one row per inbound platform update, unique by its `dedupe` key. */
13
8
  export interface BotUpdateResource extends PostgresResource<BotUpdateRecord> {}
14
9
 
@@ -16,12 +11,12 @@ export interface BotUpdateResource extends PostgresResource<BotUpdateRecord> {}
16
11
  export interface BotActivityResource extends PostgresResource<BotActivityRecord> {}
17
12
 
18
13
  export interface BotPostgresOptions {
19
- /** The `cfg.dbs` entry the four tables live in — default `postgres`. */
14
+ /** The `cfg.dbs` entry the three tables live in — default `postgres`. */
20
15
  dbAlias?: string
21
16
  /** The Postgres connection service — default `postgres`. */
22
17
  serviceAlias?: string
23
18
  /**
24
- * The resources' aliases — default `bot-connection`, `bot-rule`, `bot-update`, `bot-activity`.
19
+ * The resources' aliases — default `bot-connection`, `bot-update`, `bot-activity`.
25
20
  * The bot service must be given the same ones (`appendBot(ctx, { resources })`).
26
21
  */
27
22
  resources?: BotResourceAliases
@@ -4,20 +4,19 @@ import { addLogPlugin, memoryPlugin } from '@owlmeans/log'
4
4
  import { pgDeclarationHelper, pgDiffHelper, pgSchemaHelper } from '@owlmeans/postgres-resource'
5
5
  import type { TableSpec } from '@owlmeans/postgres-resource'
6
6
  import {
7
- BotActivityRecordSchema, BotConnectionRecordSchema, BotRuleRecordSchema, BotUpdateRecordSchema,
8
- RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE,
7
+ BotActivityRecordSchema, BotConnectionRecordSchema, BotUpdateRecordSchema, RES_BOT_ACTIVITY, RES_BOT_CONNECTION,
8
+ RES_BOT_UPDATE,
9
9
  } from '@owlmeans/server-bot'
10
10
 
11
11
  import {
12
- appendPostgresBot, makeBotActivityResource, makeBotConnectionResource, makeBotRuleResource, makeBotUpdateResource,
12
+ appendPostgresBot, makeBotActivityResource, makeBotConnectionResource, makeBotUpdateResource,
13
13
  } from '../src/index.js'
14
14
  import type { BotUpdateResource } from '../src/index.js'
15
15
 
16
- const ALIASES = [RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE, RES_BOT_ACTIVITY]
16
+ const ALIASES = [RES_BOT_CONNECTION, RES_BOT_UPDATE, RES_BOT_ACTIVITY]
17
17
 
18
18
  const SCHEMAS: Record<string, object> = {
19
19
  [RES_BOT_CONNECTION]: BotConnectionRecordSchema,
20
- [RES_BOT_RULE]: BotRuleRecordSchema,
21
20
  [RES_BOT_UPDATE]: BotUpdateRecordSchema,
22
21
  [RES_BOT_ACTIVITY]: BotActivityRecordSchema,
23
22
  }
@@ -30,7 +29,6 @@ const reset = (): void => {
30
29
 
31
30
  const makeAll = (): void => {
32
31
  makeBotConnectionResource()
33
- makeBotRuleResource()
34
32
  makeBotUpdateResource()
35
33
  makeBotActivityResource()
36
34
  }
@@ -59,7 +57,7 @@ const ddlOf = (spec: TableSpec): string[] =>
59
57
  describe('@owlmeans/bot-postgres — table shapes', () => {
60
58
  test('each maker assigns server-bot\'s schema, not a copy, under the default alias', () => {
61
59
  reset()
62
- const made = [makeBotConnectionResource(), makeBotRuleResource(), makeBotUpdateResource(), makeBotActivityResource()]
60
+ const made = [makeBotConnectionResource(), makeBotUpdateResource(), makeBotActivityResource()]
63
61
 
64
62
  expect(made.map(resource => resource.alias)).toEqual(ALIASES)
65
63
  expect(made.map(resource => resource.schema)).toEqual(ALIASES.map(alias => SCHEMAS[alias]))
@@ -84,7 +82,6 @@ describe('@owlmeans/bot-postgres — table shapes', () => {
84
82
  reset()
85
83
  makeAll()
86
84
  const connection = specOf(RES_BOT_CONNECTION)
87
- const rule = specOf(RES_BOT_RULE)
88
85
  const update = specOf(RES_BOT_UPDATE)
89
86
  const activity = specOf(RES_BOT_ACTIVITY)
90
87
 
@@ -96,7 +93,6 @@ describe('@owlmeans/bot-postgres — table shapes', () => {
96
93
  const strings = { sqlType: 'text[]', jsonb: false, array: true }
97
94
  expect(typeOf(connection, 'setup')).toEqual({ ...strings, notNull: false })
98
95
  expect(typeOf(connection, 'credentialsSet')).toEqual({ ...strings, notNull: true })
99
- expect(typeOf(rule, 'keywords')).toEqual({ ...strings, notNull: true })
100
96
  expect(typeOf(update, 'handled')).toEqual({ ...strings, notNull: true })
101
97
 
102
98
  /** The sealed credentials are ONE opaque text column, never split per credential key. */
@@ -108,17 +104,15 @@ describe('@owlmeans/bot-postgres — table shapes', () => {
108
104
  ])
109
105
  })
110
106
 
111
- test('the rule\'s order is a double precision column, quoted in the DDL', () => {
107
+ test('the activity\'s ref is a nullable text column — the handler\'s opaque reference', () => {
112
108
  reset()
113
109
  makeAll()
114
- const rule = specOf(RES_BOT_RULE)
115
-
116
- expect([rule.byProperty.order.column, rule.byProperty.order.sqlType, rule.byProperty.order.notNull])
117
- .toEqual(['order', 'double precision', true])
118
- expect(typeOf(rule, 'connection')).toEqual({ sqlType: 'text', jsonb: false, array: false, notNull: false })
119
- const [create] = ddlOf(rule)
120
- expect(create).toContain('"order" double precision NOT NULL')
121
- expect(create).not.toMatch(/[^"]order[^"]/)
110
+ const activity = specOf(RES_BOT_ACTIVITY)
111
+
112
+ expect(typeOf(activity, 'ref')).toEqual({ sqlType: 'text', jsonb: false, array: false, notNull: false })
113
+ expect(activity.byProperty.rule).toBeUndefined()
114
+ const [create] = ddlOf(activity)
115
+ expect(create).toContain('"ref" text')
122
116
  })
123
117
 
124
118
  test('the inbox dedupe key is a unique index, and every index the reads need is declared', () => {
@@ -131,10 +125,6 @@ describe('@owlmeans/bot-postgres — table shapes', () => {
131
125
  ['bot_connection_scope_created', ['scope', 'createdAt'], false],
132
126
  ['bot_connection_receive', ['enabled', 'status', 'receive'], false],
133
127
  ])
134
- expect(names(RES_BOT_RULE)).toEqual([
135
- ['bot_rule_scope', ['scope'], false],
136
- ['bot_rule_scope_connection', ['scope', 'connection'], false],
137
- ])
138
128
  expect(names(RES_BOT_UPDATE)).toEqual([
139
129
  ['bot_update_dedupe', ['dedupe'], true],
140
130
  ['bot_update_inbox', ['status', 'receivedAt'], false],
@@ -169,7 +159,7 @@ describe('@owlmeans/bot-postgres — table shapes', () => {
169
159
  }
170
160
  })
171
161
 
172
- test('appendPostgresBot registers the four once, and custom aliases name their own tables and indexes', () => {
162
+ test('appendPostgresBot registers the three once, and custom aliases name their own tables and indexes', () => {
173
163
  const context = makeBasicContext<BasicConfig>({ ready: false, service: 'bot-pg-schema', type: AppType.Backend, services: {} })
174
164
  appendPostgresBot(context)
175
165
  const first = ALIASES.map(alias => context.resource(alias))
@@ -177,7 +167,7 @@ describe('@owlmeans/bot-postgres — table shapes', () => {
177
167
  expect(ALIASES.map(alias => context.resource(alias))).toEqual(first)
178
168
  first.forEach((resource, at) => expect(context.resource(ALIASES[at])).toBe(resource))
179
169
 
180
- const custom = { connection: 'chat-connection', rule: 'chat-rule', update: 'chat-update', activity: 'chat-activity' }
170
+ const custom = { connection: 'chat-connection', update: 'chat-update', activity: 'chat-activity' }
181
171
  appendPostgresBot(context, { resources: custom })
182
172
  expect(Object.values(custom).map(alias => context.resource<BotUpdateResource>(alias).schema))
183
173
  .toEqual(ALIASES.map(alias => SCHEMAS[alias]))
@@ -1,16 +1,16 @@
1
1
  import { afterAll, describe, expect, test } from 'bun:test'
2
2
  import { makePgIntrospectHelper, pgDiffHelper } from '@owlmeans/postgres-resource'
3
3
  import type { PostgresResource } from '@owlmeans/postgres-resource'
4
- import { BotChatKind, BotMatchMode, BotPlatform, BotRuleAction, BotUpdateKind } from '@owlmeans/bot'
4
+ import { BotActionKind, BotChatKind, BotPlatform, BotTransport, BotUpdateKind } from '@owlmeans/bot'
5
5
  import { RecordExists } from '@owlmeans/resource'
6
- import { BotInboxStatus, RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE } from '@owlmeans/server-bot'
6
+ import { BotInboxStatus, RES_BOT_ACTIVITY, RES_BOT_CONNECTION, RES_BOT_UPDATE } from '@owlmeans/server-bot'
7
7
  import type { BotUpdateRecord } from '@owlmeans/server-bot'
8
8
 
9
9
  import { appendPostgresBot } from '../src/index.js'
10
- import type { BotRuleResource, BotUpdateResource } from '../src/index.js'
10
+ import type { BotActivityResource, BotUpdateResource } from '../src/index.js'
11
11
  import { gate, makeSuite } from './context.js'
12
12
 
13
- const ALIASES = [RES_BOT_CONNECTION, RES_BOT_RULE, RES_BOT_UPDATE, RES_BOT_ACTIVITY]
13
+ const ALIASES = [RES_BOT_CONNECTION, RES_BOT_UPDATE, RES_BOT_ACTIVITY]
14
14
 
15
15
  const suite = makeSuite('tables')
16
16
  const it = gate.skip ? test.skip : test
@@ -36,7 +36,7 @@ describe('@owlmeans/bot-postgres — tables against a real database', () => {
36
36
  await suite.teardown()
37
37
  })
38
38
 
39
- it('a second boot reconciles nothing on any of the four tables', async () => {
39
+ it('a second boot reconciles nothing on any of the three tables', async () => {
40
40
  await suite.boot()
41
41
  const again = await suite.boot()
42
42
  const { pool } = await again.context.resource<PostgresResource<never>>(RES_BOT_CONNECTION).db()
@@ -53,10 +53,10 @@ describe('@owlmeans/bot-postgres — tables against a real database', () => {
53
53
  }
54
54
  })
55
55
 
56
- it('round-trips nested values, string lists and the order column; the dedupe key is unique', async () => {
56
+ it('round-trips nested values, string lists and the activity ref; the dedupe key is unique', async () => {
57
57
  const { context } = await suite.boot()
58
58
  const updates = context.resource<BotUpdateResource>(RES_BOT_UPDATE)
59
- const rules = context.resource<BotRuleResource>(RES_BOT_RULE)
59
+ const activities = context.resource<BotActivityResource>(RES_BOT_ACTIVITY)
60
60
 
61
61
  const row = await updates.create(inboxRow('c-1:telegram:1'))
62
62
  expect(typeof row.id).toBe('string')
@@ -64,18 +64,24 @@ describe('@owlmeans/bot-postgres — tables against a real database', () => {
64
64
  expect([stored.handled, stored.update.chat, stored.claimedAt]).toEqual([[], { id: '-100', kind: BotChatKind.Group }, null])
65
65
  await expect(updates.create(inboxRow('c-1:telegram:1'))).rejects.toThrow(RecordExists)
66
66
 
67
- const rule = await rules.create({
68
- scope: 'tables', name: 'Spam', keywords: ['casino', 'free money'], mode: BotMatchMode.Word, action: BotRuleAction.Delete,
69
- enabled: true, order: 2.5, createdAt: '2026-10-26T10:00:00.000Z', updatedAt: '2026-10-26T10:00:00.000Z',
67
+ const followed = await activities.create({
68
+ scope: 'tables', connection: 'c-1', platform: BotPlatform.Telegram, update: row.id!, action: BotActionKind.Delete,
69
+ target: { chat: '-100', message: '7' }, ref: 'group-spam', ok: true, transport: BotTransport.Mock,
70
+ at: '2026-10-26T10:00:01.000Z',
70
71
  })
71
- const sorted = await rules.list({ scope: 'tables' }, { sort: [{ field: 'order', order: 'desc' }] })
72
- expect(sorted.items.map(item => [item.id, item.order, item.keywords, item.connection])).toEqual([
73
- [rule.id, 2.5, ['casino', 'free money'], null],
72
+ const plain = await activities.create({
73
+ scope: 'tables', connection: 'c-1', platform: BotPlatform.Telegram, action: BotActionKind.Send,
74
+ target: { chat: '-100' }, text: 'Announcement', ok: true, transport: BotTransport.Mock, at: '2026-10-26T10:00:02.000Z',
75
+ })
76
+ const newest = await activities.list({ scope: 'tables' }, { sort: [{ field: 'at', order: 'desc' }] })
77
+ expect(newest.items.map(item => [item.id, item.ref, item.target])).toEqual([
78
+ [plain.id, null, { chat: '-100' }],
79
+ [followed.id, 'group-spam', { chat: '-100', message: '7' }],
74
80
  ])
75
81
  })
76
82
 
77
83
  it('custom aliases get tables and index names of their own', async () => {
78
- const custom = { connection: 'chat-connection', rule: 'chat-rule', update: 'chat-update', activity: 'chat-activity' }
84
+ const custom = { connection: 'chat-connection', update: 'chat-update', activity: 'chat-activity' }
79
85
  const { context } = await suite.boot({ bot: { resources: custom } })
80
86
  const registered = context.resource(custom.update)
81
87
  appendPostgresBot(context, { resources: custom })