Skip to content

Commit 0bd2ba9

Browse files
authored
Merge pull request #337 from orbitjs/update-orbit
Update orbit to v0.17.0-beta.16 and introduce model-aware normalizers and builders
2 parents 98f3577 + e7a23a6 commit 0bd2ba9

22 files changed

Lines changed: 651 additions & 421 deletions

addon/-private/cache.ts

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { deepGet } from '@orbit/utils';
1+
import { registerDestructor } from '@ember/destroyable';
22
import { Orbit } from '@orbit/core';
33
import {
44
buildQuery,
@@ -7,29 +7,34 @@ import {
77
FullResponse,
88
RequestOptions
99
} from '@orbit/data';
10+
import IdentityMap from '@orbit/identity-map';
11+
import { MemoryCache } from '@orbit/memory';
12+
import {
13+
RecordCacheQueryOptions,
14+
RecordCacheTransformOptions
15+
} from '@orbit/record-cache';
1016
import {
17+
InitializedRecord,
1118
RecordIdentity,
12-
RecordOperation,
13-
Record,
1419
RecordKeyMap,
15-
RecordQueryOrExpressions,
16-
RecordSchema,
17-
RecordTransformBuilder,
20+
RecordOperation,
21+
RecordOperationResult,
1822
RecordQuery,
19-
RecordTransform,
20-
RecordQueryResult,
2123
RecordQueryExpressionResult,
22-
RecordTransformResult,
23-
RecordOperationResult,
24-
RecordQueryBuilder
24+
RecordQueryResult,
25+
RecordSchema,
26+
RecordTransform,
27+
RecordTransformResult
2528
} from '@orbit/records';
26-
import { RecordCacheQueryOptions } from '@orbit/record-cache';
27-
import { MemoryCache } from '@orbit/memory';
28-
import IdentityMap from '@orbit/identity-map';
29-
import { registerDestructor } from '@ember/destroyable';
30-
import Model from './model';
29+
import { deepGet } from '@orbit/utils';
3130
import LiveQuery from './live-query';
31+
import Model from './model';
3232
import ModelFactory from './model-factory';
33+
import {
34+
ModelAwareQueryBuilder,
35+
ModelAwareQueryOrExpressions,
36+
ModelAwareTransformBuilder
37+
} from './utils/model-aware-types';
3338
import recordIdentitySerializer from './utils/record-identity-serializer';
3439

3540
const { assert } = Orbit;
@@ -40,7 +45,12 @@ export interface CacheSettings {
4045
}
4146

4247
export default class Cache {
43-
private _sourceCache: MemoryCache;
48+
private _sourceCache: MemoryCache<
49+
RecordCacheQueryOptions,
50+
RecordCacheTransformOptions,
51+
ModelAwareQueryBuilder,
52+
ModelAwareTransformBuilder
53+
>;
4454
private _modelFactory: ModelFactory;
4555
private _identityMap: IdentityMap<RecordIdentity, Model> = new IdentityMap({
4656
serializer: recordIdentitySerializer
@@ -69,11 +79,11 @@ export default class Cache {
6979
return this._sourceCache.schema;
7080
}
7181

72-
get queryBuilder(): RecordQueryBuilder {
82+
get queryBuilder(): ModelAwareQueryBuilder {
7383
return this._sourceCache.queryBuilder;
7484
}
7585

76-
get transformBuilder(): RecordTransformBuilder {
86+
get transformBuilder(): ModelAwareTransformBuilder {
7787
return this._sourceCache.transformBuilder;
7888
}
7989

@@ -90,18 +100,18 @@ export default class Cache {
90100
}
91101

92102
get defaultTransformOptions():
93-
| DefaultRequestOptions<RequestOptions>
103+
| DefaultRequestOptions<RecordCacheTransformOptions>
94104
| undefined {
95105
return this._sourceCache.defaultTransformOptions;
96106
}
97107

98108
set defaultTransformOptions(
99-
options: DefaultRequestOptions<RequestOptions> | undefined
109+
options: DefaultRequestOptions<RecordCacheTransformOptions> | undefined
100110
) {
101111
this._sourceCache.defaultTransformOptions = options;
102112
}
103113

104-
peekRecordData(type: string, id: string): Record | undefined {
114+
peekRecordData(type: string, id: string): InitializedRecord | undefined {
105115
return this._sourceCache.getRecordSync({ type, id });
106116
}
107117

@@ -186,21 +196,21 @@ export default class Cache {
186196
query<
187197
RequestData extends RecordQueryResult<Model> = RecordQueryResult<Model>
188198
>(
189-
queryOrExpressions: RecordQueryOrExpressions,
199+
queryOrExpressions: ModelAwareQueryOrExpressions,
190200
options?: DefaultRequestOptions<RecordCacheQueryOptions>,
191201
id?: string
192202
): RequestData;
193203
query<
194204
RequestData extends RecordQueryResult<Model> = RecordQueryResult<Model>
195205
>(
196-
queryOrExpressions: RecordQueryOrExpressions,
206+
queryOrExpressions: ModelAwareQueryOrExpressions,
197207
options: FullRequestOptions<RecordCacheQueryOptions>,
198208
id?: string
199209
): FullResponse<RequestData, undefined, RecordOperation>;
200210
query<
201211
RequestData extends RecordQueryResult<Model> = RecordQueryResult<Model>
202212
>(
203-
queryOrExpressions: RecordQueryOrExpressions,
213+
queryOrExpressions: ModelAwareQueryOrExpressions,
204214
options?: RecordCacheQueryOptions,
205215
id?: string
206216
): RequestData | FullResponse<RequestData, undefined, RecordOperation> {
@@ -224,7 +234,7 @@ export default class Cache {
224234
}
225235

226236
liveQuery(
227-
queryOrExpressions: RecordQueryOrExpressions,
237+
queryOrExpressions: ModelAwareQueryOrExpressions,
228238
options?: RequestOptions,
229239
id?: string
230240
): LiveQuery {
@@ -269,7 +279,7 @@ export default class Cache {
269279
}
270280
}
271281

272-
lookup(record: Record): Model {
282+
lookup(record: InitializedRecord): Model {
273283
let model = this._identityMap.get(record);
274284

275285
if (!model) {
@@ -282,13 +292,16 @@ export default class Cache {
282292

283293
lookupQueryResult(
284294
query: RecordQuery,
285-
result: RecordQueryResult<Record>
295+
result: RecordQueryResult<InitializedRecord>
286296
): RecordQueryResult<Model> {
287297
if (
288-
isQueryExpressionResultArray<Record>(result, query.expressions.length)
298+
isQueryExpressionResultArray<InitializedRecord>(
299+
result,
300+
query.expressions.length
301+
)
289302
) {
290-
return (result as RecordQueryExpressionResult<Record>[]).map((i) =>
291-
this.lookupQueryExpressionResult(i)
303+
return (result as RecordQueryExpressionResult<InitializedRecord>[]).map(
304+
(i) => this.lookupQueryExpressionResult(i)
292305
);
293306
} else {
294307
return this.lookupQueryExpressionResult(result);
@@ -297,17 +310,22 @@ export default class Cache {
297310

298311
lookupTransformResult(
299312
transform: RecordTransform,
300-
result: RecordTransformResult<Record>
313+
result: RecordTransformResult<InitializedRecord>
301314
): RecordTransformResult<Model> {
302-
if (isOperationResultArray<Record>(result, transform.operations.length)) {
315+
if (
316+
isOperationResultArray<InitializedRecord>(
317+
result,
318+
transform.operations.length
319+
)
320+
) {
303321
return result.map((i) => this.lookupOperationResult(i));
304322
} else {
305323
return this.lookupOperationResult(result);
306324
}
307325
}
308326

309327
private lookupQueryExpressionResult(
310-
result: RecordQueryExpressionResult<Record>
328+
result: RecordQueryExpressionResult<InitializedRecord>
311329
): RecordQueryExpressionResult<Model> {
312330
if (Array.isArray(result)) {
313331
return result.map((i) => (i ? this.lookup(i) : i));
@@ -319,7 +337,7 @@ export default class Cache {
319337
}
320338

321339
private lookupOperationResult(
322-
result: RecordOperationResult<Record>
340+
result: RecordOperationResult<InitializedRecord>
323341
): RecordOperationResult<Model> {
324342
if (result) {
325343
return this.lookup(result);
@@ -341,7 +359,7 @@ export default class Cache {
341359

342360
private generatePatchListener(): (operation: RecordOperation) => void {
343361
return (operation: RecordOperation) => {
344-
const record = operation.record as Record;
362+
const record = operation.record as InitializedRecord;
345363
const { type, id, keys, attributes, relationships } = record;
346364
const identity = { type, id };
347365

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { MemorySource, MemorySourceSettings } from '@orbit/memory';
2+
import { ModelAwareNormalizer } from '../utils/model-aware-normalizer';
23

34
export default {
45
create(injections: MemorySourceSettings): MemorySource {
5-
injections.name = injections.name || 'store';
6+
const { schema } = injections;
7+
injections.name = injections.name ?? 'store';
68
injections.cacheSettings = { debounceLiveQueries: false };
9+
injections.normalizer = new ModelAwareNormalizer({ schema });
710
return new MemorySource(injections);
811
}
912
};

addon/-private/factories/schema-factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default {
2525

2626
let orbitConfig = app.lookup('ember-orbit:config');
2727
let modelNames =
28-
injections.modelNames ||
28+
injections.modelNames ??
2929
getRegisteredModels(
3030
app.base.modulePrefix,
3131
orbitConfig.collections.models

addon/-private/fields/attr.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,27 @@ export interface TrackedAttr {
1212
set(this: Model, value: unknown): void;
1313
}
1414

15-
export default function attr(target: Model, key: string): any;
16-
export default function attr(type?: string, options?: AttributeDefinition): any;
15+
export default function attr(type: string): any;
16+
export default function attr(def: AttributeDefinition): any;
1717
export default function attr(
18-
type?: Model | string,
19-
options: string | AttributeDefinition = {}
18+
typeOrDef?: string | AttributeDefinition,
19+
def?: AttributeDefinition
2020
): any {
21-
function trackedAttr(
22-
target: Model,
23-
property: string,
24-
_: PropertyDescriptor
25-
): TrackedAttr {
21+
let attrDef: AttributeDefinition;
22+
23+
if (typeof typeOrDef === 'string') {
24+
attrDef = def ?? {};
25+
attrDef.type = typeOrDef;
26+
} else {
27+
attrDef = typeOrDef ?? {};
28+
29+
assert(
30+
'@attr can be defined with a `type` and `definition` object but not two `definition` objects',
31+
def === undefined
32+
);
33+
}
34+
35+
return (target: Model, property: string): TrackedAttr => {
2636
function get(this: Model): unknown {
2737
assert(
2838
`The ${this.type} record has been removed from the store, so we cannot lookup the ${property} attr from the cache.`,
@@ -44,16 +54,8 @@ export default function attr(
4454
}
4555
}
4656

47-
defineAttribute(target, property, options as AttributeDefinition);
57+
defineAttribute(target, property, attrDef);
4858

4959
return { get, set };
50-
}
51-
52-
if (typeof options === 'string') {
53-
options = {};
54-
return trackedAttr.apply(null, arguments as any);
55-
}
56-
57-
options.type = type as string;
58-
return trackedAttr;
60+
};
5961
}

addon/-private/fields/has-many.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Orbit } from '@orbit/core';
2-
import { RelationshipDefinition } from '@orbit/records';
2+
import { HasManyRelationshipDefinition } from '@orbit/records';
33

44
import Model from '../model';
55
import { getHasManyCache } from '../utils/property-cache';
@@ -11,19 +11,37 @@ export interface TrackedHasMany {
1111
get(this: Model): Model[];
1212
}
1313

14+
export default function hasMany(type: string | string[]): any;
15+
export default function hasMany(
16+
def: Partial<HasManyRelationshipDefinition>
17+
): any;
1418
export default function hasMany(
1519
type: string | string[],
16-
options: Partial<RelationshipDefinition> = {}
20+
def?: Partial<HasManyRelationshipDefinition>
21+
): any;
22+
export default function hasMany(
23+
typeOrDef: string | string[] | Partial<HasManyRelationshipDefinition>,
24+
def?: Partial<HasManyRelationshipDefinition>
1725
): any {
18-
function trackedHasMany(
19-
target: any,
20-
property: string,
21-
_: PropertyDescriptor
22-
): TrackedHasMany {
23-
if (!options.type) {
24-
throw new TypeError('@hasMany() require `type` argument.');
25-
}
26+
let relDef: Partial<HasManyRelationshipDefinition>;
27+
28+
if (typeof typeOrDef === 'string' || Array.isArray(typeOrDef)) {
29+
relDef = def ?? {};
30+
relDef.type = typeOrDef;
31+
} else {
32+
relDef = typeOrDef;
33+
34+
assert(
35+
'@hasMany can be defined with a `type` and `definition` object but not two `definition` objects',
36+
def === undefined
37+
);
38+
39+
assert('@hasMany() requires a `type` argument.', relDef.type !== undefined);
40+
}
41+
42+
relDef.kind = 'hasMany';
2643

44+
return (target: Model, property: string): TrackedHasMany => {
2745
function get(this: Model): Model[] {
2846
assert(
2947
`The ${this.type} record has been removed from the store, so we cannot lookup the ${property} hasMany from the cache.`,
@@ -33,17 +51,12 @@ export default function hasMany(
3351
return getHasManyCache(this, property).value as Model[];
3452
}
3553

36-
defineRelationship(target, property, options);
54+
defineRelationship(
55+
target,
56+
property,
57+
relDef as HasManyRelationshipDefinition
58+
);
3759

3860
return { get };
39-
}
40-
41-
if (arguments.length === 3) {
42-
options = {};
43-
return trackedHasMany.apply(null, arguments as any);
44-
}
45-
46-
options.type = type;
47-
options.kind = 'hasMany';
48-
return trackedHasMany;
61+
};
4962
}

0 commit comments

Comments
 (0)