Skip to content

Commit 54540e4

Browse files
committed
chore: fixup types
1 parent 816e80c commit 54540e4

File tree

17 files changed

+305
-159
lines changed

17 files changed

+305
-159
lines changed

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

+130-6
Original file line numberDiff line numberDiff line change
@@ -919,25 +919,51 @@ export type FieldSchema =
919919
| LegacyBelongsToField
920920
| LegacyHasManyField;
921921

922-
export type ResourceSchema = {
922+
export type ObjectFieldSchema =
923+
| GenericField
924+
| AliasField
925+
| LocalField
926+
| ObjectField
927+
| SchemaObjectField
928+
| ArrayField
929+
| SchemaArrayField
930+
| DerivedField;
931+
932+
/**
933+
* Represents a schema for a primary resource.
934+
*
935+
* Primary resources are objects with a unique identity of their
936+
* own which may allow them to appear in relationships, or is multiple
937+
* response document.
938+
*
939+
* @typedoc
940+
*/
941+
export interface ResourceSchema {
923942
legacy?: boolean;
943+
924944
/**
925945
* For primary resources, this should be an IdentityField
926946
*
927947
* for schema-objects, this should be either a HashField or null
928948
*
929949
* @typedoc
930950
*/
931-
identity: IdentityField | HashField | null;
951+
identity: IdentityField;
952+
932953
/**
933954
* The name of the schema
934955
*
935956
* For cacheable resources, this should be the
936957
* primary resource type.
937958
*
938959
* For object schemas, this should be the name
939-
* of the object schema. object schemas should
940-
* follow the following guidelines for naming
960+
* of the object schema.
961+
*
962+
* The names of object and resource schemas share
963+
* a single namespace and must not conflict.
964+
*
965+
* We recommend a naming convention for object schemas
966+
* such as below for ensuring uniqueness:
941967
*
942968
* - for globally shared objects: The pattern `$field:${KlassName}` e.g. `$field:AddressObject`
943969
* - for resource-specific objects: The pattern `$${ResourceKlassName}:$field:${KlassName}` e.g. `$User:$field:ReusableAddress`
@@ -946,9 +972,107 @@ export type ResourceSchema = {
946972
* @typedoc
947973
*/
948974
type: string;
949-
traits?: string[];
975+
976+
/**
977+
* The fields that make up the shape of the resource
978+
*/
950979
fields: FieldSchema[];
951-
};
980+
981+
/**
982+
* A list of traits that this resource implements. The fields for these
983+
* traits should still be defined in the fields array.
984+
*
985+
* Each trait should be a string that matches the `type` of another
986+
* resource schema. The trait can be abstract and reference a resource
987+
* type that is never defined as a schema.
988+
*
989+
* @typedoc
990+
*/
991+
traits?: string[];
992+
}
993+
994+
/**
995+
* Represents a schema for an object that is not
996+
* a primary resource (has no unique identity of its own).
997+
*
998+
* ObjectSchemas may not currently contain relationships.
999+
*
1000+
* @typedoc
1001+
*/
1002+
export interface ObjectSchema {
1003+
/**
1004+
* Either a HashField from which to calculate an identity or null
1005+
*
1006+
* In the case of `null`, the object's identity will be based
1007+
* on the referential identity of the object in the cache itself
1008+
* when an identity is needed.
1009+
*
1010+
* @typedoc
1011+
*/
1012+
identity: HashField | null;
1013+
1014+
/**
1015+
* The name of the schema
1016+
*
1017+
* The names of object and resource schemas share
1018+
* a single namespace and must not conflict.
1019+
*
1020+
* We recommend a naming convention for object schemas
1021+
* such as below for ensuring uniqueness:
1022+
*
1023+
* - for globally shared objects: The pattern `$field:${KlassName}` e.g. `$field:AddressObject`
1024+
* - for resource-specific objects: The pattern `$${ResourceKlassName}:$field:${KlassName}` e.g. `$User:$field:ReusableAddress`
1025+
* - for inline objects: The pattern `$${ResourceKlassName}.${fieldPath}:$field:anonymous` e.g. `$User.shippingAddress:$field:anonymous`
1026+
*
1027+
* @typedoc
1028+
*/
1029+
type: string;
1030+
1031+
/**
1032+
* The fields that make up the shape of the object
1033+
*/
1034+
fields: ObjectFieldSchema[];
1035+
}
1036+
1037+
/**
1038+
* A no-op type utility that enables type-checking resource schema
1039+
* definitions.
1040+
*
1041+
* Will return the passed in schema.
1042+
*
1043+
* This will not validate relationship inverses or related types,
1044+
* as doing so would require a full schema graph to be passed in
1045+
* and no cycles in the graph to be present.
1046+
*
1047+
* @param {ResourceSchema} schema
1048+
* @returns {ResourceSchema} the passed in schema
1049+
*/
1050+
export function resourceSchema(schema: ResourceSchema): ResourceSchema {
1051+
return schema;
1052+
}
1053+
1054+
/**
1055+
* A no-op type utility that enables type-checking object schema
1056+
* definitions.
1057+
*
1058+
* Will return the passed in schema.
1059+
*
1060+
* @param {ObjectSchema} schema
1061+
* @returns {ObjectSchema} the passed in schema
1062+
*/
1063+
export function objectSchema(schema: ObjectSchema): ObjectSchema {
1064+
return schema;
1065+
}
1066+
1067+
/**
1068+
* A type utility to narrow a schema to a ResourceSchema
1069+
*
1070+
* @param schema
1071+
* @returns {boolean}
1072+
*/
1073+
export function isResourceSchema(schema: ResourceSchema | ObjectSchema): schema is ResourceSchema {
1074+
return schema?.identity?.kind === '@id';
1075+
}
9521076

