@superpanel-sdk/runtime 0.2.3 → 0.7.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/README.md +30 -10
- package/dist/builder/codegen/emit.d.ts +25 -12
- package/dist/builder/codegen/emit.js +339 -78
- package/dist/builder/codegen/generate.d.ts +21 -2
- package/dist/builder/codegen/generate.js +147 -34
- package/dist/builder/company-import-graph.d.ts +2 -0
- package/dist/builder/company-import-graph.js +40 -8
- package/dist/builder/company-imports.d.ts +29 -0
- package/dist/builder/company-imports.js +122 -0
- package/dist/builder/compile/compile-sequence.d.ts +61 -8
- package/dist/builder/compile/compile-sequence.js +334 -80
- package/dist/builder/compile/function-code.d.ts +19 -3
- package/dist/builder/compile/function-code.js +123 -45
- package/dist/builder/compile/registry.d.ts +7 -3
- package/dist/builder/compile/registry.js +30 -27
- package/dist/builder/errors.d.ts +9 -0
- package/dist/builder/errors.js +17 -0
- package/dist/builder/function-params.d.ts +10 -0
- package/dist/builder/function-params.js +203 -0
- package/dist/builder/load.d.ts +70 -10
- package/dist/builder/load.js +258 -67
- package/dist/builder/paths.d.ts +9 -1
- package/dist/builder/paths.js +32 -2
- package/dist/builder/schedules.d.ts +25 -0
- package/dist/builder/schedules.js +101 -0
- package/dist/builder/slot-schema-validation.d.ts +4 -0
- package/dist/builder/slot-schema-validation.js +10 -0
- package/dist/builder/typecheck.d.ts +8 -0
- package/dist/builder/typecheck.js +102 -0
- package/dist/builder/types.d.ts +127 -19
- package/dist/builder/types.js +21 -1
- package/dist/cli/auth/auth.d.ts +37 -0
- package/dist/cli/auth/auth.js +211 -0
- package/dist/cli/auth/backend-url.d.ts +5 -0
- package/dist/cli/auth/backend-url.js +25 -0
- package/dist/cli/auth/clipboard.d.ts +9 -0
- package/dist/cli/auth/clipboard.js +38 -0
- package/dist/cli/auth/http.d.ts +20 -0
- package/dist/cli/auth/http.js +27 -0
- package/dist/cli/auth/index.d.ts +10 -0
- package/dist/cli/auth/index.js +27 -0
- package/dist/cli/auth/progress.d.ts +12 -0
- package/dist/cli/auth/progress.js +15 -0
- package/dist/cli/auth/serve-login.d.ts +8 -0
- package/dist/cli/auth/serve-login.js +24 -0
- package/dist/cli/calls/index.d.ts +177 -0
- package/dist/cli/calls/index.js +96 -0
- package/dist/cli/compile/index.js +3 -0
- package/dist/cli/config.d.ts +10 -0
- package/dist/cli/config.js +52 -0
- package/dist/cli/debug/index.d.ts +31 -0
- package/dist/cli/debug/index.js +119 -0
- package/dist/cli/exec/index.d.ts +39 -0
- package/dist/cli/exec/index.js +138 -0
- package/dist/cli/exec/session.d.ts +48 -0
- package/dist/cli/exec/session.js +82 -0
- package/dist/cli/exec/trace.d.ts +18 -0
- package/dist/cli/exec/trace.js +52 -0
- package/dist/cli/index.js +112 -9
- package/dist/cli/logs/index.d.ts +47 -0
- package/dist/cli/logs/index.js +113 -0
- package/dist/cli/mobile/index.d.ts +12 -0
- package/dist/cli/mobile/index.js +405 -0
- package/dist/cli/serve/index.d.ts +109 -3
- package/dist/cli/serve/index.js +506 -118
- package/dist/cli/turns/index.d.ts +105 -0
- package/dist/cli/turns/index.js +128 -0
- package/dist/cli/turns/run.d.ts +13 -0
- package/dist/cli/turns/run.js +57 -0
- package/dist/cli/turns/shadow.d.ts +112 -0
- package/dist/cli/turns/shadow.js +54 -0
- package/dist/cli/type-gen/index.js +9 -9
- package/dist/compiler.d.ts +7 -0
- package/dist/compiler.js +7 -0
- package/dist/compute-host/compute-host.d.ts +14 -23
- package/dist/compute-host/compute-host.js +18 -30
- package/dist/compute-host/index.d.ts +2 -4
- package/dist/compute-host/index.js +1 -2
- package/dist/compute-host/source-compute-host.d.ts +10 -10
- package/dist/compute-host/source-compute-host.js +33 -40
- package/dist/core/case-orchestrator/contact-hours.d.ts +70 -0
- package/dist/core/case-orchestrator/contact-hours.js +127 -0
- package/dist/core/case-orchestrator/index.d.ts +3 -0
- package/dist/core/case-orchestrator/index.js +3 -0
- package/dist/core/case-orchestrator/render.d.ts +75 -0
- package/dist/core/case-orchestrator/render.js +244 -0
- package/dist/core/case-orchestrator/time.d.ts +11 -0
- package/dist/core/case-orchestrator/time.js +29 -0
- package/dist/core/case-orchestrator/types.d.ts +708 -0
- package/dist/core/case-orchestrator/types.js +42 -0
- package/dist/core/context/call.d.ts +291 -0
- package/dist/core/context/call.js +94 -0
- package/dist/core/context/channels.d.ts +60 -0
- package/dist/core/context/channels.js +35 -0
- package/dist/core/context/contact.d.ts +96 -6
- package/dist/core/context/contact.js +48 -2
- package/dist/core/context/email-message.d.ts +198 -0
- package/dist/core/context/email-message.js +86 -0
- package/dist/core/context/email.d.ts +109 -0
- package/dist/core/context/email.js +90 -0
- package/dist/core/context/exchanges.d.ts +167 -0
- package/dist/core/context/exchanges.js +81 -0
- package/dist/core/context/instances.d.ts +307 -0
- package/dist/core/context/instances.js +137 -0
- package/dist/core/context/kv.d.ts +113 -0
- package/dist/core/context/kv.js +60 -0
- package/dist/core/context/platform-registry.d.ts +544 -4
- package/dist/core/context/platform-registry.js +14 -2
- package/dist/core/context/platform.d.ts +2 -1
- package/dist/core/context/sms.d.ts +177 -0
- package/dist/core/context/sms.js +77 -0
- package/dist/core/context/types.d.ts +79 -48
- package/dist/core/context/types.js +1 -7
- package/dist/core/conversation/index.d.ts +85 -0
- package/dist/core/conversation/index.js +133 -0
- package/dist/core/functions/errors.d.ts +74 -0
- package/dist/core/functions/errors.js +26 -0
- package/dist/core/functions/events.d.ts +192 -0
- package/dist/core/functions/events.js +23 -0
- package/dist/core/functions/schedules.d.ts +50 -0
- package/dist/core/functions/schedules.js +20 -0
- package/dist/core/functions/types.d.ts +29 -73
- package/dist/core/functions/types.js +1 -4
- package/dist/core/office-hours/index.d.ts +39 -0
- package/dist/core/office-hours/index.js +187 -0
- package/dist/core/page/define.d.ts +904 -0
- package/dist/core/page/define.js +518 -0
- package/dist/core/page/envelope.d.ts +55 -0
- package/dist/core/page/envelope.js +4 -0
- package/dist/core/page/fns.d.ts +448 -0
- package/dist/core/page/fns.js +539 -0
- package/dist/core/page/memory-reader.d.ts +27 -0
- package/dist/core/page/memory-reader.js +299 -0
- package/dist/core/page/ops.d.ts +58 -0
- package/dist/core/page/ops.js +220 -0
- package/dist/core/page/page-host.d.ts +20 -0
- package/dist/core/page/page-host.js +57 -0
- package/dist/core/page/records-query.d.ts +234 -0
- package/dist/core/page/records-query.js +780 -0
- package/dist/core/page/render.d.ts +295 -0
- package/dist/core/page/render.js +1060 -0
- package/dist/core/page/sandbox.d.ts +85 -0
- package/dist/core/page/sandbox.js +357 -0
- package/dist/core/page/time-format.d.ts +46 -0
- package/dist/core/page/time-format.js +125 -0
- package/dist/core/page/timeline.d.ts +40 -0
- package/dist/core/page/timeline.js +2 -0
- package/dist/core/page/typed.d.ts +648 -0
- package/dist/core/page/typed.js +2 -0
- package/dist/core/page/workspace.d.ts +57 -0
- package/dist/core/page/workspace.js +266 -0
- package/dist/core/party/index.d.ts +3 -0
- package/dist/core/party/index.js +3 -0
- package/dist/core/party/schema.d.ts +208 -0
- package/dist/core/party/schema.js +113 -0
- package/dist/core/party/types.d.ts +35 -0
- package/dist/core/party/types.js +15 -0
- package/dist/core/sequence/define.d.ts +56 -0
- package/dist/core/sequence/define.js +10 -0
- package/dist/core/sequence/index.d.ts +63 -0
- package/dist/core/sequence/index.js +231 -0
- package/dist/core/slot/binding.d.ts +40 -0
- package/dist/core/slot/binding.js +2 -0
- package/dist/core/slot/company-metadata.d.ts +102 -0
- package/dist/core/slot/company-metadata.js +536 -0
- package/dist/core/slot/compile-schema.d.ts +19 -13
- package/dist/core/slot/compile-schema.js +51 -248
- package/dist/core/slot/contact-timezone.d.ts +110 -0
- package/dist/core/slot/contact-timezone.js +186 -0
- package/dist/core/slot/field.d.ts +2 -25
- package/dist/core/slot/field.js +0 -71
- package/dist/core/slot/id-ref.d.ts +17 -2
- package/dist/core/slot/id-ref.js +16 -8
- package/dist/core/slot/index.d.ts +12 -13
- package/dist/core/slot/index.js +11 -12
- package/dist/core/slot/naming.d.ts +15 -0
- package/dist/core/slot/naming.js +96 -0
- package/dist/core/slot/platform-fields.d.ts +119 -0
- package/dist/core/slot/platform-fields.js +121 -0
- package/dist/core/slot/ref.d.ts +16 -0
- package/dist/core/slot/ref.js +14 -0
- package/dist/core/slot/row.d.ts +2 -9
- package/dist/core/slot/row.js +13 -23
- package/dist/core/slot/schema-compat.d.ts +17 -0
- package/dist/core/slot/schema-compat.js +103 -0
- package/dist/core/slot/schema.d.ts +353 -76
- package/dist/core/slot/schema.js +163 -10
- package/dist/core/slot/types.d.ts +30 -103
- package/dist/core/slot/value.d.ts +28 -3
- package/dist/core/slot/value.js +93 -57
- package/dist/dev-overlay/protocol.d.ts +74 -8
- package/dist/fn-context/build-context.d.ts +3 -1
- package/dist/fn-context/build-context.js +26 -10
- package/dist/fn-context/fake/empty-api.js +9 -28
- package/dist/fn-context/fake/index.d.ts +13 -4
- package/dist/fn-context/fake/index.js +29 -2
- package/dist/fn-context/fn-params.d.ts +3 -0
- package/dist/fn-context/fn-params.js +10 -0
- package/dist/fn-context/index.d.ts +5 -5
- package/dist/fn-context/index.js +4 -4
- package/dist/fn-context/log.js +2 -2
- package/dist/fn-context/make-ctx.d.ts +11 -0
- package/dist/fn-context/make-ctx.js +20 -9
- package/dist/fn-context/rpc/case-orchestrator-tools.d.ts +32 -0
- package/dist/fn-context/rpc/case-orchestrator-tools.js +12 -0
- package/dist/fn-context/rpc/errors.d.ts +13 -0
- package/dist/fn-context/rpc/errors.js +22 -0
- package/dist/fn-context/rpc/index.d.ts +4 -2
- package/dist/fn-context/rpc/index.js +4 -2
- package/dist/fn-context/rpc/integration/index.d.ts +15 -5
- package/dist/fn-context/rpc/integration/index.js +1 -1
- package/dist/fn-context/rpc/integration/list-surfaces.d.ts +21 -0
- package/dist/fn-context/rpc/integration/{list-bindings.js → list-surfaces.js} +4 -4
- package/dist/fn-context/rpc/log.d.ts +11 -1
- package/dist/fn-context/rpc/platform.d.ts +13 -3
- package/dist/fn-context/rpc/platform.js +1 -1
- package/dist/fn-context/rpc/records.d.ts +85 -0
- package/dist/fn-context/rpc/records.js +24 -0
- package/dist/fn-context/rpc/trpc-client.d.ts +44 -2
- package/dist/fn-context/rpc/trpc-client.js +222 -12
- package/dist/fn-context/rpc/trpc-init.d.ts +21 -3
- package/dist/fn-context/rpc/trpc-init.js +10 -4
- package/dist/fn-context/rpc/trpc-router-factory.d.ts +111 -7
- package/dist/fn-context/rpc/trpc-router-factory.js +2 -0
- package/dist/fn-context/run-scope.d.ts +4 -0
- package/dist/fn-context/run-scope.js +9 -0
- package/dist/fn-context/types.d.ts +52 -5
- package/dist/index.d.ts +36 -46
- package/dist/index.js +30 -33
- package/dist/logger.d.ts +11 -0
- package/dist/logger.js +49 -0
- package/dist/platform.d.ts +75 -0
- package/dist/platform.js +57 -0
- package/dist/testing-compile-child.d.ts +2 -0
- package/dist/testing-compile-child.js +20 -0
- package/dist/testing.d.ts +368 -0
- package/dist/testing.js +439 -0
- package/dist/voice-service/actions.d.ts +50 -6
- package/dist/voice-service/index.d.ts +2 -0
- package/dist/voice-service/index.js +2 -0
- package/dist/voice-service/protocol.d.ts +604 -0
- package/dist/voice-service/protocol.js +67 -0
- package/dist/voice-service/types.d.ts +55 -8
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +11 -0
- package/package.json +38 -15
- package/dist/builder/compile/compile-agenda.d.ts +0 -15
- package/dist/builder/compile/compile-agenda.js +0 -64
- package/dist/builder/merge.d.ts +0 -4
- package/dist/builder/merge.js +0 -19
- package/dist/compute-host/read-only-cache.d.ts +0 -20
- package/dist/compute-host/read-only-cache.js +0 -61
- package/dist/core/context/db.d.ts +0 -69
- package/dist/core/context/db.js +0 -44
- package/dist/core/context/docusign.d.ts +0 -134
- package/dist/core/context/docusign.js +0 -108
- package/dist/core/context/filevine.d.ts +0 -323
- package/dist/core/context/filevine.js +0 -254
- package/dist/core/context/http.d.ts +0 -9
- package/dist/core/context/http.js +0 -4
- package/dist/core/context/hubspot.d.ts +0 -250
- package/dist/core/context/hubspot.js +0 -191
- package/dist/core/context/twilio.d.ts +0 -50
- package/dist/core/context/twilio.js +0 -42
- package/dist/core/functions/define/case-context.d.ts +0 -14
- package/dist/core/functions/define/case-context.js +0 -15
- package/dist/core/functions/define/compute.d.ts +0 -7
- package/dist/core/functions/define/compute.js +0 -17
- package/dist/core/functions/define/custom.d.ts +0 -4
- package/dist/core/functions/define/custom.js +0 -8
- package/dist/core/functions/define/system.d.ts +0 -7
- package/dist/core/functions/define/system.js +0 -12
- package/dist/core/functions/func-ref.d.ts +0 -16
- package/dist/core/functions/func-ref.js +0 -20
- package/dist/core/slot/deps.d.ts +0 -15
- package/dist/core/slot/deps.js +0 -88
- package/dist/core/slot/derived.d.ts +0 -32
- package/dist/core/slot/derived.js +0 -115
- package/dist/core/slot/platform-session-fields.d.ts +0 -38
- package/dist/core/slot/platform-session-fields.js +0 -48
- package/dist/core/slot/sf-schema.d.ts +0 -23
- package/dist/core/slot/sf-schema.js +0 -125
- package/dist/core/slot/sf-validate.d.ts +0 -14
- package/dist/core/slot/sf-validate.js +0 -132
- package/dist/core/slot/snapshot.d.ts +0 -18
- package/dist/core/slot/snapshot.js +0 -138
- package/dist/core/slot/write.d.ts +0 -48
- package/dist/core/slot/write.js +0 -426
- package/dist/core/stage/builders.d.ts +0 -54
- package/dist/core/stage/builders.js +0 -31
- package/dist/core/stage/condition.d.ts +0 -17
- package/dist/core/stage/condition.js +0 -198
- package/dist/core/stage/drive.d.ts +0 -43
- package/dist/core/stage/drive.js +0 -78
- package/dist/core/stage/finish-when.d.ts +0 -20
- package/dist/core/stage/finish-when.js +0 -82
- package/dist/core/stage/flatten.d.ts +0 -27
- package/dist/core/stage/flatten.js +0 -466
- package/dist/core/stage/index.d.ts +0 -15
- package/dist/core/stage/index.js +0 -13
- package/dist/core/stage/interrupts.d.ts +0 -28
- package/dist/core/stage/interrupts.js +0 -120
- package/dist/core/stage/ivr-fields.d.ts +0 -9
- package/dist/core/stage/ivr-fields.js +0 -75
- package/dist/core/stage/simulate.d.ts +0 -24
- package/dist/core/stage/simulate.js +0 -33
- package/dist/core/stage/transfer-fields.d.ts +0 -19
- package/dist/core/stage/transfer-fields.js +0 -129
- package/dist/core/stage/transfer-spec.d.ts +0 -48
- package/dist/core/stage/transfer-spec.js +0 -113
- package/dist/core/stage/types.d.ts +0 -208
- package/dist/core/stage/types.js +0 -2
- package/dist/core/stage/validate.d.ts +0 -11
- package/dist/core/stage/validate.js +0 -330
- package/dist/core/stage/walk.d.ts +0 -39
- package/dist/core/stage/walk.js +0 -119
- package/dist/fn-context/rpc/integration/list-bindings.d.ts +0 -21
- package/dist/fn-context/system-args.d.ts +0 -6
- package/dist/fn-context/system-args.js +0 -14
package/dist/core/slot/schema.js
CHANGED
|
@@ -1,17 +1,170 @@
|
|
|
1
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const SCALAR_DATA_TYPES = [
|
|
3
|
+
'string',
|
|
4
|
+
'text',
|
|
5
|
+
'phone',
|
|
6
|
+
'email',
|
|
7
|
+
'number',
|
|
8
|
+
'boolean',
|
|
9
|
+
'date',
|
|
10
|
+
'datetime',
|
|
11
|
+
'time',
|
|
12
|
+
'select',
|
|
13
|
+
'multi_select',
|
|
14
|
+
];
|
|
15
|
+
/** The types that take `options` (27 §2–§3). */
|
|
16
|
+
export const OPTION_DATA_TYPES = new Set(['select', 'multi_select']);
|
|
17
|
+
const dataTypeSchema = z.enum([...SCALAR_DATA_TYPES, 'contact_schedule']);
|
|
18
|
+
/** Field keys derived fields used; they were removed (13-data-model-v1 §21) and are reported when found. */
|
|
19
|
+
export const REMOVED_DERIVED_KEYS = ['derived', 'dependsOn', 'computeFn'];
|
|
20
|
+
/** A field's `source`, removed (19-page-writable-cells): a page decides what the AI may write. */
|
|
21
|
+
export const REMOVED_SOURCE_KEY = 'source';
|
|
22
|
+
/**
|
|
23
|
+
* A field's `nullable`, removed: no write ever checked it. Every field starts empty and can be
|
|
24
|
+
* cleared; a page's `required` says when one must be filled, and the platform keeps a row's id and
|
|
25
|
+
* parent itself.
|
|
26
|
+
*/
|
|
27
|
+
export const REMOVED_NULLABLE_KEY = 'nullable';
|
|
28
|
+
/**
|
|
29
|
+
* A field's `enum`, removed (27 §2): a field of a known set of values is a `select` (or `multi_select`)
|
|
30
|
+
* with `options`.
|
|
31
|
+
*/
|
|
32
|
+
export const REMOVED_ENUM_KEY = 'enum';
|
|
33
|
+
/**
|
|
34
|
+
* A field's `identifier`, removed: nothing found a contact by it. Who a conversation is with is the
|
|
35
|
+
* repo's `resolve` to decide; `ctx.api.contact.find` and clearing a contact use `phone` and `email`.
|
|
36
|
+
*/
|
|
37
|
+
export const REMOVED_IDENTIFIER_KEY = 'identifier';
|
|
38
|
+
/** Every row's id: the platform's, on every table; a schema does not write it. */
|
|
2
39
|
export const ROW_ID_FIELD = 'id';
|
|
40
|
+
/**
|
|
41
|
+
* What every row has besides its fields, the platform's (never a field of a schema): its `id`, when
|
|
42
|
+
* it was created and when it was last written (ISO 8601). A read can filter and order by them.
|
|
43
|
+
*/
|
|
44
|
+
export const ROW_SYSTEM_KEYS = ['id', 'createdAt', 'updatedAt'];
|
|
45
|
+
/** The row's times: `createdAt`, `updatedAt`. */
|
|
46
|
+
export const ROW_TIME_KEYS = ['createdAt', 'updatedAt'];
|
|
47
|
+
export function isRowTimeKey(key) {
|
|
48
|
+
return ROW_TIME_KEYS.includes(key);
|
|
49
|
+
}
|
|
50
|
+
/** The definition of every row's `id` (added by the platform to every table and the session). */
|
|
3
51
|
export const idFieldCore = {
|
|
4
|
-
derived: false,
|
|
5
52
|
label: 'Id',
|
|
6
53
|
dataType: 'string',
|
|
7
|
-
source: 'system',
|
|
8
54
|
extraction: 'Row identity',
|
|
9
|
-
enum: null,
|
|
10
|
-
nullable: false,
|
|
11
|
-
};
|
|
12
|
-
/** Unified row id. Write `id: idField` on every table. */
|
|
13
|
-
export const idField = {
|
|
14
|
-
...idFieldCore,
|
|
15
|
-
identifier: null,
|
|
16
55
|
};
|
|
56
|
+
export const normalFieldCoreSchema = z
|
|
57
|
+
.object({
|
|
58
|
+
label: z.string(),
|
|
59
|
+
dataType: dataTypeSchema,
|
|
60
|
+
extraction: z.string(),
|
|
61
|
+
options: z.array(z.string()).optional(),
|
|
62
|
+
})
|
|
63
|
+
.strict();
|
|
64
|
+
export const tableRefSchema = z
|
|
65
|
+
.object({
|
|
66
|
+
table: z.string().min(1),
|
|
67
|
+
kind: z.enum(['parent', 'lookup']),
|
|
68
|
+
relatedName: z.string().optional(),
|
|
69
|
+
})
|
|
70
|
+
.strict();
|
|
71
|
+
export const companyNormalFieldDefSchema = normalFieldCoreSchema
|
|
72
|
+
.extend({
|
|
73
|
+
ref: tableRefSchema.optional(),
|
|
74
|
+
unique: z.literal(true).optional(),
|
|
75
|
+
deprecated: z.boolean().optional(),
|
|
76
|
+
})
|
|
77
|
+
.strict();
|
|
78
|
+
const localTime = /^(?:[01]\d|2[0-3]):[0-5]\d$/;
|
|
79
|
+
const localEndTime = /^(?:(?:[01]\d|2[0-3]):[0-5]\d|24:00)$/;
|
|
80
|
+
const localDate = /^\d{4}-\d{2}-\d{2}$/;
|
|
81
|
+
export const localTimeRangeSchema = z
|
|
82
|
+
.object({ start: z.string().regex(localTime), end: z.string().regex(localEndTime) })
|
|
83
|
+
.strict()
|
|
84
|
+
.refine((range) => range.start < range.end, { message: 'start must be before end' });
|
|
85
|
+
export const weekdaySchema = z.enum(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);
|
|
86
|
+
function validateWindows(windows, ctx) {
|
|
87
|
+
for (let index = 1; index < windows.length; index += 1) {
|
|
88
|
+
const previous = windows[index - 1];
|
|
89
|
+
const current = windows[index];
|
|
90
|
+
if (current.start < previous.start) {
|
|
91
|
+
ctx.addIssue({ code: 'custom', path: [index], message: 'windows must be sorted by start time' });
|
|
92
|
+
}
|
|
93
|
+
else if (current.start < previous.end) {
|
|
94
|
+
ctx.addIssue({ code: 'custom', path: [index], message: 'windows must not overlap' });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const windowsSchema = z.array(localTimeRangeSchema).superRefine(validateWindows);
|
|
99
|
+
const weeklySchema = z
|
|
100
|
+
.object({
|
|
101
|
+
mon: windowsSchema,
|
|
102
|
+
tue: windowsSchema,
|
|
103
|
+
wed: windowsSchema,
|
|
104
|
+
thu: windowsSchema,
|
|
105
|
+
fri: windowsSchema,
|
|
106
|
+
sat: windowsSchema,
|
|
107
|
+
sun: windowsSchema,
|
|
108
|
+
})
|
|
109
|
+
.strict();
|
|
110
|
+
function isValidLocalDate(value) {
|
|
111
|
+
if (!localDate.test(value))
|
|
112
|
+
return false;
|
|
113
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
114
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
115
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
116
|
+
}
|
|
117
|
+
export const contactScheduleValueSchema = z
|
|
118
|
+
.object({
|
|
119
|
+
weekly: weeklySchema.nullable(),
|
|
120
|
+
dateOverrides: z.array(z
|
|
121
|
+
.object({
|
|
122
|
+
dates: z.array(z.string().refine(isValidLocalDate, 'expected a valid YYYY-MM-DD date')).min(1),
|
|
123
|
+
windows: windowsSchema,
|
|
124
|
+
})
|
|
125
|
+
.strict()),
|
|
126
|
+
})
|
|
127
|
+
.strict()
|
|
128
|
+
.superRefine((schedule, ctx) => {
|
|
129
|
+
const seen = new Set();
|
|
130
|
+
schedule.dateOverrides.forEach((override, overrideIndex) => {
|
|
131
|
+
override.dates.forEach((date, dateIndex) => {
|
|
132
|
+
if (seen.has(date)) {
|
|
133
|
+
ctx.addIssue({
|
|
134
|
+
code: 'custom',
|
|
135
|
+
path: ['dateOverrides', overrideIndex, 'dates', dateIndex],
|
|
136
|
+
message: 'each override date may appear only once',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
seen.add(date);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
export const companyFieldDefSchema = companyNormalFieldDefSchema;
|
|
144
|
+
export const companyTableDefSchema = z
|
|
145
|
+
.object({
|
|
146
|
+
label: z.string(),
|
|
147
|
+
description: z.string(),
|
|
148
|
+
fields: z.record(z.string(), companyFieldDefSchema),
|
|
149
|
+
})
|
|
150
|
+
.strict();
|
|
151
|
+
export const companySchemaSchema = z
|
|
152
|
+
.record(z.string().min(1), companyTableDefSchema)
|
|
153
|
+
.refine((schema) => Object.keys(schema).length > 0, {
|
|
154
|
+
message: 'company schema must define at least one table',
|
|
155
|
+
});
|
|
156
|
+
/** A company with no `schema/session.ts`: sessions have no fields. */
|
|
157
|
+
export const EMPTY_SESSION_SCHEMA = { fields: {} };
|
|
158
|
+
export const sessionFieldDefSchema = normalFieldCoreSchema
|
|
159
|
+
.extend({
|
|
160
|
+
dataType: z.enum(SCALAR_DATA_TYPES),
|
|
161
|
+
deprecated: z.boolean().optional(),
|
|
162
|
+
})
|
|
163
|
+
.strict();
|
|
164
|
+
export const sessionSchemaSchema = z
|
|
165
|
+
.object({ fields: z.record(z.string().min(1), sessionFieldDefSchema) })
|
|
166
|
+
.strict();
|
|
167
|
+
export function isCompanySchema(value) {
|
|
168
|
+
return companySchemaSchema.safeParse(value).success;
|
|
169
|
+
}
|
|
17
170
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1,89 +1,52 @@
|
|
|
1
|
-
import type { DataType } from './schema.js';
|
|
2
|
-
import type { FieldPath } from './path.js';
|
|
1
|
+
import type { ContactSchedule, DataType, TableRef } from './schema.js';
|
|
3
2
|
import type { FieldState } from '../context/types.js';
|
|
4
|
-
export type UpdatedBy = 'slot-filling' | '
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
at: number;
|
|
10
|
-
by: UpdatedBy;
|
|
11
|
-
};
|
|
12
|
-
/** In-memory field envelope (01-slot-design §2 + 01-slot-db §4 history). */
|
|
3
|
+
export type UpdatedBy = 'slot-filling' | 'function' | 'human' | 'import' | 'platform';
|
|
4
|
+
/**
|
|
5
|
+
* In-memory field envelope (01-slot-design §2): the current value only. Earlier values are in the
|
|
6
|
+
* change log (`SlotWriteLog`, 36 §3).
|
|
7
|
+
*/
|
|
13
8
|
export type FieldValue = {
|
|
9
|
+
/**
|
|
10
|
+
* Dialogue evidence quote or write justification (`null` when the writer gave none: plain
|
|
11
|
+
* function / platform writes, row inserts, imports).
|
|
12
|
+
* Updating `reason` alone does not count as a C5 state/value change.
|
|
13
|
+
*/
|
|
14
14
|
reason: string | null;
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Current value; always `null` when `state` is `'empty'` or `'declined'`. `'asked_unknown'` is
|
|
17
|
+
* `null` unless the field's extraction allows a coarse value; `'filled'` is non-null.
|
|
18
|
+
*/
|
|
19
|
+
value: SlotValue;
|
|
16
20
|
state: FieldState;
|
|
21
|
+
/** Epoch milliseconds of the last value/state change. */
|
|
17
22
|
updatedAt: number;
|
|
18
23
|
updatedBy: UpdatedBy;
|
|
19
|
-
/** Past generations ascending; excludes current. Appended only on C5 change. */
|
|
20
|
-
history: FieldHistoryEntry[];
|
|
21
|
-
};
|
|
22
|
-
/** One history append produced by a write batch (for platform write_log). */
|
|
23
|
-
export type HistoryAppend = {
|
|
24
|
-
path: FieldPath;
|
|
25
|
-
entry: FieldHistoryEntry;
|
|
26
|
-
/** Set when the write targeted a specific snapshot row. */
|
|
27
|
-
rowId?: string;
|
|
28
|
-
};
|
|
29
|
-
export type ExtractedField = {
|
|
30
|
-
reason: string;
|
|
31
|
-
value: string | number | boolean | null;
|
|
32
|
-
state: 'filled' | 'asked_unknown' | 'declined';
|
|
33
24
|
};
|
|
34
|
-
export type
|
|
35
|
-
export type
|
|
36
|
-
rowKey: string;
|
|
37
|
-
fields: Record<string, ExtractedField>;
|
|
38
|
-
}>;
|
|
39
|
-
export type SlotFillingOutput = Record<string, SingleRowProjection | MultiRowProjection>;
|
|
40
|
-
export type RuntimeNormalFieldDef = {
|
|
41
|
-
derived: false;
|
|
25
|
+
export type SlotValue = string | number | boolean | string[] | ContactSchedule | null;
|
|
26
|
+
export type RuntimeFieldDef = {
|
|
42
27
|
label: string;
|
|
28
|
+
/** Sequence-specific field meaning shown to slot-filling consumers. */
|
|
29
|
+
description?: string;
|
|
43
30
|
dataType: DataType;
|
|
44
|
-
source: 'conversation' | 'system';
|
|
45
31
|
extraction: string;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
ref: null | {
|
|
52
|
-
table: string;
|
|
53
|
-
};
|
|
32
|
+
/** A `select` / `multi_select` field's choices; null on every other type. */
|
|
33
|
+
options: string[] | null;
|
|
34
|
+
ref: null | TableRef;
|
|
35
|
+
/** No two rows of the table hold the same value (18-record-search-index §4.5). */
|
|
36
|
+
unique?: true;
|
|
54
37
|
deprecated?: boolean;
|
|
55
38
|
};
|
|
56
|
-
export type RuntimeDerivedFieldDef = {
|
|
57
|
-
derived: true;
|
|
58
|
-
label: string;
|
|
59
|
-
dataType: DataType;
|
|
60
|
-
dependsOn: FieldPath[];
|
|
61
|
-
computeFn: string;
|
|
62
|
-
deprecated?: boolean;
|
|
63
|
-
};
|
|
64
|
-
export type RuntimeFieldDef = RuntimeNormalFieldDef | RuntimeDerivedFieldDef;
|
|
65
39
|
export type RuntimeTableDef = {
|
|
66
40
|
label: string;
|
|
67
|
-
rows: 'single' | 'multi';
|
|
68
41
|
description: string;
|
|
69
42
|
fields: Record<string, RuntimeFieldDef>;
|
|
70
43
|
};
|
|
71
44
|
/**
|
|
72
|
-
* Compiled schema: one key per table
|
|
73
|
-
* `
|
|
45
|
+
* Compiled schema: one key per table. Builds compiled before V1.16 also carry `derivedOrder` /
|
|
46
|
+
* `reverseDeps` (always empty there); those names stay reserved and are skipped when reading.
|
|
74
47
|
*/
|
|
75
48
|
export type CompiledSlotSchema = {
|
|
76
|
-
|
|
77
|
-
derivedOrder: FieldPath[];
|
|
78
|
-
/** `table.field` → derived fields that list it in dependsOn. */
|
|
79
|
-
reverseDeps: Record<FieldPath, FieldPath[]>;
|
|
80
|
-
[table: string]: RuntimeTableDef | FieldPath[] | Record<FieldPath, FieldPath[]>;
|
|
81
|
-
};
|
|
82
|
-
export type SlotCurrent = {
|
|
83
|
-
contactId: string;
|
|
84
|
-
caseContactId: string;
|
|
85
|
-
caseFileId: string;
|
|
86
|
-
sessionId: string | null;
|
|
49
|
+
[table: string]: RuntimeTableDef;
|
|
87
50
|
};
|
|
88
51
|
export type SingleRowTableData = {
|
|
89
52
|
id: string;
|
|
@@ -95,15 +58,6 @@ export type MultiRowRecord = {
|
|
|
95
58
|
[field: string]: FieldValue | string;
|
|
96
59
|
};
|
|
97
60
|
export type MultiRowTableData = MultiRowRecord[];
|
|
98
|
-
export type TableData = SingleRowTableData | MultiRowTableData;
|
|
99
|
-
/**
|
|
100
|
-
* Runtime snapshot: `current` plus one key per table.
|
|
101
|
-
* `current` is reserved and cannot be a table name.
|
|
102
|
-
*/
|
|
103
|
-
export type RuntimeSlotsSnapshot = {
|
|
104
|
-
current?: SlotCurrent;
|
|
105
|
-
[table: string]: TableData | SlotCurrent | undefined;
|
|
106
|
-
};
|
|
107
61
|
export type ValidationIssue = {
|
|
108
62
|
code: string;
|
|
109
63
|
message: string;
|
|
@@ -115,32 +69,5 @@ export type ValidationResult = {
|
|
|
115
69
|
ok: false;
|
|
116
70
|
issues: ValidationIssue[];
|
|
117
71
|
};
|
|
118
|
-
export type WriteSource =
|
|
119
|
-
export type ApplyWritesOptions = {
|
|
120
|
-
source: WriteSource;
|
|
121
|
-
now?: number;
|
|
122
|
-
/** When true (default for function/platform), only `source: system` normals. */
|
|
123
|
-
systemOnly?: boolean;
|
|
124
|
-
};
|
|
125
|
-
export type ApplyWritesResult = {
|
|
126
|
-
snapshot: RuntimeSlotsSnapshot;
|
|
127
|
-
changed: FieldPath[];
|
|
128
|
-
/** Previous generations archived into field envelopes this batch. */
|
|
129
|
-
history: HistoryAppend[];
|
|
130
|
-
};
|
|
131
|
-
export type RecomputeResult = {
|
|
132
|
-
snapshot: RuntimeSlotsSnapshot;
|
|
133
|
-
changed: FieldPath[];
|
|
134
|
-
history: HistoryAppend[];
|
|
135
|
-
};
|
|
136
|
-
export type SlotFillingValidateResult = {
|
|
137
|
-
ok: true;
|
|
138
|
-
accepted: SlotFillingOutput;
|
|
139
|
-
/** Fields that failed type/enum checks — caller may re-extract. */
|
|
140
|
-
rejected: FieldPath[];
|
|
141
|
-
} | {
|
|
142
|
-
ok: false;
|
|
143
|
-
reason: 'stale-version' | 'invalid-shape';
|
|
144
|
-
issues: ValidationIssue[];
|
|
145
|
-
};
|
|
72
|
+
export type WriteSource = UpdatedBy;
|
|
146
73
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
import type { DataType } from './schema.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RuntimeFieldDef, ValidationIssue } from './types.js';
|
|
3
|
+
/** date values slot filling must write. Partial precision is the coarse form C3 still accepts. */
|
|
4
|
+
export declare const DATE_VALUE_PATTERN: string;
|
|
5
|
+
export declare const DATE_VALUE_FORMAT = "YYYY, YYYY-MM, or YYYY-MM-DD";
|
|
6
|
+
/** ISO-8601 datetime with a timezone offset or Z. */
|
|
7
|
+
export declare const DATETIME_VALUE_PATTERN: string;
|
|
8
|
+
export declare const DATETIME_VALUE_FORMAT = "ISO-8601 datetime with a timezone offset or Z";
|
|
9
|
+
/** A time of day (27 §4): `HH:mm`, 24-hour, `00:00`–`23:59`. */
|
|
10
|
+
export declare const TIME_VALUE_PATTERN: string;
|
|
11
|
+
export declare const TIME_VALUE_FORMAT = "a time of day HH:mm, 24-hour (15:30)";
|
|
12
|
+
/**
|
|
13
|
+
* A `phone` value as stored: E.164, any country, with an extension in RFC 3966 form when there is one
|
|
14
|
+
* (`+14155550123;ext=123`). The write entry converts what it is given first.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PHONE_VALUE_PATTERN: string;
|
|
17
|
+
/** An `email` value as stored: lower-cased (the write entry lower-cases what it is given first). */
|
|
18
|
+
export declare const EMAIL_VALUE_PATTERN: string;
|
|
19
|
+
/** Characters of a string, as Postgres and people count them (a surrogate pair is one). */
|
|
20
|
+
export declare function stringChars(value: string): number;
|
|
21
|
+
/** UTF-8 bytes of a string. */
|
|
22
|
+
export declare function utf8Bytes(value: string): number;
|
|
23
|
+
/** UTF-8 bytes a `string` takes in its indexes: as written, or lower-cased if that is longer. */
|
|
24
|
+
export declare function indexedBytes(value: string): number;
|
|
25
|
+
/** What a value of `dataType` must look like, for messages. */
|
|
26
|
+
export declare function dataTypeFormat(dataType: DataType): string;
|
|
3
27
|
export declare function isValidDataTypeValue(dataType: DataType, value: unknown): boolean;
|
|
4
|
-
|
|
5
|
-
/** Validate a bare write value for a normal or derived field. */
|
|
28
|
+
/** Validate a bare write value for a field. */
|
|
6
29
|
export declare function validateBareValue(field: RuntimeFieldDef, value: unknown, path: string, options?: {
|
|
7
30
|
allowNull?: boolean;
|
|
8
31
|
}): ValidationIssue[];
|
|
32
|
+
/** What of a `select` / `multi_select` value is not one of the field's options; empty for any other field. */
|
|
33
|
+
export declare function optionsOutside(field: Pick<RuntimeFieldDef, 'options'>, value: unknown): unknown[];
|
|
9
34
|
//# sourceMappingURL=value.d.ts.map
|
package/dist/core/slot/value.js
CHANGED
|
@@ -1,12 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { LIMITS } from './company-metadata.js';
|
|
2
|
+
import { contactScheduleValueSchema } from './schema.js';
|
|
3
|
+
/** date values slot filling must write. Partial precision is the coarse form C3 still accepts. */
|
|
4
|
+
export const DATE_VALUE_PATTERN = String.raw `^\d{4}(-\d{2}(-\d{2})?)?$`;
|
|
5
|
+
export const DATE_VALUE_FORMAT = 'YYYY, YYYY-MM, or YYYY-MM-DD';
|
|
6
|
+
/** ISO-8601 datetime with a timezone offset or Z. */
|
|
7
|
+
export const DATETIME_VALUE_PATTERN = String.raw `^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$`;
|
|
8
|
+
export const DATETIME_VALUE_FORMAT = 'ISO-8601 datetime with a timezone offset or Z';
|
|
9
|
+
/** A time of day (27 §4): `HH:mm`, 24-hour, `00:00`–`23:59`. */
|
|
10
|
+
export const TIME_VALUE_PATTERN = String.raw `^(?:[01]\d|2[0-3]):[0-5]\d$`;
|
|
11
|
+
export const TIME_VALUE_FORMAT = 'a time of day HH:mm, 24-hour (15:30)';
|
|
12
|
+
/**
|
|
13
|
+
* A `phone` value as stored: E.164, any country, with an extension in RFC 3966 form when there is one
|
|
14
|
+
* (`+14155550123;ext=123`). The write entry converts what it is given first.
|
|
15
|
+
*/
|
|
16
|
+
export const PHONE_VALUE_PATTERN = String.raw `^\+[1-9]\d{6,14}(;ext=\d{1,10})?$`;
|
|
17
|
+
/** An `email` value as stored: lower-cased (the write entry lower-cases what it is given first). */
|
|
18
|
+
export const EMAIL_VALUE_PATTERN = String.raw `^[^\sA-Z@]+@[^\sA-Z@]+\.[^\sA-Z@]+$`;
|
|
19
|
+
const DATE_RE = new RegExp(DATE_VALUE_PATTERN);
|
|
20
|
+
const DATETIME_RE = new RegExp(DATETIME_VALUE_PATTERN);
|
|
21
|
+
const TIME_RE = new RegExp(TIME_VALUE_PATTERN);
|
|
22
|
+
const PHONE_RE = new RegExp(PHONE_VALUE_PATTERN);
|
|
23
|
+
const EMAIL_RE = new RegExp(EMAIL_VALUE_PATTERN);
|
|
24
|
+
const utf8 = new TextEncoder();
|
|
25
|
+
/** Characters of a string, as Postgres and people count them (a surrogate pair is one). */
|
|
26
|
+
export function stringChars(value) {
|
|
27
|
+
let count = 0;
|
|
28
|
+
for (const _ of value)
|
|
29
|
+
count += 1;
|
|
30
|
+
return count;
|
|
31
|
+
}
|
|
32
|
+
/** UTF-8 bytes of a string. */
|
|
33
|
+
export function utf8Bytes(value) {
|
|
34
|
+
return utf8.encode(value).length;
|
|
35
|
+
}
|
|
36
|
+
/** UTF-8 bytes a `string` takes in its indexes: as written, or lower-cased if that is longer. */
|
|
37
|
+
export function indexedBytes(value) {
|
|
38
|
+
return Math.max(utf8Bytes(value), utf8Bytes(value.toLowerCase()));
|
|
39
|
+
}
|
|
40
|
+
/** What a value of `dataType` must look like, for messages. */
|
|
41
|
+
export function dataTypeFormat(dataType) {
|
|
42
|
+
switch (dataType) {
|
|
43
|
+
case 'string':
|
|
44
|
+
return `a string of at most ${LIMITS.stringBytes} bytes (UTF-8; a longer value is a text field)`;
|
|
45
|
+
case 'text':
|
|
46
|
+
return `a string of at most ${LIMITS.textBytes} bytes`;
|
|
47
|
+
case 'phone':
|
|
48
|
+
return 'a phone number, any country (stored as E.164, e.g. +14155550123; with an extension +14155550123;ext=12)';
|
|
49
|
+
case 'email':
|
|
50
|
+
return 'an email address';
|
|
51
|
+
case 'date':
|
|
52
|
+
return DATE_VALUE_FORMAT;
|
|
53
|
+
case 'datetime':
|
|
54
|
+
return DATETIME_VALUE_FORMAT;
|
|
55
|
+
case 'time':
|
|
56
|
+
return TIME_VALUE_FORMAT;
|
|
57
|
+
case 'select':
|
|
58
|
+
return 'one of its options';
|
|
59
|
+
case 'multi_select':
|
|
60
|
+
return 'a list of its options ([] for none of them)';
|
|
61
|
+
default:
|
|
62
|
+
return dataType;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
4
65
|
export function isValidDataTypeValue(dataType, value) {
|
|
5
66
|
if (value === null)
|
|
6
67
|
return true;
|
|
7
68
|
switch (dataType) {
|
|
8
69
|
case 'string':
|
|
9
|
-
return typeof value === 'string';
|
|
70
|
+
return typeof value === 'string' && indexedBytes(value) <= LIMITS.stringBytes;
|
|
71
|
+
case 'text':
|
|
72
|
+
return typeof value === 'string' && utf8Bytes(value) <= LIMITS.textBytes;
|
|
73
|
+
case 'phone':
|
|
74
|
+
return typeof value === 'string' && PHONE_RE.test(value);
|
|
75
|
+
case 'email':
|
|
76
|
+
return typeof value === 'string' && EMAIL_RE.test(value);
|
|
10
77
|
case 'number':
|
|
11
78
|
return typeof value === 'number' && Number.isFinite(value);
|
|
12
79
|
case 'boolean':
|
|
@@ -15,61 +82,22 @@ export function isValidDataTypeValue(dataType, value) {
|
|
|
15
82
|
return typeof value === 'string' && DATE_RE.test(value);
|
|
16
83
|
case 'datetime':
|
|
17
84
|
return typeof value === 'string' && DATETIME_RE.test(value);
|
|
85
|
+
case 'time':
|
|
86
|
+
return typeof value === 'string' && TIME_RE.test(value);
|
|
87
|
+
case 'select':
|
|
88
|
+
return typeof value === 'string';
|
|
89
|
+
case 'multi_select':
|
|
90
|
+
return Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
91
|
+
case 'contact_schedule':
|
|
92
|
+
return contactScheduleValueSchema.safeParse(value).success;
|
|
18
93
|
}
|
|
19
94
|
}
|
|
20
|
-
|
|
21
|
-
const issues = [];
|
|
22
|
-
if (typeof extracted.reason !== 'string' || extracted.reason.length === 0) {
|
|
23
|
-
issues.push({
|
|
24
|
-
code: 'missing-reason',
|
|
25
|
-
message: 'Extracted field requires a non-empty reason',
|
|
26
|
-
path,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
if (extracted.state !== 'filled' && extracted.state !== 'asked_unknown' && extracted.state !== 'declined') {
|
|
30
|
-
issues.push({
|
|
31
|
-
code: 'invalid-state',
|
|
32
|
-
message: `Invalid extracted state: ${String(extracted.state)}`,
|
|
33
|
-
path,
|
|
34
|
-
});
|
|
35
|
-
return issues;
|
|
36
|
-
}
|
|
37
|
-
if (extracted.state === 'declined' && extracted.value !== null) {
|
|
38
|
-
issues.push({
|
|
39
|
-
code: 'declined-non-null',
|
|
40
|
-
message: 'declined fields must have value null',
|
|
41
|
-
path,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
if (extracted.state === 'filled' && extracted.value === null && !field.nullable) {
|
|
45
|
-
issues.push({
|
|
46
|
-
code: 'filled-null',
|
|
47
|
-
message: 'filled requires non-null value unless nullable: true',
|
|
48
|
-
path,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
if (extracted.value !== null && !isValidDataTypeValue(field.dataType, extracted.value)) {
|
|
52
|
-
issues.push({
|
|
53
|
-
code: 'type-mismatch',
|
|
54
|
-
message: `value does not match dataType ${field.dataType}`,
|
|
55
|
-
path,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
if (extracted.value !== null && field.enum && !field.enum.includes(extracted.value)) {
|
|
59
|
-
issues.push({
|
|
60
|
-
code: 'enum-mismatch',
|
|
61
|
-
message: `value ${String(extracted.value)} not in enum`,
|
|
62
|
-
path,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return issues;
|
|
66
|
-
}
|
|
67
|
-
/** Validate a bare write value for a normal or derived field. */
|
|
95
|
+
/** Validate a bare write value for a field. */
|
|
68
96
|
export function validateBareValue(field, value, path, options = {}) {
|
|
69
97
|
const issues = [];
|
|
70
98
|
const allowNull = options.allowNull ?? true;
|
|
71
99
|
if (value === null || value === undefined) {
|
|
72
|
-
if (!allowNull
|
|
100
|
+
if (!allowNull) {
|
|
73
101
|
issues.push({
|
|
74
102
|
code: 'null-not-allowed',
|
|
75
103
|
message: 'null is not allowed for this field',
|
|
@@ -81,17 +109,25 @@ export function validateBareValue(field, value, path, options = {}) {
|
|
|
81
109
|
if (!isValidDataTypeValue(field.dataType, value)) {
|
|
82
110
|
issues.push({
|
|
83
111
|
code: 'type-mismatch',
|
|
84
|
-
message: `value does not match dataType ${field.dataType}`,
|
|
112
|
+
message: `value does not match dataType ${field.dataType}: expected ${dataTypeFormat(field.dataType)}`,
|
|
85
113
|
path,
|
|
86
114
|
});
|
|
87
115
|
}
|
|
88
|
-
|
|
116
|
+
const outside = optionsOutside(field, value);
|
|
117
|
+
if (outside.length > 0) {
|
|
89
118
|
issues.push({
|
|
90
|
-
code: '
|
|
91
|
-
message:
|
|
119
|
+
code: 'not-an-option',
|
|
120
|
+
message: `${outside.map((v) => JSON.stringify(v)).join(', ')} not one of the options (${field.options.join(', ')})`,
|
|
92
121
|
path,
|
|
93
122
|
});
|
|
94
123
|
}
|
|
95
124
|
return issues;
|
|
96
125
|
}
|
|
126
|
+
/** What of a `select` / `multi_select` value is not one of the field's options; empty for any other field. */
|
|
127
|
+
export function optionsOutside(field, value) {
|
|
128
|
+
if (!field.options)
|
|
129
|
+
return [];
|
|
130
|
+
const items = Array.isArray(value) ? value : [value];
|
|
131
|
+
return items.filter((item) => !field.options.includes(item));
|
|
132
|
+
}
|
|
97
133
|
//# sourceMappingURL=value.js.map
|