@segmentstream-cloud/ontology 0.9.0 → 0.10.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/analyze.js +16 -1
- package/dist/blob.d.ts +39 -0
- package/dist/blob.js +49 -0
- package/dist/entity.d.ts +5 -3
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- package/dist/manifest.d.ts +23 -7
- package/dist/manifest.js +9 -1
- package/dist/migrate/model.d.ts +7 -2
- package/dist/migrate/plan.js +26 -2
- package/dist/migrate/storage.d.ts +2 -0
- package/dist/migrate/storage.js +13 -0
- package/dist/property.d.ts +10 -1
- package/dist/property.js +12 -1
- package/dist/query.js +6 -1
- package/dist/runtime/generated-actions.js +7 -3
- package/dist/runtime/history.d.ts +3 -0
- package/dist/runtime/pipeline.d.ts +5 -1
- package/dist/runtime/pipeline.js +87 -3
- package/dist/runtime/records.js +9 -0
- package/dist/runtime/service-binding.d.ts +2 -1
- package/dist/runtime/service-binding.js +13 -2
- package/dist/runtime/writes.js +17 -3
- package/dist/service/api.js +15 -0
- package/dist/service/config.d.ts +3 -0
- package/dist/service/config.js +18 -0
- package/dist/service/handlers.js +40 -1
- package/dist/service/runtime-contract.d.ts +9 -0
- package/dist/service/schemas.d.ts +10 -2
- package/dist/service/schemas.js +18 -2
- package/dist/service/service.js +18 -3
- package/dist/storage/api.d.ts +4 -0
- package/dist/storage/api.js +39 -0
- package/dist/storage/authorization.d.ts +8 -0
- package/dist/storage/authorization.js +30 -0
- package/dist/storage/maintenance-auth.d.ts +20 -0
- package/dist/storage/maintenance-auth.js +24 -0
- package/dist/storage/maintenance.d.ts +7 -0
- package/dist/storage/maintenance.js +50 -0
- package/dist/storage/neon.d.ts +3 -0
- package/dist/storage/neon.js +212 -0
- package/dist/storage/operator.d.ts +10 -0
- package/dist/storage/operator.js +30 -0
- package/dist/storage/provider.d.ts +80 -0
- package/dist/storage/provider.js +20 -0
- package/dist/storage/sessions.d.ts +87 -0
- package/dist/storage/sessions.js +341 -0
- package/dist/storage/tables.d.ts +2 -0
- package/dist/storage/tables.js +55 -0
- package/dist/storage/writes.d.ts +7 -0
- package/dist/storage/writes.js +88 -0
- package/package.json +3 -1
package/dist/analyze.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { checkWarehouseSource } from "./warehouse-backed.js";
|
|
2
2
|
import { Schema } from "effect";
|
|
3
|
+
import { BLOB_UPLOAD_ANNOTATION } from "./blob.js";
|
|
4
|
+
import { BLOB_CONTENT_TYPES, MAX_BLOB_BYTES } from "./blob.js";
|
|
3
5
|
import { isAction } from "./action.js";
|
|
4
6
|
import { CONNECTION_KEY, isConnection } from "./connection.js";
|
|
5
7
|
import { isEntity } from "./entity.js";
|
|
@@ -340,6 +342,19 @@ function resolveProperties(candidate, scope) {
|
|
|
340
342
|
return properties;
|
|
341
343
|
}
|
|
342
344
|
function checkProperty(path, schema, definition, report) {
|
|
345
|
+
if (definition.type === "blob") {
|
|
346
|
+
if (definition.unique || "default" in definition) {
|
|
347
|
+
report("invalid-property", path, "Blob properties cannot be unique or have a default.");
|
|
348
|
+
}
|
|
349
|
+
if (!definition.accept?.length ||
|
|
350
|
+
definition.accept.some((type) => !BLOB_CONTENT_TYPES.includes(type)) ||
|
|
351
|
+
new Set(definition.accept).size !== definition.accept.length ||
|
|
352
|
+
!Number.isInteger(definition.maxBytes) ||
|
|
353
|
+
definition.maxBytes < 1 ||
|
|
354
|
+
definition.maxBytes > MAX_BLOB_BYTES) {
|
|
355
|
+
report("invalid-constraint", path, "Use supported content types and a limit from 1 byte to 25 MiB.");
|
|
356
|
+
}
|
|
357
|
+
}
|
|
343
358
|
if (definition.type === "select") {
|
|
344
359
|
checkSelectOptions(path, definition, report);
|
|
345
360
|
}
|
|
@@ -563,7 +578,7 @@ function resolveInput(path, input, scope) {
|
|
|
563
578
|
}
|
|
564
579
|
try {
|
|
565
580
|
const document = Schema.toJsonSchemaDocument(input, {
|
|
566
|
-
includeAnnotationKey: (key) => key === REFERENCE_ANNOTATION,
|
|
581
|
+
includeAnnotationKey: (key) => key === REFERENCE_ANNOTATION || key === BLOB_UPLOAD_ANNOTATION,
|
|
567
582
|
onExcessProperty: "error",
|
|
568
583
|
});
|
|
569
584
|
const schema = document.schema;
|
package/dist/blob.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Metadata of an immutable file revision. Provider keys and grants never appear in records. */
|
|
3
|
+
export declare const BlobValue: Schema.Struct<{
|
|
4
|
+
readonly id: Schema.String;
|
|
5
|
+
readonly filename: Schema.String;
|
|
6
|
+
readonly contentType: Schema.String;
|
|
7
|
+
readonly size: Schema.Int;
|
|
8
|
+
readonly createdAt: Schema.String;
|
|
9
|
+
}>;
|
|
10
|
+
export type BlobValue = typeof BlobValue.Type;
|
|
11
|
+
/** An opaque completed-upload ticket. Only the action runtime may resolve and consume it. */
|
|
12
|
+
declare function uploadCodec(entity?: string, property?: string): Schema.decodeTo<Schema.Struct<{
|
|
13
|
+
readonly uploadId: Schema.String;
|
|
14
|
+
}>, Schema.Struct<{
|
|
15
|
+
readonly upload_id: Schema.String;
|
|
16
|
+
}>, never, never>;
|
|
17
|
+
export declare const BlobUpload: Schema.Struct<{
|
|
18
|
+
readonly uploadId: Schema.String;
|
|
19
|
+
}>;
|
|
20
|
+
export type BlobUpload = typeof BlobUpload.Type;
|
|
21
|
+
export declare const BLOB_UPLOAD_ANNOTATION = "x-ontology-upload";
|
|
22
|
+
export declare const MAX_BLOB_BYTES: number;
|
|
23
|
+
export declare const BLOB_CONTENT_TYPES: readonly ["application/pdf", "image/jpeg", "image/png", "text/plain"];
|
|
24
|
+
type SchemaValue<S> = S extends {
|
|
25
|
+
readonly Type: infer T;
|
|
26
|
+
} ? T : S extends Schema.optionalKey<infer Inner> ? Inner["Type"] : never;
|
|
27
|
+
type BlobPropertyKey<P> = {
|
|
28
|
+
[K in keyof P]: NonNullable<SchemaValue<P[K]>> extends BlobValue ? K : never;
|
|
29
|
+
}[keyof P] & string;
|
|
30
|
+
/** Internal wire codec for session tickets and generated action inputs. */
|
|
31
|
+
export declare function uploadInput(entity?: string, property?: string): ReturnType<typeof uploadCodec>;
|
|
32
|
+
/** Declares which blob field an authored action's upload input may write. */
|
|
33
|
+
export declare const uploads: {
|
|
34
|
+
for<const P extends Readonly<Record<string, unknown>>>(entity: {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly properties: P;
|
|
37
|
+
}, property: BlobPropertyKey<P>): typeof BlobUpload;
|
|
38
|
+
};
|
|
39
|
+
export {};
|
package/dist/blob.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Schema, SchemaTransformation } from "effect";
|
|
2
|
+
import { nameToWire } from "./authoring-names.js";
|
|
3
|
+
/** Metadata of an immutable file revision. Provider keys and grants never appear in records. */
|
|
4
|
+
export const BlobValue = Schema.Struct({
|
|
5
|
+
id: Schema.String.check(Schema.isUUID()),
|
|
6
|
+
filename: Schema.String,
|
|
7
|
+
contentType: Schema.String,
|
|
8
|
+
size: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
9
|
+
createdAt: Schema.String,
|
|
10
|
+
});
|
|
11
|
+
/** An opaque completed-upload ticket. Only the action runtime may resolve and consume it. */
|
|
12
|
+
function uploadCodec(entity, property) {
|
|
13
|
+
const id = Schema.String.check(Schema.isUUID());
|
|
14
|
+
return Schema.Struct({ upload_id: id })
|
|
15
|
+
.annotate({
|
|
16
|
+
...(entity && property
|
|
17
|
+
? {
|
|
18
|
+
description: `A completed upload for ${entity}.${property}.`,
|
|
19
|
+
"x-ontology-upload": { entity, property },
|
|
20
|
+
}
|
|
21
|
+
: {}),
|
|
22
|
+
})
|
|
23
|
+
.pipe(Schema.decodeTo(Schema.Struct({ uploadId: id }), SchemaTransformation.transform({
|
|
24
|
+
decode: (value) => ({ uploadId: value.upload_id }),
|
|
25
|
+
encode: (value) => ({ upload_id: value.uploadId }),
|
|
26
|
+
})));
|
|
27
|
+
}
|
|
28
|
+
export const BlobUpload = Schema.Struct({ uploadId: Schema.String.check(Schema.isUUID()) });
|
|
29
|
+
export const BLOB_UPLOAD_ANNOTATION = "x-ontology-upload";
|
|
30
|
+
export const MAX_BLOB_BYTES = 25 * 1024 * 1024;
|
|
31
|
+
export const BLOB_CONTENT_TYPES = [
|
|
32
|
+
"application/pdf",
|
|
33
|
+
"image/jpeg",
|
|
34
|
+
"image/png",
|
|
35
|
+
"text/plain",
|
|
36
|
+
];
|
|
37
|
+
/** Internal wire codec for session tickets and generated action inputs. */
|
|
38
|
+
export function uploadInput(entity, property) {
|
|
39
|
+
return uploadCodec(entity, property);
|
|
40
|
+
}
|
|
41
|
+
/** Declares which blob field an authored action's upload input may write. */
|
|
42
|
+
export const uploads = {
|
|
43
|
+
for(entity, property) {
|
|
44
|
+
return BlobUpload.annotate({
|
|
45
|
+
description: `A completed upload for ${entity.name}.${property}.`,
|
|
46
|
+
"x-ontology-upload": { entity: nameToWire(entity.name), property: nameToWire(property) },
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
};
|
package/dist/entity.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BlobUpload, BlobValue } from "./blob.js";
|
|
1
2
|
import { Effect, type Schema } from "effect";
|
|
2
3
|
import type { Measures } from "./measure.js";
|
|
3
4
|
import type { WarehouseSource } from "./source.js";
|
|
@@ -39,6 +40,7 @@ type IsOptional<S> = S extends {
|
|
|
39
40
|
type ValueOf<S> = S extends {
|
|
40
41
|
readonly Type: infer T;
|
|
41
42
|
} ? IsOptional<S> extends true ? T | null : T : never;
|
|
43
|
+
type WriteValueOf<S> = NonNullable<ValueOf<S>> extends BlobValue ? BlobUpload | (null extends ValueOf<S> ? null : never) : ValueOf<S>;
|
|
42
44
|
type RequiredOnCreate<S> = IsOptional<S> extends true ? false : S extends {
|
|
43
45
|
readonly "~ontology.defaulted": true;
|
|
44
46
|
} ? false : true;
|
|
@@ -68,9 +70,9 @@ export type EntityRecord<P, R> = Simplify<SystemFields & {
|
|
|
68
70
|
* relationships take ids by relationship name (`{ lead: lead.id }`), `rel.many` a list of ids.
|
|
69
71
|
*/
|
|
70
72
|
export type CreateValues<P, R> = Simplify<{
|
|
71
|
-
readonly [K in RequiredPropertyKeys<P>]:
|
|
73
|
+
readonly [K in RequiredPropertyKeys<P>]: WriteValueOf<P[K]>;
|
|
72
74
|
} & {
|
|
73
|
-
readonly [K in Exclude<keyof P, RequiredPropertyKeys<P>>]?:
|
|
75
|
+
readonly [K in Exclude<keyof P, RequiredPropertyKeys<P>>]?: WriteValueOf<P[K]>;
|
|
74
76
|
} & {
|
|
75
77
|
readonly [K in RequiredOneKeys<R>]: string;
|
|
76
78
|
} & {
|
|
@@ -80,7 +82,7 @@ export type CreateValues<P, R> = Simplify<{
|
|
|
80
82
|
}>;
|
|
81
83
|
/** Values for `update`. Handlers may write `managed` properties; the generated `update` may not. */
|
|
82
84
|
export type UpdateValues<P, R> = Simplify<{
|
|
83
|
-
readonly [K in keyof P]?:
|
|
85
|
+
readonly [K in keyof P]?: WriteValueOf<P[K]>;
|
|
84
86
|
} & {
|
|
85
87
|
readonly [K in OneKeys<R>]?: R[K] extends OneRelationship<true> ? string | null : string;
|
|
86
88
|
} & {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { BlobValue, BlobUpload, uploads, BLOB_CONTENT_TYPES, MAX_BLOB_BYTES } from "./blob.js";
|
|
1
2
|
export { warehouse, compatibleWarehouseColumn, warehouseColumnType, validateWarehouseSource, } from "./source.js";
|
|
2
3
|
export type { WarehouseSource } from "./source.js";
|
|
3
4
|
export { m } from "./measure.js";
|
|
@@ -21,7 +22,7 @@ export type { Ontology } from "./ontology.js";
|
|
|
21
22
|
export { DEFAULT_MEMBER_PERMISSIONS, generatedActionPermissions, grants, isAllowed, parsePermission, permissionsOf, READ_VERB, rolesGranting, WILDCARD, } from "./permissions.js";
|
|
22
23
|
export type { ParsedPermission, PermissionHolder, RolePermissions } from "./permissions.js";
|
|
23
24
|
export { p, PROPERTY_TYPES, propertyDefinition } from "./property.js";
|
|
24
|
-
export type { AnyProperty, NumberOptions, Property, PropertyDefinition, PropertyOf, PropertyOptions, PropertyType, ReferenceOptions, SelectOption, SelectOptionInput, TextOptions, } from "./property.js";
|
|
25
|
+
export type { AnyProperty, NumberOptions, Property, PropertyDefinition, PropertyOf, PropertyOptions, BlobOptions, PropertyType, ReferenceOptions, SelectOption, SelectOptionInput, TextOptions, } from "./property.js";
|
|
25
26
|
export { ON_DELETE, rel } from "./relationship.js";
|
|
26
27
|
export type { AnyRelationship, EntityTarget, LazyEntity, ManyOptions, ManyRelationship, OnDelete, OneOptions, OneRelationship, Phrase, } from "./relationship.js";
|
|
27
28
|
export { renderCatalog } from "./render.js";
|
|
@@ -59,3 +60,5 @@ export { createOntologyService, ONTOLOGY_HASH_HEADER, REQUEST_ID_HEADER, } from
|
|
|
59
60
|
export type { OntologyService } from "./service/service.js";
|
|
60
61
|
export { applyMigration, CatalogInvalid, CatalogMismatch, isNoopMigration, migrate, MIGRATION_REFUSAL_CODES, MIGRATION_STEP_CLASSIFICATIONS, MIGRATION_STEP_KINDS, MigrationFailed, MigrationPlan, MigrationRefusal, MigrationRefused, MigrationStep, OntologyStorage, planMigration, readCatalog, } from "./migrate/index.js";
|
|
61
62
|
export type { ApplyMigrationError, ApplyMigrationOptions, CatalogInput, MigrateInput, MigrationOptions, MigrationRefusalCode, MigrationResult, MigrationStepClassification, MigrationStepKind, PlanMigrationInput, } from "./migrate/index.js";
|
|
63
|
+
export type { BlobStorageBinding } from "./storage/provider.js";
|
|
64
|
+
export { runBlobStorageMaintenance } from "./storage/operator.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { BlobValue, BlobUpload, uploads, BLOB_CONTENT_TYPES, MAX_BLOB_BYTES } from "./blob.js";
|
|
1
2
|
export { warehouse, compatibleWarehouseColumn, warehouseColumnType, validateWarehouseSource, } from "./source.js";
|
|
2
3
|
export { m } from "./measure.js";
|
|
3
4
|
export { action, isAction } from "./action.js";
|
|
@@ -35,3 +36,4 @@ export { NotInvited, OntologyBackend } from "./service/runtime-contract.js";
|
|
|
35
36
|
export { createOntologyService, ONTOLOGY_HASH_HEADER, REQUEST_ID_HEADER, } from "./service/service.js";
|
|
36
37
|
// Migrations: the planner, the applier and the physical mapping they share with the runtime.
|
|
37
38
|
export { applyMigration, CatalogInvalid, CatalogMismatch, isNoopMigration, migrate, MIGRATION_REFUSAL_CODES, MIGRATION_STEP_CLASSIFICATIONS, MIGRATION_STEP_KINDS, MigrationFailed, MigrationPlan, MigrationRefusal, MigrationRefused, MigrationStep, OntologyStorage, planMigration, readCatalog, } from "./migrate/index.js";
|
|
39
|
+
export { runBlobStorageMaintenance } from "./storage/operator.js";
|
package/dist/manifest.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare const PropertyManifest: Schema.Struct<{
|
|
|
21
21
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
22
22
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
23
23
|
readonly name: Schema.String;
|
|
24
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
24
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
25
25
|
readonly label: Schema.String;
|
|
26
26
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
27
27
|
readonly optional: Schema.Boolean;
|
|
@@ -33,6 +33,8 @@ export declare const PropertyManifest: Schema.Struct<{
|
|
|
33
33
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
34
34
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
35
35
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
36
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
37
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
36
38
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
37
39
|
readonly value: Schema.String;
|
|
38
40
|
readonly label: Schema.String;
|
|
@@ -126,7 +128,7 @@ export declare const EntityManifest: Schema.Struct<{
|
|
|
126
128
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
127
129
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
128
130
|
readonly name: Schema.String;
|
|
129
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
131
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
130
132
|
readonly label: Schema.String;
|
|
131
133
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
132
134
|
readonly optional: Schema.Boolean;
|
|
@@ -138,6 +140,8 @@ export declare const EntityManifest: Schema.Struct<{
|
|
|
138
140
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
139
141
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
140
142
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
143
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
144
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
141
145
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
142
146
|
readonly value: Schema.String;
|
|
143
147
|
readonly label: Schema.String;
|
|
@@ -227,7 +231,7 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
|
|
|
227
231
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
228
232
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
229
233
|
readonly name: Schema.String;
|
|
230
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
234
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
231
235
|
readonly label: Schema.String;
|
|
232
236
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
233
237
|
readonly optional: Schema.Boolean;
|
|
@@ -239,6 +243,8 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
|
|
|
239
243
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
240
244
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
241
245
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
246
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
247
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
242
248
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
243
249
|
readonly value: Schema.String;
|
|
244
250
|
readonly label: Schema.String;
|
|
@@ -247,6 +253,7 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
|
|
|
247
253
|
}>, {
|
|
248
254
|
readonly renamedFrom: "renamed_from";
|
|
249
255
|
readonly maxLength: "max_length";
|
|
256
|
+
readonly maxBytes: "max_bytes";
|
|
250
257
|
}>>;
|
|
251
258
|
readonly relationships: Schema.$Array<Schema.encodeKeys<Schema.Struct<{
|
|
252
259
|
readonly on: Schema.optionalKey<Schema.encodeKeys<Schema.Struct<{
|
|
@@ -359,7 +366,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
|
|
|
359
366
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
360
367
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
361
368
|
readonly name: Schema.String;
|
|
362
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
369
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
363
370
|
readonly label: Schema.String;
|
|
364
371
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
365
372
|
readonly optional: Schema.Boolean;
|
|
@@ -371,6 +378,8 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
|
|
|
371
378
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
372
379
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
373
380
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
381
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
382
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
374
383
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
375
384
|
readonly value: Schema.String;
|
|
376
385
|
readonly label: Schema.String;
|
|
@@ -379,6 +388,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
|
|
|
379
388
|
}>, {
|
|
380
389
|
readonly renamedFrom: "renamed_from";
|
|
381
390
|
readonly maxLength: "max_length";
|
|
391
|
+
readonly maxBytes: "max_bytes";
|
|
382
392
|
}>>;
|
|
383
393
|
readonly relationships: Schema.$Array<Schema.encodeKeys<Schema.Struct<{
|
|
384
394
|
readonly on: Schema.optionalKey<Schema.encodeKeys<Schema.Struct<{
|
|
@@ -514,7 +524,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
|
|
|
514
524
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
515
525
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
516
526
|
readonly name: Schema.String;
|
|
517
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
527
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
518
528
|
readonly label: Schema.String;
|
|
519
529
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
520
530
|
readonly optional: Schema.Boolean;
|
|
@@ -526,6 +536,8 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
|
|
|
526
536
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
527
537
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
528
538
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
539
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
540
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
529
541
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
530
542
|
readonly value: Schema.String;
|
|
531
543
|
readonly label: Schema.String;
|
|
@@ -623,7 +635,7 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
|
|
|
623
635
|
readonly optional: boolean;
|
|
624
636
|
readonly name: string;
|
|
625
637
|
readonly label: string;
|
|
626
|
-
readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json";
|
|
638
|
+
readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json" | "blob";
|
|
627
639
|
readonly unique: boolean;
|
|
628
640
|
readonly managed: boolean;
|
|
629
641
|
readonly column?: string | undefined;
|
|
@@ -640,6 +652,8 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
|
|
|
640
652
|
}[] | undefined;
|
|
641
653
|
readonly renamedFrom?: string | undefined;
|
|
642
654
|
readonly display?: string | undefined;
|
|
655
|
+
readonly accept?: readonly string[] | undefined;
|
|
656
|
+
readonly maxBytes?: number | undefined;
|
|
643
657
|
}[];
|
|
644
658
|
readonly relationships: readonly {
|
|
645
659
|
readonly name: string;
|
|
@@ -721,7 +735,7 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
|
|
|
721
735
|
readonly optional: boolean;
|
|
722
736
|
readonly name: string;
|
|
723
737
|
readonly label: string;
|
|
724
|
-
readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json";
|
|
738
|
+
readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json" | "blob";
|
|
725
739
|
readonly unique: boolean;
|
|
726
740
|
readonly managed: boolean;
|
|
727
741
|
readonly column?: string | undefined;
|
|
@@ -738,6 +752,8 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
|
|
|
738
752
|
}[] | undefined;
|
|
739
753
|
readonly renamedFrom?: string | undefined;
|
|
740
754
|
readonly display?: string | undefined;
|
|
755
|
+
readonly accept?: readonly string[] | undefined;
|
|
756
|
+
readonly maxBytes?: number | undefined;
|
|
741
757
|
}[];
|
|
742
758
|
readonly relationships: readonly {
|
|
743
759
|
readonly name: string;
|
package/dist/manifest.js
CHANGED
|
@@ -36,6 +36,8 @@ export const PropertyManifest = Schema.Struct({
|
|
|
36
36
|
min: Schema.optionalKey(Schema.Number),
|
|
37
37
|
max: Schema.optionalKey(Schema.Number),
|
|
38
38
|
maxLength: Schema.optionalKey(Schema.Number),
|
|
39
|
+
accept: Schema.optionalKey(Schema.Array(Schema.String)),
|
|
40
|
+
maxBytes: Schema.optionalKey(Schema.Number),
|
|
39
41
|
options: Schema.optionalKey(Schema.Array(SelectOptionManifest)),
|
|
40
42
|
});
|
|
41
43
|
/**
|
|
@@ -160,7 +162,11 @@ const OntologyManifestModel = Schema.Struct({
|
|
|
160
162
|
/** The connections the actions call. Written only when there are some; absent reads as none. */
|
|
161
163
|
connections: Schema.optionalKey(Schema.Array(ConnectionManifest)),
|
|
162
164
|
});
|
|
163
|
-
const PropertyManifestWire = PropertyManifest.pipe(Schema.encodeKeys({
|
|
165
|
+
const PropertyManifestWire = PropertyManifest.pipe(Schema.encodeKeys({
|
|
166
|
+
renamedFrom: "renamed_from",
|
|
167
|
+
maxLength: "max_length",
|
|
168
|
+
maxBytes: "max_bytes",
|
|
169
|
+
}));
|
|
164
170
|
const OnDeleteWire = Schema.Literals(["set_null", "cascade", "restrict"]).pipe(Schema.decodeTo(Schema.Literals(ON_DELETE), SchemaTransformation.transform({
|
|
165
171
|
decode: (value) => (value === "set_null" ? "setNull" : value),
|
|
166
172
|
encode: (value) => (value === "setNull" ? "set_null" : value),
|
|
@@ -265,6 +271,8 @@ function propertyManifest({ name, definition }) {
|
|
|
265
271
|
...(definition.min !== undefined ? { min: definition.min } : {}),
|
|
266
272
|
...(definition.max !== undefined ? { max: definition.max } : {}),
|
|
267
273
|
...(definition.maxLength !== undefined ? { maxLength: definition.maxLength } : {}),
|
|
274
|
+
...(definition.accept !== undefined ? { accept: definition.accept } : {}),
|
|
275
|
+
...(definition.maxBytes !== undefined ? { maxBytes: definition.maxBytes } : {}),
|
|
268
276
|
...(definition.options !== undefined
|
|
269
277
|
? {
|
|
270
278
|
options: definition.options.map((option) => ({
|
package/dist/migrate/model.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export declare const MigrationPlan: Schema.Struct<{
|
|
|
48
48
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
49
49
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
50
50
|
readonly name: Schema.String;
|
|
51
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
51
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
52
52
|
readonly label: Schema.String;
|
|
53
53
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
54
54
|
readonly optional: Schema.Boolean;
|
|
@@ -60,6 +60,8 @@ export declare const MigrationPlan: Schema.Struct<{
|
|
|
60
60
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
61
61
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
62
62
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
63
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
64
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
63
65
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
64
66
|
readonly value: Schema.String;
|
|
65
67
|
readonly label: Schema.String;
|
|
@@ -68,6 +70,7 @@ export declare const MigrationPlan: Schema.Struct<{
|
|
|
68
70
|
}>, {
|
|
69
71
|
readonly renamedFrom: "renamed_from";
|
|
70
72
|
readonly maxLength: "max_length";
|
|
73
|
+
readonly maxBytes: "max_bytes";
|
|
71
74
|
}>>;
|
|
72
75
|
readonly relationships: Schema.$Array<Schema.encodeKeys<Schema.Struct<{
|
|
73
76
|
readonly on: Schema.optionalKey<Schema.encodeKeys<Schema.Struct<{
|
|
@@ -182,7 +185,7 @@ export declare const MigrationPlan: Schema.Struct<{
|
|
|
182
185
|
readonly column: Schema.optionalKey<Schema.String>;
|
|
183
186
|
readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
184
187
|
readonly name: Schema.String;
|
|
185
|
-
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
|
|
188
|
+
readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
|
|
186
189
|
readonly label: Schema.String;
|
|
187
190
|
readonly description: Schema.optionalKey<Schema.String>;
|
|
188
191
|
readonly optional: Schema.Boolean;
|
|
@@ -194,6 +197,8 @@ export declare const MigrationPlan: Schema.Struct<{
|
|
|
194
197
|
readonly min: Schema.optionalKey<Schema.Number>;
|
|
195
198
|
readonly max: Schema.optionalKey<Schema.Number>;
|
|
196
199
|
readonly maxLength: Schema.optionalKey<Schema.Number>;
|
|
200
|
+
readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
201
|
+
readonly maxBytes: Schema.optionalKey<Schema.Number>;
|
|
197
202
|
readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
198
203
|
readonly value: Schema.String;
|
|
199
204
|
readonly label: Schema.String;
|
package/dist/migrate/plan.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { BLOB_TABLES_DDL } from "../storage/tables.js";
|
|
1
2
|
import { SNAKE_CASE_NAME, isSystemProperty, toSnakeCase } from "../names.js";
|
|
2
|
-
import { CATALOG_TABLE_DDL, MAX_IDENTIFIER_LENGTH, USER_TABLE, addConstraintStatement, columnDefinition, constraintDefinition, createEnumStatement, createIndexStatement, createTableStatement, defaultExpression, entityStorage, enumTypeName, fieldColumnName, joinTable, propertyCheck, propertyColumn, propertyEnum, quoteIdentifier, quoteLiteral, relationshipColumn, RUNTIME_TABLES_DDL, relationshipForeignKey, SYSTEM_COLUMNS, tableName, } from "./storage.js";
|
|
3
|
+
import { CATALOG_TABLE_DDL, MAX_IDENTIFIER_LENGTH, USER_TABLE, addConstraintStatement, columnDefinition, constraintDefinition, createEnumStatement, createIndexStatement, createTableStatement, defaultExpression, entityStorage, enumTypeName, fieldColumnName, joinTable, propertyCheck, blobForeignKey, propertyColumn, propertyEnum, quoteIdentifier, quoteLiteral, relationshipColumn, RUNTIME_TABLES_DDL, relationshipForeignKey, SYSTEM_COLUMNS, tableName, } from "./storage.js";
|
|
3
4
|
const GLOBAL_KINDS = new Set(["table", "type", "index"]);
|
|
4
5
|
function step(input) {
|
|
5
6
|
return {
|
|
@@ -72,6 +73,15 @@ export function planMigration(input) {
|
|
|
72
73
|
sql: RUNTIME_TABLES_DDL,
|
|
73
74
|
}));
|
|
74
75
|
}
|
|
76
|
+
if (storedTargets.some((entity) => entity.properties.some((property) => property.type === "blob")) &&
|
|
77
|
+
!current?.entities.some((entity) => entity.properties.some((property) => property.type === "blob"))) {
|
|
78
|
+
draft.runtimeTables.push(step({
|
|
79
|
+
kind: "createCatalog",
|
|
80
|
+
classification: "additive",
|
|
81
|
+
description: "Create the ontology's file revision and upload tables.",
|
|
82
|
+
sql: BLOB_TABLES_DDL,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
75
85
|
planDrops({ pairs, removedEntities, addedEntities, allowDrops, draft });
|
|
76
86
|
const renamed = planRenames({ pairs, draft });
|
|
77
87
|
const appliedNames = new Set(storageObjects(currentEntities)
|
|
@@ -573,6 +583,12 @@ function logicalRenames(pairs, refusals) {
|
|
|
573
583
|
path: `${pair.target.name}.properties.${to}`,
|
|
574
584
|
description: `Rename property ${pair.target.name}.${from} to ${to}.`,
|
|
575
585
|
apply: (model) => renameProperty(model, pair.target.id, from, to),
|
|
586
|
+
...(pair.current.properties.some((property) => property.name === from && property.type === "blob")
|
|
587
|
+
? {
|
|
588
|
+
metadataSql: ["_blobs", "_blob_uploads", "_blob_references"].map((table) => `UPDATE ${quoteIdentifier(table)} SET property_id = ${quoteLiteral(to)} ` +
|
|
589
|
+
`WHERE entity_id = ${quoteLiteral(pair.target.id)} AND property_id = ${quoteLiteral(from)}`),
|
|
590
|
+
}
|
|
591
|
+
: {}),
|
|
576
592
|
});
|
|
577
593
|
}
|
|
578
594
|
}
|
|
@@ -595,7 +611,7 @@ function planRenames(input) {
|
|
|
595
611
|
kind: rename.kind,
|
|
596
612
|
classification: "rename",
|
|
597
613
|
description: rename.description,
|
|
598
|
-
sql: statements,
|
|
614
|
+
sql: [...statements, ...(rename.metadataSql ?? [])],
|
|
599
615
|
}));
|
|
600
616
|
model = next;
|
|
601
617
|
}
|
|
@@ -893,6 +909,14 @@ function planEntityChanges(input) {
|
|
|
893
909
|
}
|
|
894
910
|
}
|
|
895
911
|
for (const property of pair.addedProperties) {
|
|
912
|
+
if (property.type === "blob") {
|
|
913
|
+
draft.foreignKeys.push(step({
|
|
914
|
+
kind: "addProperty",
|
|
915
|
+
classification: "additive",
|
|
916
|
+
description: `Reference the file revision for ${entity}.${property.name}.`,
|
|
917
|
+
sql: [addConstraintStatement(table, blobForeignKey(entity, property))],
|
|
918
|
+
}));
|
|
919
|
+
}
|
|
896
920
|
const enumStorage = propertyEnum(entity, property);
|
|
897
921
|
const check = propertyCheck(entity, property);
|
|
898
922
|
const column = propertyColumn(entity, property);
|
|
@@ -30,6 +30,7 @@ export declare const COLUMN_TYPES: {
|
|
|
30
30
|
readonly date: "date";
|
|
31
31
|
readonly timestamp: "timestamptz";
|
|
32
32
|
readonly json: "jsonb";
|
|
33
|
+
readonly blob: "uuid";
|
|
33
34
|
};
|
|
34
35
|
export interface ColumnStorage {
|
|
35
36
|
readonly name: string;
|
|
@@ -130,6 +131,7 @@ export declare function checkExpression(property: PropertyManifest): string | un
|
|
|
130
131
|
export declare function propertyColumn(entity: string, property: PropertyManifest): ColumnStorage;
|
|
131
132
|
export declare function propertyCheck(entity: string, property: PropertyManifest): ConstraintStorage | undefined;
|
|
132
133
|
export declare function propertyEnum(entity: string, property: PropertyManifest): EnumStorage | undefined;
|
|
134
|
+
export declare function blobForeignKey(entity: string, property: PropertyManifest): ConstraintStorage;
|
|
133
135
|
/** The key column of a `rel.one`. */
|
|
134
136
|
export declare function relationshipColumn(relationship: RelationshipManifest): ColumnStorage;
|
|
135
137
|
/** The foreign key of a `rel.one`, with its `onDelete` action. */
|
package/dist/migrate/storage.js
CHANGED
|
@@ -29,6 +29,7 @@ export const COLUMN_TYPES = {
|
|
|
29
29
|
date: "date",
|
|
30
30
|
timestamp: "timestamptz",
|
|
31
31
|
json: "jsonb",
|
|
32
|
+
blob: "uuid",
|
|
32
33
|
};
|
|
33
34
|
const ON_DELETE_ACTIONS = {
|
|
34
35
|
setNull: "SET NULL",
|
|
@@ -198,6 +199,15 @@ function foreignKeyDefinition(input) {
|
|
|
198
199
|
`REFERENCES ${quoteIdentifier(input.references)} (${quoteIdentifier(SYSTEM_COLUMNS.id)})`;
|
|
199
200
|
return input.onDelete === undefined ? reference : `${reference} ON DELETE ${input.onDelete}`;
|
|
200
201
|
}
|
|
202
|
+
export function blobForeignKey(entity, property) {
|
|
203
|
+
const column = columnName(property.name);
|
|
204
|
+
return {
|
|
205
|
+
name: foreignKeyName(entity, column),
|
|
206
|
+
kind: "foreignKey",
|
|
207
|
+
definition: foreignKeyDefinition({ column, references: "_blobs" }),
|
|
208
|
+
references: "_blobs",
|
|
209
|
+
};
|
|
210
|
+
}
|
|
201
211
|
function userReference(table, column) {
|
|
202
212
|
return {
|
|
203
213
|
name: foreignKeyName(table, column),
|
|
@@ -389,6 +399,9 @@ export function entityStorage(entity) {
|
|
|
389
399
|
userReference(table, SYSTEM_COLUMNS.created_by),
|
|
390
400
|
userReference(table, SYSTEM_COLUMNS.updated_by),
|
|
391
401
|
...checks,
|
|
402
|
+
...entity.properties
|
|
403
|
+
.filter((property) => property.type === "blob")
|
|
404
|
+
.map((property) => blobForeignKey(entity.name, property)),
|
|
392
405
|
...ones.map((relationship) => relationshipForeignKey(entity.name, relationship)),
|
|
393
406
|
],
|
|
394
407
|
indexes: entityIndexes(entity),
|
package/dist/property.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
+
import { BlobValue, type BLOB_CONTENT_TYPES } from "./blob.js";
|
|
2
3
|
/** The closed set of storage types. Each has a known column, JSON Schema, filters and rendering. */
|
|
3
|
-
export declare const PROPERTY_TYPES: readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"];
|
|
4
|
+
export declare const PROPERTY_TYPES: readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"];
|
|
4
5
|
export type PropertyType = (typeof PROPERTY_TYPES)[number];
|
|
5
6
|
/** Schema annotation that carries a property's storage metadata. */
|
|
6
7
|
export declare const PROPERTY_ANNOTATION = "segmentstream/ontology/property";
|
|
@@ -40,6 +41,8 @@ export interface PropertyDefinition {
|
|
|
40
41
|
readonly max?: number;
|
|
41
42
|
readonly maxLength?: number;
|
|
42
43
|
readonly options?: ReadonlyArray<SelectOption>;
|
|
44
|
+
readonly accept?: ReadonlyArray<string>;
|
|
45
|
+
readonly maxBytes?: number;
|
|
43
46
|
}
|
|
44
47
|
/**
|
|
45
48
|
* A property: an Effect Schema of its value, usable in action inputs, with its storage metadata in
|
|
@@ -127,6 +130,11 @@ declare function ref<const O extends ReferenceOptions>(target: string | {
|
|
|
127
130
|
readonly name: string;
|
|
128
131
|
}, options?: O): ReferenceOf<O>;
|
|
129
132
|
/** Property constructors. */
|
|
133
|
+
export interface BlobOptions extends Omit<PropertyOptions<BlobValue>, "default" | "unique"> {
|
|
134
|
+
readonly accept: ReadonlyArray<(typeof BLOB_CONTENT_TYPES)[number]>;
|
|
135
|
+
readonly maxBytes?: number;
|
|
136
|
+
}
|
|
137
|
+
declare function blob<const O extends BlobOptions>(options: O): PropertyOf<BlobValue, O>;
|
|
130
138
|
export declare const p: {
|
|
131
139
|
readonly text: typeof text;
|
|
132
140
|
readonly email: typeof email;
|
|
@@ -138,6 +146,7 @@ export declare const p: {
|
|
|
138
146
|
readonly timestamp: typeof timestamp;
|
|
139
147
|
readonly select: typeof select;
|
|
140
148
|
readonly json: typeof json;
|
|
149
|
+
readonly blob: typeof blob;
|
|
141
150
|
readonly ref: typeof ref;
|
|
142
151
|
};
|
|
143
152
|
/** The storage metadata of a schema built with a `p.*` constructor, or `undefined` for any other value. */
|
package/dist/property.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { humanize } from "./names.js";
|
|
3
|
+
import { BlobValue, MAX_BLOB_BYTES } from "./blob.js";
|
|
3
4
|
import { nameToWire } from "./authoring-names.js";
|
|
4
5
|
/** The closed set of storage types. Each has a known column, JSON Schema, filters and rendering. */
|
|
5
6
|
export const PROPERTY_TYPES = [
|
|
@@ -13,6 +14,7 @@ export const PROPERTY_TYPES = [
|
|
|
13
14
|
"timestamp",
|
|
14
15
|
"select",
|
|
15
16
|
"json",
|
|
17
|
+
"blob",
|
|
16
18
|
];
|
|
17
19
|
/** Schema annotation that carries a property's storage metadata. */
|
|
18
20
|
export const PROPERTY_ANNOTATION = "segmentstream/ontology/property";
|
|
@@ -47,6 +49,8 @@ function construct({ type, base, options, checks = [], format, selectOptions, })
|
|
|
47
49
|
...(options.min !== undefined ? { min: options.min } : {}),
|
|
48
50
|
...(options.max !== undefined ? { max: options.max } : {}),
|
|
49
51
|
...(options.maxLength !== undefined ? { maxLength: options.maxLength } : {}),
|
|
52
|
+
...(options.accept !== undefined ? { accept: options.accept } : {}),
|
|
53
|
+
...(options.maxBytes !== undefined ? { maxBytes: options.maxBytes } : {}),
|
|
50
54
|
...(selectOptions !== undefined ? { options: selectOptions } : {}),
|
|
51
55
|
};
|
|
52
56
|
// Annotations go on the base node, before the checks, so that the JSON Schema keeps them at the top
|
|
@@ -176,7 +180,13 @@ function ref(target, options) {
|
|
|
176
180
|
}).check(Schema.isPattern(UUID));
|
|
177
181
|
return (settings.optional === true ? Schema.optionalKey(schema) : schema);
|
|
178
182
|
}
|
|
179
|
-
|
|
183
|
+
function blob(options) {
|
|
184
|
+
return construct({
|
|
185
|
+
type: "blob",
|
|
186
|
+
base: BlobValue,
|
|
187
|
+
options: { ...options, maxBytes: options.maxBytes ?? MAX_BLOB_BYTES },
|
|
188
|
+
});
|
|
189
|
+
}
|
|
180
190
|
export const p = {
|
|
181
191
|
text,
|
|
182
192
|
email,
|
|
@@ -188,6 +198,7 @@ export const p = {
|
|
|
188
198
|
timestamp,
|
|
189
199
|
select,
|
|
190
200
|
json,
|
|
201
|
+
blob,
|
|
191
202
|
ref,
|
|
192
203
|
};
|
|
193
204
|
function findAnnotation(ast, key) {
|
package/dist/query.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { wireStruct } from "./wire.js";
|
|
3
|
+
import { BlobValue } from "./blob.js";
|
|
3
4
|
/**
|
|
4
5
|
* The query language of `find` and of the HTTP API's list and query endpoints.
|
|
5
6
|
*
|
|
@@ -194,12 +195,13 @@ export function fieldValueSchema(field) {
|
|
|
194
195
|
case "json":
|
|
195
196
|
return JsonValue;
|
|
196
197
|
case "uuid":
|
|
198
|
+
case "blob":
|
|
197
199
|
return UuidValue;
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
202
|
/** Fields a query can sort on: every field but `json` properties. */
|
|
201
203
|
export function isOrderable(field) {
|
|
202
|
-
return field.storage !== "json";
|
|
204
|
+
return field.storage !== "json" && field.storage !== "blob";
|
|
203
205
|
}
|
|
204
206
|
const FILTER_IDENTIFIERS = {
|
|
205
207
|
text: "TextFilter",
|
|
@@ -212,6 +214,7 @@ const FILTER_IDENTIFIERS = {
|
|
|
212
214
|
timestamp: "TimestampFilter",
|
|
213
215
|
json: "JsonFilter",
|
|
214
216
|
uuid: "IdFilter",
|
|
217
|
+
blob: "IdFilter",
|
|
215
218
|
};
|
|
216
219
|
const FILTER_DESCRIPTIONS = {
|
|
217
220
|
TextFilter: "contains and startsWith ignore case.",
|
|
@@ -413,6 +416,8 @@ function recordValueSchema(field) {
|
|
|
413
416
|
return Schema.Literals(field.options ?? []);
|
|
414
417
|
case "json":
|
|
415
418
|
return Schema.Json;
|
|
419
|
+
case "blob":
|
|
420
|
+
return BlobValue;
|
|
416
421
|
default:
|
|
417
422
|
return Schema.String;
|
|
418
423
|
}
|