wirejs-resources 0.1.35-table-resource → 0.1.37-table-resource

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export { withContext, requiresContext, Context, ContextWrapped } from './adapter
6
6
  export { Resource } from './resource.js';
7
7
  export { overrides } from './overrides.js';
8
8
  export { Secret } from './resources/secret.js';
9
- export { AnyKeyFieldOption, DistributedTable, DistributedTableOptions, Filter, FieldComparison, FieldComparisonOptions, FieldType, KeyFieldDefinition, KeyFieldOptions, Parser, PassThruParser, PKFieldTypes, RecordType, RecordKey, matchesFilter, } from './resources/distributed-table.js';
10
- export * from './types.js';
9
+ export { DistributedTable, PassThruParser, matchesFilter, indexName } from './resources/distributed-table.js';
10
+ export type * from './resources/distributed-table.js';
11
+ export * from './types/index.js';
11
12
  export * from './derived-types.js';
package/dist/index.js CHANGED
@@ -6,6 +6,6 @@ export { withContext, requiresContext, Context } from './adapters/context.js';
6
6
  export { Resource } from './resource.js';
7
7
  export { overrides } from './overrides.js';
8
8
  export { Secret } from './resources/secret.js';
9
- export { DistributedTable, PassThruParser, matchesFilter, } from './resources/distributed-table.js';
10
- export * from './types.js';
9
+ export { DistributedTable, PassThruParser, matchesFilter, indexName } from './resources/distributed-table.js';
10
+ export * from './types/index.js';
11
11
  export * from './derived-types.js';
@@ -1,62 +1,6 @@
1
1
  import { Resource } from '../resource.js';
2
- export type KindaPretty<T> = T extends object ? {
3
- [K in keyof T]: KindaPretty<T[K]>;
4
- } : T;
5
- export type PKFieldTypes = 'string' | 'number';
6
- export type DistributedTableOptions<T> = {
7
- parse: Parser<T>;
8
- key: {
9
- partition: AnyKeyFieldOption<T>;
10
- sort?: AnyKeyFieldOption<T>;
11
- };
12
- };
13
- export type KeyFieldOptions<T> = {
14
- [K in keyof T as K extends string ? K : never]: K extends string ? KeyFieldDefinition<T, K, T[K]> : never;
15
- };
16
- export type AnyKeyFieldOption<T> = KeyFieldOptions<T>[keyof KeyFieldOptions<T>];
17
- export type KeyFieldDefinition<T, FieldName extends string & keyof T, FieldType> = FieldType extends number ? {
18
- field: FieldName & keyof T;
19
- type: 'number';
20
- } : {
21
- field: FieldName & keyof T;
22
- type: 'string';
23
- };
24
- export type Parser<T> = (record: Record<string, any>) => T;
25
- export type RecordType<T extends DistributedTableOptions<any>> = T extends DistributedTableOptions<infer IT> ? IT : Record<string, any>;
26
- export type RecordKey<T, PK extends AnyKeyFieldOption<T>, SK extends AnyKeyFieldOption<T> | undefined> = Pick<T, PK['field'] | (SK extends Record<string, any> ? (SK extends undefined ? never : SK['field']) : never)>;
27
- export type FieldType<T> = undefined extends T ? (T | null) : T;
28
- export type FieldComparisonOptions<T> = {
29
- [K in keyof T & string]?: {
30
- eq: FieldType<T[K]>;
31
- } | {
32
- ne: FieldType<T[K]>;
33
- } | {
34
- gt: FieldType<T[K]>;
35
- } | {
36
- ge: FieldType<T[K]>;
37
- } | {
38
- lt: FieldType<T[K]>;
39
- } | {
40
- le: FieldType<T[K]>;
41
- } | {
42
- between: [FieldType<T[K]>, FieldType<T[K]>];
43
- } | {
44
- beginsWith: FieldType<T[K]>;
45
- };
46
- };
47
- export type FieldComparison<T> = {
48
- [K in keyof FieldComparisonOptions<T>]: Record<K, FieldComparisonOptions<T>[K]> & NoneOf<Exclude<keyof FieldComparisonOptions<T>, K>>;
49
- }[keyof FieldComparisonOptions<T>];
50
- export type NoneOf<Fields> = {
51
- [K in Fields & string]?: never;
52
- };
53
- export type Filter<T> = (FieldComparison<T> & NoneOf<'and' | 'or' | 'not'>) | ({
54
- and: (Filter<T>)[];
55
- } & NoneOf<keyof T | 'or' | 'not'>) | ({
56
- or: (Filter<T>)[];
57
- } & NoneOf<keyof T | 'and' | 'not'>) | ({
58
- not: Filter<T>;
59
- } & NoneOf<keyof T | 'and' | 'or'>);
2
+ import { AllIndexesByName, AnyDistributedTable, Filter, Index, IndexFieldNames, IndexName, KeyCondition, KindaPretty, Parser, RecordKey } from '../types/resources/distributed-table.js';
3
+ export declare function indexName<Idx extends Index<any>>(index: Idx): IndexName<Idx>;
60
4
  export declare function matchesFilter<T>(record: T, filter: Filter<T>): boolean;