9531077
export type LegacyFieldSchema = LegacyAttributeField | LegacyBelongsToField | LegacyHasManyField;
9541078
export type LegacyRelationshipSchema = LegacyBelongsToField | LegacyHasManyField;

packages/model/src/-private/schema-provider.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
LegacyFieldSchema,
1818
LegacyRelationshipSchema,
1919
ObjectField,
20+
ObjectSchema,
2021
ResourceSchema,
2122
} from '@warp-drive/core-types/schema/fields';
2223

@@ -69,7 +70,7 @@ export class ModelSchemaProvider implements SchemaService {
6970
hashFn(field: HashField | { type: string }): HashFn {
7071
assert(`hashFn is not available with @ember-data/model's SchemaService`);
7172
}
72-
resource(resource: StableRecordIdentifier | { type: string }): ResourceSchema {
73+
resource(resource: StableRecordIdentifier | { type: string }): ResourceSchema | ObjectSchema {
7374
const type = normalizeModelName(resource.type);
7475

7576
if (!this._schemas.has(type)) {
@@ -78,10 +79,10 @@ export class ModelSchemaProvider implements SchemaService {
7879

7980
return this._schemas.get(type)!.schema;
8081
}
81-
registerResources(schemas: ResourceSchema[]): void {
82+
registerResources(schemas: Array<ResourceSchema | ObjectSchema>): void {
8283
assert(`registerResources is not available with @ember-data/model's SchemaService`);
8384
}
84-
registerResource(schema: ResourceSchema): void {
85+
registerResource(schema: ResourceSchema | ObjectSchema): void {
8586
assert(`registerResource is not available with @ember-data/model's SchemaService`);
8687
}
8788
registerTransformation(transform: Transformation): void {

packages/model/src/migration-support.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
GenericField,
1616
HashField,
1717
ObjectField,
18+
ObjectSchema,
1819
ResourceSchema,
1920
} from '@warp-drive/core-types/schema/fields';
2021
import { Type } from '@warp-drive/core-types/symbols';
@@ -227,16 +228,16 @@ export class DelegatingSchemaService implements SchemaService {
227228
derivation(field: DerivedField | { type: string }): Derivation {
228229
return this._preferred.derivation(field);
229230
}
230-
resource(resource: StableRecordIdentifier | { type: string }): ResourceSchema {
231+
resource(resource: StableRecordIdentifier | { type: string }): ResourceSchema | ObjectSchema {
231232
if (this._preferred.hasResource(resource)) {
232233
return this._preferred.resource(resource);
233234
}
234235
return this._secondary.resource(resource);
235236
}
236-
registerResources(schemas: ResourceSchema[]): void {
237+
registerResources(schemas: Array<ResourceSchema | ObjectSchema>): void {
237238
this._preferred.registerResources(schemas);
238239
}
239-
registerResource(schema: ResourceSchema): void {
240+
registerResource(schema: ResourceSchema | ObjectSchema): void {
240241
this._preferred.registerResource(schema);
241242
}
242243
registerTransformation(transform: Transformation): void {

packages/request/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"include": ["src/**/*"],
33
"compilerOptions": {
4-
"target": "ES2024",
4+
"target": "ESNext",
55
"module": "ESNext",
66
"moduleResolution": "bundler",
77
"skipLibCheck": true,

packages/schema-record/src/-private/hooks.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type Store from '@ember-data/store';
22
import { assert } from '@warp-drive/build-config/macros';
33
import type { StableRecordIdentifier } from '@warp-drive/core-types';
4+
import { isResourceSchema } from '@warp-drive/core-types/schema/fields';
45

56
import { SchemaRecord } from './record';
67
import type { SchemaService } from './schema';
@@ -12,7 +13,9 @@ export function instantiateRecord(
1213
createArgs?: Record<string, unknown>
1314
): SchemaRecord {
1415
const schema = store.schema as unknown as SchemaService;
15-
const isLegacy = schema.resource(identifier)?.legacy ?? false;
16+
const resourceSchema = schema.resource(identifier);
17+
assert(`Expected a resource schema`, isResourceSchema(resourceSchema));
18+
const isLegacy = resourceSchema?.legacy ?? false;
1619
const isEditable = isLegacy || store.cache.isNew(identifier);
1720
const record = new SchemaRecord(store, identifier, {
1821
[Editable]: isEditable,

packages/schema-record/src/-private/schema.ts

+19-17
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ import type { StableRecordIdentifier } from '@warp-drive/core-types';
1111
import { getOrSetGlobal } from '@warp-drive/core-types/-private';
1212
import type { ObjectValue, Value } from '@warp-drive/core-types/json/raw';
1313
import type { Derivation, HashFn } from '@warp-drive/core-types/schema/concepts';
14-
import type {
15-
ArrayField,
16-
DerivedField,
17-
FieldSchema,
18-
GenericField,
19-
HashField,
20-
LegacyAttributeField,
21-
LegacyRelationshipSchema,
22-
ObjectField,
23-
ResourceSchema,
14+
import {
15+
type ArrayField,
16+
type DerivedField,
17+
type FieldSchema,
18+
type GenericField,
19+
type HashField,
20+
isResourceSchema,
21+
type LegacyAttributeField,
22+
type LegacyRelationshipSchema,
23+
type ObjectField,
24+
type ObjectSchema,
25+
type ResourceSchema,
2426
} from '@warp-drive/core-types/schema/fields';
2527
import { Type } from '@warp-drive/core-types/symbols';
2628
import type { WithPartial } from '@warp-drive/core-types/utils';
@@ -91,13 +93,13 @@ export function registerDerivations(schema: SchemaServiceInterface) {
9193
schema.registerDerivation(_constructor);
9294
}
9395

94-
type InternalSchema = {
95-
original: ResourceSchema;
96+
interface InternalSchema {
97+
original: ResourceSchema | ObjectSchema;
9698
traits: Set<string>;
9799
fields: Map<string, FieldSchema>;
98100
attributes: Record<string, LegacyAttributeField>;
99101
relationships: Record<string, LegacyRelationshipSchema>;
100-
};
102+
}
101103

102104
export type Transformation<T extends Value = Value, PT = unknown> = {
103105
serialize(value: PT, options: Record<string, unknown> | null, record: SchemaRecord): T;
@@ -209,16 +211,16 @@ export class SchemaService implements SchemaServiceInterface {
209211
);
210212
return this._hashFns.get(field.type)!;
211213
}
212-
resource(resource: StableRecordIdentifier | { type: string }): ResourceSchema {
214+
resource(resource: StableRecordIdentifier | { type: string }): ResourceSchema | ObjectSchema {
213215
assert(`No resource registered with name '${resource.type}'`, this._schemas.has(resource.type));
214216
return this._schemas.get(resource.type)!.original;
215217
}
216-
registerResources(schemas: ResourceSchema[]): void {
218+
registerResources(schemas: Array<ResourceSchema | ObjectSchema>): void {
217219
schemas.forEach((schema) => {
218220
this.registerResource(schema);
219221
});
220222
}
221-
registerResource(schema: ResourceSchema): void {
223+
registerResource(schema: ResourceSchema | ObjectSchema): void {
222224
const fields = new Map<string, FieldSchema>();
223225
const relationships: Record<string, LegacyRelationshipSchema> = {};
224226
const attributes: Record<string, LegacyAttributeField> = {};
@@ -237,7 +239,7 @@ export class SchemaService implements SchemaServiceInterface {
237239
}
238240
});
239241

240-
const traits = new Set<string>(schema.traits);
242+
const traits = new Set<string>(isResourceSchema(schema) ? schema.traits : []);
241243
traits.forEach((trait) => {
242244
this._traits.add(trait);
243245
});

packages/store/src/-types/q/schema-service.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
LegacyBelongsToField,
1717
LegacyHasManyField,
1818
ObjectField,
19+
ObjectSchema,
1920
ResourceSchema,
2021
} from '@warp-drive/core-types/schema/fields';
2122

@@ -171,7 +172,7 @@ export interface SchemaService {
171172
* @param {StableRecordIdentifier|{ type: string }} resource
172173
* @return {ResourceSchema}
173174
*/
174-
resource(resource: { type: string } | StableRecordIdentifier): ResourceSchema;
175+
resource(resource: { type: string } | StableRecordIdentifier): ResourceSchema | ObjectSchema;
175176

176177
/**
177178
* Enables registration of multiple ResourceSchemas at once.
@@ -184,7 +185,7 @@ export interface SchemaService {
184185
* @public
185186
* @param schemas
186187
*/
187-
registerResources(schemas: ResourceSchema[]): void;
188+
registerResources(schemas: Array<ResourceSchema | ObjectSchema>): void;
188189

189190
/**
190191
* Enables registration of a single ResourceSchema.
@@ -197,7 +198,7 @@ export interface SchemaService {
197198
* @public
198199
* @param {ResourceSchema} schema
199200
*/
200-
registerResource(schema: ResourceSchema): void;
201+
registerResource(schema: ResourceSchema | ObjectSchema): void;
201202

202203
/**
203204
* Enables registration of a transformation.

0 commit comments

Comments
 (0)