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

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,3 +1,144 @@
1
- # Temporary Holding Version
1
+ # @owlmeans/bot-postgres
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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
5
+ the shared AJV schemas and the indexes the service reads by. A Postgres-backed server (typically a
6
+ generated target project) adds it next to `appendBot`.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ bun add @owlmeans/bot-postgres@^0.1.18-rc.2
12
+ ```
13
+
14
+ Peer dependencies: `pg`, `ajv`.
15
+
16
+ ## Concepts
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`.
21
+ - **Shared schemas** — `resource.schema` is exactly `server-bot`'s record schema; this package
22
+ declares no schema of its own.
23
+ - **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.
27
+ - **Unique inbox key** — `dedupe` carries a unique index, so a redelivered update is one row even
28
+ when two deliveries race.
29
+ - **Ids** — records are created without one; Postgres mints it.
30
+
31
+ ## Usage
32
+
33
+ ### Register the resources and the service
34
+
35
+ ```typescript
36
+ import { appendPostgres } from '@owlmeans/postgres'
37
+ import { appendPostgresBot } from '@owlmeans/bot-postgres'
38
+ import { appendBot } from '@owlmeans/server-bot'
39
+
40
+ appendPostgres(context) // the Postgres connection service, cfg.dbs[...]
41
+ appendPostgresBot(context) // the four resources
42
+ appendBot(context) // the service that resolves them by alias
43
+
44
+ await context.configure().init() // resource init reconciles tables and indexes (meta.autoSync, default Full)
45
+ ```
46
+
47
+ `appendPostgresBot` skips a resource whose alias is already registered, so calling it twice is safe.
48
+
49
+ ### Another database, connection service or alias set
50
+
51
+ ```typescript
52
+ const resources = { connection: 'chat-connection', rule: 'chat-rule', update: 'chat-update', activity: 'chat-activity' }
53
+
54
+ appendPostgresBot(context, { dbAlias: 'bots', serviceAlias: 'postgres-secondary', resources })
55
+ appendBot(context, { resources })
56
+ ```
57
+
58
+ ### One resource per file (a generated target)
59
+
60
+ The second maker argument is the resource alias, so a target's file wraps the maker into a
61
+ `ResourceMaker`:
62
+
63
+ ```typescript
64
+ // sources/backend/src/resources/bot/connection.ts
65
+ import { makeBotConnectionResource } from '@owlmeans/bot-postgres'
66
+ import type { BotConnectionResource } from '@owlmeans/bot-postgres'
67
+ import { RES_BOT_CONNECTION } from '@owlmeans/server-bot'
68
+ import type { BotConnectionRecord } from '@owlmeans/server-bot'
69
+ import type { ResourceMaker } from '@owlmeans/resource'
70
+
71
+ export const makeResource: ResourceMaker<BotConnectionRecord, BotConnectionResource> =
72
+ (dbAlias, serviceAlias) => makeBotConnectionResource(dbAlias, RES_BOT_CONNECTION, serviceAlias)
73
+ ```
74
+
75
+ `rule.ts`, `update.ts` and `activity.ts` follow the same shape.
76
+
77
+ ## API
78
+
79
+ | Symbol | Kind | Purpose |
80
+ |---|---|---|
81
+ | `appendPostgresBot(ctx, opts?)` | function | Registers the four resources, each only if its alias is free |
82
+ | `makeBotConnectionResource(dbAlias?, alias?, serviceAlias?)` | function | `BotConnectionResource` |
83
+ | `makeBotRuleResource(dbAlias?, alias?, serviceAlias?)` | function | `BotRuleResource` |
84
+ | `makeBotUpdateResource(dbAlias?, alias?, serviceAlias?)` | function | `BotUpdateResource` (the inbox) |
85
+ | `makeBotActivityResource(dbAlias?, alias?, serviceAlias?)` | function | `BotActivityResource` |
86
+ | `BotPostgresOptions` | type | `{ dbAlias?, serviceAlias?, resources? }` |
87
+
88
+ ### Indexes
89
+
90
+ Named `<table>_<suffix>`:
91
+
92
+ | Table | Suffix | Columns |
93
+ |---|---|---|
94
+ | `bot_connection` | `scope_created` | `scope`, `createdAt` |
95
+ | `bot_connection` | `receive` | `enabled`, `status`, `receive` |
96
+ | `bot_rule` | `scope` | `scope` |
97
+ | `bot_rule` | `scope_connection` | `scope`, `connection` |
98
+ | `bot_update` | `dedupe` (unique) | `dedupe` |
99
+ | `bot_update` | `inbox` | `status`, `receivedAt` |
100
+ | `bot_update` | `lease` | `status`, `claimedAt` |
101
+ | `bot_update` | `connection_received` | `connection`, `receivedAt` |
102
+ | `bot_update` | `retention` | `status`, `processedAt` |
103
+ | `bot_activity` | `scope_at` | `scope`, `at` |
104
+ | `bot_activity` | `scope_connection_at` | `scope`, `connection`, `at` |
105
+
106
+ ## Testing
107
+
108
+ `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.
110
+ `tests/conformance.spec.ts` (the `@owlmeans/server-bot/conformance` store suite, every case including
111
+ the unique one) and `tests/tables.spec.ts` (a second boot plans no DDL; the round trips) are
112
+ integration suites gated on `POSTGRES_URL`; they skip without one.
113
+
114
+ ## Common pitfalls
115
+
116
+ - Using a maker directly as a `ResourceMaker` — its second argument is the resource alias, not the
117
+ service alias.
118
+ - Registering custom aliases here but not on `appendBot` — the service looks the defaults up and fails.
119
+ - Redeclaring a schema locally — the table would drift from what the service reads and writes.
120
+
121
+ The `bot-postgres` skill covers this package; the `server-bot` skill covers the records and the service.
122
+
123
+ ## Related packages
124
+
125
+ - [`@owlmeans/server-bot`](../server-bot) — the service, record types, schemas, aliases and the conformance suite
126
+ - [`@owlmeans/bot`](../bot) — the chat-bot contract
127
+ - [`@owlmeans/postgres-resource`](../postgres-resource) — `makePostgresResource`, `index()`, the schema-to-table compiler
128
+ - [`@owlmeans/postgres`](../postgres) — `appendPostgres`, the connection service
129
+
130
+ <!-- owlmeans:agent-guidance:start -->
131
+ ## Agent guidance
132
+
133
+ This package ships embedded agent skills under `agent-meta/`. After installing your
134
+ `@owlmeans/*` packages, run the OwlMeans agent-skills installer to place them into
135
+ your project's skill store (`.agents/skills/`):
136
+
137
+ ```sh
138
+ npx @owlmeans/agent-skills@^0.1.18-rc.59
139
+ ```
140
+
141
+ The embedded files are version-matched to this package release. Do not edit them
142
+ directly — they are regenerated on each publish. To contribute guidance edits,
143
+ open a PR against the source monorepo.
144
+ <!-- owlmeans:agent-guidance:end -->
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 3,
3
+ "package": "@owlmeans/bot-postgres",
4
+ "version": "0.1.18-rc.2",
5
+ "generatedAt": "2026-10-26T22:23:53.840Z",
6
+ "canonicalRepo": "https://github.com/owlmeans/common",
7
+ "entries": [
8
+ {
9
+ "kind": "skill",
10
+ "name": "bot-postgres",
11
+ "category": "package-specific",
12
+ "file": "skills/bot-postgres/SKILL.md",
13
+ "canonicalPath": ".agents/skills/bot-postgres/SKILL.md"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,181 @@
1
+ ---
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.
4
+ user-invocable: false
5
+ ---
6
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
7
+
8
+ # @owlmeans/bot-postgres
9
+
10
+ **Layer:** Infra extension
11
+ **Install:** `"@owlmeans/bot-postgres": "^0.1.18-rc.2"` in `dependencies` (peers `pg`, `ajv`)
12
+
13
+ The Postgres store of `@owlmeans/server-bot`: four `@owlmeans/postgres-resource` resources over the
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
16
+ independently, in any order.
17
+
18
+ ## Key Exports
19
+
20
+ | Export | Description |
21
+ |--------|-------------|
22
+ | `makeBotConnectionResource(dbAlias?, alias?, serviceAlias?)` | `BotConnectionResource` (`PostgresResource<BotConnectionRecord>`), alias default `RES_BOT_CONNECTION` |
23
+ | `makeBotRuleResource(dbAlias?, alias?, serviceAlias?)` | `BotRuleResource`, default `RES_BOT_RULE` |
24
+ | `makeBotUpdateResource(dbAlias?, alias?, serviceAlias?)` | `BotUpdateResource` — the inbox, default `RES_BOT_UPDATE` |
25
+ | `makeBotActivityResource(dbAlias?, alias?, serviceAlias?)` | `BotActivityResource`, default `RES_BOT_ACTIVITY` |
26
+ | `appendPostgresBot(ctx, opts?)` | Registers the four, each only while its alias is free — idempotent |
27
+ | `BotPostgresOptions` | `{ dbAlias?, serviceAlias?, resources?: BotResourceAliases }` |
28
+
29
+ `dbAlias` is the `cfg.dbs` entry (default `postgres`), `serviceAlias` the connection service (default
30
+ `postgres`). The second argument is the RESOURCE alias, not the service alias — so a maker is not a
31
+ `ResourceMaker` as is; a target file wraps it (below).
32
+
33
+ ## The schema is imported, never redeclared
34
+
35
+ Each maker assigns `BotConnectionRecordSchema` / `BotRuleRecordSchema` / `BotUpdateRecordSchema` /
36
+ `BotActivityRecordSchema` from `@owlmeans/server-bot` to `resource.schema` — the same object, never a
37
+ copy, and no `pg:` override. A change to a record is a change to `server-bot`'s schema; this package
38
+ follows it at the next boot (`PgAutoSync.Full` reconciles the table).
39
+
40
+ ## Table shapes
41
+
42
+ What `postgres-resource`'s default compiler makes of the shared schemas (`tests/schema.spec.ts` pins it):
43
+
44
+ | Values | Column | Properties |
45
+ |---|---|---|
46
+ | 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` |
48
+ | timestamps | `text` (ISO, sortable as stored — no `format`, so never `timestamptz`) | `createdAt`, `updatedAt`, `receivedAt`, `claimedAt`, `retryAt`, `processedAt`, `at` |
49
+ | 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` |
52
+
53
+ Records are created without an `id` (Postgres mints `gen_random_uuid()::text`); `update`/`save` with an
54
+ id REPLACES the whole row. Absent optional fields come back `null`; the service reads `null` as absent.
55
+
56
+ ## Indexes
57
+
58
+ Index names are `<table>_<suffix>`, so a second set of bot tables under custom aliases in the same
59
+ schema never collides; a maker run twice declares each index once.
60
+
61
+ | Table | Index | Columns | Serves |
62
+ |---|---|---|---|
63
+ | `bot_connection` | `scope_created` | `scope`, `createdAt` | a scope's connections in order |
64
+ | `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
+ | `bot_update` | `dedupe` **UNIQUE** | `dedupe` | one row per redelivered update |
68
+ | `bot_update` | `inbox` | `status`, `receivedAt` | pending rows, oldest first |
69
+ | `bot_update` | `lease` | `status`, `claimedAt` | expired `processing` claims |
70
+ | `bot_update` | `connection_received` | `connection`, `receivedAt` | a connection's newest update, its inbox purge |
71
+ | `bot_update` | `retention` | `status`, `processedAt` | the purge of old `done` rows |
72
+ | `bot_activity` | `scope_at` | `scope`, `at` | the activity feed, newest first |
73
+ | `bot_activity` | `scope_connection_at` | `scope`, `connection`, `at` | one connection's feed |
74
+
75
+ The unique `dedupe` is the store's backstop against two concurrent deliveries: the loser's `create`
76
+ throws `RecordExists` and the service reads the stored row back. It is what qualifies this store for
77
+ the conformance suite's `unique` capability.
78
+
79
+ ## Target wiring
80
+
81
+ **Backs:** chat-bot connections with sealed credentials, keyword rules, the inbound update inbox and the bots' activity log
82
+
83
+ | Sub-project | Packages |
84
+ |---|---|
85
+ | backend | `@owlmeans/bot-postgres`, `@owlmeans/server-bot`, `@owlmeans/bot` |
86
+
87
+ One file per resource under `sources/backend/src/resources/bot/`: the generated registry imports each
88
+ file's zero-argument `makeResource` and registers it before `init()` creates the table. The path
89
+ names the alias (`bot/connection.ts` → `bot-connection`), which is exactly `server-bot`'s default, so
90
+ `appendBot(context)` needs no `resources` option. The bot service itself, the api trees and the
91
+ worker runtime are `server-bot`'s wiring.
92
+
93
+ ```ts file=sources/backend/src/resources/bot/connection.ts
94
+ import { makeBotConnectionResource } from '@owlmeans/bot-postgres'
95
+ import type { BotConnectionResource } from '@owlmeans/bot-postgres'
96
+ import { RES_BOT_CONNECTION } from '@owlmeans/server-bot'
97
+ import type { BotConnectionRecord } from '@owlmeans/server-bot'
98
+ import type { ResourceMaker } from '@owlmeans/resource'
99
+
100
+ /**
101
+ * The bot's connections (`bot-connection`) — credentials sealed with APP_SECRET, never stored in
102
+ * clear. The maker is a thin wrapper: the schema and indexes are the package's own.
103
+ */
104
+ export const makeResource: ResourceMaker<BotConnectionRecord, BotConnectionResource> =
105
+ (dbAlias, serviceAlias) => makeBotConnectionResource(dbAlias, RES_BOT_CONNECTION, serviceAlias)
106
+ ```
107
+
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
+ ```ts file=sources/backend/src/resources/bot/update.ts
121
+ import { makeBotUpdateResource } from '@owlmeans/bot-postgres'
122
+ import type { BotUpdateResource } from '@owlmeans/bot-postgres'
123
+ import { RES_BOT_UPDATE } from '@owlmeans/server-bot'
124
+ import type { BotUpdateRecord } from '@owlmeans/server-bot'
125
+ import type { ResourceMaker } from '@owlmeans/resource'
126
+
127
+ /** The inbox (`bot-update`) — one row per inbound update, unique by its dedupe key; the worker drains it. */
128
+ export const makeResource: ResourceMaker<BotUpdateRecord, BotUpdateResource> =
129
+ (dbAlias, serviceAlias) => makeBotUpdateResource(dbAlias, RES_BOT_UPDATE, serviceAlias)
130
+ ```
131
+
132
+ ```ts file=sources/backend/src/resources/bot/activity.ts
133
+ import { makeBotActivityResource } from '@owlmeans/bot-postgres'
134
+ import type { BotActivityResource } from '@owlmeans/bot-postgres'
135
+ import { RES_BOT_ACTIVITY } from '@owlmeans/server-bot'
136
+ import type { BotActivityRecord } from '@owlmeans/server-bot'
137
+ import type { ResourceMaker } from '@owlmeans/resource'
138
+
139
+ /** What every bot action did (`bot-activity`) — kept when its connection is removed. */
140
+ export const makeResource: ResourceMaker<BotActivityRecord, BotActivityResource> =
141
+ (dbAlias, serviceAlias) => makeBotActivityResource(dbAlias, RES_BOT_ACTIVITY, serviceAlias)
142
+ ```
143
+
144
+ All four are required: the service reads and writes every one of them. Never pass a maker to
145
+ `ResourceMaker` directly (`makeResource = makeBotConnectionResource`) — a caller's `serviceAlias`
146
+ would land in the resource-alias position.
147
+
148
+ ## Wiring outside a target
149
+
150
+ ```ts
151
+ import { appendPostgres } from '@owlmeans/postgres'
152
+ import { appendPostgresBot } from '@owlmeans/bot-postgres'
153
+ import { appendBot } from '@owlmeans/server-bot'
154
+
155
+ appendPostgres(context) // the connection service, cfg.dbs[...]
156
+ appendPostgresBot(context) // the four resources
157
+ appendBot(context) // the service, which resolves them by alias per call
158
+ await context.configure().init() // init reconciles the four tables and their indexes
159
+ ```
160
+
161
+ Custom aliases go to both sides:
162
+ `appendPostgresBot(ctx, { resources })` and `appendBot(ctx, { resources })`.
163
+
164
+ ## Testing
165
+
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`
168
+ runs `server-bot`'s store suite — `botConformanceCasesFor(['unique'])` over
169
+ `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`
171
+ (`gateHelper.postgresGate()`, each spec file its own throwaway schema) and skip cleanly without it.
172
+ With no database of this checkout's own, run them against a throwaway container
173
+ (`docker run --rm -d -p 127.0.0.1:<port>:5432 -e POSTGRES_PASSWORD=… postgres:<tag>`) — never another
174
+ slot's test database. A new conformance case runs here only after `server-bot` is rebuilt.
175
+
176
+ ## Related
177
+
178
+ - `server-bot` — the service, the record types and schemas, the aliases, the conformance suite (read its skill first)
179
+ - `bot` — the contract the records carry (platforms, statuses, enums)
180
+ - `postgres-resource` — the table compiler, `index()`, the reconciliation · `postgres` — the connection service
181
+ - `marketing-consent-postgres`, `planning-postgres` — the same import-the-schema pattern for other features
@@ -0,0 +1,9 @@
1
+ import type { BasicContext } from '@owlmeans/context';
2
+ import type { BotPostgresOptions } from './types.js';
3
+ /**
4
+ * Registers the four bot resources, each only while its alias is free — a second call (a context
5
+ * composed in two places, a hot reload) leaves the registered ones alone. Registration order against
6
+ * `appendBot` is free: the service resolves its resources by alias on every call.
7
+ */
8
+ export declare const appendPostgresBot: (ctx: BasicContext<any>, opts?: BotPostgresOptions) => void;
9
+ //# sourceMappingURL=helper.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,27 @@
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';
3
+ /**
4
+ * Registers the four bot resources, each only while its alias is free — a second call (a context
5
+ * composed in two places, a hot reload) leaves the registered ones alone. Registration order against
6
+ * `appendBot` is free: the service resolves its resources by alias on every call.
7
+ */
8
+ export const appendPostgresBot = (ctx, opts = {}) => {
9
+ const { dbAlias, serviceAlias, resources = {} } = opts;
10
+ const connection = resources.connection ?? RES_BOT_CONNECTION;
11
+ const rule = resources.rule ?? RES_BOT_RULE;
12
+ const update = resources.update ?? RES_BOT_UPDATE;
13
+ const activity = resources.activity ?? RES_BOT_ACTIVITY;
14
+ if (!ctx.hasResource(connection)) {
15
+ ctx.registerResource(makeBotConnectionResource(dbAlias, connection, serviceAlias));
16
+ }
17
+ if (!ctx.hasResource(rule)) {
18
+ ctx.registerResource(makeBotRuleResource(dbAlias, rule, serviceAlias));
19
+ }
20
+ if (!ctx.hasResource(update)) {
21
+ ctx.registerResource(makeBotUpdateResource(dbAlias, update, serviceAlias));
22
+ }
23
+ if (!ctx.hasResource(activity)) {
24
+ ctx.registerResource(makeBotActivityResource(dbAlias, activity, serviceAlias));
25
+ }
26
+ };
27
+ //# sourceMappingURL=helper.js.map
@@ -0,0 +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"}
@@ -0,0 +1,4 @@
1
+ export type * from './types.js';
2
+ export * from './resource.js';
3
+ export * from './helper.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA"}
package/build/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './resource.js';
2
+ export * from './helper.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA"}
@@ -0,0 +1,23 @@
1
+ import type { BotActivityResource, BotConnectionResource, BotRuleResource, BotUpdateResource } from './types.js';
2
+ /**
3
+ * `bot-connection` — the connections of every scope. The schema is `server-bot`'s own, assigned, never
4
+ * copied: `identity` compiles to one `jsonb` column, `setup` and `credentialsSet` to `text[]`, the
5
+ * sealed credentials to one `text` column. Indexes follow the reads: a scope's list by creation, and
6
+ * the worker's reconciliation (enabled, connected, polling or on the gateway).
7
+ */
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
+ /**
15
+ * `bot-update` — the inbox. `dedupe` is UNIQUE: two concurrent deliveries of one platform update
16
+ * collide here (`RecordExists`) and the service reads the stored row back. The normalized `update`
17
+ * is one `jsonb` column, `handled` a `text[]`. Indexes follow the dispatcher (pending rows by age,
18
+ * expired leases), a connection's newest update, and the retention purge.
19
+ */
20
+ 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. */
22
+ export declare const makeBotActivityResource: (dbAlias?: string, alias?: string, serviceAlias?: string) => BotActivityResource;
23
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,75 @@
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';
3
+ /**
4
+ * Declare the indexes a maker owns, each once. Declarations are kept per alias at module scope, so a
5
+ * maker that runs twice (a target's file wrapping it, a spec) would otherwise declare every index
6
+ * again and the compiler would warn about the duplicate on every boot. The name carries the table,
7
+ * so a second set of bot tables under other aliases in the same schema never collides with the first.
8
+ */
9
+ const declareIndexes = (resource, alias, indexes) => {
10
+ const table = pgNameHelper.pgIdentifier(alias);
11
+ const declared = pgDeclarationHelper.getDeclaration(alias).indexes;
12
+ for (const [suffix, spec] of indexes) {
13
+ const name = `${table}_${suffix}`;
14
+ if (!declared.some(index => index.name === name)) {
15
+ resource.index(name, spec);
16
+ }
17
+ }
18
+ };
19
+ /**
20
+ * `bot-connection` — the connections of every scope. The schema is `server-bot`'s own, assigned, never
21
+ * copied: `identity` compiles to one `jsonb` column, `setup` and `credentialsSet` to `text[]`, the
22
+ * sealed credentials to one `text` column. Indexes follow the reads: a scope's list by creation, and
23
+ * the worker's reconciliation (enabled, connected, polling or on the gateway).
24
+ */
25
+ export const makeBotConnectionResource = (dbAlias, alias = RES_BOT_CONNECTION, serviceAlias) => {
26
+ const resource = makePostgresResource(alias, dbAlias, serviceAlias);
27
+ resource.schema = BotConnectionRecordSchema;
28
+ declareIndexes(resource, alias, [
29
+ ['scope_created', { columns: ['scope', 'createdAt'] }],
30
+ ['receive', { columns: ['enabled', 'status', 'receive'] }],
31
+ ]);
32
+ return resource;
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
+ /**
48
+ * `bot-update` — the inbox. `dedupe` is UNIQUE: two concurrent deliveries of one platform update
49
+ * collide here (`RecordExists`) and the service reads the stored row back. The normalized `update`
50
+ * is one `jsonb` column, `handled` a `text[]`. Indexes follow the dispatcher (pending rows by age,
51
+ * expired leases), a connection's newest update, and the retention purge.
52
+ */
53
+ export const makeBotUpdateResource = (dbAlias, alias = RES_BOT_UPDATE, serviceAlias) => {
54
+ const resource = makePostgresResource(alias, dbAlias, serviceAlias);
55
+ resource.schema = BotUpdateRecordSchema;
56
+ declareIndexes(resource, alias, [
57
+ ['dedupe', { columns: ['dedupe'], unique: true }],
58
+ ['inbox', { columns: ['status', 'receivedAt'] }],
59
+ ['lease', { columns: ['status', 'claimedAt'] }],
60
+ ['connection_received', { columns: ['connection', 'receivedAt'] }],
61
+ ['retention', { columns: ['status', 'processedAt'] }],
62
+ ]);
63
+ return resource;
64
+ };
65
+ /** `bot-activity` — what every action did; `target` is one `jsonb` column. Read newest first per scope. */
66
+ export const makeBotActivityResource = (dbAlias, alias = RES_BOT_ACTIVITY, serviceAlias) => {
67
+ const resource = makePostgresResource(alias, dbAlias, serviceAlias);
68
+ resource.schema = BotActivityRecordSchema;
69
+ declareIndexes(resource, alias, [
70
+ ['scope_at', { columns: ['scope', 'at'] }],
71
+ ['scope_connection_at', { columns: ['scope', 'connection', 'at'] }],
72
+ ]);
73
+ return resource;
74
+ };
75
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { PostgresResource } from '@owlmeans/postgres-resource';
2
+ import type { BotActivityRecord, BotConnectionRecord, BotResourceAliases, BotRuleRecord, BotUpdateRecord } from '@owlmeans/server-bot';
3
+ /** `bot-connection` — one row per connected bot, its credentials sealed in one text column. */
4
+ export interface BotConnectionResource extends PostgresResource<BotConnectionRecord> {
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
+ /** `bot-update` — the inbox: one row per inbound platform update, unique by its `dedupe` key. */
10
+ export interface BotUpdateResource extends PostgresResource<BotUpdateRecord> {
11
+ }
12
+ /** `bot-activity` — one row per action a bot took (or refused), newest read first. */
13
+ export interface BotActivityResource extends PostgresResource<BotActivityRecord> {
14
+ }
15
+ export interface BotPostgresOptions {
16
+ /** The `cfg.dbs` entry the four tables live in — default `postgres`. */
17
+ dbAlias?: string;
18
+ /** The Postgres connection service — default `postgres`. */
19
+ serviceAlias?: string;
20
+ /**
21
+ * The resources' aliases — default `bot-connection`, `bot-rule`, `bot-update`, `bot-activity`.
22
+ * The bot service must be given the same ones (`appendBot(ctx, { resources })`).
23
+ */
24
+ resources?: BotResourceAliases;
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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"}
package/build/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { PgIndexSpec } from '@owlmeans/postgres-resource';
2
+ /** The indexes a maker owns, by name suffix — the full name is `<table>_<suffix>`. */
3
+ export type IndexList = ReadonlyArray<readonly [suffix: string, spec: PgIndexSpec]>;
4
+ //# sourceMappingURL=types.local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.local.d.ts","sourceRoot":"","sources":["../src/types.local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAE9D,sFAAsF;AACtF,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.local.js","sourceRoot":"","sources":["../src/types.local.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@owlmeans/bot-postgres",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.18-rc.2",
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.",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc -b",
9
+ "dev": "sleep 14 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
10
+ "watch": "tsc -b -w --preserveWatchOutput --pretty",
11
+ "test": "bun test ./tests"
12
+ },
13
+ "main": "build/index.js",
14
+ "module": "build/index.js",
15
+ "types": "build/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "import": "./build/index.js",
19
+ "require": "./build/index.js",
20
+ "default": "./build/index.js",
21
+ "module": "./build/index.js",
22
+ "types": "./build/index.d.ts"
23
+ }
24
+ },
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"
30
+ },
31
+ "peerDependencies": {
32
+ "ajv": "*",
33
+ "pg": "*"
34
+ },
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",
43
+ "@types/bun": "^1.4.2",
44
+ "@types/node": "^26.6.4",
45
+ "@types/pg": "^8.23.1",
46
+ "ajv": "^8.20.0",
47
+ "nodemon": "^3.1.14",
48
+ "pg": "^8.23.1",
49
+ "typescript": "^7.0.2"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ }
54
+ }