61
5
  export declare function PassThruParser<T>(record: Record<string, any>): T;
62
6
  /**
@@ -70,29 +14,48 @@ export declare function PassThruParser<T>(record: Record<string, any>): T;
70
14
  *
71
15
  * High cardinality, non-sequential partition keys allow for the best overall scaling.
72
16
  */
73
- export declare class DistributedTable<const P extends Parser<any>, const T extends KindaPretty<ReturnType<P>>, const PK extends AnyKeyFieldOption<T>, const SK extends AnyKeyFieldOption<T> | undefined> extends Resource {
17
+ export declare class DistributedTable<const P extends Parser<any>, const T extends KindaPretty<ReturnType<P>>, const Key extends Index<T>, const Indexes extends Index<T>[] | undefined = undefined> extends Resource implements AnyDistributedTable {
74
18
  #private;
75
19
  parse: P;
76
- partitionKey: PK;
77
- sort: SK | undefined;
20
+ key: Key;
21
+ indexes: Indexes | undefined;
78
22
  constructor(scope: Resource | string, id: string, options: {
79
23
  parse: P;
80
- key: {
81
- partition: PK;
82
- sort?: SK;
83
- };
24
+ key: Key;
25
+ indexes?: Indexes;
84
26
  });
85
- get partitionKeyName(): PK['field'];
86
- get sortKeyName(): 'field' extends keyof SK ? SK['field'] : undefined;
27
+ get partitionKeyName(): Key['partition']['field'];
28
+ get sortKeyName(): 'field' extends keyof Key['sort'] ? (Key['sort']['field'] extends string ? Key['sort']['field'] : undefined) : undefined;
87
29
  save(item: T): Promise<void>;
88
30
  saveMany(items: T[]): Promise<void>;
89
- delete(item: KindaPretty<RecordKey<T, PK, SK>>): Promise<void>;
90
- deleteMany(items: (KindaPretty<RecordKey<T, PK, SK>>)[]): Promise<void>;
91
- get(key: KindaPretty<RecordKey<T, PK, SK>>): Promise<KindaPretty<T> | undefined>;
31
+ delete(item: KindaPretty<RecordKey<T, Key>>): Promise<void>;
32
+ deleteMany(items: (KindaPretty<RecordKey<T, Key>>)[]): Promise<void>;
33
+ get(key: KindaPretty<RecordKey<T, Key>>): Promise<KindaPretty<T> | undefined>;
34
+ /**
35
+ * Performs a scan of the entire table.
36
+ *
37
+ * This is not recommended for large tables. It may be slow and expensive.
38
+ *
39
+ * Favor queries against the primary key and indexes instead.
40
+ *
41
+ * @param options
42
+ */
92
43
  scan(options: {
93
44
  filter?: Filter<T>;
94
45
  }): AsyncGenerator<T>;
95
- query(partition: KindaPretty<Pick<T, PK['field']>>, options?: {
96
- filter?: Filter<T>;
46
+ /**
47
+ * Performs a query of the table within a partition of either the primary key or
48
+ * an index.
49
+ *
50
+ * In local development environments, this is currently implemented as a full table
51
+ * scan. In production environments, this will generally implemented as a query against
52
+ * an index followed by a filtering step.
53
+ *
54
+ * @param options
55
+ */
56
+ query<const GivenPartition extends keyof AllIndexesByName<DistributedTable<P, T, Key, Indexes>> & string>(options: {
57
+ by: GivenPartition;
58
+ where: KeyCondition<DistributedTable<P, T, Key, Indexes>, GivenPartition>;
59
+ filter?: Filter<Omit<T, IndexFieldNames<DistributedTable<P, T, Key, Indexes>, GivenPartition> & string>>;
97
60
  }): AsyncGenerator<T>;
98
61
  }
@@ -1,6 +1,9 @@
1
1
  import { Resource } from '../resource.js';
2
2
  import { FileService } from '../services/file.js';
3
3
  import { overrides } from '../overrides.js';
4
+ export function indexName(index) {
5
+ return `${index.partition.field}${index.sort ? `-${index.sort.field}` : ''}`;
6
+ }
4
7
  export function matchesFilter(record, filter) {
5
8
  if (filter.and) {
6
9
  return filter.and.every(sub => matchesFilter(record, sub));
@@ -54,23 +57,21 @@ export function PassThruParser(record) {
54
57
  */
55
58
  export class DistributedTable extends Resource {
56
59
  parse;
57
- partitionKey;
58
- sort;
60
+ key;
61
+ indexes;
59
62
  #fileService;
60
63
  constructor(scope, id, options) {
61
64
  super(scope, id);
62
65
  this.parse = options.parse;
63
- this.partitionKey = options.key.partition;
64
- this.sort = options.key.sort;
66
+ this.key = options.key;
67
+ this.indexes = options.indexes;
65
68
  this.#fileService = new (overrides.FileService || FileService)(this, 'files');
66
69
  }
67
70
  get partitionKeyName() {
68
- const [pkField] = Object.keys(this.partitionKey);
69
- return pkField;
71
+ return this.key.partition.field;
70
72
  }
71
73
  get sortKeyName() {
72
- const [skField] = Object.keys(this.sort ?? {});
73
- return skField;
74
+ return this.key.sort?.field;
74
75
  }
75
76
  #getFilename(key) {
76
77
  const parts = [key[this.partitionKeyName]];
@@ -113,6 +114,15 @@ export class DistributedTable extends Resource {
113
114
  throw err;
114
115
  }
115
116
  }
117
+ /**
118
+ * Performs a scan of the entire table.
119
+ *
120
+ * This is not recommended for large tables. It may be slow and expensive.
121
+ *
122
+ * Favor queries against the primary key and indexes instead.
123
+ *
124
+ * @param options
125
+ */
116
126
  async *scan(options) {
117
127
  for await (const filename of this.#fileService.list()) {
118
128
  const data = await this.#fileService.read(filename);
@@ -122,16 +132,30 @@ export class DistributedTable extends Resource {
122
132
  }
123
133
  }
124
134
  }
125
- async *query(partition, options = {}) {
126
- const prefix = partition[this.partitionKeyName];
127
- for await (const filename of this.#fileService.list({ prefix })) {
128
- const data = await this.#fileService.read(filename);
129
- const record = this.parse(JSON.parse(data));
130
- if (record[this.partitionKeyName] === partition[this.partitionKeyName]
131
- && (!options.filter || matchesFilter(record, options.filter))) {
132
- yield record;
135
+ /**
136
+ * Performs a query of the table within a partition of either the primary key or
137
+ * an index.
138
+ *
139
+ * In local development environments, this is currently implemented as a full table
140
+ * scan. In production environments, this will generally implemented as a query against
141
+ * an index followed by a filtering step.
142
+ *
143
+ * @param options
144
+ */
145
+ async *query(options) {
146
+ // decompose for injection into `and` clause, wherein each k-v condition
147
+ // is expected to be independent.
148
+ const decomposedWhere = Object.entries(options.where).map(([k, v]) => ({
149
+ [k]: v
150
+ }));
151
+ yield* this.scan({
152
+ filter: {
153
+ and: [
154
+ ...decomposedWhere,
155
+ ...(options.filter ? [options.filter] : [])
156
+ ]
133
157
  }
134
- }
158
+ });
135
159
  }
136
160
  }
137
161
  // export type Todo = {
@@ -142,7 +166,40 @@ export class DistributedTable extends Resource {
142
166
  // const userTodos = new DistributedTable('app', 'userTodos', {
143
167
  // parse: PassThruParser<Todo & { userId: string }>,
144
168
  // key: {
145
- // partition: { userId: 'string' },
146
- // sort: { id: 'string' }
147
- // }
169
+ // partition: { field: 'userId', type: 'string' },
170
+ // sort: { field: 'order', type: 'number' }
171
+ // // sort: { field: 'id', type: 'string' }
172
+ // // sort: { }
173
+ // },
174
+ // indexes: [
175
+ // {
176
+ // partition: { field: 'text', type: 'string' },
177
+ // sort: { field: 'userId', type: 'string' }
178
+ // // sort: { field: 'order', type: 'number' }
179
+ // }
180
+ // ]
148
181
  // });
182
+ // type I = typeof userTodos['key'];
183
+ // type T1 = typeof userTodos['key']['partition']['field'];
184
+ // type T2 = typeof userTodos['key']['sort']['field'];
185
+ // type T3 = typeof userTodos['indexes'];
186
+ // type TTT1 = AllIndexes<typeof userTodos>;
187
+ // type TTT2 = AllIndexesByName<typeof userTodos>;
188
+ // type AnyIndex = Index<any>;
189
+ // type TEST1 = I extends Index<any> ? 'yes' : 'no';
190
+ // userTodos.query({
191
+ // by: 'userId-order',
192
+ // where: {
193
+ // // maybe the key here can be the actual name of the field.
194
+ // // maybe even follow the filter pattern, but only expose the `eq` operation:
195
+ // // { [field]: { eq: T } }
196
+ // userId: { eq: 'something' },
197
+ // // id: {
198
+ // // eq: 'something'
199
+ // // }
200
+ // // same here. name of the actual sort key field.
201
+ // // id: {
202
+ // // beginsWith: 'something'
203
+ // // },
204
+ // },
205
+ // })
@@ -1,7 +1,7 @@
1
1
  import { Resource } from '../resource.js';
2
2
  import { ContextWrapped } from '../adapters/context.js';
3
3
  import type { CookieJar } from '../adapters/cookie-jar.js';
4
- import type { User, AuthenticationError, AuthenticationMachineInput, AuthenticationMachineState, AuthenticationServiceOptions } from '../types.js';
4
+ import type { User, AuthenticationError, AuthenticationMachineInput, AuthenticationMachineState, AuthenticationServiceOptions } from '../types/index.js';
5
5
  export declare class AuthenticationService extends Resource {
6
6
  #private;
7
7
  constructor(scope: Resource | string, id: string, { duration, keepalive, cookie }?: AuthenticationServiceOptions);
@@ -0,0 +1,74 @@
1
+ export * from './resources/distributed-table.js';
2
+ export type User = {
3
+ /**
4
+ * Something that uniquely identifies the user in the authentication system
5
+ * and does not change over time.
6
+ */
7
+ id: string;
8
+ /**
9
+ * The self-identifier the user has chosen to log in with.
10
+ */
11
+ username: string;
12
+ /**
13
+ * The name this user will be known by to other users.
14
+ */
15
+ displayName: string;
16
+ };
17
+ export type AuthenticationField = {
18
+ label: string;
19
+ type: 'text' | 'password';
20
+ isRequired?: boolean;
21
+ };
22
+ export type AuthenticationAction = {
23
+ name: string;
24
+ title?: string;
25
+ description?: string;
26
+ message?: string;
27
+ fields?: Record<string, AuthenticationField>;
28
+ buttons?: readonly string[];
29
+ };
30
+ export type AuthenticationState = {
31
+ state: 'authenticated';
32
+ user: User;
33
+ } | {
34
+ state: 'unauthenticated';
35
+ user: undefined;
36
+ };
37
+ export type AuthenticationMachineAction = Readonly<AuthenticationAction & {
38
+ key: string;
39
+ }>;
40
+ export type AuthenticationMachineState = AuthenticationState & {
41
+ message?: string;
42
+ actions: Record<string, AuthenticationMachineAction>;
43
+ };
44
+ export type AuthenticationMachineInput = {
45
+ key: string;
46
+ inputs?: Record<string, string | number | boolean>;
47
+ verb?: string;
48
+ };
49
+ export type AuthenticationMachineInputFor<T extends AuthenticationMachineAction> = {
50
+ key: T['key'];
51
+ verb: string;
52
+ inputs: T['fields'] extends undefined ? Record<string, never> : {
53
+ [K in keyof T['fields']]: FieldInputFor<T['fields'][K]>;
54
+ };
55
+ };
56
+ export type FieldInputFor<T> = T extends AuthenticationField ? T['type'] extends ('text' | 'password') ? string : never : never;
57
+ export type AuthenticationError = {
58
+ message: string;
59
+ field?: string;
60
+ };
61
+ export type AuthenticationServiceOptions = {
62
+ /**
63
+ * The number of seconds the authentication session stays alive.
64
+ */
65
+ duration?: number;
66
+ /**
67
+ * Whether to automatically extend (keep alive) an authentication session when used.
68
+ */
69
+ keepalive?: boolean;
70
+ /**
71
+ * The name of the cookie to use to store the authentication state JWT.
72
+ */
73
+ cookie?: string;
74
+ };
@@ -0,0 +1 @@
1
+ export * from './resources/distributed-table.js';
@@ -0,0 +1,116 @@
1
+ import type { Resource } from '../../resource.js';
2
+ export type KindaPretty<T> = T extends object ? {
3
+ [K in keyof T]: KindaPretty<T[K]>;
4
+ } : T;
5
+ export type PKFieldTypes = 'string' | 'number';
6
+ export type StringToType<S extends 'string' | 'number'> = S extends 'string' ? string : S extends 'number' ? number : never;
7
+ export type IDistributedTableOptions<T> = {
8
+ parse: Parser<T>;
9
+ key: {
10
+ partition: AnyKeyFieldOption<T>;
11
+ sort?: AnyKeyFieldOption<T>;
12
+ };
13
+ };
14
+ export type KeyFieldOptions<T> = {
15
+ [K in keyof T as K extends string ? K : never]: K extends string ? KeyFieldDefinition<T, K, T[K]> : never;
16
+ };
17
+ export type AnyKeyFieldOption<T> = KeyFieldOptions<T>[keyof KeyFieldOptions<T>];
18
+ export type KeyFieldDefinition<T = Record<string, any>, FieldName extends string & keyof T = string & keyof T, FieldType = T[FieldName]> = FieldType extends number ? {
19
+ readonly field: FieldName & keyof T;
20
+ readonly type: 'number';
21
+ } : {
22
+ readonly field: FieldName & keyof T;
23
+ readonly type: 'string';
24
+ };
25
+ export type Index<T> = {
26
+ readonly partition: AnyKeyFieldOption<T>;
27
+ readonly sort?: AnyKeyFieldOption<T>;
28
+ };
29
+ export type Parser<T> = (record: Record<string, any>) => T;
30
+ export type RecordType<T extends IDistributedTableOptions<any>> = T extends IDistributedTableOptions<infer IT> ? IT : Record<string, any>;
31
+ export type RecordKey<T, Idx extends Index<T>> = Pick<T, Idx['partition']['field'] | ('field' extends keyof Idx['sort'] ? (Idx['sort']['field'] extends keyof T ? Idx['sort']['field'] : never) : never)>;
32
+ export type FieldType<T> = undefined extends T ? (T | null) : T;
33
+ export type FieldComparisonOptions<T> = {
34
+ [K in keyof T & string]?: {
35
+ eq: FieldType<T[K]>;
36
+ } | {
37
+ ne: FieldType<T[K]>;
38
+ } | {
39
+ gt: FieldType<T[K]>;
40
+ } | {
41
+ ge: FieldType<T[K]>;
42
+ } | {
43
+ lt: FieldType<T[K]>;
44
+ } | {
45
+ le: FieldType<T[K]>;
46
+ } | {
47
+ between: [FieldType<T[K]>, FieldType<T[K]>];
48
+ } | {
49
+ beginsWith: FieldType<T[K]>;
50
+ };
51
+ };
52
+ export type FieldComparison<T> = {
53
+ [K in keyof FieldComparisonOptions<T>]: Record<K, FieldComparisonOptions<T>[K]> & NoneOf<Exclude<keyof FieldComparisonOptions<T>, K>>;
54
+ }[keyof FieldComparisonOptions<T>];
55
+ export type NoneOf<Fields> = {
56
+ [K in Fields & string]?: never;
57
+ };
58
+ export type Filter<T> = (FieldComparison<T> & NoneOf<'and' | 'or' | 'not'>) | ({
59
+ and: (Filter<T>)[];
60
+ } & NoneOf<keyof T | 'or' | 'not'>) | ({
61
+ or: (Filter<T>)[];
62
+ } & NoneOf<keyof T | 'and' | 'not'>) | ({
63
+ not: Filter<T>;
64
+ } & NoneOf<keyof T | 'and' | 'or'>);
65
+ export type IndexName<I extends Index<any>> = I extends {
66
+ readonly partition: infer P extends {
67
+ readonly field: string;
68
+ };
69
+ readonly sort?: infer S;
70
+ } ? `${P['field']}${S extends {
71
+ readonly field: string;
72
+ } ? `-${S['field']}` : ''}` : never;
73
+ export type IndexNames<Indexes> = (keyof IndexesByName<Indexes>) & string;
74
+ export type IndexesByName<Indexes> = KindaPretty<Indexes extends [infer I extends Index<any>, ...infer Rest] ? Record<IndexName<I>, I> & IndexesByName<Rest> : unknown>;
75
+ export type AllIndexes<T extends AnyDistributedTable> = T extends AnyDistributedTable ? [
76
+ T['key'],
77
+ ...(Exclude<T['indexes'], undefined> extends never ? [] : Exclude<T['indexes'], undefined>)
78
+ ] : never;
79
+ export type AllIndexesByName<T extends AnyDistributedTable> = IndexesByName<AllIndexes<T>>;
80
+ export type KeyCondition<T extends AnyDistributedTable, Index extends keyof AllIndexesByName<T>> = {
81
+ [K in PartitionKeyName<T, Index> & string]: {
82
+ eq: PartitionKeyType<T, Index>;
83
+ };
84
+ } & {
85
+ [K in MatchingSortKeyName<T, Index>]+?: SortKeyCondition<T, Index>;
86
+ };
87
+ export type PartitionKeyType<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = AllIndexesByName<T>[Idx] extends Index<any> ? StringToType<AllIndexesByName<T>[Idx]['partition']['type']> : never;
88
+ export type PartitionKeyName<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = AllIndexesByName<T>[Idx] extends Index<any> ? AllIndexesByName<T>[Idx]['partition']['field'] : never;
89
+ export type MatchingSortKeyDefinition<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = AllIndexesByName<T>[Idx] extends Index<any> ? AllIndexesByName<T>[Idx]['sort'] : never;
90
+ export type MatchingSortKeyType<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = MatchingSortKeyDefinition<T, Idx> extends AnyKeyFieldOption<any> ? StringToType<MatchingSortKeyDefinition<T, Idx>['type']> : never;
91
+ export type MatchingSortKeyName<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = MatchingSortKeyDefinition<T, Idx> extends AnyKeyFieldOption<any> ? MatchingSortKeyDefinition<T, Idx>['field'] : never;
92
+ export type SortKeyCondition<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = MatchingSortKeyType<T, Idx> extends (string | number) ? ({
93
+ eq: MatchingSortKeyType<T, Idx>;
94
+ } | {
95
+ ne: MatchingSortKeyType<T, Idx>;
96
+ } | {
97
+ lt: MatchingSortKeyType<T, Idx>;
98
+ } | {
99
+ le: MatchingSortKeyType<T, Idx>;
100
+ } | {
101
+ gt: MatchingSortKeyType<T, Idx>;
102
+ } | {
103
+ ge: MatchingSortKeyType<T, Idx>;
104
+ } | {
105
+ between: MatchingSortKeyType<T, Idx>;
106
+ } | {
107
+ beginsWith: MatchingSortKeyType<T, Idx>;
108
+ }) : never;
109
+ export type IndexFieldNames<T extends AnyDistributedTable, Idx extends keyof AllIndexesByName<T>> = PartitionKeyName<T, Idx> | MatchingSortKeyName<T, Idx>;
110
+ export interface AnyDistributedTable extends Resource {
111
+ parse: Parser<any>;
112
+ key: Index<any>;
113
+ indexes: Index<any>[] | undefined;
114
+ get partitionKeyName(): string;
115
+ get sortKeyName(): string | undefined;
116
+ }
@@ -0,0 +1,2 @@
1
+ ;
2
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wirejs-resources",
3
- "version": "0.1.35-table-resource",
3
+ "version": "0.1.37-table-resource",
4
4
  "description": "Basic services and server-side resources for wirejs apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",