Skip to content

Commit 3bc0369

Browse files
committed
chore: cleanup types
1 parent c55b558 commit 3bc0369

File tree

28 files changed

+278
-89
lines changed

28 files changed

+278
-89
lines changed

packages/core-types/src/schema/fields.ts

+124-9
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export interface GenericField {
6666
*
6767
* @typedoc
6868
*/
69-
export interface AliasField {
69+
export interface LegacyAliasField {
7070
kind: 'alias';
7171
name: string;
7272
type: null; // should always be null
@@ -82,13 +82,104 @@ export interface AliasField {
8282
| SchemaObjectField
8383
| ArrayField
8484
| SchemaArrayField
85-
| ResourceField
86-
| CollectionField
85+
// | ResourceField
86+
// | CollectionField
8787
| LegacyAttributeField
8888
| LegacyBelongsToField
8989
| LegacyHasManyField;
9090
}
9191

92+
/**
93+
* A field that can be used to alias one key to another
94+
* key present in the cache version of the resource.
95+
*
96+
* Unlike DerivedField, an AliasField may write to its
97+
* source when a record is in an editable mode.
98+
*
99+
* AliasFields may utilize a transform, specified by type,
100+
* to pre/post process the field.
101+
*
102+
* An AliasField may also specify a `kind` via options.
103+
* `kind` may be any other valid field kind other than
104+
*
105+
* - `@hash`
106+
* - `@id`
107+
* - `@local`
108+
* - `derived`
109+
*
110+
* This allows an AliasField to rename any field in the cache.
111+
*
112+
* Alias fields are generally intended to be used to support migrating
113+
* between different schemas, though there are times where they are useful
114+
* as a form of advanced derivation when used with a transform. For instance,
115+
* an AliasField could be used to expose both a string and a Date version of the
116+
* same field, with both being capable of being written to.
117+
*
118+
* @typedoc
119+
*/
120+
export interface PolarisAliasField {
121+
kind: 'alias';
122+
name: string;
123+
type: null; // should always be null
124+
125+
/**
126+
* The field def for which this is an alias.
127+
*
128+
* @typedoc
129+
*/
130+
options:
131+
| GenericField
132+
| ObjectField
133+
| SchemaObjectField
134+
| ArrayField
135+
| SchemaArrayField
136+
// | ResourceField
137+
// | CollectionField
138+
| LinksModeBelongsToField
139+
| LinksModeHasManyField;
140+
}
141+
142+
/**
143+
* A field that can be used to alias one key to another
144+
* key present in the cache version of the resource.
145+
*
146+
* Unlike DerivedField, an AliasField may write to its
147+
* source when a record is in an editable mode.
148+
*
149+
* AliasFields may utilize a transform, specified by type,
150+
* to pre/post process the field.
151+
*
152+
* An AliasField may also specify a `kind` via options.
153+
* `kind` may be any other valid field kind other than
154+
*
155+
* - `@hash`
156+
* - `@id`
157+
* - `@local`
158+
* - `derived`
159+
*
160+
* This allows an AliasField to rename any field in the cache.
161+
*
162+
* Alias fields are generally intended to be used to support migrating
163+
* between different schemas, though there are times where they are useful
164+
* as a form of advanced derivation when used with a transform. For instance,
165+
* an AliasField could be used to expose both a string and a Date version of the
166+
* same field, with both being capable of being written to.
167+
*
168+
* @typedoc
169+
*/
170+
export interface ObjectAliasField {
171+
kind: 'alias';
172+
name: string;
173+
type: null; // should always be null
174+
175+
/**
176+
* The field def for which this is an alias.
177+
*
178+
* @typedoc
179+
*/
180+
options: GenericField | ObjectField | SchemaObjectField | ArrayField | SchemaArrayField;
181+
}
182+
92183
/**
93184
* Represents a field whose value is the primary
94185
* key of the resource.
@@ -1178,7 +1269,7 @@ export interface LinksModeHasManyField {
11781269
*/
11791270
export type LegacyModeFieldSchema =
11801271
| GenericField
1181-
| AliasField
1272+
| LegacyAliasField
11821273
| LocalField
11831274
| ObjectField
11841275
| SchemaObjectField
@@ -1198,7 +1289,7 @@ export type LegacyModeFieldSchema =
11981289
*/
11991290
export type PolarisModeFieldSchema =
12001291
| GenericField
1201-
| AliasField
1292+
| PolarisAliasField
12021293
| LocalField
12031294
| ObjectField
12041295
| SchemaObjectField
@@ -1223,7 +1314,8 @@ export type PolarisModeFieldSchema =
12231314
*/
12241315
export type FieldSchema =
12251316
| GenericField
1226-
| AliasField
1317+
| LegacyAliasField
1318+
| PolarisAliasField
12271319
| LocalField
12281320
| ObjectField
12291321
| SchemaObjectField
@@ -1246,7 +1338,7 @@ export type FieldSchema =
12461338
*/
12471339
export type ObjectFieldSchema =
12481340
| GenericField
1249-
| AliasField
1341+
| ObjectAliasField
12501342
| LocalField
12511343
| ObjectField
12521344
| SchemaObjectField
@@ -1494,5 +1586,28 @@ export function isResourceSchema(schema: ResourceSchema | ObjectSchema): schema
14941586
return schema?.identity?.kind === '@id';
14951587
}
14961588

1497-
export type LegacyFieldSchema = LegacyAttributeField | LegacyBelongsToField | LegacyHasManyField;
1498-
export type LegacyRelationshipSchema = LegacyBelongsToField | LegacyHasManyField;
1589+
/**
1590+
* A type utility to narrow a schema to LegacyResourceSchema
1591+
*
1592+
* @method isLegacyResourceSchema
1593+
* @static
1594+
* @for @warp-drive/core-types
1595+
* @param schema
1596+
* @returns {boolean}
1597+
* @public
1598+
*/
1599+
export function isLegacyResourceSchema(schema: ResourceSchema | ObjectSchema): schema is LegacyResourceSchema {
1600+
return isResourceSchema(schema) && schema.legacy === true;
1601+
}
1602+
1603+
export type LegacyField =
1604+
| LegacyAttributeField
1605+
| LegacyBelongsToField
1606+
| LegacyHasManyField
1607+
| LinksModeBelongsToField
1608+
| LinksModeHasManyField;
1609+
export type LegacyRelationshipField =
1610+
| LegacyBelongsToField
1611+
| LegacyHasManyField
1612+
| LinksModeBelongsToField
1613+
| LinksModeHasManyField;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { resourceSchema } from './fields';
2+
3+
// @ts-expect-error attribute field should result in an invalid schema
4+
// unless marked legacy
5+
resourceSchema({
6+
type: 'user',
7+
identity: { name: 'id', kind: '@id' },
8+
fields: [
9+
{
10+
name: 'name',
11+
kind: 'attribute',
12+
},
13+
],
14+
});
15+
resourceSchema({
16+
legacy: true,
17+
type: 'user',
18+
identity: { name: 'id', kind: '@id' },
19+
fields: [
20+
{
21+
name: 'name',
22+
kind: 'attribute',
23+
},
24+
],
25+
});
26+
27+
// @ts-expect-error relationship field should result in an invalid schema
28+
// unless marked legacy or linksMode
29+
resourceSchema({
30+
type: 'user',
31+
identity: { name: 'id', kind: '@id' },
32+
fields: [
33+
{
34+
name: 'friends',
35+
kind: 'hasMany',
36+
type: 'user',
37+
options: { async: false, inverse: null },
38+
},
39+
],
40+
});
41+
resourceSchema({
42+
legacy: true,
43+
type: 'user',
44+
identity: { name: 'id', kind: '@id' },
45+
fields: [
46+
{
47+
name: 'friends',
48+
kind: 'hasMany',
49+
type: 'user',
50+
options: { async: false, inverse: null },
51+
},
52+
],
53+
});
54+
resourceSchema({
55+
type: 'user',
56+
identity: { name: 'id', kind: '@id' },
57+
fields: [
58+
{
59+
name: 'friends',
60+
kind: 'hasMany',
61+
type: 'user',
62+
options: {
63+
async: false,
64+
inverse: null,
65+
linksMode: true,
66+
resetOnRemoteUpdate: false,
67+
},
68+
},
69+
],
70+
});

packages/json-api/src/-private/cache.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import type {
3131
CollectionField,
3232
FieldSchema,
3333
LegacyHasManyField,
34-
LegacyRelationshipSchema,
34+
LegacyRelationshipField,
3535
ResourceField,
3636
} from '@warp-drive/core-types/schema/fields';
3737
import type {
@@ -1817,6 +1817,8 @@ function getDefaultValue(
18171817
identifier: StableRecordIdentifier,
18181818
store: Store
18191819
): Value | undefined {
1820+
assert(`AliasFields should not be directly accessed from the cache`, schema?.kind !== 'alias');
1821+
18201822
const options = schema?.options;
18211823

18221824
if (!schema || (!options && !schema.type)) {
@@ -1989,7 +1991,7 @@ function setupRelationships(
19891991
}
19901992
}
19911993

1992-
function isRelationship(field: FieldSchema): field is LegacyRelationshipSchema | CollectionField | ResourceField {
1994+
function isRelationship(field: FieldSchema): field is LegacyRelationshipField | CollectionField | ResourceField {
19931995
const { kind } = field;
19941996
return kind === 'hasMany' || kind === 'belongsTo' || kind === 'resource' || kind === 'collection';
19951997
}

packages/legacy-compat/src/legacy-network-handler/legacy-data-fetch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { BaseFinderOptions } from '@ember-data/store/types';
33
import { DEBUG } from '@warp-drive/build-config/env';
44
import { assert } from '@warp-drive/build-config/macros';
55
import type { StableRecordIdentifier } from '@warp-drive/core-types';
6-
import type { LegacyRelationshipSchema as RelationshipSchema } from '@warp-drive/core-types/schema/fields';
6+
import type { LegacyRelationshipField as RelationshipSchema } from '@warp-drive/core-types/schema/fields';
77
import type { ExistingResourceObject, JsonApiDocument } from '@warp-drive/core-types/spec/json-api-raw';
88

99
import { upgradeStore } from '../-private';

packages/legacy-compat/src/legacy-network-handler/legacy-network-handler.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { DEBUG, TESTING } from '@warp-drive/build-config/env';
1010
import { assert } from '@warp-drive/build-config/macros';
1111
import type { StableExistingRecordIdentifier, StableRecordIdentifier } from '@warp-drive/core-types/identifier';
1212
import type { ImmutableRequestInfo } from '@warp-drive/core-types/request';
13-
import type { LegacyRelationshipSchema as RelationshipSchema } from '@warp-drive/core-types/schema/fields';
13+
import type { LegacyRelationshipField as RelationshipSchema } from '@warp-drive/core-types/schema/fields';
1414
import type { SingleResourceDataDocument } from '@warp-drive/core-types/spec/document';
1515
import type { ApiError } from '@warp-drive/core-types/spec/error';
1616
import type {

packages/legacy-compat/src/legacy-network-handler/minimum-adapter-interface.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import type Store from '@ember-data/store';
55
import type { CollectionRecordArray } from '@ember-data/store/-private';
66
import type { ModelSchema } from '@ember-data/store/types';
7-
import type { LegacyRelationshipSchema as RelationshipSchema } from '@warp-drive/core-types/schema/fields';
7+
import type { LegacyRelationshipField as RelationshipSchema } from '@warp-drive/core-types/schema/fields';
88

99
import type { Snapshot } from './snapshot';
1010
import type { SnapshotRecordArray } from './snapshot-record-array';

packages/legacy-compat/src/legacy-network-handler/snapshot.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type { ChangedAttributesHash } from '@warp-drive/core-types/cache';
1313
import type { CollectionRelationship } from '@warp-drive/core-types/cache/relationship';
1414
import type { Value } from '@warp-drive/core-types/json/raw';
1515
import type { TypedRecordInstance, TypeFromInstance } from '@warp-drive/core-types/record';
16-
import type { LegacyAttributeField, LegacyRelationshipSchema } from '@warp-drive/core-types/schema/fields';
16+
import type { LegacyAttributeField, LegacyRelationshipField } from '@warp-drive/core-types/schema/fields';
1717

1818
import { upgradeStore } from '../-private';
1919
import type { SerializerOptions } from './minimum-serializer-interface';
@@ -519,7 +519,7 @@ export class Snapshot<R = unknown> {
519519
@param {Object} [binding] the value to which the callback's `this` should be bound
520520
@public
521521
*/
522-
eachRelationship(callback: (key: string, meta: LegacyRelationshipSchema) => void, binding?: unknown): void {
522+
eachRelationship(callback: (key: string, meta: LegacyRelationshipField) => void, binding?: unknown): void {
523523
const fields = this._store.schema.fields(this.identifier);
524524
fields.forEach((field, key) => {
525525
if (field.kind === 'belongsTo' || field.kind === 'hasMany') {

packages/model/src/-private/debug/assert-polymorphic-type.ts

+10-8
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ if (DEBUG) {
3636
}
3737
if (parentDefinition.isPolymorphic) {
3838
const meta = store.schema.fields(addedIdentifier)?.get(parentDefinition.inverseKey);
39-
assert(
40-
`Expected the schema for the field ${parentDefinition.inverseKey} on ${addedIdentifier.type} to be for a legacy relationship`,
41-
!meta || meta.kind === 'belongsTo' || meta.kind === 'hasMany'
42-
);
43-
assert(
44-
`The schema for the relationship '${parentDefinition.inverseKey}' on '${addedIdentifier.type}' type does not implement '${parentDefinition.type}' and thus cannot be assigned to the '${parentDefinition.key}' relationship in '${parentIdentifier.type}'. The definition should specify 'as: "${parentDefinition.type}"' in options.`,
45-
meta?.options.as === parentDefinition.type
46-
);
39+
if (meta) {
40+
assert(
41+
`Expected the schema for the field ${parentDefinition.inverseKey} on ${addedIdentifier.type} to be for a legacy relationship`,
42+
meta.kind === 'belongsTo' || meta.kind === 'hasMany'
43+
);
44+
assert(
45+
`The schema for the relationship '${parentDefinition.inverseKey}' on '${addedIdentifier.type}' type does not implement '${parentDefinition.type}' and thus cannot be assigned to the '${parentDefinition.key}' relationship in '${parentIdentifier.type}'. The definition should specify 'as: "${parentDefinition.type}"' in options.`,
46+
meta?.options?.as === parentDefinition.type
47+
);
48+
}
4749
}
4850
};
4951
}

0 commit comments

Comments
 (0)