typion 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +4 -2
- package/bin/typion.js +7 -0
- package/dist/auth/better-auth.d.ts +13 -0
- package/dist/auth/better-auth.js +11 -0
- package/dist/auth/better-auth.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +883 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/column-kinds-Bkm4NJI2.js +47 -0
- package/dist/column-kinds-Bkm4NJI2.js.map +1 -0
- package/dist/context-B4e2eREP.d.ts +2100 -0
- package/dist/contract/index.d.ts +137 -0
- package/dist/contract/index.js +42 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/db/pglite.d.ts +12 -0
- package/dist/db/pglite.js +27 -0
- package/dist/db/pglite.js.map +1 -0
- package/dist/descriptor-Cc3mGp73.js +12 -0
- package/dist/descriptor-Cc3mGp73.js.map +1 -0
- package/dist/errors-ChDBxeS-.js +17 -0
- package/dist/errors-ChDBxeS-.js.map +1 -0
- package/dist/errors-D-CKO-px.js +114 -0
- package/dist/errors-D-CKO-px.js.map +1 -0
- package/dist/handler-BWVU8TCR.d.ts +23 -0
- package/dist/handler-_87bFkbP.js +565 -0
- package/dist/handler-_87bFkbP.js.map +1 -0
- package/dist/hono/index.d.ts +17 -0
- package/dist/hono/index.js +26 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/http/index.d.ts +13 -0
- package/dist/http/index.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1324 -0
- package/dist/index.js.map +1 -0
- package/dist/issues-DLqCBQT1.js +42 -0
- package/dist/issues-DLqCBQT1.js.map +1 -0
- package/dist/next/index.d.ts +8 -0
- package/dist/next/index.js +18 -0
- package/dist/next/index.js.map +1 -0
- package/dist/operations-D3rOacLX.js +1811 -0
- package/dist/operations-D3rOacLX.js.map +1 -0
- package/dist/schema/index.d.ts +18 -0
- package/dist/schema/index.js +3 -0
- package/dist/schema-Rzzq97cK.js +68 -0
- package/dist/schema-Rzzq97cK.js.map +1 -0
- package/dist/seed/index.d.ts +19 -0
- package/dist/seed/index.js +85 -0
- package/dist/seed/index.js.map +1 -0
- package/dist/structural-BZnjFmCs.js +247 -0
- package/dist/structural-BZnjFmCs.js.map +1 -0
- package/dist/testing/index.d.ts +26 -0
- package/dist/testing/index.js +92 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/typion-Dh2BCSRz.js +1187 -0
- package/dist/typion-Dh2BCSRz.js.map +1 -0
- package/dist/validation/zod.d.ts +21 -0
- package/dist/validation/zod.js +84 -0
- package/dist/validation/zod.js.map +1 -0
- package/docs/README.md +145 -0
- package/docs/access.md +114 -0
- package/docs/auth.md +195 -0
- package/docs/collections.md +172 -0
- package/docs/database.md +76 -0
- package/docs/features/localization.md +112 -0
- package/docs/features/multi-tenant.md +166 -0
- package/docs/features/soft-delete.md +85 -0
- package/docs/features/versions.md +106 -0
- package/docs/hooks.md +106 -0
- package/docs/http.md +188 -0
- package/docs/queries.md +200 -0
- package/docs/testing.md +85 -0
- package/package.json +125 -3
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { $a as InferItem, $r as NoneIfEmpty, C as WireBatchEnvelope, D as WireErrorCode, Dr as TraitOptions, E as WireError, Mr as CreateOptions, Nr as DeleteOptions, O as WireErrorEnvelope, Or as TraitQueries, Qa as Descriptor, Qr as NoExtraKeys, S as ErrorStatus, T as WireEnvelope, U as TypionDefinition, Wa as TypionErrorCode, Wr as Id, Yr as LinkQueries, Za as AnyDescriptor, ai as UpdateInput, ao as descriptor, eo as InferResult, gi as Page, io as WriteOp, jr as CreateInput, k as WireIssue, m as TypionTypes, mi as InputSchema, no as RESULT, oi as UpdateManyOptions, ri as Row, ro as ReadOp, si as UpdateOptions, ti as ReadRow, to as Op, u as EntityName, vi as Result, w as WireDataEnvelope, wr as Jsonified, x as ERROR_STATUS, xa as PluginReadOptions } from "../context-B4e2eREP.js";
|
|
2
|
+
import { AnyRelations, GetTableViewFieldSelection, KnownKeysOnly } from "drizzle-orm";
|
|
3
|
+
//#region src/contract/wire.d.ts
|
|
4
|
+
type ColData<C> = C extends {
|
|
5
|
+
_: {
|
|
6
|
+
data: infer D;
|
|
7
|
+
};
|
|
8
|
+
} ? D : unknown;
|
|
9
|
+
type TargetOf<TRel> = TRel extends {
|
|
10
|
+
targetTableName: infer T extends string;
|
|
11
|
+
} ? T : never;
|
|
12
|
+
type KindOf<TRel> = TRel extends {
|
|
13
|
+
relationType: infer RT;
|
|
14
|
+
} ? RT : never;
|
|
15
|
+
type Cols<S extends AnyRelations, N extends keyof S> = GetTableViewFieldSelection<S[N]['table']>;
|
|
16
|
+
type WireSchema<TE extends TypionTypes> = InputSchema<TE, 'user'>;
|
|
17
|
+
type WireFieldFilter<T> = {
|
|
18
|
+
eq?: T;
|
|
19
|
+
ne?: T;
|
|
20
|
+
gt?: T;
|
|
21
|
+
gte?: T;
|
|
22
|
+
lt?: T;
|
|
23
|
+
lte?: T;
|
|
24
|
+
in?: T[];
|
|
25
|
+
notIn?: T[];
|
|
26
|
+
like?: string;
|
|
27
|
+
ilike?: string;
|
|
28
|
+
notLike?: string;
|
|
29
|
+
notIlike?: string;
|
|
30
|
+
isNull?: true;
|
|
31
|
+
isNotNull?: true;
|
|
32
|
+
NOT?: WireFieldFilter<T>;
|
|
33
|
+
OR?: WireFieldFilter<T>[];
|
|
34
|
+
AND?: WireFieldFilter<T>[];
|
|
35
|
+
} | (T extends object ? never : T);
|
|
36
|
+
type WireWhere<S extends AnyRelations, N extends keyof S> = { [K in keyof Cols<S, N>]?: WireFieldFilter<NonNullable<ColData<Cols<S, N>[K]>>> | undefined; } & { [K in keyof S[N]['relations']]?: boolean | WireWhere<S, TargetOf<S[N]['relations'][K]> & keyof S> | undefined; } & {
|
|
37
|
+
AND?: WireWhere<S, N>[] | undefined;
|
|
38
|
+
OR?: WireWhere<S, N>[] | undefined;
|
|
39
|
+
NOT?: WireWhere<S, N> | undefined;
|
|
40
|
+
};
|
|
41
|
+
type WireWith<S extends AnyRelations, N extends keyof S> = { [K in keyof S[N]['relations']]?: boolean | WireConfig<S, TargetOf<S[N]['relations'][K]> & keyof S, KindOf<S[N]['relations'][K]>> | undefined; };
|
|
42
|
+
type WireConfig<S extends AnyRelations, N extends keyof S, TKind> = {
|
|
43
|
+
columns?: { [K in keyof Cols<S, N>]?: boolean | undefined; } | undefined;
|
|
44
|
+
where?: WireWhere<S, N> | undefined;
|
|
45
|
+
orderBy?: { [K in keyof Cols<S, N>]?: 'asc' | 'desc' | undefined; } | undefined;
|
|
46
|
+
offset?: number | undefined;
|
|
47
|
+
} & (keyof S[N]['relations'] extends never ? {} : {
|
|
48
|
+
with?: WireWith<S, N> | undefined;
|
|
49
|
+
}) & (TKind extends 'many' ? {
|
|
50
|
+
limit?: number | undefined;
|
|
51
|
+
} : {});
|
|
52
|
+
type WireReadOptions<TE extends TypionTypes, N extends EntityName<TE>> = PluginReadOptions<TE['plugins']> & TraitOptions<TE['plugins'], TE['entities'][N]['options'], 'read'>;
|
|
53
|
+
type WireFindConfig<TE extends TypionTypes, N extends EntityName<TE>> = WireConfig<WireSchema<TE>, N, 'many'> & WireReadOptions<TE, N>;
|
|
54
|
+
type WireFirstConfig<TE extends TypionTypes, N extends EntityName<TE>> = WireConfig<WireSchema<TE>, N, 'one'> & WireReadOptions<TE, N>;
|
|
55
|
+
type WireByIdConfig<TE extends TypionTypes, N extends EntityName<TE>> = Omit<WireFirstConfig<TE, N>, 'where' | 'offset'>;
|
|
56
|
+
type WireCountConfig<TE extends TypionTypes, N extends EntityName<TE>> = {
|
|
57
|
+
where?: WireWhere<WireSchema<TE>, N> | undefined;
|
|
58
|
+
} & WireReadOptions<TE, N>;
|
|
59
|
+
type WireIdInput<TE extends TypionTypes, N extends EntityName<TE>> = {
|
|
60
|
+
id: Id<TE, N>;
|
|
61
|
+
};
|
|
62
|
+
type WireCreateInput<TE extends TypionTypes, N extends EntityName<TE>, O = {}> = {
|
|
63
|
+
data: CreateInput<TE, N, O, 'user'>;
|
|
64
|
+
options?: O & CreateOptions<TE, N> & NoExtraKeys<O, CreateOptions<TE, N>>;
|
|
65
|
+
};
|
|
66
|
+
type WireUpdateInput<TE extends TypionTypes, N extends EntityName<TE>, O = {}> = {
|
|
67
|
+
id: Id<TE, N>;
|
|
68
|
+
data: UpdateInput<TE, N, O, 'user'>;
|
|
69
|
+
options?: O & UpdateOptions<TE, N> & NoExtraKeys<O, UpdateOptions<TE, N>>;
|
|
70
|
+
};
|
|
71
|
+
type WireUpdateManyInput<TE extends TypionTypes, N extends EntityName<TE>, O = {}> = {
|
|
72
|
+
where: WireWhere<WireSchema<TE>, N>;
|
|
73
|
+
data: UpdateInput<TE, N, O, 'user'>;
|
|
74
|
+
options?: O & UpdateManyOptions<TE, N> & NoExtraKeys<O, UpdateManyOptions<TE, N>>;
|
|
75
|
+
};
|
|
76
|
+
type WireDeleteInput<TE extends TypionTypes, N extends EntityName<TE>> = {
|
|
77
|
+
id: Id<TE, N>;
|
|
78
|
+
options?: NoneIfEmpty<DeleteOptions<TE, N>>;
|
|
79
|
+
};
|
|
80
|
+
type WireDeleteManyInput<TE extends TypionTypes, N extends EntityName<TE>> = {
|
|
81
|
+
where: WireWhere<WireSchema<TE>, N>;
|
|
82
|
+
options?: {
|
|
83
|
+
max?: number;
|
|
84
|
+
} & DeleteOptions<TE, N>;
|
|
85
|
+
};
|
|
86
|
+
type WireWriteInputs<TE extends TypionTypes, N extends EntityName<TE>> = {
|
|
87
|
+
create: WireCreateInput<TE, N>;
|
|
88
|
+
update: WireUpdateInput<TE, N>;
|
|
89
|
+
updateMany: WireUpdateManyInput<TE, N>;
|
|
90
|
+
delete: WireDeleteInput<TE, N>;
|
|
91
|
+
deleteMany: WireDeleteManyInput<TE, N>;
|
|
92
|
+
};
|
|
93
|
+
type WireReadInputs<TE extends TypionTypes, N extends EntityName<TE>> = {
|
|
94
|
+
find: WireFindConfig<TE, N>;
|
|
95
|
+
findOne: WireFirstConfig<TE, N>;
|
|
96
|
+
findById: {
|
|
97
|
+
id: Id<TE, N>;
|
|
98
|
+
config?: WireByIdConfig<TE, N>;
|
|
99
|
+
};
|
|
100
|
+
count: WireCountConfig<TE, N>;
|
|
101
|
+
page: WireFindConfig<TE, N>;
|
|
102
|
+
};
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/contract/define-queries-types.d.ts
|
|
105
|
+
type AppTypes<App> = App extends {
|
|
106
|
+
readonly $def: TypionDefinition<infer TE extends TypionTypes>;
|
|
107
|
+
} ? TE : never;
|
|
108
|
+
interface QueryApi<TE extends TypionTypes, N extends EntityName<TE>> {
|
|
109
|
+
find<const C extends WireFindConfig<TE, N>>(config: KnownKeysOnly<C, WireFindConfig<TE, N>>): Descriptor<N, 'find', C, Result<TE, N, C, 'user'>[]>;
|
|
110
|
+
findOne<const C extends WireFirstConfig<TE, N>>(config: KnownKeysOnly<C, WireFirstConfig<TE, N>>): Descriptor<N, 'findOne', C, Result<TE, N, C, 'user'> | null>;
|
|
111
|
+
findById<const C extends WireByIdConfig<TE, N>>(input: {
|
|
112
|
+
id: WireIdInput<TE, N>['id'];
|
|
113
|
+
config?: KnownKeysOnly<C, WireByIdConfig<TE, N>>;
|
|
114
|
+
}): Descriptor<N, 'findById', {
|
|
115
|
+
id: WireIdInput<TE, N>['id'];
|
|
116
|
+
config?: C;
|
|
117
|
+
}, Result<TE, N, C, 'user'>>;
|
|
118
|
+
count(config: WireCountConfig<TE, N>): Descriptor<N, 'count', WireCountConfig<TE, N>, number>;
|
|
119
|
+
page<const C extends WireFindConfig<TE, N>>(config: KnownKeysOnly<C, WireFindConfig<TE, N>>): Descriptor<N, 'page', C, Page<Result<TE, N, C, 'user'>>>;
|
|
120
|
+
create<const O extends CreateOptions<TE, N>>(input: WireCreateInput<TE, N, O>): Descriptor<N, 'create', WireCreateInput<TE, N, O>, ReadRow<TE, N, O>>;
|
|
121
|
+
update<const O extends UpdateOptions<TE, N>>(input: WireUpdateInput<TE, N, O>): Descriptor<N, 'update', WireUpdateInput<TE, N, O>, ReadRow<TE, N, O>>;
|
|
122
|
+
updateMany<const O extends UpdateManyOptions<TE, N>>(input: WireUpdateManyInput<TE, N, O>): Descriptor<N, 'updateMany', WireUpdateManyInput<TE, N, O>, {
|
|
123
|
+
count: number;
|
|
124
|
+
}>;
|
|
125
|
+
delete(input: WireDeleteInput<TE, N>): Descriptor<N, 'delete', WireDeleteInput<TE, N>, Row<TE, N>>;
|
|
126
|
+
deleteMany(input: WireDeleteManyInput<TE, N>): Descriptor<N, 'deleteMany', WireDeleteManyInput<TE, N>, {
|
|
127
|
+
count: number;
|
|
128
|
+
}>;
|
|
129
|
+
}
|
|
130
|
+
type QueriesOf<TE extends TypionTypes> = { [N in EntityName<TE>]: QueryApi<TE, N> & TraitQueries<TE, N> & LinkQueries<TE, N>; };
|
|
131
|
+
type Queries<App> = [AppTypes<App>] extends [never] ? never : QueriesOf<AppTypes<App>>;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/contract/define-queries.d.ts
|
|
134
|
+
export declare function defineQueries<App>(): Queries<App>;
|
|
135
|
+
//#endregion
|
|
136
|
+
export { type AnyDescriptor, type AppTypes, type Descriptor, ERROR_STATUS, type ErrorStatus, type InferItem, type InferResult, type Jsonified, type Op, type Queries, type QueriesOf, type QueryApi, type RESULT, type ReadOp, type TypionErrorCode, type WireBatchEnvelope, type WireByIdConfig, type WireConfig, type WireCountConfig, type WireCreateInput, type WireDataEnvelope, type WireDeleteInput, type WireDeleteManyInput, type WireEnvelope, type WireError, type WireErrorCode, type WireErrorEnvelope, type WireFieldFilter, type WireFindConfig, type WireFirstConfig, type WireIdInput, type WireIssue, type WireReadInputs, type WireReadOptions, type WireSchema, type WireUpdateInput, type WireUpdateManyInput, type WireWhere, type WireWith, type WireWriteInputs, type WriteOp, descriptor };
|
|
137
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { t as descriptor } from "../descriptor-Cc3mGp73.js";
|
|
2
|
+
import { t as ERROR_STATUS } from "../errors-ChDBxeS-.js";
|
|
3
|
+
//#region src/contract/define-queries.ts
|
|
4
|
+
function opFactory(entity, op) {
|
|
5
|
+
const make = (input) => ({
|
|
6
|
+
entity,
|
|
7
|
+
op,
|
|
8
|
+
input: input ?? {}
|
|
9
|
+
});
|
|
10
|
+
return new Proxy(make, { get(target, key) {
|
|
11
|
+
if (typeof key !== "string" || key in target || key === "then") return Reflect.get(target, key);
|
|
12
|
+
return opFactory(entity, `${op}.${key}`);
|
|
13
|
+
} });
|
|
14
|
+
}
|
|
15
|
+
function entityQueries(entity) {
|
|
16
|
+
const cache = /* @__PURE__ */ new Map();
|
|
17
|
+
return new Proxy({}, { get(_target, op) {
|
|
18
|
+
if (typeof op !== "string" || op === "then") return void 0;
|
|
19
|
+
let factory = cache.get(op);
|
|
20
|
+
if (factory === void 0) {
|
|
21
|
+
factory = opFactory(entity, op);
|
|
22
|
+
cache.set(op, factory);
|
|
23
|
+
}
|
|
24
|
+
return factory;
|
|
25
|
+
} });
|
|
26
|
+
}
|
|
27
|
+
function defineQueries() {
|
|
28
|
+
const cache = /* @__PURE__ */ new Map();
|
|
29
|
+
return new Proxy({}, { get(_target, entity) {
|
|
30
|
+
if (typeof entity !== "string") return void 0;
|
|
31
|
+
let api = cache.get(entity);
|
|
32
|
+
if (api === void 0) {
|
|
33
|
+
api = entityQueries(entity);
|
|
34
|
+
cache.set(entity, api);
|
|
35
|
+
}
|
|
36
|
+
return api;
|
|
37
|
+
} });
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { ERROR_STATUS, defineQueries, descriptor };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/contract/define-queries.ts"],"sourcesContent":["import type { Queries } from './define-queries-types.js'\nimport type { AnyDescriptor } from './descriptor.js'\n\n// Every method name is an op, and a nested one joins with a dot (`versions.list`): the client knows neither\n// the engine nor its plugins, so `restore` on an entity whose plugin adds it is built like any other.\nfunction opFactory(entity: string, op: string): unknown {\n const make = (input: unknown): AnyDescriptor => ({ entity, op, input: input ?? {} })\n return new Proxy(make, {\n get(target, key) {\n // A function's own members stay what they are, and a factory is never a thenable.\n if (typeof key !== 'string' || key in target || key === 'then')\n return Reflect.get(target, key)\n return opFactory(entity, `${op}.${key}`)\n },\n })\n}\n\nfunction entityQueries(entity: string) {\n const cache = new Map<string, unknown>()\n return new Proxy({} as Record<string, unknown>, {\n get(_target, op) {\n if (typeof op !== 'string' || op === 'then') return undefined\n let factory = cache.get(op)\n if (factory === undefined) {\n factory = opFactory(entity, op)\n cache.set(op, factory)\n }\n return factory\n },\n })\n}\n\n// The engine type is only referenced as a type argument, so a client bundle gets descriptors with exact\n// result types and none of the server code (no Drizzle, no engine runtime).\nexport function defineQueries<App>(): Queries<App> {\n const cache = new Map<string, unknown>()\n return new Proxy({} as Record<string, unknown>, {\n get(_target, entity) {\n if (typeof entity !== 'string') return undefined\n let api = cache.get(entity)\n if (api === undefined) {\n api = entityQueries(entity)\n cache.set(entity, api)\n }\n return api\n },\n }) as unknown as Queries<App>\n}\n"],"mappings":";;;AAKA,SAAS,UAAU,QAAgB,IAAqB;CACtD,MAAM,QAAQ,WAAmC;EAAE;EAAQ;EAAI,OAAO,SAAS,CAAC;CAAE;CAClF,OAAO,IAAI,MAAM,MAAM,EACrB,IAAI,QAAQ,KAAK;EAEf,IAAI,OAAO,QAAQ,YAAY,OAAO,UAAU,QAAQ,QACtD,OAAO,QAAQ,IAAI,QAAQ,GAAG;EAChC,OAAO,UAAU,QAAQ,GAAG,GAAG,GAAG,KAAK;CACzC,EACF,CAAC;AACH;AAEA,SAAS,cAAc,QAAgB;CACrC,MAAM,wBAAQ,IAAI,IAAqB;CACvC,OAAO,IAAI,MAAM,CAAC,GAA8B,EAC9C,IAAI,SAAS,IAAI;EACf,IAAI,OAAO,OAAO,YAAY,OAAO,QAAQ,OAAO,KAAA;EACpD,IAAI,UAAU,MAAM,IAAI,EAAE;EAC1B,IAAI,YAAY,KAAA,GAAW;GACzB,UAAU,UAAU,QAAQ,EAAE;GAC9B,MAAM,IAAI,IAAI,OAAO;EACvB;EACA,OAAO;CACT,EACF,CAAC;AACH;AAIA,SAAgB,gBAAmC;CACjD,MAAM,wBAAQ,IAAI,IAAqB;CACvC,OAAO,IAAI,MAAM,CAAC,GAA8B,EAC9C,IAAI,SAAS,QAAQ;EACnB,IAAI,OAAO,WAAW,UAAU,OAAO,KAAA;EACvC,IAAI,MAAM,MAAM,IAAI,MAAM;EAC1B,IAAI,QAAQ,KAAA,GAAW;GACrB,MAAM,cAAc,MAAM;GAC1B,MAAM,IAAI,QAAQ,GAAG;EACvB;EACA,OAAO;CACT,EACF,CAAC;AACH"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Kt as DbAdapter } from "../context-B4e2eREP.js";
|
|
2
|
+
import { PGlite } from "@electric-sql/pglite";
|
|
3
|
+
//#region src/db/pglite.d.ts
|
|
4
|
+
export type PgliteAdapter = DbAdapter & {
|
|
5
|
+
client(): PGlite;
|
|
6
|
+
};
|
|
7
|
+
export declare function pglite(options?: {
|
|
8
|
+
dataDir?: string;
|
|
9
|
+
client?: PGlite;
|
|
10
|
+
}): PgliteAdapter;
|
|
11
|
+
//#endregion
|
|
12
|
+
//# sourceMappingURL=pglite.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PGlite } from "@electric-sql/pglite";
|
|
2
|
+
import { drizzle } from "drizzle-orm/pglite";
|
|
3
|
+
//#region src/db/pglite.ts
|
|
4
|
+
function pglite(options = {}) {
|
|
5
|
+
let client = options.client;
|
|
6
|
+
const open = () => client ??= new PGlite(options.dataDir);
|
|
7
|
+
return {
|
|
8
|
+
client: open,
|
|
9
|
+
connect: (relations) => drizzle({
|
|
10
|
+
client: open(),
|
|
11
|
+
relations
|
|
12
|
+
}),
|
|
13
|
+
credentials: () => ({
|
|
14
|
+
driver: "pglite",
|
|
15
|
+
client: open()
|
|
16
|
+
}),
|
|
17
|
+
close: async () => {
|
|
18
|
+
const opened = client;
|
|
19
|
+
client = void 0;
|
|
20
|
+
await opened?.close();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { pglite };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=pglite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pglite.js","names":[],"sources":["../../src/db/pglite.ts"],"sourcesContent":["import { PGlite } from '@electric-sql/pglite'\nimport { drizzle } from 'drizzle-orm/pglite'\nimport type { DbAdapter } from '../types/collection.js'\n\nexport type PgliteAdapter = DbAdapter & { client(): PGlite }\n\n// In-process Postgres: no data directory means in memory, which is what tests use.\nexport function pglite(options: { dataDir?: string; client?: PGlite } = {}): PgliteAdapter {\n let client = options.client\n const open = () => (client ??= new PGlite(options.dataDir))\n return {\n client: open,\n connect: (relations) => drizzle({ client: open(), relations }) as never,\n credentials: () => ({ driver: 'pglite' as const, client: open() }),\n close: async () => {\n const opened = client\n // Forgotten, so that a later connect opens a fresh database rather than the closed one.\n client = undefined\n await opened?.close()\n },\n }\n}\n"],"mappings":";;;AAOA,SAAgB,OAAO,UAAiD,CAAC,GAAkB;CACzF,IAAI,SAAS,QAAQ;CACrB,MAAM,aAAc,WAAW,IAAI,OAAO,QAAQ,OAAO;CACzD,OAAO;EACL,QAAQ;EACR,UAAU,cAAc,QAAQ;GAAE,QAAQ,KAAK;GAAG;EAAU,CAAC;EAC7D,oBAAoB;GAAE,QAAQ;GAAmB,QAAQ,KAAK;EAAE;EAChE,OAAO,YAAY;GACjB,MAAM,SAAS;GAEf,SAAS,KAAA;GACT,MAAM,QAAQ,MAAM;EACtB;CACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptor-Cc3mGp73.js","names":[],"sources":["../src/contract/descriptor.ts"],"sourcesContent":["// The phantom result key is declared exactly once, here. A second `declare const RESULT: unique symbol`\n// anywhere else is a different symbol and silently makes `InferResult` resolve to `unknown`.\nexport declare const RESULT: unique symbol\n\nexport type ReadOp = 'find' | 'findOne' | 'findById' | 'count' | 'page'\nexport type WriteOp = 'create' | 'update' | 'updateMany' | 'delete' | 'deleteMany'\n// An operation a plugin adds to the entities it acts on (`restore`, `versions.list`) is an op of its own name.\nexport type Op = ReadOp | WriteOp | (string & {})\n\nexport interface Descriptor<TEntity extends string, TOp extends Op, TInput, TResult> {\n readonly entity: TEntity\n readonly op: TOp\n readonly input: TInput\n readonly [RESULT]?: TResult\n}\n\nexport type AnyDescriptor = Descriptor<string, Op, unknown, unknown>\n\nexport type InferResult<Q> = Q extends { readonly [RESULT]?: infer T } ? T : never\n\nexport type InferItem<Q> =\n InferResult<Q> extends readonly (infer El)[]\n ? El\n : InferResult<Q> extends { items: readonly (infer El)[] }\n ? El\n : NonNullable<InferResult<Q>>\n\nexport function descriptor<E extends string, O extends Op, I>(\n entity: E,\n op: O,\n input: I,\n): Descriptor<E, O, I, unknown> {\n return { entity, op, input }\n}\n"],"mappings":";AA2BA,SAAgB,WACd,QACA,IACA,OAC8B;CAC9B,OAAO;EAAE;EAAQ;EAAI;CAAM;AAC7B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/contract/errors.ts
|
|
2
|
+
const ERROR_STATUS = {
|
|
3
|
+
NOT_FOUND: 404,
|
|
4
|
+
FORBIDDEN: 403,
|
|
5
|
+
VALIDATION: 422,
|
|
6
|
+
CONFLICT: 409,
|
|
7
|
+
INVALID_STATE: 409,
|
|
8
|
+
BAD_REQUEST: 400,
|
|
9
|
+
UNSUPPORTED: 400,
|
|
10
|
+
PLUGIN: 500,
|
|
11
|
+
CONFIG: 500,
|
|
12
|
+
INTERNAL: 500
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ERROR_STATUS as t };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=errors-ChDBxeS-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-ChDBxeS-.js","names":[],"sources":["../src/contract/errors.ts"],"sourcesContent":["import type { TypionErrorCode } from '../errors.js'\n\n// Shared by the HTTP handler and clients so status mapping never drifts between them. PLUGIN carries the\n// plugin-declared status at runtime; 500 is the fallback when a plugin declares none.\nexport const ERROR_STATUS = {\n NOT_FOUND: 404,\n FORBIDDEN: 403,\n VALIDATION: 422,\n CONFLICT: 409,\n INVALID_STATE: 409,\n BAD_REQUEST: 400,\n UNSUPPORTED: 400,\n PLUGIN: 500,\n CONFIG: 500,\n INTERNAL: 500,\n} as const satisfies Record<TypionErrorCode, number>\n\nexport type ErrorStatus = (typeof ERROR_STATUS)[TypionErrorCode]\n\nexport type WireIssue = { readonly path: readonly (string | number)[]; readonly message: string }\n\n// Over HTTP a refusal of a caller who has not signed in is `UNAUTHENTICATED` (401), so a client can tell \"sign in\" from\n// \"not allowed\"; in process it stays `FORBIDDEN`, since the server knows who calls.\nexport type WireErrorCode = TypionErrorCode | 'UNAUTHENTICATED'\n\nexport type WireError = {\n readonly code: WireErrorCode\n readonly status: number\n readonly message: string\n readonly entity?: string\n readonly issues?: readonly WireIssue[]\n readonly details?: Record<string, unknown>\n}\n\nexport type WireErrorEnvelope = { readonly error: WireError }\nexport type WireDataEnvelope<T> = { readonly data: T }\nexport type WireEnvelope<T> = WireDataEnvelope<T> | WireErrorEnvelope\nexport type WireBatchEnvelope<T = unknown> = { readonly results: readonly WireEnvelope<T>[] }\n"],"mappings":";AAIA,MAAa,eAAe;CAC1B,WAAW;CACX,WAAW;CACX,YAAY;CACZ,UAAU;CACV,eAAe;CACf,aAAa;CACb,aAAa;CACb,QAAQ;CACR,QAAQ;CACR,UAAU;AACZ"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
var TypionError = class extends Error {
|
|
3
|
+
entity;
|
|
4
|
+
details;
|
|
5
|
+
constructor(message, opts = {}) {
|
|
6
|
+
super(message, opts.cause === void 0 ? void 0 : { cause: opts.cause });
|
|
7
|
+
this.name = new.target.name;
|
|
8
|
+
this.entity = opts.entity;
|
|
9
|
+
this.details = opts.details;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var NotFoundError = class extends TypionError {
|
|
13
|
+
code = "NOT_FOUND";
|
|
14
|
+
status = 404;
|
|
15
|
+
};
|
|
16
|
+
var ForbiddenError = class extends TypionError {
|
|
17
|
+
code = "FORBIDDEN";
|
|
18
|
+
status = 403;
|
|
19
|
+
operation;
|
|
20
|
+
rule;
|
|
21
|
+
constructor(message, opts = {}) {
|
|
22
|
+
super(message, opts);
|
|
23
|
+
this.operation = opts.operation;
|
|
24
|
+
this.rule = opts.rule;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var ValidationError = class extends TypionError {
|
|
28
|
+
code = "VALIDATION";
|
|
29
|
+
status = 422;
|
|
30
|
+
issues;
|
|
31
|
+
constructor(message, issues, opts = {}) {
|
|
32
|
+
super(message, opts);
|
|
33
|
+
this.issues = issues;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var ConflictError = class extends TypionError {
|
|
37
|
+
code = "CONFLICT";
|
|
38
|
+
status = 409;
|
|
39
|
+
kind;
|
|
40
|
+
constraint;
|
|
41
|
+
retryable;
|
|
42
|
+
constructor(message, kind, opts = {}) {
|
|
43
|
+
super(message, opts);
|
|
44
|
+
this.kind = kind;
|
|
45
|
+
this.constraint = opts.constraint;
|
|
46
|
+
this.retryable = opts.retryable ?? (kind === "serialization" || kind === "deadlock");
|
|
47
|
+
if (opts.issues !== void 0) this.issues = opts.issues;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var InvalidStateError = class extends TypionError {
|
|
51
|
+
code = "INVALID_STATE";
|
|
52
|
+
status = 409;
|
|
53
|
+
};
|
|
54
|
+
var BadRequestError = class extends TypionError {
|
|
55
|
+
code = "BAD_REQUEST";
|
|
56
|
+
status = 400;
|
|
57
|
+
};
|
|
58
|
+
var UnsupportedError = class extends TypionError {
|
|
59
|
+
code = "UNSUPPORTED";
|
|
60
|
+
status = 400;
|
|
61
|
+
};
|
|
62
|
+
var PluginError = class extends TypionError {
|
|
63
|
+
code = "PLUGIN";
|
|
64
|
+
status;
|
|
65
|
+
pluginId;
|
|
66
|
+
pluginCode;
|
|
67
|
+
constructor(message, pluginId, pluginCode, opts = {}) {
|
|
68
|
+
super(message, {
|
|
69
|
+
...opts,
|
|
70
|
+
details: {
|
|
71
|
+
...opts.details,
|
|
72
|
+
pluginId,
|
|
73
|
+
pluginCode
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
this.status = opts.status ?? 500;
|
|
77
|
+
this.pluginId = pluginId;
|
|
78
|
+
this.pluginCode = pluginCode;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var ConfigError = class extends TypionError {
|
|
82
|
+
code = "CONFIG";
|
|
83
|
+
status = 500;
|
|
84
|
+
kind;
|
|
85
|
+
constructor(message, kind = "config", opts = {}) {
|
|
86
|
+
super(message, opts);
|
|
87
|
+
this.kind = kind;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var InternalError = class extends TypionError {
|
|
91
|
+
code = "INTERNAL";
|
|
92
|
+
status = 500;
|
|
93
|
+
};
|
|
94
|
+
function isTypionError(e, code) {
|
|
95
|
+
return e instanceof TypionError && (code === void 0 || e.code === code);
|
|
96
|
+
}
|
|
97
|
+
async function attempt(fn) {
|
|
98
|
+
try {
|
|
99
|
+
return {
|
|
100
|
+
ok: true,
|
|
101
|
+
data: await fn()
|
|
102
|
+
};
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (isTypionError(error)) return {
|
|
105
|
+
ok: false,
|
|
106
|
+
error
|
|
107
|
+
};
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { InternalError as a, PluginError as c, ValidationError as d, attempt as f, ForbiddenError as i, TypionError as l, ConfigError as n, InvalidStateError as o, isTypionError as p, ConflictError as r, NotFoundError as s, BadRequestError as t, UnsupportedError as u };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=errors-D-CKO-px.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-D-CKO-px.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["export type TypionErrorCode =\n | 'NOT_FOUND'\n | 'FORBIDDEN'\n | 'VALIDATION'\n | 'CONFLICT'\n | 'INVALID_STATE'\n | 'BAD_REQUEST'\n | 'UNSUPPORTED'\n | 'PLUGIN'\n | 'CONFIG'\n | 'INTERNAL'\n\nexport type TypionErrorOptions = {\n entity?: string\n details?: Record<string, unknown>\n cause?: unknown\n}\n\nexport abstract class TypionError extends Error {\n abstract readonly code: TypionErrorCode\n abstract readonly status: number\n readonly entity: string | undefined\n readonly details: Record<string, unknown> | undefined\n\n constructor(message: string, opts: TypionErrorOptions = {}) {\n super(message, opts.cause === undefined ? undefined : { cause: opts.cause })\n this.name = new.target.name\n this.entity = opts.entity\n this.details = opts.details\n }\n}\n\nexport class NotFoundError extends TypionError {\n readonly code = 'NOT_FOUND' as const\n readonly status = 404 as const\n}\n\nexport type ForbiddenErrorOptions = TypionErrorOptions & { operation?: string; rule?: string }\n\nexport class ForbiddenError extends TypionError {\n readonly code = 'FORBIDDEN' as const\n readonly status = 403 as const\n readonly operation: string | undefined\n readonly rule: string | undefined\n\n constructor(message: string, opts: ForbiddenErrorOptions = {}) {\n super(message, opts)\n this.operation = opts.operation\n this.rule = opts.rule\n }\n}\n\nexport type ValidationIssue = { readonly path: readonly PropertyKey[]; readonly message: string }\n\nexport class ValidationError extends TypionError {\n readonly code = 'VALIDATION' as const\n readonly status = 422 as const\n readonly issues: readonly ValidationIssue[]\n\n constructor(message: string, issues: readonly ValidationIssue[], opts: TypionErrorOptions = {}) {\n super(message, opts)\n this.issues = issues\n }\n}\n\nexport type ConflictKind = 'unique' | 'foreign_key' | 'check' | 'serialization' | 'deadlock'\n\nexport type ConflictErrorOptions = TypionErrorOptions & {\n constraint?: string\n retryable?: boolean\n // The columns a unique or foreign key constraint covers, when the engine knows them.\n issues?: readonly ValidationIssue[]\n}\n\nexport class ConflictError extends TypionError {\n readonly code = 'CONFLICT' as const\n readonly status = 409 as const\n readonly kind: ConflictKind\n readonly constraint: string | undefined\n readonly retryable: boolean\n // Declared, not initialized: an error without issues has no such key, which the wire reads.\n declare readonly issues?: readonly ValidationIssue[]\n\n constructor(message: string, kind: ConflictKind, opts: ConflictErrorOptions = {}) {\n super(message, opts)\n this.kind = kind\n this.constraint = opts.constraint\n this.retryable = opts.retryable ?? (kind === 'serialization' || kind === 'deadlock')\n if (opts.issues !== undefined)\n (this as { issues?: readonly ValidationIssue[] }).issues = opts.issues\n }\n}\n\nexport class InvalidStateError extends TypionError {\n readonly code = 'INVALID_STATE' as const\n readonly status = 409 as const\n}\n\nexport class BadRequestError extends TypionError {\n readonly code = 'BAD_REQUEST' as const\n readonly status = 400 as const\n}\n\nexport class UnsupportedError extends TypionError {\n readonly code = 'UNSUPPORTED' as const\n readonly status = 400 as const\n}\n\nexport type PluginErrorOptions = TypionErrorOptions & { status?: number }\n\nexport class PluginError extends TypionError {\n readonly code = 'PLUGIN' as const\n readonly status: number\n readonly pluginId: string\n readonly pluginCode: string\n\n constructor(\n message: string,\n pluginId: string,\n pluginCode: string,\n opts: PluginErrorOptions = {},\n ) {\n super(message, {\n ...opts,\n details: { ...opts.details, pluginId, pluginCode },\n })\n this.status = opts.status ?? 500\n this.pluginId = pluginId\n this.pluginCode = pluginCode\n }\n}\n\nexport type ConfigErrorKind = 'config' | 'schema_drift' | 'relations_mismatch'\n\nexport class ConfigError extends TypionError {\n readonly code = 'CONFIG' as const\n readonly status = 500 as const\n readonly kind: ConfigErrorKind\n\n constructor(message: string, kind: ConfigErrorKind = 'config', opts: TypionErrorOptions = {}) {\n super(message, opts)\n this.kind = kind\n }\n}\n\nexport class InternalError extends TypionError {\n readonly code = 'INTERNAL' as const\n readonly status = 500 as const\n}\n\nexport function isTypionError(e: unknown, code?: TypionErrorCode): e is TypionError {\n return e instanceof TypionError && (code === undefined || e.code === code)\n}\n\nexport type Attempt<T> = { ok: true; data: T } | { ok: false; error: TypionError }\n\nexport async function attempt<T>(fn: () => Promise<T>): Promise<Attempt<T>> {\n try {\n return { ok: true, data: await fn() }\n } catch (error) {\n if (isTypionError(error)) return { ok: false, error }\n throw error\n }\n}\n"],"mappings":";AAkBA,IAAsB,cAAtB,cAA0C,MAAM;CAG9C;CACA;CAEA,YAAY,SAAiB,OAA2B,CAAC,GAAG;EAC1D,MAAM,SAAS,KAAK,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,KAAK,MAAM,CAAC;EAC3E,KAAK,OAAO,WAAW;EACvB,KAAK,SAAS,KAAK;EACnB,KAAK,UAAU,KAAK;CACtB;AACF;AAEA,IAAa,gBAAb,cAAmC,YAAY;CAC7C,OAAgB;CAChB,SAAkB;AACpB;AAIA,IAAa,iBAAb,cAAoC,YAAY;CAC9C,OAAgB;CAChB,SAAkB;CAClB;CACA;CAEA,YAAY,SAAiB,OAA8B,CAAC,GAAG;EAC7D,MAAM,SAAS,IAAI;EACnB,KAAK,YAAY,KAAK;EACtB,KAAK,OAAO,KAAK;CACnB;AACF;AAIA,IAAa,kBAAb,cAAqC,YAAY;CAC/C,OAAgB;CAChB,SAAkB;CAClB;CAEA,YAAY,SAAiB,QAAoC,OAA2B,CAAC,GAAG;EAC9F,MAAM,SAAS,IAAI;EACnB,KAAK,SAAS;CAChB;AACF;AAWA,IAAa,gBAAb,cAAmC,YAAY;CAC7C,OAAgB;CAChB,SAAkB;CAClB;CACA;CACA;CAIA,YAAY,SAAiB,MAAoB,OAA6B,CAAC,GAAG;EAChF,MAAM,SAAS,IAAI;EACnB,KAAK,OAAO;EACZ,KAAK,aAAa,KAAK;EACvB,KAAK,YAAY,KAAK,cAAc,SAAS,mBAAmB,SAAS;EACzE,IAAI,KAAK,WAAW,KAAA,GAClB,KAAkD,SAAS,KAAK;CACpE;AACF;AAEA,IAAa,oBAAb,cAAuC,YAAY;CACjD,OAAgB;CAChB,SAAkB;AACpB;AAEA,IAAa,kBAAb,cAAqC,YAAY;CAC/C,OAAgB;CAChB,SAAkB;AACpB;AAEA,IAAa,mBAAb,cAAsC,YAAY;CAChD,OAAgB;CAChB,SAAkB;AACpB;AAIA,IAAa,cAAb,cAAiC,YAAY;CAC3C,OAAgB;CAChB;CACA;CACA;CAEA,YACE,SACA,UACA,YACA,OAA2B,CAAC,GAC5B;EACA,MAAM,SAAS;GACb,GAAG;GACH,SAAS;IAAE,GAAG,KAAK;IAAS;IAAU;GAAW;EACnD,CAAC;EACD,KAAK,SAAS,KAAK,UAAU;EAC7B,KAAK,WAAW;EAChB,KAAK,aAAa;CACpB;AACF;AAIA,IAAa,cAAb,cAAiC,YAAY;CAC3C,OAAgB;CAChB,SAAkB;CAClB;CAEA,YAAY,SAAiB,OAAwB,UAAU,OAA2B,CAAC,GAAG;EAC5F,MAAM,SAAS,IAAI;EACnB,KAAK,OAAO;CACd;AACF;AAEA,IAAa,gBAAb,cAAmC,YAAY;CAC7C,OAAgB;CAChB,SAAkB;AACpB;AAEA,SAAgB,cAAc,GAAY,MAA0C;CAClF,OAAO,aAAa,gBAAgB,SAAS,KAAA,KAAa,EAAE,SAAS;AACvE;AAIA,eAAsB,QAAW,IAA2C;CAC1E,IAAI;EACF,OAAO;GAAE,IAAI;GAAM,MAAM,MAAM,GAAG;EAAE;CACtC,SAAS,OAAO;EACd,IAAI,cAAc,KAAK,GAAG,OAAO;GAAE,IAAI;GAAO;EAAM;EACpD,MAAM;CACR;AACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { d as HandlerOptions, m as TypionTypes, p as TypionEngine } from "./context-B4e2eREP.js";
|
|
2
|
+
//#region src/http/handler.d.ts
|
|
3
|
+
declare function typionErrorResponse(error: unknown, options?: {
|
|
4
|
+
debug?: boolean;
|
|
5
|
+
caller?: {
|
|
6
|
+
readonly $ctx: {
|
|
7
|
+
readonly actorId: string | null;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
}): Response;
|
|
11
|
+
declare function createHandler<TE extends TypionTypes>(engine: TypionEngine<TE>, options: HandlerOptions<TE>): (request: Request) => Promise<Response>;
|
|
12
|
+
type RouteHandlers = {
|
|
13
|
+
GET: (request: Request) => Promise<Response>;
|
|
14
|
+
POST: (request: Request) => Promise<Response>;
|
|
15
|
+
PATCH: (request: Request) => Promise<Response>;
|
|
16
|
+
PUT: (request: Request) => Promise<Response>;
|
|
17
|
+
DELETE: (request: Request) => Promise<Response>;
|
|
18
|
+
OPTIONS: (request: Request) => Promise<Response>;
|
|
19
|
+
};
|
|
20
|
+
declare function toRouteHandlers(handler: (request: Request) => Promise<Response>): RouteHandlers;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { typionErrorResponse as i, createHandler as n, toRouteHandlers as r, RouteHandlers as t };
|
|
23
|
+
//# sourceMappingURL=handler-BWVU8TCR.d.ts.map
|