@onkeiki/agents 0.1.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/dist/Alert.d.ts +56 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Alert.js +8 -0
- package/dist/Alert.js.map +1 -0
- package/dist/Entity.d.ts +158 -0
- package/dist/Entity.d.ts.map +1 -0
- package/dist/Entity.js +289 -0
- package/dist/Entity.js.map +1 -0
- package/dist/Kit.d.ts +138 -0
- package/dist/Kit.d.ts.map +1 -0
- package/dist/Kit.js +517 -0
- package/dist/Kit.js.map +1 -0
- package/dist/OpenApi.d.ts +151 -0
- package/dist/OpenApi.d.ts.map +1 -0
- package/dist/OpenApi.js +222 -0
- package/dist/OpenApi.js.map +1 -0
- package/dist/Plugin.d.ts +183 -0
- package/dist/Plugin.d.ts.map +1 -0
- package/dist/Plugin.js +10 -0
- package/dist/Plugin.js.map +1 -0
- package/dist/Server.d.ts +71 -0
- package/dist/Server.d.ts.map +1 -0
- package/dist/Server.js +476 -0
- package/dist/Server.js.map +1 -0
- package/dist/Tool.d.ts +86 -0
- package/dist/Tool.d.ts.map +1 -0
- package/dist/Tool.js +27 -0
- package/dist/Tool.js.map +1 -0
- package/dist/bundle.d.ts +17 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +101 -0
- package/dist/bundle.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/services/Blackboard.d.ts +18 -0
- package/dist/services/Blackboard.d.ts.map +1 -0
- package/dist/services/Blackboard.js +4 -0
- package/dist/services/Blackboard.js.map +1 -0
- package/dist/services/Observability.d.ts +102 -0
- package/dist/services/Observability.d.ts.map +1 -0
- package/dist/services/Observability.js +238 -0
- package/dist/services/Observability.js.map +1 -0
- package/dist/services/Platform.d.ts +112 -0
- package/dist/services/Platform.d.ts.map +1 -0
- package/dist/services/Platform.js +13 -0
- package/dist/services/Platform.js.map +1 -0
- package/dist/services/PluginDb.d.ts +44 -0
- package/dist/services/PluginDb.d.ts.map +1 -0
- package/dist/services/PluginDb.js +5 -0
- package/dist/services/PluginDb.js.map +1 -0
- package/dist/services/Sandbox.d.ts +68 -0
- package/dist/services/Sandbox.d.ts.map +1 -0
- package/dist/services/Sandbox.js +4 -0
- package/dist/services/Sandbox.js.map +1 -0
- package/dist/services/Steering.d.ts +46 -0
- package/dist/services/Steering.d.ts.map +1 -0
- package/dist/services/Steering.js +4 -0
- package/dist/services/Steering.js.map +1 -0
- package/dist/services/Storage.d.ts +63 -0
- package/dist/services/Storage.d.ts.map +1 -0
- package/dist/services/Storage.js +13 -0
- package/dist/services/Storage.js.map +1 -0
- package/dist/services/Transport.d.ts +19 -0
- package/dist/services/Transport.d.ts.map +1 -0
- package/dist/services/Transport.js +4 -0
- package/dist/services/Transport.js.map +1 -0
- package/dist/services/index.d.ts +9 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +9 -0
- package/dist/services/index.js.map +1 -0
- package/dist/types/config.d.ts +526 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/message.d.ts +54 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +47 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/user.d.ts +16 -0
- package/dist/types/user.d.ts.map +1 -0
- package/dist/types/user.js +14 -0
- package/dist/types/user.js.map +1 -0
- package/package.json +39 -0
- package/src/Alert.ts +51 -0
- package/src/Entity.ts +543 -0
- package/src/Kit.ts +705 -0
- package/src/OpenApi.ts +343 -0
- package/src/Plugin.ts +209 -0
- package/src/Server.ts +618 -0
- package/src/Tool.ts +110 -0
- package/src/bundle.ts +114 -0
- package/src/index.ts +209 -0
- package/src/services/Blackboard.ts +19 -0
- package/src/services/Observability.ts +320 -0
- package/src/services/Platform.ts +125 -0
- package/src/services/PluginDb.ts +48 -0
- package/src/services/Sandbox.ts +74 -0
- package/src/services/Steering.ts +45 -0
- package/src/services/Storage.ts +76 -0
- package/src/services/Transport.ts +21 -0
- package/src/services/index.ts +8 -0
- package/src/types/config.ts +531 -0
- package/src/types/index.ts +3 -0
- package/src/types/message.ts +60 -0
- package/src/types/user.ts +17 -0
package/dist/Alert.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
export type AlertSchedule = {
|
|
3
|
+
readonly type: 'cron';
|
|
4
|
+
readonly expression: string;
|
|
5
|
+
readonly timezone?: string;
|
|
6
|
+
} | {
|
|
7
|
+
readonly type: 'interval';
|
|
8
|
+
readonly every: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly type: 'webhook';
|
|
11
|
+
readonly path: string;
|
|
12
|
+
};
|
|
13
|
+
export type AlertMedia = {
|
|
14
|
+
readonly url: string;
|
|
15
|
+
readonly mimeType: string;
|
|
16
|
+
};
|
|
17
|
+
/** One outbound message of a multi-message alert. */
|
|
18
|
+
export type AlertMessage = {
|
|
19
|
+
readonly text: string;
|
|
20
|
+
readonly media?: ReadonlyArray<AlertMedia>;
|
|
21
|
+
};
|
|
22
|
+
export type AlertContent = {
|
|
23
|
+
readonly text: string;
|
|
24
|
+
readonly media?: AlertMedia;
|
|
25
|
+
/** Additional messages delivered after the first, in order. */
|
|
26
|
+
readonly messages?: ReadonlyArray<AlertMessage>;
|
|
27
|
+
};
|
|
28
|
+
/** Durable per-(alert, subscriber) KV state, persisted across runs. */
|
|
29
|
+
export interface AlertStateService {
|
|
30
|
+
readonly get: (key: string) => Effect.Effect<unknown>;
|
|
31
|
+
readonly set: (key: string, value: unknown) => Effect.Effect<void>;
|
|
32
|
+
}
|
|
33
|
+
export type AlertContext = {
|
|
34
|
+
readonly subscriber: {
|
|
35
|
+
phone: string;
|
|
36
|
+
chatId: string;
|
|
37
|
+
preferences: Record<string, unknown>;
|
|
38
|
+
};
|
|
39
|
+
readonly now: Date;
|
|
40
|
+
/** Developer secrets synced to the platform, resolved for this run. */
|
|
41
|
+
readonly secrets: Readonly<Record<string, string>>;
|
|
42
|
+
readonly state: AlertStateService;
|
|
43
|
+
};
|
|
44
|
+
export type AlertDefinition = {
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly description: string;
|
|
47
|
+
readonly schedule: AlertSchedule;
|
|
48
|
+
readonly dedupKey?: (ctx: AlertContext) => string;
|
|
49
|
+
readonly shouldSend?: (ctx: AlertContext) => Effect.Effect<boolean>;
|
|
50
|
+
readonly generate: (ctx: AlertContext) => Effect.Effect<AlertContent | null>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Define a scheduled or triggered alert.
|
|
54
|
+
*/
|
|
55
|
+
export declare function defineAlert(def: AlertDefinition): AlertDefinition;
|
|
56
|
+
//# sourceMappingURL=Alert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../src/Alert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5E,qDAAqD;AACrD,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAA;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;CAChD,CAAA;AAED,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACrD,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CACnE;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAA;IAC5F,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,MAAM,CAAA;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACnE,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;CAC7E,CAAA;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,eAAe,CAEjE"}
|
package/dist/Alert.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.js","sourceRoot":"","sources":["../src/Alert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AA6C/B;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAoB;IAC9C,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
package/dist/Entity.d.ts
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Effect, Schema } from 'effect';
|
|
2
|
+
import { type ToolDefinition } from './Tool.js';
|
|
3
|
+
import type { PluginDbService, PluginMigration } from './services/PluginDb.js';
|
|
4
|
+
import { StorageError } from './services/Storage.js';
|
|
5
|
+
/**
|
|
6
|
+
* Entities — typed, tenant-scoped persistence for agents.
|
|
7
|
+
*
|
|
8
|
+
* An entity is a named, schema-validated collection stored in the plugin
|
|
9
|
+
* database. Declaring an entity gives you:
|
|
10
|
+
*
|
|
11
|
+
* - A migration creating its table (`entityMigrations`)
|
|
12
|
+
* - Bounded, tenant-scoped CRUD tools for the model (`entityTools`)
|
|
13
|
+
* - A typed database API for codemode / programmatic use (`createEntityDb`)
|
|
14
|
+
*
|
|
15
|
+
* The model never sees SQL: every read and write goes through generated
|
|
16
|
+
* tools that validate against the schema and are scoped to the current
|
|
17
|
+
* user (phone). Rows are soft-deleted, versioned for optimistic
|
|
18
|
+
* concurrency, and audited.
|
|
19
|
+
*
|
|
20
|
+
* The generated SQL targets Postgres (JSONB, GIN indexes,
|
|
21
|
+
* `gen_random_uuid()`); other storage adapters are not supported yet.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const reminders = defineEntity({
|
|
26
|
+
* name: 'reminders',
|
|
27
|
+
* description: 'Scheduled reminders for the user',
|
|
28
|
+
* schema: Schema.Struct({
|
|
29
|
+
* text: Schema.String,
|
|
30
|
+
* dueAt: Schema.String,
|
|
31
|
+
* done: Schema.Boolean,
|
|
32
|
+
* }),
|
|
33
|
+
* indexes: ['dueAt'],
|
|
34
|
+
* })
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export type EntityDefinition<A extends Record<string, unknown> = Record<string, unknown>> = {
|
|
38
|
+
/** Unique entity name — lowercase snake_case (becomes part of the table name). */
|
|
39
|
+
readonly name: string;
|
|
40
|
+
/** What this entity stores, shown to the model in generated tool descriptions. */
|
|
41
|
+
readonly description: string;
|
|
42
|
+
/** Effect Schema describing a row's data. Validated on every write. */
|
|
43
|
+
readonly schema: Schema.Schema<A, any>;
|
|
44
|
+
/** Field names to index for query filters (expression indexes on the JSONB data). */
|
|
45
|
+
readonly indexes?: ReadonlyArray<string>;
|
|
46
|
+
/** Maximum rows per user. Creates beyond this fail. Default 10 000. */
|
|
47
|
+
readonly maxRowsPerUser?: number;
|
|
48
|
+
};
|
|
49
|
+
export declare function defineEntity<A extends Record<string, unknown>>(def: EntityDefinition<A>): EntityDefinition<A>;
|
|
50
|
+
/** A stored entity row, as returned to the model and codemode. */
|
|
51
|
+
export type EntityRow<A> = {
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly version: number;
|
|
54
|
+
readonly createdAt: string;
|
|
55
|
+
readonly updatedAt: string;
|
|
56
|
+
readonly data: A;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Build the plugin migrations for a set of entities. Pass the result to a
|
|
60
|
+
* plugin's `migrations` (or spread into an existing list). Each entity's
|
|
61
|
+
* migration version is derived from its name, so the list can be reordered
|
|
62
|
+
* or extended freely without shifting versions of already-applied entities.
|
|
63
|
+
*/
|
|
64
|
+
export declare function entityMigrations(entities: ReadonlyArray<EntityDefinition<any>>, startVersion?: number): PluginMigration[];
|
|
65
|
+
/** Raw stored row shape exchanged with an {@link EntityStore}. */
|
|
66
|
+
export type EntityStoreRow = {
|
|
67
|
+
id: string;
|
|
68
|
+
version: number;
|
|
69
|
+
created_at: string;
|
|
70
|
+
updated_at: string;
|
|
71
|
+
data: unknown;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Storage backend for entity rows. `makeAccessor` handles validation,
|
|
75
|
+
* quotas, merge semantics and audit *decisions*; a store only persists.
|
|
76
|
+
* Two implementations exist: `sqlEntityStore` (direct SQL over the plugin
|
|
77
|
+
* database, used by SDK-local execution) and the actor host bridge (cloud
|
|
78
|
+
* bundle execution, proxied through the platform's actor-runtime API).
|
|
79
|
+
* Promise-based so it can cross the actor host boundary unchanged.
|
|
80
|
+
*/
|
|
81
|
+
export interface EntityStore {
|
|
82
|
+
get(entityName: string, phone: string, id: string): Promise<EntityStoreRow | null>;
|
|
83
|
+
query(entityName: string, phone: string, opts: {
|
|
84
|
+
filter?: Record<string, unknown>;
|
|
85
|
+
limit: number;
|
|
86
|
+
orderBy?: {
|
|
87
|
+
field: string;
|
|
88
|
+
direction: 'asc' | 'desc';
|
|
89
|
+
};
|
|
90
|
+
}): Promise<EntityStoreRow[]>;
|
|
91
|
+
count(entityName: string, phone: string): Promise<number>;
|
|
92
|
+
insert(entityName: string, phone: string, data: Record<string, unknown>): Promise<EntityStoreRow>;
|
|
93
|
+
/** Full-row replace with version bump. Returns null when the row is gone or `expectedVersion` no longer matches. */
|
|
94
|
+
update(entityName: string, phone: string, id: string, data: Record<string, unknown>, expectedVersion?: number): Promise<EntityStoreRow | null>;
|
|
95
|
+
softDelete(entityName: string, phone: string, id: string): Promise<boolean>;
|
|
96
|
+
audit(entityName: string, phone: string, rowId: string, op: string, patch?: unknown): Promise<void>;
|
|
97
|
+
}
|
|
98
|
+
/** EntityStore over the plugin database (the per-entity `smskit_entity_*` tables). */
|
|
99
|
+
export declare function sqlEntityStore(db: PluginDbService): EntityStore;
|
|
100
|
+
export declare class EntityError extends Error {
|
|
101
|
+
readonly code: 'not_found' | 'conflict' | 'quota' | 'validation';
|
|
102
|
+
constructor(message: string, code: 'not_found' | 'conflict' | 'quota' | 'validation');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Tenant-scoped typed accessor for one entity. All operations are scoped
|
|
106
|
+
* to a single user (phone), bounded, soft-deleting, and audited.
|
|
107
|
+
*
|
|
108
|
+
* Representation convention: write inputs (`create` data, `update` patch)
|
|
109
|
+
* and `query` filters are in the schema's ENCODED (JSON) representation —
|
|
110
|
+
* what the model produces and what is stored. Returned rows carry the
|
|
111
|
+
* DECODED representation in `data`.
|
|
112
|
+
*/
|
|
113
|
+
export type EntityAccessError = EntityError | StorageError;
|
|
114
|
+
export type EntityAccessor<A extends Record<string, unknown>> = {
|
|
115
|
+
readonly get: (id: string) => Effect.Effect<EntityRow<A> | null, EntityAccessError>;
|
|
116
|
+
/** Equality filters on indexed fields; bounded to 100 rows. */
|
|
117
|
+
readonly query: (opts?: {
|
|
118
|
+
readonly filter?: Partial<A>;
|
|
119
|
+
readonly limit?: number;
|
|
120
|
+
readonly orderBy?: {
|
|
121
|
+
readonly field: string;
|
|
122
|
+
readonly direction?: 'asc' | 'desc';
|
|
123
|
+
};
|
|
124
|
+
}) => Effect.Effect<EntityRow<A>[], EntityAccessError>;
|
|
125
|
+
readonly create: (data: A) => Effect.Effect<EntityRow<A>, EntityAccessError>;
|
|
126
|
+
/**
|
|
127
|
+
* Merge-patch a row. If `expectedVersion` is given the update fails with
|
|
128
|
+
* a conflict error when the row has changed since it was read.
|
|
129
|
+
*/
|
|
130
|
+
readonly update: (id: string, patch: Partial<A>, opts?: {
|
|
131
|
+
readonly expectedVersion?: number;
|
|
132
|
+
}) => Effect.Effect<EntityRow<A>, EntityAccessError>;
|
|
133
|
+
/** Soft-delete a row. */
|
|
134
|
+
readonly delete: (id: string) => Effect.Effect<boolean, EntityAccessError>;
|
|
135
|
+
};
|
|
136
|
+
export type EntityDb<E extends Record<string, EntityDefinition<any>>> = {
|
|
137
|
+
readonly [K in keyof E]: E[K] extends EntityDefinition<infer A> ? EntityAccessor<A & Record<string, unknown>> : never;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Build the typed entity database for a user. This is what codemode and
|
|
141
|
+
* loops use: `db.reminders.query({ filter: { done: false } })`.
|
|
142
|
+
*/
|
|
143
|
+
export declare function createEntityDb<E extends Record<string, EntityDefinition<any>>>(entities: E, db: PluginDbService | EntityStore, phone: string): EntityDb<E>;
|
|
144
|
+
/**
|
|
145
|
+
* The entity store for a tool context: the actor host bridge when the tool is
|
|
146
|
+
* running as a cloud bundle, otherwise direct SQL over the plugin database.
|
|
147
|
+
*/
|
|
148
|
+
export declare function contextEntityStore(ctx: {
|
|
149
|
+
entityStore?: EntityStore;
|
|
150
|
+
db: PluginDbService;
|
|
151
|
+
}): EntityStore;
|
|
152
|
+
/**
|
|
153
|
+
* Generate the model-facing CRUD tools for an entity:
|
|
154
|
+
* `<name>_query`, `<name>_create`, `<name>_update`, `<name>_delete`.
|
|
155
|
+
* All are tenant-scoped to the current user and bounded.
|
|
156
|
+
*/
|
|
157
|
+
export declare function entityTools<A extends Record<string, unknown>>(entity: EntityDefinition<A>): ToolDefinition<any, any>[];
|
|
158
|
+
//# sourceMappingURL=Entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Entity.d.ts","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC1F,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtC,qFAAqF;IACrF,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACxC,uEAAuE;IACvE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC,GACvB,gBAAgB,CAAC,CAAC,CAAC,CAUrB;AAED,kEAAkE;AAClE,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CACjB,CAAA;AAmBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAC9C,YAAY,SAAI,GACf,eAAe,EAAE,CAiDnB;AAED,kEAAkE;AAClE,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IAClF,KAAK,CACH,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;QACJ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAChC,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;SAAE,CAAA;KACvD,GACA,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IAC5B,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACzD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;IACjG,oHAAoH;IACpH,MAAM,CACJ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACjC,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3E,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpG;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,EAAE,EAAE,eAAe,GAAG,WAAW,CAoF/D;AAwBD,qBAAa,WAAY,SAAQ,KAAK;IAGlC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY;IAFlE,YACE,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,EAIjE;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,YAAY,CAAA;AAE1D,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9D,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,iBAAiB,CAAC,CAAA;IACnF,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE;QACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;QAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,OAAO,CAAC,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;SAAE,CAAA;KACnF,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAA;IACtD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;IAC5E;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,CACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,KACzC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;IACnD,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAA;CAC3E,CAAA;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI;IACtE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAC3D,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC3C,KAAK;CACV,CAAA;AAsGD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAC5E,QAAQ,EAAE,CAAC,EACX,EAAE,EAAE,eAAe,GAAG,WAAW,EACjC,KAAK,EAAE,MAAM,GACZ,QAAQ,CAAC,CAAC,CAAC,CAOb;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,eAAe,CAAA;CAAE,GAAG,WAAW,CAEvG;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC1B,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAsD5B"}
|
package/dist/Entity.js
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { Effect, Schema } from 'effect';
|
|
2
|
+
import { defineTool } from './Tool.js';
|
|
3
|
+
import { StorageError } from './services/Storage.js';
|
|
4
|
+
export function defineEntity(def) {
|
|
5
|
+
if (!/^[a-z][a-z0-9_]*$/.test(def.name)) {
|
|
6
|
+
throw new Error(`Entity name must be lowercase snake_case: ${def.name}`);
|
|
7
|
+
}
|
|
8
|
+
for (const field of def.indexes ?? []) {
|
|
9
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(field) || field.length > 40) {
|
|
10
|
+
throw new Error(`Entity index field must be a short identifier: ${field}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return def;
|
|
14
|
+
}
|
|
15
|
+
const DEFAULT_MAX_ROWS = 10_000;
|
|
16
|
+
const MAX_QUERY_LIMIT = 100;
|
|
17
|
+
const DEFAULT_QUERY_LIMIT = 25;
|
|
18
|
+
function tableName(entity) {
|
|
19
|
+
return `smskit_entity_${entity}`;
|
|
20
|
+
}
|
|
21
|
+
function entityVersion(name, startVersion) {
|
|
22
|
+
let hash = 2166136261;
|
|
23
|
+
for (let i = 0; i < name.length; i++) {
|
|
24
|
+
hash ^= name.charCodeAt(i);
|
|
25
|
+
hash = Math.imul(hash, 16777619);
|
|
26
|
+
}
|
|
27
|
+
return startVersion + 1 + ((hash >>> 0) % 1_000_000_000);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build the plugin migrations for a set of entities. Pass the result to a
|
|
31
|
+
* plugin's `migrations` (or spread into an existing list). Each entity's
|
|
32
|
+
* migration version is derived from its name, so the list can be reordered
|
|
33
|
+
* or extended freely without shifting versions of already-applied entities.
|
|
34
|
+
*/
|
|
35
|
+
export function entityMigrations(entities, startVersion = 1) {
|
|
36
|
+
const versions = new Map();
|
|
37
|
+
const migrations = [
|
|
38
|
+
{
|
|
39
|
+
version: startVersion,
|
|
40
|
+
name: 'entity-audit-log',
|
|
41
|
+
up: `CREATE TABLE IF NOT EXISTS smskit_entity_audit (
|
|
42
|
+
id BIGSERIAL PRIMARY KEY,
|
|
43
|
+
entity TEXT NOT NULL,
|
|
44
|
+
row_id TEXT NOT NULL,
|
|
45
|
+
phone TEXT NOT NULL,
|
|
46
|
+
op TEXT NOT NULL,
|
|
47
|
+
patch JSONB,
|
|
48
|
+
at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
49
|
+
)`,
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
for (const entity of entities) {
|
|
53
|
+
defineEntity(entity);
|
|
54
|
+
const version = entityVersion(entity.name, startVersion);
|
|
55
|
+
const clash = versions.get(version);
|
|
56
|
+
if (clash) {
|
|
57
|
+
throw new Error(`Entity migration version collision between ${clash} and ${entity.name}; rename one of them`);
|
|
58
|
+
}
|
|
59
|
+
versions.set(version, entity.name);
|
|
60
|
+
const table = tableName(entity.name);
|
|
61
|
+
const indexes = (entity.indexes ?? [])
|
|
62
|
+
.map((field) => `CREATE INDEX IF NOT EXISTS ${table}_${field}_idx ON ${table} ((data->>'${field}'))`)
|
|
63
|
+
.join('; ');
|
|
64
|
+
migrations.push({
|
|
65
|
+
version,
|
|
66
|
+
name: `entity-${entity.name}`,
|
|
67
|
+
up: `CREATE TABLE IF NOT EXISTS ${table} (
|
|
68
|
+
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
69
|
+
phone TEXT NOT NULL,
|
|
70
|
+
data JSONB NOT NULL,
|
|
71
|
+
version INT NOT NULL DEFAULT 1,
|
|
72
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
73
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
74
|
+
deleted_at TIMESTAMPTZ
|
|
75
|
+
);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS ${table}_phone_idx ON ${table} (phone) WHERE deleted_at IS NULL;
|
|
77
|
+
CREATE INDEX IF NOT EXISTS ${table}_data_gin_idx ON ${table} USING GIN (data jsonb_path_ops)${indexes ? '; ' + indexes : ''}`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return migrations;
|
|
81
|
+
}
|
|
82
|
+
/** EntityStore over the plugin database (the per-entity `smskit_entity_*` tables). */
|
|
83
|
+
export function sqlEntityStore(db) {
|
|
84
|
+
const run = (effect) => Effect.runPromise(effect);
|
|
85
|
+
return {
|
|
86
|
+
get: (entityName, phone, id) => run(db.queryOne(`SELECT id, version, created_at, updated_at, data FROM ${tableName(entityName)}
|
|
87
|
+
WHERE id = $1 AND phone = $2 AND deleted_at IS NULL`, [id, phone])),
|
|
88
|
+
query: (entityName, phone, opts) => {
|
|
89
|
+
const params = [phone];
|
|
90
|
+
let where = `phone = $1 AND deleted_at IS NULL`;
|
|
91
|
+
if (opts.filter && Object.keys(opts.filter).length > 0) {
|
|
92
|
+
params.push(JSON.stringify(opts.filter));
|
|
93
|
+
where += ` AND data @> $${params.length}::jsonb`;
|
|
94
|
+
}
|
|
95
|
+
let order = `updated_at DESC`;
|
|
96
|
+
if (opts.orderBy) {
|
|
97
|
+
order = `data->>'${opts.orderBy.field}' ${opts.orderBy.direction === 'asc' ? 'ASC' : 'DESC'}`;
|
|
98
|
+
}
|
|
99
|
+
params.push(opts.limit);
|
|
100
|
+
return run(db.query(`SELECT id, version, created_at, updated_at, data FROM ${tableName(entityName)}
|
|
101
|
+
WHERE ${where} ORDER BY ${order} LIMIT $${params.length}`, params));
|
|
102
|
+
},
|
|
103
|
+
count: async (entityName, phone) => {
|
|
104
|
+
const row = await run(db.queryOne(`SELECT count(*)::text AS n FROM ${tableName(entityName)} WHERE phone = $1 AND deleted_at IS NULL`, [phone]));
|
|
105
|
+
return row ? Number(row.n) : 0;
|
|
106
|
+
},
|
|
107
|
+
insert: async (entityName, phone, data) => {
|
|
108
|
+
const raw = await run(db.queryOne(`INSERT INTO ${tableName(entityName)} (phone, data) VALUES ($1, $2)
|
|
109
|
+
RETURNING id, version, created_at, updated_at, data`, [phone, JSON.stringify(data)]));
|
|
110
|
+
if (!raw)
|
|
111
|
+
throw new Error('Insert returned no row');
|
|
112
|
+
return raw;
|
|
113
|
+
},
|
|
114
|
+
update: (entityName, phone, id, data, expectedVersion) => {
|
|
115
|
+
const versionClause = expectedVersion !== undefined ? ` AND version = $4` : '';
|
|
116
|
+
const params = [JSON.stringify(data), id, phone];
|
|
117
|
+
if (expectedVersion !== undefined)
|
|
118
|
+
params.push(expectedVersion);
|
|
119
|
+
return run(db.queryOne(`UPDATE ${tableName(entityName)} SET data = $1, version = version + 1, updated_at = now()
|
|
120
|
+
WHERE id = $2 AND phone = $3 AND deleted_at IS NULL${versionClause}
|
|
121
|
+
RETURNING id, version, created_at, updated_at, data`, params));
|
|
122
|
+
},
|
|
123
|
+
softDelete: async (entityName, phone, id) => {
|
|
124
|
+
const raw = await run(db.queryOne(`UPDATE ${tableName(entityName)} SET deleted_at = now()
|
|
125
|
+
WHERE id = $1 AND phone = $2 AND deleted_at IS NULL RETURNING id`, [id, phone]));
|
|
126
|
+
return raw !== null;
|
|
127
|
+
},
|
|
128
|
+
audit: (entityName, phone, rowId, op, patch) => run(db
|
|
129
|
+
.execute(`INSERT INTO smskit_entity_audit (entity, row_id, phone, op, patch) VALUES ($1, $2, $3, $4, $5)`, [entityName, rowId, phone, op, patch === undefined ? null : JSON.stringify(patch)])
|
|
130
|
+
.pipe(Effect.catchAll(() => Effect.void))),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function toRow(entity, raw) {
|
|
134
|
+
return Schema.decodeUnknown(entity.schema)(raw.data).pipe(Effect.mapError((e) => new EntityError(`Stored ${entity.name} row ${raw.id} no longer matches its schema: ${e.message}`, 'validation')), Effect.map((data) => ({
|
|
135
|
+
id: raw.id,
|
|
136
|
+
version: raw.version,
|
|
137
|
+
createdAt: toIso(raw.created_at),
|
|
138
|
+
updatedAt: toIso(raw.updated_at),
|
|
139
|
+
data: data,
|
|
140
|
+
})));
|
|
141
|
+
}
|
|
142
|
+
function toIso(value) {
|
|
143
|
+
return value instanceof Date ? value.toISOString() : String(value);
|
|
144
|
+
}
|
|
145
|
+
export class EntityError extends Error {
|
|
146
|
+
code;
|
|
147
|
+
constructor(message, code) {
|
|
148
|
+
super(message);
|
|
149
|
+
this.code = code;
|
|
150
|
+
this.name = 'EntityError';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function storeCall(what, run) {
|
|
154
|
+
return Effect.tryPromise({
|
|
155
|
+
try: run,
|
|
156
|
+
catch: (e) => new StorageError(`Entity store ${what} failed: ${e instanceof Error ? e.message : String(e)}`, e),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function makeAccessor(entity, store, phone) {
|
|
160
|
+
defineEntity(entity);
|
|
161
|
+
// Validate then persist the ENCODED form, so transforming schemas
|
|
162
|
+
// (NumberFromString, date transforms, ...) round-trip through storage.
|
|
163
|
+
const validateToStored = (data) => Schema.decodeUnknown(entity.schema)(data).pipe(Effect.flatMap((decoded) => Schema.encode(entity.schema)(decoded)), Effect.mapError((e) => new EntityError(`Invalid ${entity.name} data: ${e.message}`, 'validation')));
|
|
164
|
+
const audit = (rowId, op, patch) => storeCall('audit', () => store.audit(entity.name, phone, rowId, op, patch)).pipe(Effect.catchAll(() => Effect.void));
|
|
165
|
+
return {
|
|
166
|
+
get: (id) => storeCall('get', () => store.get(entity.name, phone, id)).pipe(Effect.flatMap((raw) => (raw ? toRow(entity, raw) : Effect.succeed(null)))),
|
|
167
|
+
query: (opts) => Effect.gen(function* () {
|
|
168
|
+
const limit = Math.min(Math.max(opts?.limit ?? DEFAULT_QUERY_LIMIT, 1), MAX_QUERY_LIMIT);
|
|
169
|
+
let orderBy;
|
|
170
|
+
if (opts?.orderBy) {
|
|
171
|
+
if (!/^[a-zA-Z0-9_]+$/.test(opts.orderBy.field)) {
|
|
172
|
+
return yield* Effect.fail(new EntityError(`Invalid order field`, 'validation'));
|
|
173
|
+
}
|
|
174
|
+
orderBy = { field: opts.orderBy.field, direction: opts.orderBy.direction === 'asc' ? 'asc' : 'desc' };
|
|
175
|
+
}
|
|
176
|
+
const rows = yield* storeCall('query', () => store.query(entity.name, phone, {
|
|
177
|
+
filter: opts?.filter,
|
|
178
|
+
limit,
|
|
179
|
+
orderBy,
|
|
180
|
+
}));
|
|
181
|
+
return yield* Effect.all(rows.map((raw) => toRow(entity, raw)));
|
|
182
|
+
}),
|
|
183
|
+
create: (data) => Effect.gen(function* () {
|
|
184
|
+
const stored = yield* validateToStored(data);
|
|
185
|
+
const max = entity.maxRowsPerUser ?? DEFAULT_MAX_ROWS;
|
|
186
|
+
const count = yield* storeCall('count', () => store.count(entity.name, phone));
|
|
187
|
+
if (count >= max) {
|
|
188
|
+
return yield* Effect.fail(new EntityError(`Row quota reached for ${entity.name} (${max})`, 'quota'));
|
|
189
|
+
}
|
|
190
|
+
const raw = yield* storeCall('insert', () => store.insert(entity.name, phone, stored));
|
|
191
|
+
yield* audit(raw.id, 'create', stored);
|
|
192
|
+
return yield* toRow(entity, raw);
|
|
193
|
+
}),
|
|
194
|
+
update: (id, patch, opts) => Effect.gen(function* () {
|
|
195
|
+
const existing = yield* storeCall('get', () => store.get(entity.name, phone, id));
|
|
196
|
+
if (!existing) {
|
|
197
|
+
return yield* Effect.fail(new EntityError(`${entity.name} row not found: ${id}`, 'not_found'));
|
|
198
|
+
}
|
|
199
|
+
// Merge in the encoded representation: stored JSON + encoded patch.
|
|
200
|
+
const merged = yield* validateToStored({
|
|
201
|
+
...existing.data,
|
|
202
|
+
...patch,
|
|
203
|
+
});
|
|
204
|
+
const raw = yield* storeCall('update', () => store.update(entity.name, phone, id, merged, opts?.expectedVersion));
|
|
205
|
+
if (!raw) {
|
|
206
|
+
return yield* Effect.fail(new EntityError(`${entity.name} row ${id} changed since it was read`, 'conflict'));
|
|
207
|
+
}
|
|
208
|
+
yield* audit(id, 'update', patch);
|
|
209
|
+
return yield* toRow(entity, raw);
|
|
210
|
+
}),
|
|
211
|
+
delete: (id) => Effect.gen(function* () {
|
|
212
|
+
const deleted = yield* storeCall('delete', () => store.softDelete(entity.name, phone, id));
|
|
213
|
+
if (deleted)
|
|
214
|
+
yield* audit(id, 'delete');
|
|
215
|
+
return deleted;
|
|
216
|
+
}),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Build the typed entity database for a user. This is what codemode and
|
|
221
|
+
* loops use: `db.reminders.query({ filter: { done: false } })`.
|
|
222
|
+
*/
|
|
223
|
+
export function createEntityDb(entities, db, phone) {
|
|
224
|
+
const store = isEntityStore(db) ? db : sqlEntityStore(db);
|
|
225
|
+
const out = {};
|
|
226
|
+
for (const [key, entity] of Object.entries(entities)) {
|
|
227
|
+
out[key] = makeAccessor(entity, store, phone);
|
|
228
|
+
}
|
|
229
|
+
return out;
|
|
230
|
+
}
|
|
231
|
+
function isEntityStore(db) {
|
|
232
|
+
return 'softDelete' in db;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The entity store for a tool context: the actor host bridge when the tool is
|
|
236
|
+
* running as a cloud bundle, otherwise direct SQL over the plugin database.
|
|
237
|
+
*/
|
|
238
|
+
export function contextEntityStore(ctx) {
|
|
239
|
+
return ctx.entityStore ?? sqlEntityStore(ctx.db);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Generate the model-facing CRUD tools for an entity:
|
|
243
|
+
* `<name>_query`, `<name>_create`, `<name>_update`, `<name>_delete`.
|
|
244
|
+
* All are tenant-scoped to the current user and bounded.
|
|
245
|
+
*/
|
|
246
|
+
export function entityTools(entity) {
|
|
247
|
+
const jsonSchema = Schema.Record({ key: Schema.String, value: Schema.Unknown });
|
|
248
|
+
const query = defineTool({
|
|
249
|
+
name: `${entity.name}_query`,
|
|
250
|
+
description: `Query ${entity.name}. ${entity.description} Returns up to ${MAX_QUERY_LIMIT} rows for the current user, newest first. Filter is an equality match on fields.`,
|
|
251
|
+
input: Schema.Struct({
|
|
252
|
+
filter: Schema.optional(jsonSchema),
|
|
253
|
+
limit: Schema.optional(Schema.Number),
|
|
254
|
+
}),
|
|
255
|
+
execute: (input, ctx) => makeAccessor(entity, contextEntityStore(ctx), ctx.phone)
|
|
256
|
+
.query({ filter: input.filter, limit: input.limit })
|
|
257
|
+
.pipe(Effect.catchAll((e) => Effect.succeed({ error: e.message }))),
|
|
258
|
+
});
|
|
259
|
+
const create = defineTool({
|
|
260
|
+
name: `${entity.name}_create`,
|
|
261
|
+
description: `Create a ${entity.name} row for the current user. ${entity.description}`,
|
|
262
|
+
input: Schema.Struct({ data: jsonSchema }),
|
|
263
|
+
execute: (input, ctx) => makeAccessor(entity, contextEntityStore(ctx), ctx.phone)
|
|
264
|
+
.create(input.data)
|
|
265
|
+
.pipe(Effect.catchAll((e) => Effect.succeed({ error: e.message }))),
|
|
266
|
+
});
|
|
267
|
+
const update = defineTool({
|
|
268
|
+
name: `${entity.name}_update`,
|
|
269
|
+
description: `Update a ${entity.name} row by id (merge-patch). Fails if the row was changed since read when expectedVersion is provided.`,
|
|
270
|
+
input: Schema.Struct({
|
|
271
|
+
id: Schema.String,
|
|
272
|
+
patch: jsonSchema,
|
|
273
|
+
expectedVersion: Schema.optional(Schema.Number),
|
|
274
|
+
}),
|
|
275
|
+
execute: (input, ctx) => makeAccessor(entity, contextEntityStore(ctx), ctx.phone)
|
|
276
|
+
.update(input.id, input.patch, { expectedVersion: input.expectedVersion })
|
|
277
|
+
.pipe(Effect.catchAll((e) => Effect.succeed({ error: e.message }))),
|
|
278
|
+
});
|
|
279
|
+
const del = defineTool({
|
|
280
|
+
name: `${entity.name}_delete`,
|
|
281
|
+
description: `Delete a ${entity.name} row by id (soft delete).`,
|
|
282
|
+
input: Schema.Struct({ id: Schema.String }),
|
|
283
|
+
execute: (input, ctx) => makeAccessor(entity, contextEntityStore(ctx), ctx.phone)
|
|
284
|
+
.delete(input.id)
|
|
285
|
+
.pipe(Effect.map((deleted) => ({ deleted })), Effect.catchAll((e) => Effect.succeed({ error: e.message }))),
|
|
286
|
+
});
|
|
287
|
+
return [query, create, update, del];
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=Entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Entity.js","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":"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"}
|