@drhomet/mithaq 0.0.0-stage → 0.2.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.
Files changed (152) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSES/openstatus-time-picker.txt +21 -0
  3. package/LICENSES/payload.txt +22 -0
  4. package/LICENSES/ponytail.txt +21 -0
  5. package/README.md +160 -2
  6. package/dist/asas/actor.d.ts +96 -0
  7. package/dist/asas/actor.js +114 -0
  8. package/dist/asas/build.d.ts +239 -0
  9. package/dist/asas/build.js +834 -0
  10. package/dist/asas/cli/mithaq.d.ts +2 -0
  11. package/dist/asas/cli/mithaq.js +177 -0
  12. package/dist/asas/cli/upgrade.d.ts +33 -0
  13. package/dist/asas/cli/upgrade.js +256 -0
  14. package/dist/asas/http/fetch.d.ts +41 -0
  15. package/dist/asas/http/fetch.js +178 -0
  16. package/dist/asas/http/orpc.d.ts +45 -0
  17. package/dist/asas/http/orpc.js +153 -0
  18. package/dist/asas/runner/bulk.d.ts +20 -0
  19. package/dist/asas/runner/bulk.js +196 -0
  20. package/dist/asas/runner/errors.d.ts +63 -0
  21. package/dist/asas/runner/errors.js +75 -0
  22. package/dist/asas/runner/read.d.ts +72 -0
  23. package/dist/asas/runner/read.js +601 -0
  24. package/dist/asas/runner/runtime.d.ts +21 -0
  25. package/dist/asas/runner/runtime.js +8 -0
  26. package/dist/asas/runner/steps.d.ts +418 -0
  27. package/dist/asas/runner/steps.js +277 -0
  28. package/dist/asas/runner/store.d.ts +4 -0
  29. package/dist/asas/runner/store.js +21 -0
  30. package/dist/asas/runner/tenant.d.ts +54 -0
  31. package/dist/asas/runner/tenant.js +275 -0
  32. package/dist/asas/runner/write.d.ts +606 -0
  33. package/dist/asas/runner/write.js +1019 -0
  34. package/dist/auth/better-auth/access.d.ts +29 -0
  35. package/dist/auth/better-auth/access.js +103 -0
  36. package/dist/auth/better-auth/generate.d.ts +31 -0
  37. package/dist/auth/better-auth/generate.js +328 -0
  38. package/dist/auth/better-auth/index.d.ts +94 -0
  39. package/dist/auth/better-auth/index.js +81 -0
  40. package/dist/auth/better-auth/tenant.d.ts +26 -0
  41. package/dist/auth/better-auth/tenant.js +34 -0
  42. package/dist/auth/local/index.d.ts +285 -0
  43. package/dist/auth/local/index.js +738 -0
  44. package/dist/base/decimal.d.ts +9 -0
  45. package/dist/base/decimal.js +16 -0
  46. package/dist/base/fields.d.ts +124 -0
  47. package/dist/base/fields.js +52 -0
  48. package/dist/base/index.d.ts +47 -0
  49. package/dist/base/index.js +5 -0
  50. package/dist/base/json-schema.d.ts +7 -0
  51. package/dist/base/json-schema.js +35 -0
  52. package/dist/base/kinds.d.ts +75 -0
  53. package/dist/base/kinds.js +123 -0
  54. package/dist/base/rules.d.ts +73 -0
  55. package/dist/base/rules.js +81 -0
  56. package/dist/drizzle/index.d.ts +308 -0
  57. package/dist/drizzle/index.js +951 -0
  58. package/dist/drizzle/kinds.d.ts +28 -0
  59. package/dist/drizzle/kinds.js +43 -0
  60. package/dist/drizzle/migrate.d.ts +159 -0
  61. package/dist/drizzle/migrate.js +1328 -0
  62. package/dist/drizzle/proxy/index.d.ts +1 -0
  63. package/dist/drizzle/proxy/index.js +1 -0
  64. package/dist/drizzle/proxy/node-postgres.d.ts +1 -0
  65. package/dist/drizzle/proxy/node-postgres.js +1 -0
  66. package/dist/drizzle/proxy/pg-core.d.ts +1 -0
  67. package/dist/drizzle/proxy/pg-core.js +1 -0
  68. package/dist/drizzle/rules.d.ts +336 -0
  69. package/dist/drizzle/rules.js +44 -0
  70. package/dist/index.d.ts +35 -0
  71. package/dist/index.js +26 -0
  72. package/dist/mithaq/define.d.ts +335 -0
  73. package/dist/mithaq/define.js +57 -0
  74. package/dist/mithaq/generate-messages.d.ts +38 -0
  75. package/dist/mithaq/generate-messages.js +235 -0
  76. package/dist/mithaq/language.d.ts +374 -0
  77. package/dist/mithaq/language.js +76 -0
  78. package/dist/mithaq/lock.d.ts +71 -0
  79. package/dist/mithaq/lock.js +329 -0
  80. package/dist/mithaq/message-file.d.ts +13 -0
  81. package/dist/mithaq/message-file.js +29 -0
  82. package/dist/mithaq/messages.d.ts +55 -0
  83. package/dist/mithaq/messages.js +111 -0
  84. package/dist/mithaq/refusal.d.ts +6 -0
  85. package/dist/mithaq/refusal.js +6 -0
  86. package/dist/mithaq/resolve.d.ts +10 -0
  87. package/dist/mithaq/resolve.js +1014 -0
  88. package/dist/mithaq/rows.d.ts +87 -0
  89. package/dist/mithaq/rows.js +174 -0
  90. package/dist/mithaq/rukn.d.ts +72 -0
  91. package/dist/mithaq/rukn.js +15 -0
  92. package/dist/mithaq/standard-schema.d.ts +38 -0
  93. package/dist/mithaq/standard-schema.js +2 -0
  94. package/dist/mithaq/types.d.ts +386 -0
  95. package/dist/mithaq/types.js +15 -0
  96. package/dist/mithaq/user.d.ts +19 -0
  97. package/dist/mithaq/user.js +16 -0
  98. package/dist/mithaq/where.d.ts +32 -0
  99. package/dist/mithaq/where.js +87 -0
  100. package/dist/rbac/index.d.ts +105 -0
  101. package/dist/rbac/index.js +182 -0
  102. package/dist/rbac/steps.d.ts +22 -0
  103. package/dist/rbac/steps.js +161 -0
  104. package/dist/rich-text/index.d.ts +28 -0
  105. package/dist/rich-text/index.js +59 -0
  106. package/dist/rich-text/rich-text.d.ts +106 -0
  107. package/dist/rich-text/rich-text.js +249 -0
  108. package/dist/rich-text/value.d.ts +55 -0
  109. package/dist/rich-text/value.js +126 -0
  110. package/dist/screen/client.d.ts +156 -0
  111. package/dist/screen/client.js +71 -0
  112. package/dist/screen/generate.d.ts +14 -0
  113. package/dist/screen/generate.js +268 -0
  114. package/dist/screen/index.d.ts +496 -0
  115. package/dist/screen/index.js +663 -0
  116. package/dist/screen/react.d.ts +97 -0
  117. package/dist/screen/react.js +58 -0
  118. package/dist/screen/studio.d.ts +24 -0
  119. package/dist/screen/studio.js +68 -0
  120. package/dist/service/index.d.ts +63 -0
  121. package/dist/service/index.js +15 -0
  122. package/dist/storage/allowed-type.d.ts +5 -0
  123. package/dist/storage/allowed-type.js +7 -0
  124. package/dist/storage/index.d.ts +42 -0
  125. package/dist/storage/index.js +43 -0
  126. package/dist/storage/storage.d.ts +386 -0
  127. package/dist/storage/storage.js +412 -0
  128. package/dist/targets.d.ts +14 -0
  129. package/dist/targets.js +16 -0
  130. package/dist/versions/index.d.ts +37 -0
  131. package/dist/versions/index.js +8 -0
  132. package/dist/versions/versions.d.ts +104 -0
  133. package/dist/versions/versions.js +160 -0
  134. package/dist/vite.d.ts +7 -0
  135. package/dist/vite.js +81 -0
  136. package/dist/zod/index.d.ts +193 -0
  137. package/dist/zod/index.js +122 -0
  138. package/dist/zod/kinds.d.ts +36 -0
  139. package/dist/zod/kinds.js +58 -0
  140. package/dist/zod/rules.d.ts +117 -0
  141. package/dist/zod/rules.js +67 -0
  142. package/docs/packages/mithaq/README.md +962 -0
  143. package/docs/packages/mithaq/src/asas/cli/README.md +252 -0
  144. package/docs/packages/mithaq/src/asas/runner/README.md +472 -0
  145. package/docs/packages/mithaq/src/drizzle/README.md +39 -0
  146. package/docs/packages/mithaq-admin/README.md +312 -0
  147. package/docs/templates/asas/README.md +1056 -0
  148. package/package.json +92 -4
  149. package/skills/add-field/SKILL.md +27 -0
  150. package/skills/add-kayan/SKILL.md +26 -0
  151. package/skills/eject-admin-piece/SKILL.md +28 -0
  152. package/skills/upgrade-mithaq/SKILL.md +35 -0
