ultimabase 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +4 -2
- package/dist/access.d.ts +62 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +258 -0
- package/dist/adapter-errors.d.ts +43 -0
- package/dist/adapter-errors.d.ts.map +1 -0
- package/dist/adapter-errors.js +72 -0
- package/dist/adapter-json.d.ts +20 -0
- package/dist/adapter-json.d.ts.map +1 -0
- package/dist/adapter-json.js +2 -0
- package/dist/adapter-migrations.d.ts +90 -0
- package/dist/adapter-migrations.d.ts.map +1 -0
- package/dist/adapter-migrations.js +1 -0
- package/dist/adapter.d.ts +333 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +5 -0
- package/dist/aggregate.d.ts +31 -0
- package/dist/aggregate.d.ts.map +1 -0
- package/dist/aggregate.js +99 -0
- package/dist/app-internals.d.ts +10 -0
- package/dist/app-internals.d.ts.map +1 -0
- package/dist/app-internals.js +12 -0
- package/dist/app-options.d.ts +22 -0
- package/dist/app-options.d.ts.map +1 -0
- package/dist/app-options.js +3 -0
- package/dist/cascade.d.ts +47 -0
- package/dist/cascade.d.ts.map +1 -0
- package/dist/cascade.js +209 -0
- package/dist/cli-config.d.ts +6 -0
- package/dist/cli-config.d.ts.map +1 -0
- package/dist/cli-config.js +45 -0
- package/dist/cli-deploy.d.ts +14 -0
- package/dist/cli-deploy.d.ts.map +1 -0
- package/dist/cli-deploy.js +193 -0
- package/dist/cli-main.d.ts +16 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +151 -0
- package/dist/cli-migrate.d.ts +20 -0
- package/dist/cli-migrate.d.ts.map +1 -0
- package/dist/cli-migrate.js +105 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +4 -0
- package/dist/complete.d.ts +13 -0
- package/dist/complete.d.ts.map +1 -0
- package/dist/complete.js +60 -0
- package/dist/console-logger.d.ts +3 -0
- package/dist/console-logger.d.ts.map +1 -0
- package/dist/console-logger.js +62 -0
- package/dist/create-many.d.ts +7 -0
- package/dist/create-many.d.ts.map +1 -0
- package/dist/create-many.js +88 -0
- package/dist/decimal.d.ts +23 -0
- package/dist/decimal.d.ts.map +1 -0
- package/dist/decimal.js +50 -0
- package/dist/define-app.d.ts +59 -0
- package/dist/define-app.d.ts.map +1 -0
- package/dist/define-app.js +5 -0
- package/dist/define-enum.d.ts +6 -0
- package/dist/define-enum.d.ts.map +1 -0
- package/dist/define-enum.js +18 -0
- package/dist/define-function.d.ts +25 -0
- package/dist/define-function.d.ts.map +1 -0
- package/dist/define-function.js +111 -0
- package/dist/define-model.d.ts +48 -0
- package/dist/define-model.d.ts.map +1 -0
- package/dist/define-model.js +85 -0
- package/dist/definition.d.ts +179 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +165 -0
- package/dist/delete-many.d.ts +13 -0
- package/dist/delete-many.d.ts.map +1 -0
- package/dist/delete-many.js +58 -0
- package/dist/engine.d.ts +16 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +174 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +43 -0
- package/dist/exact.d.ts +20 -0
- package/dist/exact.d.ts.map +1 -0
- package/dist/exact.js +1 -0
- package/dist/feed.d.ts +6 -0
- package/dist/feed.d.ts.map +1 -0
- package/dist/feed.js +33 -0
- package/dist/field-codec.d.ts +11 -0
- package/dist/field-codec.d.ts.map +1 -0
- package/dist/field-codec.js +48 -0
- package/dist/field-rules.d.ts +57 -0
- package/dist/field-rules.d.ts.map +1 -0
- package/dist/field-rules.js +1 -0
- package/dist/field-type.d.ts +51 -0
- package/dist/field-type.d.ts.map +1 -0
- package/dist/field-type.js +106 -0
- package/dist/fields.d.ts +295 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +1 -0
- package/dist/function.d.ts +126 -0
- package/dist/function.d.ts.map +1 -0
- package/dist/function.js +1 -0
- package/dist/functions.d.ts +18 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +99 -0
- package/dist/group-by.d.ts +10 -0
- package/dist/group-by.d.ts.map +1 -0
- package/dist/group-by.js +145 -0
- package/dist/group-having.d.ts +8 -0
- package/dist/group-having.d.ts.map +1 -0
- package/dist/group-having.js +97 -0
- package/dist/hooks.d.ts +41 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +149 -0
- package/dist/hosts.d.ts +3 -0
- package/dist/hosts.d.ts.map +1 -0
- package/dist/hosts.js +8 -0
- package/dist/identify.d.ts +15 -0
- package/dist/identify.d.ts.map +1 -0
- package/dist/identify.js +71 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/internal.d.ts +28 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +39 -0
- package/dist/lifecycle.d.ts +21 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +149 -0
- package/dist/list-update.d.ts +12 -0
- package/dist/list-update.d.ts.map +1 -0
- package/dist/list-update.js +52 -0
- package/dist/live.d.ts +37 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +139 -0
- package/dist/manifest.d.ts +11 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +60 -0
- package/dist/memory-aggregate.d.ts +7 -0
- package/dist/memory-aggregate.d.ts.map +1 -0
- package/dist/memory-aggregate.js +107 -0
- package/dist/memory-conditions.d.ts +8 -0
- package/dist/memory-conditions.d.ts.map +1 -0
- package/dist/memory-conditions.js +82 -0
- package/dist/memory-draft.d.ts +34 -0
- package/dist/memory-draft.d.ts.map +1 -0
- package/dist/memory-draft.js +255 -0
- package/dist/memory-json.d.ts +6 -0
- package/dist/memory-json.d.ts.map +1 -0
- package/dist/memory-json.js +86 -0
- package/dist/memory-read.d.ts +45 -0
- package/dist/memory-read.d.ts.map +1 -0
- package/dist/memory-read.js +244 -0
- package/dist/memory-search.d.ts +16 -0
- package/dist/memory-search.d.ts.map +1 -0
- package/dist/memory-search.js +110 -0
- package/dist/memory-values.d.ts +23 -0
- package/dist/memory-values.d.ts.map +1 -0
- package/dist/memory-values.js +82 -0
- package/dist/memory.d.ts +4 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +157 -0
- package/dist/migrate.d.ts +22 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +131 -0
- package/dist/model.d.ts +239 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +1 -0
- package/dist/nested-write.d.ts +64 -0
- package/dist/nested-write.d.ts.map +1 -0
- package/dist/nested-write.js +274 -0
- package/dist/number-update.d.ts +18 -0
- package/dist/number-update.d.ts.map +1 -0
- package/dist/number-update.js +96 -0
- package/dist/plugin-app.d.ts +48 -0
- package/dist/plugin-app.d.ts.map +1 -0
- package/dist/plugin-app.js +230 -0
- package/dist/plugin-code.d.ts +17 -0
- package/dist/plugin-code.d.ts.map +1 -0
- package/dist/plugin-code.js +125 -0
- package/dist/plugin-use.d.ts +22 -0
- package/dist/plugin-use.d.ts.map +1 -0
- package/dist/plugin-use.js +161 -0
- package/dist/plugin.d.ts +357 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +17 -0
- package/dist/query-aggregate.d.ts +82 -0
- package/dist/query-aggregate.d.ts.map +1 -0
- package/dist/query-aggregate.js +1 -0
- package/dist/query-args.d.ts +41 -0
- package/dist/query-args.d.ts.map +1 -0
- package/dist/query-args.js +263 -0
- package/dist/query-bulk.d.ts +35 -0
- package/dist/query-bulk.d.ts.map +1 -0
- package/dist/query-bulk.js +1 -0
- package/dist/query-conditions.d.ts +9 -0
- package/dist/query-conditions.d.ts.map +1 -0
- package/dist/query-conditions.js +46 -0
- package/dist/query-context.d.ts +32 -0
- package/dist/query-context.d.ts.map +1 -0
- package/dist/query-context.js +55 -0
- package/dist/query-filter.d.ts +46 -0
- package/dist/query-filter.d.ts.map +1 -0
- package/dist/query-filter.js +1 -0
- package/dist/query-group.d.ts +82 -0
- package/dist/query-group.d.ts.map +1 -0
- package/dist/query-group.js +1 -0
- package/dist/query-json.d.ts +9 -0
- package/dist/query-json.d.ts.map +1 -0
- package/dist/query-json.js +66 -0
- package/dist/query-order.d.ts +15 -0
- package/dist/query-order.d.ts.map +1 -0
- package/dist/query-order.js +115 -0
- package/dist/query-project.d.ts +15 -0
- package/dist/query-project.d.ts.map +1 -0
- package/dist/query-project.js +45 -0
- package/dist/query-search.d.ts +24 -0
- package/dist/query-search.d.ts.map +1 -0
- package/dist/query-search.js +2 -0
- package/dist/query-values.d.ts +28 -0
- package/dist/query-values.d.ts.map +1 -0
- package/dist/query-values.js +91 -0
- package/dist/query-where.d.ts +46 -0
- package/dist/query-where.d.ts.map +1 -0
- package/dist/query-where.js +200 -0
- package/dist/query-write.d.ts +14 -0
- package/dist/query-write.d.ts.map +1 -0
- package/dist/query-write.js +260 -0
- package/dist/query.d.ts +254 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +1 -0
- package/dist/record.d.ts +257 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +1 -0
- package/dist/recorder.d.ts +32 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +152 -0
- package/dist/relation-write.d.ts +41 -0
- package/dist/relation-write.d.ts.map +1 -0
- package/dist/relation-write.js +112 -0
- package/dist/relations.d.ts +42 -0
- package/dist/relations.d.ts.map +1 -0
- package/dist/relations.js +119 -0
- package/dist/rules.d.ts +97 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +71 -0
- package/dist/running.d.ts +29 -0
- package/dist/running.d.ts.map +1 -0
- package/dist/running.js +39 -0
- package/dist/schema-indexes.d.ts +11 -0
- package/dist/schema-indexes.d.ts.map +1 -0
- package/dist/schema-indexes.js +59 -0
- package/dist/schema-virtuals.d.ts +19 -0
- package/dist/schema-virtuals.d.ts.map +1 -0
- package/dist/schema-virtuals.js +100 -0
- package/dist/schema.d.ts +35 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +267 -0
- package/dist/scope.d.ts +46 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +82 -0
- package/dist/scratch.d.ts +14 -0
- package/dist/scratch.d.ts.map +1 -0
- package/dist/scratch.js +10 -0
- package/dist/serve.d.ts +2 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +4 -0
- package/dist/symbols.d.ts +10 -0
- package/dist/symbols.d.ts.map +1 -0
- package/dist/symbols.js +1 -0
- package/dist/transaction.d.ts +28 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +156 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/update-many.d.ts +7 -0
- package/dist/update-many.d.ts.map +1 -0
- package/dist/update-many.js +182 -0
- package/dist/uuid.d.ts +7 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +48 -0
- package/dist/validation.d.ts +24 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +72 -0
- package/dist/virtual-read.d.ts +9 -0
- package/dist/virtual-read.d.ts.map +1 -0
- package/dist/virtual-read.js +145 -0
- package/dist/virtual.d.ts +142 -0
- package/dist/virtual.d.ts.map +1 -0
- package/dist/virtual.js +1 -0
- package/dist/write-context.d.ts +46 -0
- package/dist/write-context.d.ts.map +1 -0
- package/dist/write-context.js +102 -0
- package/dist/write-data.d.ts +26 -0
- package/dist/write-data.d.ts.map +1 -0
- package/dist/write-data.js +144 -0
- package/dist/write-plan.d.ts +107 -0
- package/dist/write-plan.d.ts.map +1 -0
- package/dist/write-plan.js +170 -0
- package/dist/write-target.d.ts +17 -0
- package/dist/write-target.d.ts.map +1 -0
- package/dist/write-target.js +59 -0
- package/dist/writes.d.ts +23 -0
- package/dist/writes.d.ts.map +1 -0
- package/dist/writes.js +246 -0
- package/dist/writing.d.ts +10 -0
- package/dist/writing.d.ts.map +1 -0
- package/dist/writing.js +66 -0
- package/package.json +42 -3
- package/src/access.ts +329 -0
- package/src/adapter-errors.ts +89 -0
- package/src/adapter-json.ts +21 -0
- package/src/adapter-migrations.ts +98 -0
- package/src/adapter.ts +363 -0
- package/src/aggregate.ts +136 -0
- package/src/app-internals.ts +26 -0
- package/src/app-options.ts +24 -0
- package/src/cascade.ts +297 -0
- package/src/cli-config.ts +45 -0
- package/src/cli-deploy.ts +235 -0
- package/src/cli-main.ts +165 -0
- package/src/cli-migrate.ts +143 -0
- package/src/cli.ts +5 -0
- package/src/complete.ts +73 -0
- package/src/console-logger.ts +87 -0
- package/src/create-many.ts +126 -0
- package/src/decimal.ts +74 -0
- package/src/define-app.ts +108 -0
- package/src/define-enum.ts +26 -0
- package/src/define-function.ts +188 -0
- package/src/define-model.ts +220 -0
- package/src/definition.ts +352 -0
- package/src/delete-many.ts +76 -0
- package/src/engine.ts +281 -0
- package/src/errors.ts +97 -0
- package/src/exact.ts +49 -0
- package/src/feed.ts +39 -0
- package/src/field-codec.ts +72 -0
- package/src/field-rules.ts +77 -0
- package/src/field-type.ts +219 -0
- package/src/fields.ts +383 -0
- package/src/function.ts +143 -0
- package/src/functions.ts +154 -0
- package/src/group-by.ts +186 -0
- package/src/group-having.ts +143 -0
- package/src/hooks.ts +215 -0
- package/src/hosts.ts +11 -0
- package/src/identify.ts +95 -0
- package/src/index.ts +125 -0
- package/src/internal.ts +68 -0
- package/src/lifecycle.ts +214 -0
- package/src/list-update.ts +71 -0
- package/src/live.ts +199 -0
- package/src/manifest.ts +71 -0
- package/src/memory-aggregate.ts +162 -0
- package/src/memory-conditions.ts +88 -0
- package/src/memory-draft.ts +319 -0
- package/src/memory-json.ts +91 -0
- package/src/memory-read.ts +311 -0
- package/src/memory-search.ts +149 -0
- package/src/memory-values.ts +106 -0
- package/src/memory.ts +173 -0
- package/src/migrate.ts +152 -0
- package/src/model.ts +312 -0
- package/src/nested-write.ts +390 -0
- package/src/number-update.ts +142 -0
- package/src/plugin-app.ts +308 -0
- package/src/plugin-code.ts +158 -0
- package/src/plugin-use.ts +217 -0
- package/src/plugin.ts +400 -0
- package/src/query-aggregate.ts +96 -0
- package/src/query-args.ts +375 -0
- package/src/query-bulk.ts +53 -0
- package/src/query-conditions.ts +53 -0
- package/src/query-context.ts +104 -0
- package/src/query-filter.ts +54 -0
- package/src/query-group.ts +137 -0
- package/src/query-json.ts +90 -0
- package/src/query-order.ts +158 -0
- package/src/query-project.ts +73 -0
- package/src/query-search.ts +31 -0
- package/src/query-values.ts +131 -0
- package/src/query-where.ts +318 -0
- package/src/query-write.ts +360 -0
- package/src/query.ts +400 -0
- package/src/record.ts +379 -0
- package/src/recorder.ts +212 -0
- package/src/relation-write.ts +176 -0
- package/src/relations.ts +165 -0
- package/src/rules.ts +188 -0
- package/src/running.ts +62 -0
- package/src/schema-indexes.ts +88 -0
- package/src/schema-virtuals.ts +134 -0
- package/src/schema.ts +367 -0
- package/src/scope.ts +123 -0
- package/src/scratch.ts +28 -0
- package/src/serve.ts +5 -0
- package/src/symbols.ts +11 -0
- package/src/transaction.ts +211 -0
- package/src/types.ts +79 -0
- package/src/update-many.ts +268 -0
- package/src/uuid.ts +51 -0
- package/src/validation.ts +107 -0
- package/src/virtual-read.ts +198 -0
- package/src/virtual.ts +187 -0
- package/src/write-context.ts +170 -0
- package/src/write-data.ts +188 -0
- package/src/write-plan.ts +273 -0
- package/src/write-target.ts +92 -0
- package/src/writes.ts +361 -0
- package/src/writing.ts +93 -0
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// A plugin is an interface of types and one `definePlugin` (D-57). Its types
|
|
2
|
+
// travel with its values; nothing is declared globally (D-24).
|
|
3
|
+
import type { Logger } from './app-options.ts'
|
|
4
|
+
import type { Enum, FieldBuilders, StandardSchema } from './fields.ts'
|
|
5
|
+
import type { Client, FunctionShape } from './function.ts'
|
|
6
|
+
import type { Identify } from './identify.ts'
|
|
7
|
+
import { pluginEntries, pluginValues } from './definition.ts'
|
|
8
|
+
import { pluginCode } from './plugin-code.ts'
|
|
9
|
+
import type { FieldShape, ModelHooks, ModelShape } from './model.ts'
|
|
10
|
+
import type { Changed, Row, SchemaModel } from './adapter.ts'
|
|
11
|
+
import type { Queries, QueryOptions, UniqueWhere } from './query.ts'
|
|
12
|
+
import type {
|
|
13
|
+
Caller,
|
|
14
|
+
Identity,
|
|
15
|
+
Register,
|
|
16
|
+
UserCallerKeys,
|
|
17
|
+
UserOf,
|
|
18
|
+
} from './rules.ts'
|
|
19
|
+
import type { pluginTypes } from './symbols.ts'
|
|
20
|
+
|
|
21
|
+
/** The keys of a user caller a plugin gives (D-121). */
|
|
22
|
+
type CallerKeys = Partial<UserCallerKeys> & object
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* What a plugin adds to the models that use it (D-57). `this['fields']` is
|
|
26
|
+
* the fields of the model that lists the plugin in its `use`, and
|
|
27
|
+
* `this['options']` the options of its entry there.
|
|
28
|
+
*/
|
|
29
|
+
export interface PluginTypes {
|
|
30
|
+
/** Its name, the key of its `.with` (D-24). */
|
|
31
|
+
readonly name: string
|
|
32
|
+
readonly fields: unknown
|
|
33
|
+
/** The value of the field whose `.with` holds its field rule. */
|
|
34
|
+
readonly value: unknown
|
|
35
|
+
/** Its entry's options, `softDelete({ ... })` (D-07). */
|
|
36
|
+
readonly options?: object
|
|
37
|
+
/** Its application value's options, `softDeletePlugin({ ... })` (D-24). */
|
|
38
|
+
readonly appOptions?: object
|
|
39
|
+
/** The plugins it needs, by their types (D-16). */
|
|
40
|
+
readonly requires?: PluginTypes
|
|
41
|
+
/** The plugins it uses when installed (D-16). */
|
|
42
|
+
readonly optional?: PluginTypes
|
|
43
|
+
/** What it offers other plugins (D-16). */
|
|
44
|
+
readonly api?: object
|
|
45
|
+
/** The fields it adds to the models that use it (D-07, D-15, D-89). */
|
|
46
|
+
readonly addedFields?: { readonly [field: string]: FieldShape }
|
|
47
|
+
/** Its commands (D-15). */
|
|
48
|
+
readonly commands?: object
|
|
49
|
+
/** Its key of the model's `.with` (D-42); `false` turns it off (D-107). */
|
|
50
|
+
readonly with?: object | false
|
|
51
|
+
/** Its key of a field's `.with`, read with `this['value']` (D-12). */
|
|
52
|
+
readonly fieldWith?: object
|
|
53
|
+
/** Its key of a function's `.with`; `false` stops exposing it (D-27). */
|
|
54
|
+
readonly functionWith?: object | false
|
|
55
|
+
/** Only a query may list it in its `use` (D-154). */
|
|
56
|
+
readonly queryOnly?: true
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** A plugin's types for one model's fields. */
|
|
60
|
+
export type ForModel<T, F> = T & { readonly fields: F }
|
|
61
|
+
/** What a plugin's own code sees of a model: the fields it adds. Other
|
|
62
|
+
* fields are the model's, unknown to the plugin (D-57). */
|
|
63
|
+
type Own<T> = T extends { readonly addedFields: infer A }
|
|
64
|
+
? A
|
|
65
|
+
: // oxlint-disable-next-line typescript/no-generated-empty-object-type -- no fields, not any value
|
|
66
|
+
Record<never, never>
|
|
67
|
+
type EntryOptions<T> = T extends { readonly options: infer O extends object }
|
|
68
|
+
? O
|
|
69
|
+
: { readonly [option: string]: never }
|
|
70
|
+
type AppOptions<T> = T extends { readonly appOptions: infer O } ? O : never
|
|
71
|
+
type Requires<T> = T extends { readonly requires: infer R extends PluginTypes }
|
|
72
|
+
? R['name']
|
|
73
|
+
: never
|
|
74
|
+
type Optional<T> = T extends { readonly optional: infer R extends PluginTypes }
|
|
75
|
+
? R['name']
|
|
76
|
+
: never
|
|
77
|
+
type ApiOf<X> = X extends { readonly api: infer A } ? A : undefined
|
|
78
|
+
type Apis<T> = (T extends { readonly requires: infer R extends PluginTypes }
|
|
79
|
+
? { readonly [X in R as X['name']]: ApiOf<X> }
|
|
80
|
+
: unknown) &
|
|
81
|
+
(T extends { readonly optional: infer R extends PluginTypes }
|
|
82
|
+
? { readonly [X in R as X['name']]: ApiOf<X> | undefined }
|
|
83
|
+
: unknown)
|
|
84
|
+
|
|
85
|
+
type Args = { readonly [key: string]: unknown }
|
|
86
|
+
/** A model's queries as a transport calls them, with its client's arguments. */
|
|
87
|
+
export interface ModelQueries {
|
|
88
|
+
findUnique(args: Args, options: QueryOptions): Promise<Row | null>
|
|
89
|
+
findMany(args: Args, options: QueryOptions): Promise<readonly Row[]>
|
|
90
|
+
count(args: Args, options: QueryOptions): Promise<number>
|
|
91
|
+
create(args: Args, options: QueryOptions): Promise<Row>
|
|
92
|
+
update(args: Args, options: QueryOptions): Promise<Row>
|
|
93
|
+
delete(args: Args, options: QueryOptions): Promise<Row>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** A model as transports and tools read it (D-16, D-107). */
|
|
97
|
+
export interface ExposedModel<W = unknown> {
|
|
98
|
+
/** As the adapter receives it (D-73). */
|
|
99
|
+
readonly schema: SchemaModel
|
|
100
|
+
/** The model's `description` and its fields' (D-150). */
|
|
101
|
+
readonly description: string | undefined
|
|
102
|
+
readonly descriptions: { readonly [field: string]: string }
|
|
103
|
+
/** Each field whose values are a `defineEnum` (D-150). */
|
|
104
|
+
readonly enums: { readonly [field: string]: Enum }
|
|
105
|
+
/** `id`, unique fields and unique indexes (D-52). */
|
|
106
|
+
readonly uniques: readonly (readonly string[])[]
|
|
107
|
+
/** Each field with a read rule, `private` when only Master reads it (D-44). */
|
|
108
|
+
readonly readRules: { readonly [field: string]: 'private' | 'rule' }
|
|
109
|
+
/** The fields `create` needs: neither optional nor with a default (D-53). */
|
|
110
|
+
readonly required: readonly string[]
|
|
111
|
+
/** Each `json` field's `validate`, when it is a Standard Schema (D-125). */
|
|
112
|
+
readonly validators: { readonly [field: string]: StandardSchema }
|
|
113
|
+
/** Each plugin field type's field, which a client reads as `toJSON` gives (D-122). */
|
|
114
|
+
readonly fieldTypes: {
|
|
115
|
+
readonly [field: string]: {
|
|
116
|
+
readonly plugin: string
|
|
117
|
+
/** The field type's own options the field took (D-152). */
|
|
118
|
+
readonly options: { readonly [key: string]: unknown }
|
|
119
|
+
readonly toJSON: (value: unknown) => unknown
|
|
120
|
+
/** What `toJSON` gives, if the field type says (D-152). */
|
|
121
|
+
readonly shape: StandardSchema | undefined
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** Its virtual fields, in their order (D-151). */
|
|
125
|
+
readonly virtuals: readonly ExposedVirtual[]
|
|
126
|
+
/** The plugin's key of the model's `.with`, if it was given. */
|
|
127
|
+
readonly with: W | undefined
|
|
128
|
+
/** Whether the model's `use` lists the plugin's entry. */
|
|
129
|
+
readonly used: boolean
|
|
130
|
+
readonly queries: ModelQueries
|
|
131
|
+
/** `upsert`, which also says whether it created the row (D-142). */
|
|
132
|
+
readonly upsert: (
|
|
133
|
+
args: Args,
|
|
134
|
+
options: QueryOptions,
|
|
135
|
+
) => Promise<{ readonly row: Row; readonly created: boolean }>
|
|
136
|
+
/** The `defineModel` value, which a plugin's function may return (D-113). */
|
|
137
|
+
readonly model: ModelShape
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** A virtual field as transports read it (D-151). */
|
|
141
|
+
export interface ExposedVirtual {
|
|
142
|
+
readonly name: string
|
|
143
|
+
readonly description: string | undefined
|
|
144
|
+
/** A Standard Schema of an object: the field's arguments. */
|
|
145
|
+
readonly input: StandardSchema | undefined
|
|
146
|
+
readonly output: ExposedOutput
|
|
147
|
+
/** In the row without `select`: a value without input. */
|
|
148
|
+
readonly default: boolean
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** How an output holds a model or a type (D-109). */
|
|
152
|
+
export type OutputForm = 'one' | 'nullable' | 'list'
|
|
153
|
+
|
|
154
|
+
/** A function's or a type's output, as transports read it (D-109). */
|
|
155
|
+
export type ExposedOutput =
|
|
156
|
+
| { readonly kind: 'schema'; readonly schema: StandardSchema }
|
|
157
|
+
| { readonly kind: 'model'; readonly name: string; readonly form: OutputForm }
|
|
158
|
+
| {
|
|
159
|
+
readonly kind: 'type'
|
|
160
|
+
readonly type: ExposedType
|
|
161
|
+
readonly form: OutputForm
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** A `defineType`, its fields in their order (D-109). */
|
|
165
|
+
export interface ExposedType {
|
|
166
|
+
readonly name: string
|
|
167
|
+
readonly description: string | undefined
|
|
168
|
+
readonly fields: ReadonlyMap<string, ExposedOutput>
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** A function as transports read it (D-109). */
|
|
172
|
+
export interface ExposedFunction<W = unknown> {
|
|
173
|
+
readonly name: string
|
|
174
|
+
readonly description: string | undefined
|
|
175
|
+
/** The plugin that gives it, `undefined` for the application's (D-113). */
|
|
176
|
+
readonly plugin: string | undefined
|
|
177
|
+
/** A query, which a transport may serve over GET; a mutation otherwise. */
|
|
178
|
+
readonly query: boolean
|
|
179
|
+
/** Whether the function's `use` lists the plugin (D-154). */
|
|
180
|
+
readonly used: boolean
|
|
181
|
+
readonly input: StandardSchema | undefined
|
|
182
|
+
/** `undefined` when it returns nothing. */
|
|
183
|
+
readonly output: ExposedOutput | undefined
|
|
184
|
+
/** The plugin's key of the function's `.with`, if it was given. */
|
|
185
|
+
readonly with: W | undefined
|
|
186
|
+
/** Checks access, validates the input, then runs it for `client` (D-75, D-113). */
|
|
187
|
+
run(input: unknown, options: QueryOptions, client?: Client): Promise<unknown>
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
type WithOf<T> = T extends { readonly with: infer W } ? W : never
|
|
191
|
+
type FunctionWithOf<T> = T extends { readonly functionWith: infer W }
|
|
192
|
+
? W
|
|
193
|
+
: never
|
|
194
|
+
|
|
195
|
+
/** What the plugin's start and api receive: its application options. */
|
|
196
|
+
export interface PluginContext<T> {
|
|
197
|
+
readonly options: [AppOptions<T>] extends [never]
|
|
198
|
+
? { readonly [option: string]: never }
|
|
199
|
+
: AppOptions<T>
|
|
200
|
+
readonly plugins: Apis<T>
|
|
201
|
+
readonly logger: Logger
|
|
202
|
+
/** Who sends a request: what a transport runs it as (D-106). */
|
|
203
|
+
readonly identify: Identify
|
|
204
|
+
/**
|
|
205
|
+
* The caller being built stops holding at `at`, as a session that
|
|
206
|
+
* expires: a live read builds it again then (D-154). Outside a caller's
|
|
207
|
+
* construction, it does nothing.
|
|
208
|
+
*/
|
|
209
|
+
readonly expires: (at: Date) => void
|
|
210
|
+
/** The application's models, in their order (D-107). */
|
|
211
|
+
readonly models: readonly ExposedModel<WithOf<T>>[]
|
|
212
|
+
/** The application's functions, in their order (D-109). */
|
|
213
|
+
readonly functions: readonly ExposedFunction<FunctionWithOf<T>>[]
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** A plugin's entry in a model's `use`, named after the plugin. */
|
|
217
|
+
export interface ModelUse<P extends string, T> {
|
|
218
|
+
readonly plugin: P
|
|
219
|
+
readonly [pluginTypes]: T
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** A plugin's value in the application's `plugins`. */
|
|
223
|
+
export interface PluginValue<P extends string, R extends string = never> {
|
|
224
|
+
readonly name: P
|
|
225
|
+
readonly requires?: readonly R[]
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
type HookFacts<F, K extends keyof ModelHooks<F>> = Parameters<
|
|
229
|
+
NonNullable<ModelHooks<F>[K]>
|
|
230
|
+
>[0]
|
|
231
|
+
/**
|
|
232
|
+
* The hooks a plugin runs on every model that uses it (D-15). `command` names
|
|
233
|
+
* the plugin's command the operation was called through, on that model only
|
|
234
|
+
* (D-71).
|
|
235
|
+
*/
|
|
236
|
+
export type PluginHooks<F, O, A, C> = {
|
|
237
|
+
readonly [K in keyof ModelHooks<unknown>]?: (
|
|
238
|
+
facts: HookFacts<F, K> &
|
|
239
|
+
PluginModel<F, O, A> & { readonly command: C | undefined },
|
|
240
|
+
) => ReturnType<NonNullable<ModelHooks<F>[K]>>
|
|
241
|
+
}
|
|
242
|
+
/** `redirect` replaces an operation with another (D-15). */
|
|
243
|
+
export type PluginRedirects<F, O, A> = {
|
|
244
|
+
readonly delete?: (
|
|
245
|
+
facts: {
|
|
246
|
+
readonly caller: Caller
|
|
247
|
+
readonly where: UniqueWhere<F>
|
|
248
|
+
} & PluginModel<F, O, A>,
|
|
249
|
+
) => Promise<unknown>
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** What a model gives a plugin's code. */
|
|
253
|
+
export interface PluginModel<F, O, A> {
|
|
254
|
+
/** The model's name (D-152). */
|
|
255
|
+
readonly name: string
|
|
256
|
+
readonly queries: Queries<F>
|
|
257
|
+
readonly options: O
|
|
258
|
+
readonly plugins: A
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
type CodePart<T, K extends 'commands' | 'addedFields', Out> = T extends {
|
|
262
|
+
readonly [P in K]: object
|
|
263
|
+
}
|
|
264
|
+
? { readonly [P in K]: Out }
|
|
265
|
+
: { readonly [P in K]?: never }
|
|
266
|
+
|
|
267
|
+
// A plugin without an API may still use the step that builds them, before
|
|
268
|
+
// any start, to call another plugin's API (D-107).
|
|
269
|
+
type ApiPart<T> = T extends { readonly api: object }
|
|
270
|
+
? { readonly api: (context: PluginContext<T>) => T['api'] }
|
|
271
|
+
: { readonly api?: (context: PluginContext<T>) => void }
|
|
272
|
+
|
|
273
|
+
/** A plugin's package, usually its imported `package.json` (D-57). */
|
|
274
|
+
export interface Manifest {
|
|
275
|
+
readonly name: string
|
|
276
|
+
readonly version: string
|
|
277
|
+
/** The ranges of `ultimabase` and of the plugins it needs. */
|
|
278
|
+
readonly peerDependencies?: { readonly [name: string]: string }
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
type PluginFn<N extends string> = (...args: never[]) => PluginValue<N, string>
|
|
282
|
+
// Each needed plugin's application value under its name (D-16): a missing,
|
|
283
|
+
// an extra or a swapped one is refused.
|
|
284
|
+
type Needs<K extends 'requires' | 'optional', N extends string> = [N] extends [
|
|
285
|
+
never,
|
|
286
|
+
]
|
|
287
|
+
? { readonly [P in K]?: never }
|
|
288
|
+
: { readonly [P in K]: { readonly [X in N]: PluginFn<X> } }
|
|
289
|
+
|
|
290
|
+
/** What a plugin's author writes (D-57). */
|
|
291
|
+
export type PluginDefinition<T extends PluginTypes> = {
|
|
292
|
+
readonly name: T['name']
|
|
293
|
+
readonly manifest: Manifest
|
|
294
|
+
/** The hooks it runs on each model that uses it. */
|
|
295
|
+
readonly hooks?: PluginHooks<
|
|
296
|
+
Own<T>,
|
|
297
|
+
EntryOptions<T>,
|
|
298
|
+
Apis<T>,
|
|
299
|
+
keyof ForModel<T, Own<T>>['commands'] & string
|
|
300
|
+
>
|
|
301
|
+
readonly redirect?: PluginRedirects<Own<T>, EntryOptions<T>, Apis<T>>
|
|
302
|
+
/** Runs once when the application starts (D-15). */
|
|
303
|
+
readonly start?: (context: PluginContext<T>) => void | Promise<void>
|
|
304
|
+
/** Runs once when the application stops: close, flush (D-15). */
|
|
305
|
+
readonly stop?: (context: PluginContext<T>) => void | Promise<void>
|
|
306
|
+
/**
|
|
307
|
+
* Who sends a request, or `undefined` when it is not the plugin's; the
|
|
308
|
+
* first plugin to know it wins, after the master key (D-112).
|
|
309
|
+
*/
|
|
310
|
+
readonly identify?: (
|
|
311
|
+
request: Request,
|
|
312
|
+
context: PluginContext<T>,
|
|
313
|
+
) => Promise<Identity | undefined>
|
|
314
|
+
/**
|
|
315
|
+
* The plugin's keys of a user caller, given once per caller the kernel
|
|
316
|
+
* receives, each plugin's in the order of `plugins` (D-121).
|
|
317
|
+
*/
|
|
318
|
+
readonly caller?: (
|
|
319
|
+
identity: { readonly kind: 'user'; readonly user: UserOf<Register> },
|
|
320
|
+
context: PluginContext<T>,
|
|
321
|
+
) => CallerKeys | Promise<CallerKeys>
|
|
322
|
+
/**
|
|
323
|
+
* What each commit changed, on any server: the adapter sends it only when
|
|
324
|
+
* a plugin takes it (D-154).
|
|
325
|
+
*/
|
|
326
|
+
readonly changed?: (
|
|
327
|
+
changes: readonly Changed[],
|
|
328
|
+
context: PluginContext<T>,
|
|
329
|
+
) => void
|
|
330
|
+
/** Changes may have been lost: what `changed` follows is unknown. */
|
|
331
|
+
readonly missed?: (context: PluginContext<T>) => void
|
|
332
|
+
/** Its own models, which no plugin is given (D-110). */
|
|
333
|
+
readonly models?: readonly ModelShape[]
|
|
334
|
+
/** The indexes it adds to each model that uses it (D-52, D-122). */
|
|
335
|
+
readonly addedIndexes?: readonly {
|
|
336
|
+
readonly fields: readonly (keyof Own<T> & string)[]
|
|
337
|
+
readonly unique?: boolean
|
|
338
|
+
/** A trigram index, for `contains` and `mode: 'insensitive'` (D-141). */
|
|
339
|
+
readonly contains?: true
|
|
340
|
+
}[]
|
|
341
|
+
/**
|
|
342
|
+
* Its `defineFunction` values, built once when the application starts and
|
|
343
|
+
* exposed as the application's are (D-113).
|
|
344
|
+
*/
|
|
345
|
+
readonly functions?: (
|
|
346
|
+
context: Omit<PluginContext<T>, 'functions'>,
|
|
347
|
+
) => readonly FunctionShape[]
|
|
348
|
+
} & CodePart<
|
|
349
|
+
T,
|
|
350
|
+
'commands',
|
|
351
|
+
(
|
|
352
|
+
model: PluginModel<Own<T>, EntryOptions<T>, Apis<T>>,
|
|
353
|
+
) => ForModel<T, Own<T>>['commands']
|
|
354
|
+
> &
|
|
355
|
+
ApiPart<T> &
|
|
356
|
+
CodePart<
|
|
357
|
+
T,
|
|
358
|
+
'addedFields',
|
|
359
|
+
(fields: FieldBuilders<never>, options: EntryOptions<T>) => Own<T>
|
|
360
|
+
> &
|
|
361
|
+
Needs<'requires', Requires<T>> &
|
|
362
|
+
Needs<'optional', Optional<T>>
|
|
363
|
+
|
|
364
|
+
/** A plugin's two values (D-24). */
|
|
365
|
+
export interface Plugin<T extends PluginTypes> {
|
|
366
|
+
readonly plugin: (
|
|
367
|
+
options?: AppOptions<T>,
|
|
368
|
+
) => PluginValue<T['name'], Requires<T>>
|
|
369
|
+
readonly use: PluginEntry<T>
|
|
370
|
+
}
|
|
371
|
+
/** Without options, the entry is the plugin's own types; with them, its
|
|
372
|
+
* types read the options' literal values. */
|
|
373
|
+
export interface PluginEntry<T extends PluginTypes> {
|
|
374
|
+
(): ModelUse<T['name'], T>
|
|
375
|
+
<const O extends EntryOptions<T>>(
|
|
376
|
+
options: O,
|
|
377
|
+
): ModelUse<T['name'], T & { readonly options: O }>
|
|
378
|
+
}
|
|
379
|
+
/** The type of a plugin's entry function, for its export. */
|
|
380
|
+
export type UseOf<T extends PluginTypes> = Plugin<T>['use']
|
|
381
|
+
/** The type of a plugin's application value function, for its export. */
|
|
382
|
+
export type PluginOf<T extends PluginTypes> = Plugin<T>['plugin']
|
|
383
|
+
|
|
384
|
+
export function definePlugin<T extends PluginTypes>(
|
|
385
|
+
definition: PluginDefinition<T>,
|
|
386
|
+
): Plugin<T> {
|
|
387
|
+
const code = pluginCode(definition)
|
|
388
|
+
const plugin = (options?: object): PluginValue<string, string> => {
|
|
389
|
+
const value = Object.freeze({ name: code.name, requires: code.requires })
|
|
390
|
+
pluginValues.set(value, { code, options: options ?? {} })
|
|
391
|
+
return value
|
|
392
|
+
}
|
|
393
|
+
const use = (options?: object): object => {
|
|
394
|
+
const entry = Object.freeze({ plugin: code.name, options })
|
|
395
|
+
pluginEntries.set(entry, { code, options: options ?? {} })
|
|
396
|
+
return entry
|
|
397
|
+
}
|
|
398
|
+
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- the two functions are Plugin<T>'s; their types follow T.
|
|
399
|
+
return { plugin, use } as unknown as Plugin<T>
|
|
400
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// `aggregate`'s arguments and result (D-143): the result has the keys the
|
|
2
|
+
// arguments ask for, each field typed.
|
|
3
|
+
import type { SortedKeys, Where } from './query.ts'
|
|
4
|
+
import type { StoredValue, SystemFields } from './record.ts'
|
|
5
|
+
import type { calendarDay, fieldType } from './symbols.ts'
|
|
6
|
+
|
|
7
|
+
/** A model's scalars that an aggregate takes: no list, json or plugin field. */
|
|
8
|
+
export type Aggregated<F> = SortedKeys<F> | keyof SystemFields
|
|
9
|
+
export type ValueOf<F, K> = K extends keyof SystemFields
|
|
10
|
+
? SystemFields[K]
|
|
11
|
+
: K extends keyof F
|
|
12
|
+
? NonNullable<StoredValue<F[K]>>
|
|
13
|
+
: never
|
|
14
|
+
/** The fields whose values are `V`. */
|
|
15
|
+
export type KeysWith<F, V> = {
|
|
16
|
+
[K in Aggregated<F>]: ValueOf<F, K> extends V ? K : never
|
|
17
|
+
}[Aggregated<F>]
|
|
18
|
+
/** Whether `X` is a decimal field (D-145), filtered and summed as a string. */
|
|
19
|
+
export type IsDecimal<X> = X extends {
|
|
20
|
+
readonly [fieldType]: { readonly options: { readonly precision: number } }
|
|
21
|
+
}
|
|
22
|
+
? true
|
|
23
|
+
: false
|
|
24
|
+
/** Whether `X` is a string compared in order: a decimal or a day (D-150). */
|
|
25
|
+
export type IsOrdered<X> =
|
|
26
|
+
IsDecimal<X> extends true
|
|
27
|
+
? true
|
|
28
|
+
: X extends {
|
|
29
|
+
readonly [fieldType]: {
|
|
30
|
+
readonly options: { readonly [calendarDay]: true }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
? true
|
|
34
|
+
: false
|
|
35
|
+
export type DecimalKeys<F> = {
|
|
36
|
+
[K in Aggregated<F>]: K extends keyof F
|
|
37
|
+
? IsDecimal<F[K]> extends true
|
|
38
|
+
? K
|
|
39
|
+
: never
|
|
40
|
+
: never
|
|
41
|
+
}[Aggregated<F>]
|
|
42
|
+
export type Summed<F> = KeysWith<F, number> | DecimalKeys<F>
|
|
43
|
+
type Fields<K extends PropertyKey> = { readonly [P in K]?: true | undefined }
|
|
44
|
+
|
|
45
|
+
export type AggregateArgs<F> = {
|
|
46
|
+
readonly where?: Where<F> | undefined
|
|
47
|
+
readonly _count?:
|
|
48
|
+
| true
|
|
49
|
+
| ({ readonly _all?: true | undefined } & Fields<Aggregated<F>>)
|
|
50
|
+
| undefined
|
|
51
|
+
readonly _sum?: Fields<Summed<F>> | undefined
|
|
52
|
+
readonly _avg?: Fields<Summed<F>> | undefined
|
|
53
|
+
readonly _min?: Fields<KeysWith<F, number | string | Date>> | undefined
|
|
54
|
+
readonly _max?: Fields<KeysWith<F, number | string | Date>> | undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type Asked<S> = {
|
|
58
|
+
[K in keyof S]: S[K] extends true ? K : never
|
|
59
|
+
}[keyof S]
|
|
60
|
+
/**
|
|
61
|
+
* One value per field `S` names: `null` when no row has one. An average is
|
|
62
|
+
* a number, a sum a number or a decimal's string, a minimum or a maximum
|
|
63
|
+
* the field's value.
|
|
64
|
+
*/
|
|
65
|
+
type Values<F, S, As extends 'sum' | 'avg' | 'value'> = {
|
|
66
|
+
readonly [K in Asked<S>]:
|
|
67
|
+
| (As extends 'avg'
|
|
68
|
+
? number
|
|
69
|
+
: As extends 'sum'
|
|
70
|
+
? K extends DecimalKeys<F>
|
|
71
|
+
? string
|
|
72
|
+
: number
|
|
73
|
+
: ValueOf<F, K>)
|
|
74
|
+
| null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** What `aggregate` returns for the arguments `A`. */
|
|
78
|
+
export type Aggregates<F, A> = (A extends { readonly _count: infer C }
|
|
79
|
+
? C extends true
|
|
80
|
+
? { readonly _count: number }
|
|
81
|
+
: C extends object
|
|
82
|
+
? { readonly _count: { readonly [K in Asked<C>]: number } }
|
|
83
|
+
: unknown
|
|
84
|
+
: unknown) &
|
|
85
|
+
(A extends { readonly _sum: infer S extends object }
|
|
86
|
+
? { readonly _sum: Values<F, S, 'sum'> }
|
|
87
|
+
: unknown) &
|
|
88
|
+
(A extends { readonly _avg: infer S extends object }
|
|
89
|
+
? { readonly _avg: Values<F, S, 'avg'> }
|
|
90
|
+
: unknown) &
|
|
91
|
+
(A extends { readonly _min: infer S extends object }
|
|
92
|
+
? { readonly _min: Values<F, S, 'value'> }
|
|
93
|
+
: unknown) &
|
|
94
|
+
(A extends { readonly _max: infer S extends object }
|
|
95
|
+
? { readonly _max: Values<F, S, 'value'> }
|
|
96
|
+
: unknown)
|