electrodb 1.11.1 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -94,7 +94,6 @@ tasks
94
94
 
95
95
  ------------
96
96
 
97
- ## Table of Contents
98
97
  - [ElectroDB](#electrodb)
99
98
  * [Features](#features)
100
99
  * [Table of Contents](#table-of-contents)
@@ -208,10 +207,10 @@ tasks
208
207
  - [AWS DynamoDB Client](#aws-dynamodb-client)
209
208
  * [V2 Client](#v2-client)
210
209
  * [V3 Client](#v3-client)
210
+ - [Logging](#logging)
211
211
  - [Events](#events)
212
212
  * [Query Event](#query-event)
213
213
  * [Results Event](#results-event)
214
- - [Logging](#logging)
215
214
  - [Listeners](#listeners)
216
215
  - [Errors:](#errors-)
217
216
  + [No Client Defined On Model](#no-client-defined-on-model)
@@ -273,17 +272,19 @@ tasks
273
272
  - [Stores will renewals for Q4](#stores-will-renewals-for-q4)
274
273
  - [Spite-stores with release renewals this year](#spite-stores-with-release-renewals-this-year)
275
274
  - [All Latte Larrys in a particular mall building](#all-latte-larrys-in-a-particular-mall-building)
276
- - [Exported TypeScript Types](#exported-typescript-types)
277
- * [EntityRecord Type](#entityrecord-type)
278
- * [EntityItem Type](#entityitem-type)
279
- * [CollectionItem Type](#collectionitem-type)
280
- * [CreateEntityItem Type](#createentityitem-type)
281
- * [UpdateEntityItem Type](#updateentityitem-type)
282
- * [UpdateAddEntityItem Type](#updateaddentityitem-type)
283
- * [UpdateSubtractEntityItem Type](#updatesubtractentityitem-type)
284
- * [UpdateAppendEntityItem Type](#updateappendentityitem-type)
285
- * [UpdateRemoveEntityItem Type](#updateremoveentityitem-type)
286
- * [UpdateDeleteEntityItem Type](#updatedeleteentityitem-type)
275
+ - [TypeScript](#typescript)
276
+ * [Custom Attributes](#custom-attributes)
277
+ * [Exported Types](#exported-types)
278
+ + [EntityRecord Type](#entityrecord-type)
279
+ + [EntityItem Type](#entityitem-type)
280
+ + [CollectionItem Type](#collectionitem-type)
281
+ + [CreateEntityItem Type](#createentityitem-type)
282
+ + [UpdateEntityItem Type](#updateentityitem-type)
283
+ + [UpdateAddEntityItem Type](#updateaddentityitem-type)
284
+ + [UpdateSubtractEntityItem Type](#updatesubtractentityitem-type)
285
+ + [UpdateAppendEntityItem Type](#updateappendentityitem-type)
286
+ + [UpdateRemoveEntityItem Type](#updateremoveentityitem-type)
287
+ + [UpdateDeleteEntityItem Type](#updatedeleteentityitem-type)
287
288
  - [Using ElectroDB With Existing Data](#using-electrodb-with-existing-data)
288
289
  - [Electro CLI](#electro-cli)
289
290
  - [Version 1 Migration](#version-1-migration)
@@ -776,7 +777,7 @@ attributes: {
776
777
 
777
778
  #### Set Attributes
778
779
 
779
- The Set attribute is arguably DynamoDB's most powerful type. ElectroDB supports String and Number Sets using the `items` property set as either `"string"` or `"number"`.
780
+ The Set attribute is arguably DynamoDB's most powerful type. ElectroDB supports String and Number Sets using the `items` property set as either `"string"`, `"number"`, or an array of strings or numbers. When a ReadonlyArray is provided, ElectroDB will enforce those values as a finite list of acceptable values, similar to an [Enum Attribute](#enum-attributes)
780
781
 
781
782
  In addition to having the same modeling benefits you get with other attributes, ElectroDB also simplifies the use of Sets by removing the need to use DynamoDB's special `createSet` class to work with Sets. ElectroDB Set Attributes accept Arrays, JavaScript native Sets, and objects from `createSet` as values. ElectroDB will manage the casting of values to a DynamoDB Set value prior to saving and ElectroDB will also convert Sets back to JavaScript arrays on retrieval.
782
783
 
@@ -791,6 +792,14 @@ attributes: {
791
792
  myNumberSet: {
792
793
  type: "set",
793
794
  items: "number"
795
+ },
796
+ myEnumStringSet: {
797
+ type: "set",
798
+ items: ["RED", "GREEN", "BLUE"] as const // electrodb will only accept the included values "RED", "GREEN", and/or "BLUE"
799
+ },
800
+ myEnumNumberSet: {
801
+ type: "set",
802
+ items: [1, 2, 3] as const // electrodb will only accept the included values 1, 2, and/or 3
794
803
  }
795
804
  }
796
805
  ```
@@ -1097,17 +1106,17 @@ indexes: {
1097
1106
  | Property | Type | Required | Description |
1098
1107
  | -------------- | :------------------------------------: | :------: | ----------- |
1099
1108
  | `pk` | `object` | yes | Configuration for the pk of that index or table
1100
- | `pk.composite` | `string | string[]` | yes | An array that represents the order in which attributes are concatenated to composite attributes the key (see [Composite Attributes](#composite-attributes) below for more on this functionality).
1109
+ | `pk.composite` | `string[]` | yes | An array that represents the order in which attributes are concatenated to composite attributes the key (see [Composite Attributes](#composite-attributes) below for more on this functionality).
1101
1110
  | `pk.template` | `string` | no | A string that represents the template in which attributes composed to form a key (see [Composite Attribute Templates](#composite-attribute-templates) below for more on this functionality).
1102
1111
  | `pk.field` | `string` | yes | The name of the attribute as it exists in DynamoDB, if named differently in the schema attributes.
1103
- | `pk.casing` | `default` | `upper` | `lower` | `none` | no | Choose a case for ElectroDB to convert your keys to, to avoid casing pitfalls when querying data. Default: `lower`.
1112
+ | `pk.casing` | `default`, `upper`, `lower`, `none` | no | Choose a case for ElectroDB to convert your keys to, to avoid casing pitfalls when querying data. Default: `lower`.
1104
1113
  | `sk` | `object` | no | Configuration for the sk of that index or table
1105
- | `sk.composite` | `string | string[]` | no | Either an Array that represents the order in which attributes are concatenated to composite attributes the key, or a String for a composite attribute template. (see [Composite Attributes](#composite-attributes) below for more on this functionality).
1114
+ | `sk.composite` | `string[]` | no | Either an Array that represents the order in which attributes are concatenated to composite attributes the key, or a String for a composite attribute template. (see [Composite Attributes](#composite-attributes) below for more on this functionality).
1106
1115
  | `sk.template` | `string` | no | A string that represents the template in which attributes composed to form a key (see [Composite Attribute Templates](#composite-attribute-templates) below for more on this functionality).
1107
1116
  | `sk.field` | `string` | yes | The name of the attribute as it exists in DynamoDB, if named differently in the schema attributes.
1108
- | `pk.casing` | `default` | `upper` | `lower` | `none` | no | Choose a case for ElectroDB to convert your keys to, to avoid casing pitfalls when querying data. Default: `lower`.
1117
+ | `pk.casing` | `default`, `upper`, `lower`, `none`, | no | Choose a case for ElectroDB to convert your keys to, to avoid casing pitfalls when querying data. Default: `lower`.
1109
1118
  | `index` | `string` | no | Required when the `Index` defined is a *Secondary Index*; but is left blank for the table's primary index.
1110
- | `collection` | `string | string[]` | no | Used when models are joined to a `Service`. When two entities share a `collection` on the same `index`, they can be queried with one request to DynamoDB. The name of the collection should represent what the query would return as a pseudo `Entity`. (see [Collections](#collections) below for more on this functionality).
1119
+ | `collection` | `string`, `string[]` | no | Used when models are joined to a `Service`. When two entities share a `collection` on the same `index`, they can be queried with one request to DynamoDB. The name of the collection should represent what the query would return as a pseudo `Entity`. (see [Collections](#collections) below for more on this functionality).
1111
1120
 
1112
1121
  ### Indexes Without Sort Keys
1113
1122
  When using indexes without Sort Keys, that should be expressed as an index *without* an `sk` property at all. Indexes without an `sk` cannot have a collection, see [Collections](#collections) for more detail.
@@ -1465,7 +1474,7 @@ When your attribute's name, or [`field` property](#expanded-syntax) on an attrib
1465
1474
  }
1466
1475
  ```
1467
1476
 
1468
- [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3jBUANwrpoOALxxUFAO4p0mLAAoEHOJrggIjagC5EGrSbEZshslggBXKAH0zy)
1477
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwL5wGZQQhwDkApgDZkDGMhAJgEYkDcAUG9RCgM7zAoAbmTTRMcALxwUZAO5xU6LAAoEbOHBAR6lAFyJ1GuCKWZ9AIkwQArlAD6JjJjsoAhiDLmANIY08yUILA1GQWVrZ2-oHBZC7unj5GcMJQPMDcFgCM5obYiXCuMHTAjNYwZDz6akmu1FzWaACS9FW+RlhgoXDmfFACAOY5SXltYAzWtABy1iCMAa1JGh1d5igzc1BDRti5+QI6AB4VC0Zj2hMwlQaLcGAA1ic3eMCULd219U303m1JXOAQNLlfQAbXMHxsX3MAF1fnARjceA9rjd8C8KG9zGd6BdprMAj9UXB-pAgV0wdjcesCbCbjthrk2HlEDBXIwqPoSCBMAAVNlUEjYACU7E43D4BTqkJgzUk7zqMAAtAAWACsAGYAAzmdhcXjwSlTalQOUAJk1msyooEwlEUEwhgAdGAyqpJZ8ZfQvLdxkb8SbhU7+hBlCKODaTGJHQBHawBB1JZ2+y6qCENT2BxPB0PsIA)
1469
1478
 
1470
1479
  **Using `template`**
1471
1480
 
@@ -5616,11 +5625,62 @@ let storeId = "LatteLarrys";
5616
5625
  let stores = await StoreLocations.malls({mallId}).query({buildingId, storeId}).go();
5617
5626
  ```
5618
5627
 
5619
- # Exported TypeScript Types
5628
+ # TypeScript
5629
+ ElectroDB using advanced dynamic typing techniques to automatically create types based on the configurations in your model. Changes to your model will automatically change the types returned by ElectroDB.
5630
+
5631
+ ## Custom Attributes
5632
+ If you have a need for a custom attribute type (beyond those supported by ElectroDB) you can use the the export function `createCustomAttribute`. This function takes an attribute definition and allows you to specify a custom typed attribute with ElectroDB:
5633
+
5634
+ > _NOTE: creating a custom type, ElectroDB will enforce attribute constraints based on the attribute definition provided, but will yield typing control to the user. This may result in some mismatches between your typing and the constraints enforced by ElectroDB._
5635
+
5636
+ ```typescript
5637
+ import { Entity, createCustomAttribute } from 'electrodb';
5638
+
5639
+ type PersonnelRole = {
5640
+ type: 'employee';
5641
+ startDate: string;
5642
+ endDate?: string;
5643
+ } | {
5644
+ type: 'contractor';
5645
+ contractStartDate: string;
5646
+ contractEndDate: string;
5647
+ };
5648
+
5649
+ const table = 'workplace_table';
5650
+ const person = new Entity({
5651
+ model: {
5652
+ entity: 'personnel',
5653
+ service: 'workplace',
5654
+ version: '1'
5655
+ },
5656
+ attributes: {
5657
+ id: {
5658
+ type: 'string'
5659
+ },
5660
+ role: createCustomAttribute<PersonnelRole>({
5661
+ required: true,
5662
+ }),
5663
+ },
5664
+ indexes: {
5665
+ record: {
5666
+ pk: {
5667
+ field: 'pk',
5668
+ compose: ['id']
5669
+ },
5670
+ sk: {
5671
+ field: 'sk',
5672
+ compose: [],
5673
+ }
5674
+ }
5675
+ }
5676
+ }, { table });
5677
+ ```
5678
+
5679
+ ## Exported Types
5620
5680
 
5621
5681
  The following types are exported for easier use while using ElectroDB with TypeScript:
5622
5682
 
5623
- ## EntityRecord Type
5683
+ ### EntityRecord Type
5624
5684
 
5625
5685
  The EntityRecord type is an object containing every attribute an Entity's model.
5626
5686
 
@@ -5638,7 +5698,7 @@ _Use:_
5638
5698
  type EntiySchema = EntityRecord<typeof MyEntity>
5639
5699
  ```
5640
5700
 
5641
- ## EntityItem Type
5701
+ ### EntityItem Type
5642
5702
 
5643
5703
  This type represents an item as it is returned from a query. This is different from the `EntityRecord` in that this type reflects the `required`, `hidden`, `default`, etc properties defined on the attribute.
5644
5704
 
@@ -5657,7 +5717,7 @@ _Use:_
5657
5717
  type Thing = EntityItem<typeof MyEntityInstance>;
5658
5718
  ```
5659
5719
 
5660
- ## CollectionItem Type
5720
+ ### CollectionItem Type
5661
5721
 
5662
5722
  This type represents the value returned from a collection query, and is similar to EntityItem.
5663
5723
 
@@ -5667,7 +5727,7 @@ _Use:_
5667
5727
  type CollectionResults = CollectionItem<typeof MyServiceInstance, "collectionName">
5668
5728
  ```
5669
5729
 
5670
- ## CreateEntityItem Type
5730
+ ### CreateEntityItem Type
5671
5731
 
5672
5732
  This type represents an item that you would pass your entity's `put` or `create` method
5673
5733
 
@@ -5686,7 +5746,7 @@ _Use:_
5686
5746
  type NewThing = CreateEntityItem<typeof MyEntityInstance>;
5687
5747
  ```
5688
5748
 
5689
- ## UpdateEntityItem Type
5749
+ ### UpdateEntityItem Type
5690
5750
 
5691
5751
  This type represents an item that you would pass your entity's `set` method when using `create` or `update`.
5692
5752
 
@@ -5705,8 +5765,7 @@ _Use:_
5705
5765
  type UpdateProperties = UpdateEntityItem<typeof MyEntityInstance>;
5706
5766
  ```
5707
5767
 
5708
-
5709
- ## UpdateAddEntityItem Type
5768
+ ### UpdateAddEntityItem Type
5710
5769
 
5711
5770
  This type represents an item that you would pass your entity's `add` method when using `create` or `update`.
5712
5771
 
@@ -5719,7 +5778,7 @@ export type UpdateAddEntityItem<E extends Entity<any, any, any, any>> =
5719
5778
 
5720
5779
  `````
5721
5780
 
5722
- ## UpdateSubtractEntityItem Type
5781
+ ### UpdateSubtractEntityItem Type
5723
5782
 
5724
5783
  This type represents an item that you would pass your entity's `subtract` method when using `create` or `update`.
5725
5784
 
@@ -5731,7 +5790,7 @@ export type UpdateSubtractEntityItem<E extends Entity<any, any, any, any>> =
5731
5790
  : never;
5732
5791
  ```
5733
5792
 
5734
- ## UpdateAppendEntityItem Type
5793
+ ### UpdateAppendEntityItem Type
5735
5794
 
5736
5795
  This type represents an item that you would pass your entity's `append` method when using `create` or `update`.
5737
5796
 
@@ -5743,7 +5802,7 @@ export type UpdateAppendEntityItem<E extends Entity<any, any, any, any>> =
5743
5802
  : never;
5744
5803
  ```
5745
5804
 
5746
- ## UpdateRemoveEntityItem Type
5805
+ ### UpdateRemoveEntityItem Type
5747
5806
 
5748
5807
  This type represents an item that you would pass your entity's `remove` method when using `create` or `update`.
5749
5808
 
@@ -5755,7 +5814,7 @@ export type UpdateRemoveEntityItem<E extends Entity<any, any, any, any>> =
5755
5814
  : never;
5756
5815
  ```
5757
5816
 
5758
- ## UpdateDeleteEntityItem Type
5817
+ ### UpdateDeleteEntityItem Type
5759
5818
 
5760
5819
  This type represents an item that you would pass your entity's `delete` method when using `create` or `update`.
5761
5820
 
package/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  export type DocumentClientMethod = (parameters: any) => {promise: () => Promise<any>};
2
3
 
3
4
  export type DocumentClient = {
@@ -848,7 +849,6 @@ export interface NestedEnumAttribute {
848
849
  readonly label?: string;
849
850
  }
850
851
 
851
-
852
852
  export interface EnumAttribute {
853
853
  readonly type: ReadonlyArray<string>;
854
854
  readonly required?: boolean;
@@ -1032,6 +1032,60 @@ export interface NestedStringSetAttribute {
1032
1032
  readonly field?: string;
1033
1033
  }
1034
1034
 
1035
+ export interface NestedEnumNumberSetAttribute {
1036
+ readonly type: "set";
1037
+ readonly items: ReadonlyArray<number>;
1038
+ readonly required?: boolean;
1039
+ readonly hidden?: boolean;
1040
+ readonly readOnly?: boolean;
1041
+ readonly get?: (val: Array<number>, item: any) => Array<number> | undefined | void;
1042
+ readonly set?: (val?: Array<number>, item?: any) => Array<number> | undefined | void;
1043
+ readonly default?: Array<number> | (() => Array<number>);
1044
+ readonly validate?: ((val: Array<number>) => boolean) | ((val: Array<number>) => void) | ((val: Array<number>) => string | void) | RegExp;
1045
+ readonly field?: string;
1046
+ }
1047
+
1048
+ export interface EnumNumberSetAttribute {
1049
+ readonly type: "set";
1050
+ readonly items: ReadonlyArray<number>;
1051
+ readonly required?: boolean;
1052
+ readonly hidden?: boolean;
1053
+ readonly readOnly?: boolean;
1054
+ readonly get?: (val: Array<number>, item: any) => Array<number> | undefined | void;
1055
+ readonly set?: (val?: Array<number>, item?: any) => Array<number> | undefined | void;
1056
+ readonly default?: Array<number> | (() => Array<number>);
1057
+ readonly validate?: ((val: Array<number>) => boolean) | ((val: Array<number>) => void) | ((val: Array<number>) => string | void) | RegExp;
1058
+ readonly field?: string;
1059
+ readonly watch?: ReadonlyArray<string> | "*";
1060
+ }
1061
+
1062
+ export interface NestedEnumStringSetAttribute {
1063
+ readonly type: "set";
1064
+ readonly items: ReadonlyArray<string>;
1065
+ readonly required?: boolean;
1066
+ readonly hidden?: boolean;
1067
+ readonly readOnly?: boolean;
1068
+ readonly get?: (val: Array<string>, item: any) => Array<string> | undefined | void;
1069
+ readonly set?: (val?: Array<string>, item?: any) => Array<string> | undefined | void;
1070
+ readonly default?: Array<string> | (() => Array<string>);
1071
+ readonly validate?: ((val: Array<string>) => boolean) | ((val: Array<string>) => void) | ((val: Array<string>) => string | void) | RegExp;
1072
+ readonly field?: string;
1073
+ }
1074
+
1075
+ export interface EnumStringSetAttribute {
1076
+ readonly type: "set";
1077
+ readonly items: ReadonlyArray<string>;
1078
+ readonly required?: boolean;
1079
+ readonly hidden?: boolean;
1080
+ readonly readOnly?: boolean;
1081
+ readonly get?: (val: Array<string>, item: any) => Array<string> | undefined | void;
1082
+ readonly set?: (val?: Array<string>, item?: any) => Array<string> | undefined | void;
1083
+ readonly default?: Array<string> | (() => Array<string>);
1084
+ readonly validate?: ((val: Array<string>) => boolean) | ((val: Array<string>) => void) | ((val: Array<string>) => string | void) | RegExp;
1085
+ readonly field?: string;
1086
+ readonly watch?: ReadonlyArray<string> | "*";
1087
+ }
1088
+
1035
1089
  export interface StringSetAttribute {
1036
1090
  readonly type: "set";
1037
1091
  readonly items: "string";
@@ -1073,6 +1127,25 @@ export interface NumberSetAttribute {
1073
1127
  readonly watch?: ReadonlyArray<string> | "*";
1074
1128
  }
1075
1129
 
1130
+ type StaticAttribute = {
1131
+ readonly type: "static";
1132
+ readonly hidden?: boolean;
1133
+ value: string | number | boolean;
1134
+ readonly field?: string;
1135
+ }
1136
+
1137
+ type CustomAttribute<T extends any = any> = {
1138
+ readonly type: "custom";
1139
+ readonly [CustomAttributeSymbol]: T;
1140
+ readonly hidden?: boolean;
1141
+ readonly get?: (val: T, item: any) => T | undefined | void;
1142
+ readonly set?: (val?: T, item?: any) => T | undefined | void;
1143
+ readonly default?: T | (() => T);
1144
+ readonly validate?: ((val: T) => boolean) | ((val: T) => void) | ((val: T) => string | void);
1145
+ readonly field?: string;
1146
+ readonly watch?: ReadonlyArray<string> | "*";
1147
+ };
1148
+
1076
1149
  export type Attribute =
1077
1150
  BooleanAttribute
1078
1151
  | NumberAttribute
@@ -1084,7 +1157,11 @@ export type Attribute =
1084
1157
  | NumberSetAttribute
1085
1158
  | StringListAttribute
1086
1159
  | NumberListAttribute
1087
- | MapListAttribute;
1160
+ | MapListAttribute
1161
+ | StaticAttribute
1162
+ | CustomAttribute
1163
+ | EnumNumberSetAttribute
1164
+ | EnumStringSetAttribute;
1088
1165
 
1089
1166
  export type NestedAttributes =
1090
1167
  NestedBooleanAttribute
@@ -1097,7 +1174,10 @@ export type NestedAttributes =
1097
1174
  | NestedMapListAttribute
1098
1175
  | NestedStringSetAttribute
1099
1176
  | NestedNumberSetAttribute
1100
- | NestedEnumAttribute;
1177
+ | NestedEnumAttribute
1178
+ | NestedEnumAttribute
1179
+ | NestedEnumNumberSetAttribute
1180
+ | NestedEnumStringSetAttribute;
1101
1181
 
1102
1182
  export interface IndexWithSortKey {
1103
1183
  readonly sk: {
@@ -1171,7 +1251,9 @@ type PartialDefinedKeys<T> = {
1171
1251
  }
1172
1252
 
1173
1253
  export type ItemAttribute<A extends Attribute> =
1174
- A["type"] extends infer R
1254
+ A extends CustomAttribute<infer T>
1255
+ ? T
1256
+ : A["type"] extends infer R
1175
1257
  ? R extends "string" ? string
1176
1258
  : R extends "number" ? number
1177
1259
  : R extends "boolean" ? boolean
@@ -1200,7 +1282,8 @@ export type ItemAttribute<A extends Attribute> =
1200
1282
  ? A["items"] extends infer I
1201
1283
  ? I extends "string" ? string[]
1202
1284
  : I extends "number" ? number[]
1203
- : never
1285
+ : I extends ReadonlyArray<infer ENUM> ? ENUM[]
1286
+ : never
1204
1287
  : never
1205
1288
  : never
1206
1289
  : R extends "any" ? any
@@ -1208,8 +1291,11 @@ export type ItemAttribute<A extends Attribute> =
1208
1291
  : never
1209
1292
 
1210
1293
  export type ReturnedAttribute<A extends Attribute> =
1211
- A["type"] extends infer R
1212
- ? R extends "string" ? string
1294
+ A extends CustomAttribute<infer T>
1295
+ ? T
1296
+ : A["type"] extends infer R
1297
+ ? R extends "static" ? never
1298
+ : R extends "string" ? string
1213
1299
  : R extends "number" ? number
1214
1300
  : R extends "boolean" ? boolean
1215
1301
  : R extends ReadonlyArray<infer E> ? E
@@ -1251,7 +1337,8 @@ export type ReturnedAttribute<A extends Attribute> =
1251
1337
  ? A["items"] extends infer I
1252
1338
  ? I extends "string" ? string[]
1253
1339
  : I extends "number" ? number[]
1254
- : never
1340
+ : I extends ReadonlyArray<infer ENUM> ? ENUM[]
1341
+ : never
1255
1342
  : never
1256
1343
  : never
1257
1344
  : R extends "any" ? any
@@ -1259,8 +1346,11 @@ export type ReturnedAttribute<A extends Attribute> =
1259
1346
  : never
1260
1347
 
1261
1348
  export type CreatedAttribute<A extends Attribute> =
1262
- A["type"] extends infer R
1263
- ? R extends "string" ? string
1349
+ A extends CustomAttribute<infer T>
1350
+ ? T
1351
+ : A["type"] extends infer R
1352
+ ? R extends "static" ? never
1353
+ : R extends "string" ? string
1264
1354
  : R extends "number" ? number
1265
1355
  : R extends "boolean" ? boolean
1266
1356
  : R extends ReadonlyArray<infer E> ? E
@@ -1302,7 +1392,8 @@ export type CreatedAttribute<A extends Attribute> =
1302
1392
  ? A["items"] extends infer I
1303
1393
  ? I extends "string" ? string[]
1304
1394
  : I extends "number" ? number[]
1305
- : never
1395
+ : I extends ReadonlyArray<infer ENUM> ? ENUM[]
1396
+ : never
1306
1397
  : never
1307
1398
  : never
1308
1399
  : R extends "any" ? any
@@ -1318,10 +1409,13 @@ export type CreatedItem<A extends string, F extends string, C extends string, S
1318
1409
  }
1319
1410
 
1320
1411
  export type EditableItemAttribute<A extends Attribute> =
1321
- A extends ReadOnlyAttribute
1412
+ A extends CustomAttribute<infer T>
1413
+ ? T
1414
+ : A extends ReadOnlyAttribute
1322
1415
  ? never
1323
1416
  : A["type"] extends infer R
1324
- ? R extends "string" ? string
1417
+ ? R extends "static" ? never
1418
+ : R extends "string" ? string
1325
1419
  : R extends "number" ? number
1326
1420
  : R extends "boolean" ? boolean
1327
1421
  : R extends ReadonlyArray<infer E> ? E
@@ -1353,7 +1447,8 @@ export type EditableItemAttribute<A extends Attribute> =
1353
1447
  ? A["items"] extends infer I
1354
1448
  ? I extends "string" ? string[]
1355
1449
  : I extends "number" ? number[]
1356
- : never
1450
+ : I extends ReadonlyArray<infer ENUM> ? ENUM[]
1451
+ : never
1357
1452
  : never
1358
1453
  : never
1359
1454
  : R extends "any" ? any
@@ -1361,10 +1456,13 @@ export type EditableItemAttribute<A extends Attribute> =
1361
1456
  : never
1362
1457
 
1363
1458
  export type UpdatableItemAttribute<A extends Attribute> =
1364
- A extends ReadOnlyAttribute
1459
+ A extends CustomAttribute<infer T>
1460
+ ? T
1461
+ : A extends ReadOnlyAttribute
1365
1462
  ? never
1366
1463
  : A["type"] extends infer R
1367
- ? R extends "string" ? string
1464
+ ? R extends "static" ? never
1465
+ : R extends "string" ? string
1368
1466
  : R extends "number" ? number
1369
1467
  : R extends "boolean" ? boolean
1370
1468
  : R extends ReadonlyArray<infer E> ? E
@@ -1411,7 +1509,8 @@ export type UpdatableItemAttribute<A extends Attribute> =
1411
1509
  ? A["items"] extends infer I
1412
1510
  ? I extends "string" ? string[]
1413
1511
  : I extends "number" ? number[]
1414
- : never
1512
+ : I extends ReadonlyArray<infer ENUM> ? ENUM[]
1513
+ : never
1415
1514
  : never
1416
1515
  : never
1417
1516
  : R extends "any" ? any
@@ -1419,10 +1518,13 @@ export type UpdatableItemAttribute<A extends Attribute> =
1419
1518
  : never
1420
1519
 
1421
1520
  export type RemovableItemAttribute<A extends Attribute> =
1422
- A extends ReadOnlyAttribute | RequiredAttribute
1521
+ A extends CustomAttribute<infer T>
1522
+ ? T
1523
+ : A extends ReadOnlyAttribute | RequiredAttribute
1423
1524
  ? never
1424
1525
  : A["type"] extends infer R
1425
- ? R extends "string" ? string
1526
+ ? R extends "static" ? never
1527
+ : R extends "string" ? string
1426
1528
  : R extends "number" ? number
1427
1529
  : R extends "boolean" ? boolean
1428
1530
  : R extends ReadonlyArray<infer E> ? E
@@ -1454,7 +1556,8 @@ export type RemovableItemAttribute<A extends Attribute> =
1454
1556
  ? A["items"] extends infer I
1455
1557
  ? I extends "string" ? string[]
1456
1558
  : I extends "number" ? number[]
1457
- : never
1559
+ : I extends ReadonlyArray<infer ENUM> ? ENUM[]
1560
+ : never
1458
1561
  : never
1459
1562
  : never
1460
1563
  : R extends "any" ? any
@@ -1599,7 +1702,7 @@ export type RemoveItem<A extends string, F extends string, C extends string, S e
1599
1702
  export type AppendItem<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> =
1600
1703
  {
1601
1704
  [
1602
- P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends 'list' | 'any'
1705
+ P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends 'list' | 'any' | 'custom'
1603
1706
  ? P
1604
1707
  : never
1605
1708
  ]?: P extends keyof SetItem<A,F,C,S>
@@ -1610,7 +1713,7 @@ export type AppendItem<A extends string, F extends string, C extends string, S e
1610
1713
  export type AddItem<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> =
1611
1714
  {
1612
1715
  [
1613
- P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends "number" | "any" | "set"
1716
+ P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends 'number' | 'any' | 'set' | 'custom'
1614
1717
  ? P
1615
1718
  : never
1616
1719
  ]?: P extends keyof SetItem<A,F,C,S>
@@ -1621,7 +1724,7 @@ export type AddItem<A extends string, F extends string, C extends string, S exte
1621
1724
  export type SubtractItem<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> =
1622
1725
  {
1623
1726
  [
1624
- P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends "number" | "any"
1727
+ P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends 'number' | 'any' | 'custom'
1625
1728
  ? P
1626
1729
  : never
1627
1730
  ]?: P extends keyof SetItem<A,F,C,S>
@@ -1632,7 +1735,7 @@ export type SubtractItem<A extends string, F extends string, C extends string, S
1632
1735
  export type DeleteItem<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> =
1633
1736
  {
1634
1737
  [
1635
- P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends "any" | "set"
1738
+ P in keyof ItemTypeDescription<A,F,C,S> as ItemTypeDescription<A,F,C,S>[P] extends 'any' | 'set' | 'custom'
1636
1739
  ? P
1637
1740
  : never
1638
1741
  ]?: P extends keyof SetItem<A,F,C,S>
@@ -1642,6 +1745,7 @@ export type DeleteItem<A extends string, F extends string, C extends string, S e
1642
1745
 
1643
1746
  export declare const WhereSymbol: unique symbol;
1644
1747
  export declare const UpdateDataSymbol: unique symbol;
1748
+ export declare const CustomAttributeSymbol: unique symbol;
1645
1749
 
1646
1750
  export type WhereAttributeSymbol<T extends any> =
1647
1751
  { [WhereSymbol]: void }
@@ -1821,4 +1925,18 @@ export class Service<E extends {[name: string]: Entity<any, any, any, any>}> {
1821
1925
  entities: E;
1822
1926
  collections: CollectionQueries<E, CollectionAssociations<E>>
1823
1927
  constructor(entities: E, config?: ServiceConfiguration);
1824
- }
1928
+ }
1929
+
1930
+ type CustomAttributeDefinition<T> = {
1931
+ readonly required?: boolean;
1932
+ readonly hidden?: boolean;
1933
+ readonly readOnly?: boolean;
1934
+ readonly get?: (val: T, item: any) => T | undefined | void;
1935
+ readonly set?: (val?: T, item?: any) => T | undefined | void;
1936
+ readonly default?: T | (() => T);
1937
+ readonly validate?: ((val: T) => boolean) | ((val: T) => void) | ((val: T) => string | void);
1938
+ readonly field?: string;
1939
+ readonly watch?: ReadonlyArray<string> | "*";
1940
+ }
1941
+
1942
+ declare function createCustomAttribute<T>(definition?: CustomAttributeDefinition<T>): CustomAttribute<T>;
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const { Entity } = require("./src/entity");
2
2
  const { Service } = require("./src/service");
3
+ const { createCustomAttribute } = require('./src/schema');
3
4
 
4
- module.exports = { Entity, Service };
5
+ module.exports = { Entity, Service, createCustomAttribute };
package/notes ADDED
@@ -0,0 +1,45 @@
1
+ /*
2
+
3
+ todo: better param typing
4
+ done: get typing
5
+ todo: get implementation
6
+ done: get[] typing
7
+ todo: get[] implementation
8
+ done: delete typing
9
+ todo: delete implementation
10
+ done: delete[] typing
11
+ todo: delete[] implementation
12
+ done: put[] typing
13
+ todo: put[] implementation
14
+ done: put typing
15
+ todo: put implementation
16
+ todo: update typing
17
+ done: update implementation
18
+ done: SetRecord
19
+ done: RemoveRecord
20
+ done: DataUpdateMethodRecord
21
+
22
+ done: scan typing
23
+ todo: scan implementation
24
+ done: query typing
25
+ todo: query implementation
26
+ done: find typing
27
+ todo: find implementation
28
+ done: match typing
29
+ todo: match implementation
30
+ done: parse typing
31
+ todo: parse implementation (requires cursor?)
32
+ todo: collection query
33
+ todo: collection impl
34
+
35
+ todo: add where to go?
36
+ todo: rethink option names
37
+
38
+ todo: add cursor to query options
39
+ todo: remove old doc notes on `join` and slim down `service`
40
+
41
+
42
+
43
+ find and test any add on set and number
44
+ try number enum?
45
+ integration test enum set ts