@@ -0,0 +1,386 @@
1
+ import { type Command, type Language, type Store } from '../mithaq/language.ts';
2
+ import type { ResolvedKayan } from '../mithaq/types.ts';
3
+ import { type Ctx } from '../asas/runner/steps.ts';
4
+ import type { Authorize, ManagedAdmin } from '../asas/runner/write.ts';
5
+ import type { StandardSchemaV1 } from '../mithaq/standard-schema.ts';
6
+ import { allowedType } from './allowed-type.ts';
7
+ /**
8
+ * The file columns a kayan that holds files spreads into its fields beside `defaultFields`.
9
+ * Filled from the verified upload and never changed: a file is replaced by a new row.
10
+ */
11
+ export declare const uploadFields: {
12
+ readonly filename: {
13
+ readonly kind: 'text';
14
+ readonly label: {
15
+ readonly en: 'File name';
16
+ readonly ar: 'اسم الملف';
17
+ };
18
+ readonly rules: {
19
+ readonly providedBy: {
20
+ readonly create: 'application';
21
+ readonly update: 'never';
22
+ };
23
+ readonly required: true;
24
+ readonly index: true;
25
+ };
26
+ };
27
+ readonly mimeType: {
28
+ readonly kind: 'text';
29
+ readonly label: {
30
+ readonly en: 'File type';
31
+ readonly ar: 'نوع الملف';
32
+ };
33
+ readonly rules: {
34
+ readonly providedBy: {
35
+ readonly create: 'application';
36
+ readonly update: 'never';
37
+ };
38
+ readonly required: true;
39
+ };
40
+ };
41
+ readonly filesize: {
42
+ readonly kind: 'number';
43
+ readonly label: {
44
+ readonly en: 'File size';
45
+ readonly ar: 'حجم الملف';
46
+ };
47
+ readonly rules: {
48
+ readonly providedBy: {
49
+ readonly create: 'application';
50
+ readonly update: 'never';
51
+ };
52
+ readonly required: true;
53
+ };
54
+ };
55
+ readonly width: {
56
+ readonly kind: 'number';
57
+ readonly label: {
58
+ readonly en: 'Width';
59
+ readonly ar: 'العرض';
60
+ };
61
+ readonly rules: {
62
+ readonly providedBy: {
63
+ readonly create: 'application';
64
+ readonly update: 'never';
65
+ };
66
+ };
67
+ };
68
+ readonly height: {
69
+ readonly kind: 'number';
70
+ readonly label: {
71
+ readonly en: 'Height';
72
+ readonly ar: 'الارتفاع';
73
+ };
74
+ readonly rules: {
75
+ readonly providedBy: {
76
+ readonly create: 'application';
77
+ readonly update: 'never';
78
+ };
79
+ };
80
+ };
81
+ readonly key: {
82
+ readonly kind: 'text';
83
+ readonly label: {
84
+ readonly en: 'Object key';
85
+ readonly ar: 'مفتاح الملف';
86
+ };
87
+ readonly rules: {
88
+ readonly providedBy: {
89
+ readonly create: 'application';
90
+ readonly update: 'never';
91
+ };
92
+ readonly required: true;
93
+ readonly unique: true;
94
+ };
95
+ };
96
+ readonly storage: {
97
+ readonly kind: 'text';
98
+ readonly label: {
99
+ readonly en: 'Storage';
100
+ readonly ar: 'التخزين';
101
+ };
102
+ readonly rules: {
103
+ readonly providedBy: {
104
+ readonly create: 'application';
105
+ readonly update: 'never';
106
+ };
107
+ readonly required: true;
108
+ };
109
+ };
110
+ };
111
+ /** The storage target as the language holds it: a capability, the project's config, and the `sweep` command. */
112
+ export type StorageTarget = {
113
+ readonly capability: 'storage';
114
+ readonly type: 'storage';
115
+ readonly config: StorageConfig;
116
+ readonly commands: {
117
+ readonly sweep: Command;
118
+ };
119
+ };
120
+ /** What a kayan writes under the storage target: the types it holds, its largest file in bytes, and whether its `url` is public. */
121
+ export type KayanStorage = {
122
+ readonly mimeTypes: readonly string[];
123
+ readonly fileSize?: number;
124
+ readonly public?: true;
125
+ };
126
+ /** The request the browser sends the file with. */
127
+ export type UploadRequest = {
128
+ type: 'http';
129
+ request: {
130
+ method: 'PUT' | 'POST';
131
+ url: string;
132
+ headers?: Record<string, string>;
133
+ };
134
+ };
135
+ /** What the browser sends the file with, and the signed reference the create takes back. */
136
+ export type UploadInstructions = UploadRequest & {
137
+ file: {
138
+ filename: string;
139
+ mimeType: string;
140
+ size: number;
141
+ uploadReference: UploadReference;
142
+ };
143
+ };
144
+ /** A row of a storage kayan, as much of it as an adapter reads. */
145
+ export type StoredFile = {
146
+ id: unknown;
147
+ key: string;
148
+ filename: string;
149
+ mimeType: string;
150
+ filesize: number;
151
+ storage: string;
152
+ };
153
+ /** One place files are kept. */
154
+ export type StorageAdapter = {
155
+ /** The folder of the store this adapter owns; `list` reads it alone, so a sweep of a shared bucket touches no other app's objects. */
156
+ prefix: string;
157
+ uploadInstructions: {
158
+ generate(args: {
159
+ filename: string;
160
+ filesize: number;
161
+ mimeType: string;
162
+ key: string;
163
+ }): Promise<UploadRequest>;
164
+ };
165
+ handleDelete(args: {
166
+ key: string;
167
+ }): Promise<void>;
168
+ /** The public address of an object, for a kayan that writes `public: true`. */
169
+ generateURL?(args: {
170
+ key: string;
171
+ }): string;
172
+ /** A 302 to a short-lived signed address, or the bytes themselves. */
173
+ staticHandler(request: Request, args: {
174
+ doc: StoredFile;
175
+ disposition: string;
176
+ }): Promise<Response>;
177
+ /** The stored object's size, or null where there is none. */
178
+ head(args: {
179
+ key: string;
180
+ }): Promise<{
181
+ size: number;
182
+ } | null>;
183
+ /** The first `bytes` of the stored object. */
184
+ readHead(args: {
185
+ key: string;
186
+ bytes: number;
187
+ }): Promise<Uint8Array>;
188
+ /** Every object this adapter holds, with when it was last written. */
189
+ list?(): AsyncIterable<{
190
+ key: string;
191
+ lastModified: Date;
192
+ }>;
193
+ handler?(request: Request): Promise<Response | null>;
194
+ };
195
+ /** What a verification reads, and what it answers: the image's size, or why the file is refused. */
196
+ export type VerifyArgs = {
197
+ adapter: StorageAdapter;
198
+ key: string;
199
+ mimeType: string;
200
+ size: number;
201
+ mimeTypes: readonly string[];
202
+ fileSize: number;
203
+ };
204
+ export type Verified = {
205
+ width?: number | null;
206
+ height?: number | null;
207
+ } | {
208
+ refused: string;
209
+ };
210
+ /** What a sweep is handed, per adapter, and the keys it found no row naming. */
211
+ export type SweepArgs = {
212
+ adapter: StorageAdapter;
213
+ named: ReadonlySet<string>;
214
+ check: boolean;
215
+ now: Date;
216
+ };
217
+ /** A step of the storage flow, `(ctx, tools)` as every step is. */
218
+ export type StorageStep = (ctx: Ctx, tools?: unknown) => Promise<Ctx>;
219
+ /** What the storage rukn takes, `storage(storageConfig)`. Every key is required. */
220
+ export type StorageConfig = {
221
+ /** The key upload references are signed with, 32 characters at least. */
222
+ secret: string;
223
+ /** Every adapter by the name a row's `storage` column holds. */
224
+ adapters: Readonly<Record<string, StorageAdapter>>;
225
+ /** The adapter a new upload goes to. */
226
+ adapter: string;
227
+ /** The largest file in bytes a kayan holds when its `targets.storage` names no `fileSize`. */
228
+ fileSize: number;
229
+ /** The largest request body `uploadInstructions` reads, answered 413 past it: `defaultMaxBodyBytes` or the project's own. */
230
+ maxBodyBytes: number;
231
+ /** The object key, decided before the upload. */
232
+ key: (args: {
233
+ prefix: string;
234
+ tenant: string | null;
235
+ kayan: string;
236
+ id: string;
237
+ filename: string;
238
+ }) => string;
239
+ verify: (args: VerifyArgs) => Promise<Verified>;
240
+ disposition: (args: {
241
+ filename: string;
242
+ mimeType: string;
243
+ }) => string;
244
+ sweep: (args: SweepArgs) => Promise<string[]>;
245
+ /** `POST /api/<kayan>/uploadInstructions`, asked once the actor holds the operation that makes the kayan's rows. */
246
+ instructions: (args: {
247
+ kayan: StorageKayan;
248
+ input: unknown;
249
+ actor: unknown;
250
+ }) => Promise<UploadInstructions>;
251
+ /** The `beforeTransaction` step of the operation that makes a row: the reference checked, the object verified, the file columns written. */
252
+ uploaded: StorageStep;
253
+ /** The delete's `afterCommit` step, removing the deleted row's object. */
254
+ removed: StorageStep;
255
+ /** `GET /api/<kayan>/file/<id>`: `read` is the kayan's own `findByID`, as the actor. */
256
+ serve: (args: {
257
+ request: Request;
258
+ kayan: StorageKayan;
259
+ id: string;
260
+ read: (args: {
261
+ id: string;
262
+ }) => Promise<Record<string, unknown> | null>;
263
+ }) => Promise<Response>;
264
+ /** Handed what a file route threw that is no refusal, before it answers 500 with the message replaced. */
265
+ onError: (error: unknown) => void;
266
+ };
267
+ export type ResolvedStorage = {
268
+ mimeTypes: readonly string[];
269
+ fileSize: number;
270
+ public: boolean;
271
+ config: StorageConfig;
272
+ operation: string;
273
+ exists: (id: string) => Promise<boolean>;
274
+ /** The organization this actor's files of the kayan are kept under: null for a shared kayan, nothing where a tenant-owned one has no active organization. */
275
+ tenant: (actor: unknown) => string | null | undefined;
276
+ };
277
+ /** A kayan that holds files, as `buildAsas` hands it to the storage functions. */
278
+ export type StorageKayan = ResolvedKayan & {
279
+ storage: ResolvedStorage;
280
+ };
281
+ /** The signed reference an upload's create hands back: what the server decided, and its signature. */
282
+ export type UploadReference = {
283
+ id: string;
284
+ key: string;
285
+ kayan: string;
286
+ tenant: string | null;
287
+ filename: string;
288
+ type: string;
289
+ size: number;
290
+ storage: string;
291
+ exp: number;
292
+ signature: string;
293
+ };
294
+ /** The `fileSize` the template names in its storage config: 10 MiB. */
295
+ export declare const defaultFileSize: number;
296
+ /** The type check both halves make, in a module the browser imports too. */
297
+ export { allowedType };
298
+ /** The file name with every directory part and control character dropped, or an empty string. */
299
+ export declare const sanitizeFilename: (filename: string) => string;
300
+ /** The adapter a row or a reference names. Read as an own key, so no name reaches an inherited property. */
301
+ export declare const adapterOf: ({ kayan, name }: {
302
+ kayan: ResolvedKayan;
303
+ name: unknown;
304
+ }) => StorageAdapter;
305
+ /**
306
+ * Signs the reference an upload's create must name back: the row's id, the key, the kayan,
307
+ * the actor's tenant from its session, the file, the adapter and an expiry, under HMAC-SHA256.
308
+ */
309
+ export declare const signReference: ({ kayan, actor, id, filename, type, size, }: {
310
+ kayan: ResolvedKayan;
311
+ actor: unknown;
312
+ id: string;
313
+ filename: string;
314
+ type: string;
315
+ size: number;
316
+ }) => UploadReference;
317
+ /**
318
+ * Checks the reference a create names back, refusing every way it can be wrong in one
319
+ * sentence so a forged one reads as an expired one. The signature is compared in constant time.
320
+ */
321
+ export declare const checkReference: ({ kayan, value, actor }: {
322
+ kayan: ResolvedKayan;
323
+ value: unknown;
324
+ actor: unknown;
325
+ }) => Promise<UploadReference>;
326
+ /** The create shape of a kayan holding files, with the `uploadReference` beside it. */
327
+ export declare const withUploadReference: (create: StandardSchemaV1) => StandardSchemaV1;
328
+ export declare const resolveStorage: ({ language, resolved, storeOf, active }: {
329
+ language: Language;
330
+ resolved: ResolvedKayan[];
331
+ storeOf: Swept['storeOf'];
332
+ /** The organization the actor's verified session has active, the one a tenant-owned kayan's files are kept under. */
333
+ active: (actor: unknown) => string | undefined;
334
+ }) => StorageKayan[];
335
+ /** A row's `url` and `thumbnailURL`, computed on read: the file route, or the adapter's public address. */
336
+ export declare const fileURLs: ({ kayan, stored, visible, }: {
337
+ kayan: ResolvedKayan;
338
+ stored: Record<string, unknown>;
339
+ visible: Record<string, unknown>;
340
+ }) => Record<string, unknown>;
341
+ /**
342
+ * The row a file route serves, read through the kayan's own `findByID` as the actor. Every
343
+ * reason it cannot be served is the same 404, so no answer tells one from another.
344
+ */
345
+ export declare const readForFile: ({ kayan, id, read }: {
346
+ kayan: ResolvedKayan;
347
+ id: string;
348
+ read: (args: {
349
+ id: string;
350
+ }) => Promise<Record<string, unknown> | null>;
351
+ }) => Promise<StoredFile>;
352
+ /**
353
+ * Serves a file under the headers its bytes need. An SVG is never `inline` and
354
+ * gets a policy that runs no script.
355
+ */
356
+ export declare const fileHeaders: ({ doc, disposition, answer, }: {
357
+ doc: StoredFile;
358
+ disposition: string;
359
+ answer: (args: {
360
+ disposition: string;
361
+ }) => Promise<Response>;
362
+ }) => Promise<Response>;
363
+ export declare const storageRoutes: <Actor>({ kayan, config, read, authorize, admin, }: {
364
+ kayan: readonly StorageKayan[];
365
+ config: StorageConfig;
366
+ read: (args: {
367
+ kayan: string;
368
+ id: string;
369
+ actor: Actor | null;
370
+ }) => Promise<Record<string, unknown> | null>;
371
+ authorize: Authorize;
372
+ admin?: ManagedAdmin<Actor>;
373
+ }) => (request: Request, who: () => Promise<Actor | null>) => Promise<Response | null>;
374
+ type Swept = {
375
+ config: StorageConfig;
376
+ kayan: readonly ResolvedKayan[];
377
+ storeOf: (kayan: ResolvedKayan) => Store;
378
+ };
379
+ export declare const recordStorage: (asas: object, swept: Swept) => undefined;
380
+ /** The storage target over the project's config. The storage rukn builds it. */
381
+ export declare const storageTarget: (config: StorageConfig) => StorageTarget;
382
+ declare module '../mithaq/rukn.ts' {
383
+ interface KayanConfigs<L, F, T> {
384
+ storage: KayanStorage;
385
+ }
386
+ }