diff --git a/addon/adapters/cloud-firestore-modular.ts b/addon/adapters/cloud-firestore-modular.ts index d08b3961..54116ae9 100644 --- a/addon/adapters/cloud-firestore-modular.ts +++ b/addon/adapters/cloud-firestore-modular.ts @@ -1,9 +1,16 @@ -import { getOwner } from '@ember/application'; +import { getOwner } from '@ember/owner'; import { service } from '@ember/service'; import Adapter from '@ember-data/adapter'; -import type DS from 'ember-data'; -import { type ModelSchema } from 'ember-data'; -import type ModelRegistry from 'ember-data/types/registries/model'; +import type { ModelSchema } from '@ember-data/store/types'; +import type { AdapterPayload } from '@ember-data/legacy-compat'; +import type { Snapshot as _Snapshot } from '@ember-data/legacy-compat/legacy-network-handler/snapshot'; +import type { SnapshotRecordArray as _SnapshotRecordArray } from '@ember-data/legacy-compat/-private'; +import type { Collection } from '@ember-data/store/-private/record-arrays/identifier-array'; +import type { + LegacyBelongsToField, + LegacyHasManyField, +} from '@warp-drive/core-types/schema/fields'; +import type Model from 'ember-data/model'; import RSVP from 'rsvp'; import type Store from '@ember-data/store'; @@ -41,30 +48,27 @@ export interface AdapterOption { [key: string]: unknown; } -interface Snapshot extends DS.Snapshot { +interface Snapshot extends _Snapshot { adapterOptions: AdapterOption; } -interface SnapshotRecordArray - extends DS.SnapshotRecordArray { +interface SnapshotRecordArray extends _SnapshotRecordArray { adapterOptions: AdapterOption; } -interface BelongsToRelationshipMeta { - type: keyof ModelRegistry; +type BelongsToRelationshipMeta = LegacyBelongsToField & { options: { isRealtime?: boolean }; -} +}; -interface HasManyRelationshipMeta { +type HasManyRelationshipMeta = LegacyHasManyField & { key: string; - type: string; options: { isRealtime?: boolean; buildReference?(db: Firestore, record: unknown): CollectionReference; filter?(db: CollectionReference | Query, record: unknown): Query; }; -} +}; export default class CloudFirestoreAdapter extends Adapter { @service('-firestore-data-manager') @@ -73,9 +77,9 @@ export default class CloudFirestoreAdapter extends Adapter { protected referenceKeyName = 'referenceTo'; protected get isFastBoot(): boolean { - const fastboot = getOwner(this).lookup('service:fastboot'); + const fastboot = getOwner(this)?.lookup('service:fastboot'); - return fastboot && fastboot.isFastBoot; + return !!fastboot && fastboot.isFastBoot; } public generateIdForRecord(_store: Store, type: unknown): string { @@ -89,7 +93,7 @@ export default class CloudFirestoreAdapter extends Adapter { store: Store, type: ModelSchema, snapshot: Snapshot, - ): RSVP.Promise { + ): Promise { return this.updateRecord(store, type, snapshot); } @@ -97,13 +101,13 @@ export default class CloudFirestoreAdapter extends Adapter { _store: Store, type: ModelSchema, snapshot: Snapshot, - ): RSVP.Promise { + ): Promise { return new RSVP.Promise((resolve, reject) => { const collectionRef = this.buildCollectionRef( type.modelName, snapshot.adapterOptions, ); - const docRef = doc(collectionRef, snapshot.id); + const docRef = doc(collectionRef, snapshot.id!); const batch = this.buildWriteBatch(docRef, snapshot); batch @@ -131,14 +135,14 @@ export default class CloudFirestoreAdapter extends Adapter { _store: Store, type: ModelSchema, snapshot: Snapshot, - ): RSVP.Promise { + ): Promise { return new RSVP.Promise((resolve, reject) => { const db = getFirestore(); const collectionRef = this.buildCollectionRef( type.modelName, snapshot.adapterOptions, ); - const docRef = doc(collectionRef, snapshot.id); + const docRef = doc(collectionRef, snapshot.id!); const batch = writeBatch(db); batch.delete(docRef); @@ -160,7 +164,7 @@ export default class CloudFirestoreAdapter extends Adapter { type: ModelSchema, id: string, snapshot: Snapshot, - ): RSVP.Promise { + ): Promise { return new RSVP.Promise(async (resolve, reject) => { try { const colRef = this.buildCollectionRef( @@ -194,9 +198,9 @@ export default class CloudFirestoreAdapter extends Adapter { public findAll( _store: Store, type: ModelSchema, - _sinceToken: string, - snapshotRecordArray?: SnapshotRecordArray, - ): RSVP.Promise { + _sinceToken: null, + snapshotRecordArray: SnapshotRecordArray, + ): Promise { return new RSVP.Promise(async (resolve, reject) => { try { const db = getFirestore(); @@ -223,12 +227,13 @@ export default class CloudFirestoreAdapter extends Adapter { }); } + // @ts-expect-error ember data types 3 arg public query( _store: Store, type: ModelSchema, queryOption: AdapterOption, - recordArray: DS.AdapterPopulatedRecordArray, - ): RSVP.Promise { + recordArray: Collection, + ): Promise { return new RSVP.Promise(async (resolve, reject) => { try { const colRef = this.buildCollectionRef(type.modelName, queryOption); @@ -264,7 +269,7 @@ export default class CloudFirestoreAdapter extends Adapter { _snapshot: Snapshot, url: string, relationship: BelongsToRelationshipMeta, - ): RSVP.Promise { + ): Promise { return new RSVP.Promise(async (resolve, reject) => { try { const urlNodes = url.split('/'); @@ -303,7 +308,7 @@ export default class CloudFirestoreAdapter extends Adapter { snapshot: Snapshot, url: string, relationship: HasManyRelationshipMeta, - ): RSVP.Promise { + ): Promise { return new RSVP.Promise(async (resolve, reject) => { try { const queryRef = this.buildHasManyCollectionRef( @@ -315,7 +320,7 @@ export default class CloudFirestoreAdapter extends Adapter { const config = { queryRef, modelName: snapshot.modelName, - id: snapshot.id, + id: snapshot.id!, field: relationship.key, referenceKeyName: this.referenceKeyName, }; @@ -339,7 +344,7 @@ export default class CloudFirestoreAdapter extends Adapter { } protected buildCollectionRef( - modelName: keyof ModelRegistry, + modelName: string, adapterOptions?: AdapterOption, ): CollectionReference { const db = getFirestore(); @@ -402,7 +407,7 @@ export default class CloudFirestoreAdapter extends Adapter { ); } - const modelClass = store.modelFor(snapshot.modelName); + const modelClass = store.modelFor(snapshot.modelName) as typeof Model; const cardinality = modelClass.determineRelationshipType( relationship, store, @@ -420,7 +425,7 @@ export default class CloudFirestoreAdapter extends Adapter { const collectionRef = collection(db, url); const queryRef = query( collectionRef, - where(inverse.name, '==', snapshotDocRef), + where(inverse?.name as string, '==', snapshotDocRef), ); return ( @@ -436,9 +441,3 @@ export default class CloudFirestoreAdapter extends Adapter { ); } } - -declare module 'ember-data/types/registries/adapter' { - export default interface AdapterRegistry { - 'cloud-firestore-modular': CloudFirestoreAdapter; - } -} diff --git a/addon/serializers/cloud-firestore-modular.ts b/addon/serializers/cloud-firestore-modular.ts index 62370c05..252e7fc1 100644 --- a/addon/serializers/cloud-firestore-modular.ts +++ b/addon/serializers/cloud-firestore-modular.ts @@ -4,10 +4,9 @@ */ import { isNone } from '@ember/utils'; -import type DS from 'ember-data'; -import { type ModelSchema } from 'ember-data'; +import type Model from '@ember-data/model'; +import type { Snapshot } from '@ember-data/legacy-compat/legacy-network-handler/snapshot'; import JSONSerializer from '@ember-data/serializer/json'; -import type Store from '@ember-data/store'; import type { CollectionReference, @@ -39,19 +38,13 @@ interface RelationshipDefinition { }; } -type ModelClass = ModelSchema & { - determineRelationshipType( - descriptor: { kind: string; type: string }, - store: Store, - ): string; -}; - export default class CloudFirestoreSerializer extends JSONSerializer { public extractRelationship( relationshipModelName: string, relationshipHash: DocumentReference, ): { id: string; type: string } | Record { if (isNone(relationshipHash)) { + // @ts-expect-error ember data types aren't exporting serializer types correctly return super.extractRelationship(relationshipModelName, relationshipHash); } @@ -62,7 +55,7 @@ export default class CloudFirestoreSerializer extends JSONSerializer { } public extractRelationships( - modelClass: ModelClass, + modelClass: typeof Model, resourceHash: ResourceHash, ): Record { const newResourceHash = { ...resourceHash }; @@ -99,14 +92,16 @@ export default class CloudFirestoreSerializer extends JSONSerializer { newResourceHash.links = links; + // @ts-expect-error ember data types aren't exporting serializer types correctly return super.extractRelationships(modelClass, newResourceHash); } public serializeBelongsTo( - snapshot: DS.Snapshot, + snapshot: Snapshot, json: { [key: string]: string | null | DocumentReference }, relationship: RelationshipDefinition, ): void { + // @ts-expect-error ember data types aren't exporting serializer types correctly super.serializeBelongsTo(snapshot, json, relationship); if (json[relationship.key]) { @@ -128,10 +123,11 @@ export default class CloudFirestoreSerializer extends JSONSerializer { } public serialize( - snapshot: DS.Snapshot, + snapshot: Snapshot, options: Record, ): Record { const json: { [key: string]: unknown } = { + // @ts-expect-error ember data types aren't exporting serializer types correctly ...super.serialize(snapshot, options), }; @@ -144,9 +140,3 @@ export default class CloudFirestoreSerializer extends JSONSerializer { return json; } } - -declare module 'ember-data/types/registries/serializer' { - export default interface SerializerRegistry { - 'cloud-firestore-modular': CloudFirestoreSerializer; - } -} diff --git a/addon/services/-firestore-data-manager.ts b/addon/services/-firestore-data-manager.ts index b51a7fba..ddf91069 100644 --- a/addon/services/-firestore-data-manager.ts +++ b/addon/services/-firestore-data-manager.ts @@ -1,6 +1,8 @@ import { next } from '@ember/runloop'; -import type DS from 'ember-data'; -import type ModelRegistry from 'ember-data/types/registries/model'; +import type Model from '@ember-data/model'; +import type { Collection } from '@ember-data/store/-private/record-arrays/identifier-array'; +import type { CompatStore } from '@ember-data/legacy-compat'; +import type { ObjectValue } from '@warp-drive/core-types/json/raw'; import Service, { service } from '@ember/service'; import type StoreService from '@ember-data/store'; @@ -42,15 +44,15 @@ interface QueryListeners { } interface QueryFetchConfig { - modelName: keyof ModelRegistry; + modelName: string; referenceKeyName: string; - recordArray: DS.AdapterPopulatedRecordArray; + recordArray: Collection; queryRef: Query; queryId?: string; } interface HasManyFetchConfig { - modelName: keyof ModelRegistry; + modelName: string; id: string; field: string; referenceKeyName: string; @@ -87,7 +89,7 @@ export default class FirestoreDataManager extends Service { } public async findRecordRealtime( - modelName: keyof ModelRegistry, + modelName: string, docRef: DocumentReference, ): Promise { const { path: listenerKey } = docRef; @@ -100,7 +102,7 @@ export default class FirestoreDataManager extends Service { } public async findAllRealtime( - modelName: keyof ModelRegistry, + modelName: string, colRef: CollectionReference, ): Promise { const { path: listenerKey } = colRef; @@ -167,7 +169,7 @@ export default class FirestoreDataManager extends Service { } private setupDocRealtimeUpdates( - modelName: keyof ModelRegistry, + modelName: string, docRef: DocumentReference, ): Promise { return new Promise((resolve, reject) => { @@ -202,7 +204,7 @@ export default class FirestoreDataManager extends Service { } private setupColRealtimeUpdates( - modelName: keyof ModelRegistry, + modelName: string, colRef: CollectionReference, ): Promise { return new Promise((resolve, reject) => { @@ -316,7 +318,7 @@ export default class FirestoreDataManager extends Service { private handleSubsequentDocRealtimeUpdates( docSnapshot: DocumentSnapshot, - modelName: keyof ModelRegistry, + modelName: string, listenerKey: string, ): void { if (docSnapshot.exists()) { @@ -328,7 +330,7 @@ export default class FirestoreDataManager extends Service { } private handleSubsequentColRealtimeUpdates( - modelName: keyof ModelRegistry, + modelName: string, listenerKey: string, querySnapshot: QuerySnapshot, ): void { @@ -366,7 +368,7 @@ export default class FirestoreDataManager extends Service { private handleSubsequentQueryRealtimeUpdates( queryId: string, - recordArray: DS.AdapterPopulatedRecordArray, + recordArray: Collection, ): void { // Schedule for next runloop to avoid race condition errors. This can happen when a listener // exists for a record that's part of the query array. When that happens, doing an update @@ -414,17 +416,16 @@ export default class FirestoreDataManager extends Service { // To avoid the issue, we run .reload() in the next runloop so that we allow the unload // to happen first. next(() => { - const hasManyRef = this.store - .peekRecord(config.modelName, config.id) - .hasMany(config.field); + const record = this.store.peekRecord(config.modelName, config.id); + const hasManyRef = (record as Model).hasMany(config.field); - hasManyRef.reload(); + hasManyRef?.reload(); }); } public async getReferenceToDoc( docSnapshot: DocumentSnapshot, - modelName: keyof ModelRegistry, + modelName: string, referenceKeyName: string, isRealtime = false, ): Promise { @@ -439,27 +440,23 @@ export default class FirestoreDataManager extends Service { return docSnapshot; } - private pushRecord( - modelName: keyof ModelRegistry, - snapshot: DocumentSnapshot, - ): void { + private pushRecord(modelName: string, snapshot: DocumentSnapshot): void { const flatRecord = flattenDocSnapshot(snapshot); - const normalizedRecord = this.store.normalize(modelName, flatRecord); + const normalizedRecord = (this.store as CompatStore).normalize( + modelName, + flatRecord as ObjectValue, + ); // Race condition can happen because of the realtime nature. We handle that in a try-catch // to avoid unexpected side-effects. When this happens, we just ignore it. try { - this.store.push(normalizedRecord); + this.store.push(normalizedRecord as never); } catch { // Do nothing } } - private unloadRecord( - modelName: keyof ModelRegistry, - id: string, - path?: string, - ): void { + private unloadRecord(modelName: string, id: string, path?: string): void { const record = this.store.peekRecord(modelName, id); if (record !== null) { diff --git a/addon/transforms/timestamp.ts b/addon/transforms/timestamp.ts index e296abbe..b8826072 100644 --- a/addon/transforms/timestamp.ts +++ b/addon/transforms/timestamp.ts @@ -19,9 +19,3 @@ export default class TimestampTransform extends Transform { return typeOf(value) === 'date' ? (value as Date) : serverTimestamp(); } } - -declare module 'ember-data/types/registries/transform' { - export default interface TransformRegistry { - timestamp: TimestampTransform; - } -} diff --git a/package-lock.json b/package-lock.json index 7f7dc567..2ca0904c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,16 @@ "ember-cli-typescript": "^4.2.1" }, "devDependencies": { + "@ember-data-types/adapter": "^5.3.9", + "@ember-data-types/graph": "^5.3.9", + "@ember-data-types/json-api": "^5.3.9", + "@ember-data-types/legacy-compat": "^5.3.9", + "@ember-data-types/model": "^5.3.9", + "@ember-data-types/request": "^5.3.9", + "@ember-data-types/request-utils": "^5.3.9", + "@ember-data-types/serializer": "^5.3.9", + "@ember-data-types/store": "^5.3.9", + "@ember-data-types/tracking": "^5.3.9", "@ember/optional-features": "^2.1.0", "@ember/string": "^3.1.1", "@ember/test-helpers": "^3.2.0", @@ -23,35 +33,13 @@ "@glimmer/component": "^1.1.2", "@glimmer/tracking": "^1.1.2", "@tsconfig/ember": "^3.0.8", - "@types/ember": "^4.0.11", - "@types/ember__application": "^4.0.11", - "@types/ember__array": "^4.0.10", - "@types/ember__component": "^4.0.22", - "@types/ember__controller": "^4.0.12", - "@types/ember__debug": "^4.0.8", - "@types/ember__engine": "^4.0.11", - "@types/ember__error": "^4.0.6", - "@types/ember__object": "^4.0.12", - "@types/ember__owner": "^4.0.9", - "@types/ember__polyfills": "^4.0.6", - "@types/ember__routing": "^4.0.22", - "@types/ember__runloop": "^4.0.10", - "@types/ember__service": "^4.0.9", - "@types/ember__string": "^3.0.15", - "@types/ember__template": "^4.0.7", - "@types/ember__test": "^4.0.6", - "@types/ember__utils": "^4.0.7", - "@types/ember-data": "^4.4.16", - "@types/ember-data__adapter": "^4.0.6", - "@types/ember-data__model": "^4.0.5", - "@types/ember-data__serializer": "^4.0.6", - "@types/ember-data__store": "^4.0.7", "@types/node": "^20.14.2", "@types/qunit": "^2.19.10", "@types/rsvp": "^4.0.9", "@types/sinon": "^17.0.3", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", + "@warp-drive-types/core-types": "^0.0.0-alpha.107", "broccoli-asset-rev": "^3.0.0", "concurrently": "^8.2.2", "ember-cli": "~5.4.2", @@ -63,6 +51,7 @@ "ember-cli-terser": "^4.0.2", "ember-cli-typescript-blueprints": "^3.0.0", "ember-data": "~4.11.2", + "ember-data-types": "^5.3.9", "ember-fetch": "^8.1.2", "ember-load-initializers": "^2.1.2", "ember-page-title": "^8.0.0", @@ -2140,6 +2129,66 @@ "postcss-selector-parser": "^6.0.13" } }, + "node_modules/@ember-data-types/adapter": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/adapter/-/adapter-5.3.9.tgz", + "integrity": "sha512-soCShQiwEtV3kqGOSPgB6UljFY7NAlWDy06XqiNTPiBBiilPjYG+EJeWwoXbNbWf70XPdWG4ecIJd56Nz/Fhyw==", + "dev": true + }, + "node_modules/@ember-data-types/graph": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/graph/-/graph-5.3.9.tgz", + "integrity": "sha512-Qo6N+KYZATeheB55dEhQAXzsGVNOtUiLdOfUITAOxvv+wmvbKuGjNfffJ4HuNJBT2ZWB1R6XzCL+YYk2Q+dMyQ==", + "dev": true + }, + "node_modules/@ember-data-types/json-api": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/json-api/-/json-api-5.3.9.tgz", + "integrity": "sha512-Yi41shKtFyoveIW8NIfyTDCQImDxQqT5OANL2+ZHR/4xnkt9292NOfwFFDwTxGIt3BS/NcfOFUJSRZp3gPONmA==", + "dev": true + }, + "node_modules/@ember-data-types/legacy-compat": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/legacy-compat/-/legacy-compat-5.3.9.tgz", + "integrity": "sha512-WQKez8tL60bjRUYt2mMjUWZI9FaSSCSKEPTnQSX5t6cIsuC67y3mDt5vmwMEITqw82uV8yXu8J44A1D/bY1aNw==", + "dev": true + }, + "node_modules/@ember-data-types/model": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/model/-/model-5.3.9.tgz", + "integrity": "sha512-N1KJ/qMdqI4wCV8TcyBGR583dqtqwyFcR5rjP0W2pZZ8khRDk3XROMzOa7wki/BYGkJxwfHxvlFVLRdAP/vF3w==", + "dev": true + }, + "node_modules/@ember-data-types/request": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/request/-/request-5.3.9.tgz", + "integrity": "sha512-uD3hQCNkSvHFVmKXt4FCJY+GuU/6jL9c6lC5tAD+TMa/C6JrOoJAzeBoWt61xRxtVUcxQB6g4qjm11YsUy5tGw==", + "dev": true + }, + "node_modules/@ember-data-types/request-utils": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/request-utils/-/request-utils-5.3.9.tgz", + "integrity": "sha512-7Iy23SE8404QD+eH9DuE2R3McW2A6Odsn/wKCwo7gmGyvDZB/5Ca9OOVsm2U9swO2xaQrlB4sE/139jkAji54A==", + "dev": true + }, + "node_modules/@ember-data-types/serializer": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/serializer/-/serializer-5.3.9.tgz", + "integrity": "sha512-WqzguopBOzm657s1bAGFK3E2O5+nvx2jJRi1kpsYrELxfbXpWCUWit3E9d8FGUqlMYoyBtQWdAwPosjuJTb2/Q==", + "dev": true + }, + "node_modules/@ember-data-types/store": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/store/-/store-5.3.9.tgz", + "integrity": "sha512-d6iEm6rktkVXmOzhi4QfKlt3dTCVOdSO569RAeDw8Ak3d8zCX3rLu/rcjOnISvGHQ0lVfDG3tHIpgfGpZmb5yg==", + "dev": true + }, + "node_modules/@ember-data-types/tracking": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/tracking/-/tracking-5.3.9.tgz", + "integrity": "sha512-4vrPQBo0Hf5TpOuGNMMHWJItqcfuj/oc1RqmEkL9C0Sv60UGnfNLQ994Dsye7CPtjIcIQOdU7/1vhSBqybMgKA==", + "dev": true + }, "node_modules/@ember-data/adapter": { "version": "4.11.3", "resolved": "https://registry.npmjs.org/@ember-data/adapter/-/adapter-4.11.3.tgz", @@ -11608,230 +11657,6 @@ "@types/node": "*" } }, - "node_modules/@types/ember": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/ember/-/ember-4.0.11.tgz", - "integrity": "sha512-v7VIex0YILK8fP87LkIfzeeYKNnu74+xwf6U56v6MUDDGfSs9q/6NCxiUfwkxD+z5nQiUcwvfKVokX8qzZFRLw==", - "dev": true, - "dependencies": { - "@types/ember__application": "*", - "@types/ember__array": "*", - "@types/ember__component": "*", - "@types/ember__controller": "*", - "@types/ember__debug": "*", - "@types/ember__engine": "*", - "@types/ember__error": "*", - "@types/ember__object": "*", - "@types/ember__polyfills": "*", - "@types/ember__routing": "*", - "@types/ember__runloop": "*", - "@types/ember__service": "*", - "@types/ember__string": "*", - "@types/ember__template": "*", - "@types/ember__test": "*", - "@types/ember__utils": "*", - "@types/rsvp": "*" - } - }, - "node_modules/@types/ember__application": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/ember__application/-/ember__application-4.0.11.tgz", - "integrity": "sha512-U1S7XW0V70nTWbFckWoraJbYGBJK69muP/CsPFLeAuUYHfkkDiwh1SfqgAUN9aHtrEJM5SuSYVYp2YsTI2yLuA==", - "dev": true, - "dependencies": { - "@glimmer/component": "^1.1.0", - "@types/ember": "*", - "@types/ember__engine": "*", - "@types/ember__object": "*", - "@types/ember__owner": "*", - "@types/ember__routing": "*" - } - }, - "node_modules/@types/ember__array": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@types/ember__array/-/ember__array-4.0.10.tgz", - "integrity": "sha512-UrhDbopLI3jB0MqV14y8yji2IuPNmeDrtT1PRYJL4CThLHrRkfeYyFvxqvrxWxn0wXKjbbjfH1gOe7BU57QrLQ==", - "dev": true, - "dependencies": { - "@types/ember": "*", - "@types/ember__object": "*" - } - }, - "node_modules/@types/ember__component": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@types/ember__component/-/ember__component-4.0.22.tgz", - "integrity": "sha512-m72EtmBN/RxOChXqRsyOg4RR5+AiB4LQ8s1CEKNYAfvANt18m4hjqxtA7QZYLTq2ZjEVJGpdMsrdDuONWjwRSQ==", - "dev": true, - "dependencies": { - "@types/ember": "*", - "@types/ember__object": "*" - } - }, - "node_modules/@types/ember__controller": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/@types/ember__controller/-/ember__controller-4.0.12.tgz", - "integrity": "sha512-80rdnSC0UJBqoUX5/vkQcM2xkRdTPTvY0dPXEfY5cC5OZITbcSeRo5qa7ZGhgNBfH6XYyh55Lo/b811LwU3N9w==", - "dev": true, - "dependencies": { - "@types/ember__object": "*" - } - }, - "node_modules/@types/ember__debug": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/ember__debug/-/ember__debug-4.0.8.tgz", - "integrity": "sha512-9wF7STmDHDsUxSjyCq2lpMq/03QOPkBQMGJnV8yOBnVZxB6f+FJH/kxaCprdMkUe7iwAPNEC2zrFFx1tzH75Kg==", - "dev": true, - "dependencies": { - "@types/ember__object": "*", - "@types/ember__owner": "*" - } - }, - "node_modules/@types/ember__engine": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/ember__engine/-/ember__engine-4.0.11.tgz", - "integrity": "sha512-ryR4Q1Xm3kQ3Ap58w10CxV3+vb3hs1cJqi7UZ5IlSdLRql7AbpS6hIjxSQ3EQ4zadeeJ6/D8JJcSwqR7eX3PFA==", - "dev": true, - "dependencies": { - "@types/ember__object": "*", - "@types/ember__owner": "*" - } - }, - "node_modules/@types/ember__error": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember__error/-/ember__error-4.0.6.tgz", - "integrity": "sha512-vYrLaGGjHkN14K89Vm8yqB2mkpJQefE5w7QJkkgYyV+smzns1vKlPbvuFevRtoeYNn4u4yY0JyF7HceNkm3H0Q==", - "dev": true - }, - "node_modules/@types/ember__object": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/@types/ember__object/-/ember__object-4.0.12.tgz", - "integrity": "sha512-ZEpikPjZ02m1QCBiTPTayMJwVwF4UBlHlGDoScRB3IP/SUS1O5mmn1/CnSQDxzzF3ctfmhNuTZzVBBc1Y8OC1A==", - "dev": true, - "dependencies": { - "@types/ember": "*", - "@types/rsvp": "*" - } - }, - "node_modules/@types/ember__owner": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/ember__owner/-/ember__owner-4.0.9.tgz", - "integrity": "sha512-iyBda4aUIjBmeiKTKmPow/EJO7xWn8m85CnQTOCqQzTWJyJpgfObbXSHahOHXOfMm279Oa5NlbmS/EontB+XiQ==", - "dev": true - }, - "node_modules/@types/ember__polyfills": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember__polyfills/-/ember__polyfills-4.0.6.tgz", - "integrity": "sha512-hbds3Qv+oVm/QKIaY1E6atvrCoJTH/MPSl4swOhX6P0RiMB2fOfFCrFSD1mP1KrU1LqpHJ2Rzs7XLe53SWVzgw==", - "dev": true - }, - "node_modules/@types/ember__routing": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@types/ember__routing/-/ember__routing-4.0.22.tgz", - "integrity": "sha512-qLk9Vd2GMxdlGmX9xbzg4Farths+AQGzYDH901Wo2Nsre+Cwv1Tk1rbCiay2V3ICYZYufytdWT6V++DISF3nvw==", - "dev": true, - "dependencies": { - "@types/ember": "*", - "@types/ember__controller": "*", - "@types/ember__object": "*", - "@types/ember__service": "*" - } - }, - "node_modules/@types/ember__runloop": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@types/ember__runloop/-/ember__runloop-4.0.10.tgz", - "integrity": "sha512-9MZfOJBXuUP7RqLjovmzy1yY2xKTxVpqHMapqy6QJ8mjAekRmq9IJ+ni2zJ5CWftyb3Lqu3Eks05CL7fnbhcJA==", - "dev": true, - "dependencies": { - "@types/ember": "*" - } - }, - "node_modules/@types/ember__service": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/ember__service/-/ember__service-4.0.9.tgz", - "integrity": "sha512-DrepocL/4hH5YxbDWbxEKMDcAchBPSGGa4g+LEINW1Po81RmSdKw5GZV4UO0mvRWgkdu3EbWUxbTzB4gmbDSeQ==", - "dev": true, - "dependencies": { - "@types/ember__object": "*" - } - }, - "node_modules/@types/ember__string": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/ember__string/-/ember__string-3.0.15.tgz", - "integrity": "sha512-SxoaweAJUJKSIt82clIwpi/Fm0IfeisozLnXthnBp/hE2JyVcnOb1wMIbw0CCfzercmyWG1njV45VBqy8SrLDQ==", - "dev": true - }, - "node_modules/@types/ember__template": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/ember__template/-/ember__template-4.0.7.tgz", - "integrity": "sha512-jv4hhG+8d1zdma+jhbCdJ3Ak7C22YNatGyWWvB3N9zbXq358AAPXaJoyNY8QTDbD/RIR9P6yoRk4u9vLbF6zfA==", - "dev": true - }, - "node_modules/@types/ember__test": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember__test/-/ember__test-4.0.6.tgz", - "integrity": "sha512-Nswm/epfTepXknT8scZvWyyop1aqJcZcyzY4THGHFcXvYQQfA9rgmgrx6vo9vCJmYHh3jm0TTAIAIfoCvGaX5g==", - "dev": true, - "dependencies": { - "@types/ember__application": "*" - } - }, - "node_modules/@types/ember__utils": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/ember__utils/-/ember__utils-4.0.7.tgz", - "integrity": "sha512-qQPBeWRyIPigKnZ68POlkqI5e6XA78Q4G3xHo687wQTcEtfoL/iZyPC4hn70mdijcZq8Hjch2Y3E5yhsEMzK+g==", - "dev": true, - "dependencies": { - "@types/ember": "*" - } - }, - "node_modules/@types/ember-data": { - "version": "4.4.16", - "resolved": "https://registry.npmjs.org/@types/ember-data/-/ember-data-4.4.16.tgz", - "integrity": "sha512-plFqPkgw7n4YlkzvApkQAIhvvYTERlx8PeI2J5gSFtMtsKuoaIo8fXm4w22ZdBQtTzeh/kwvpO2WY8R/d5Ttfg==", - "dev": true, - "dependencies": { - "@types/ember": "*", - "@types/ember__error": "*", - "@types/ember__object": "*", - "@types/rsvp": "*" - } - }, - "node_modules/@types/ember-data__adapter": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember-data__adapter/-/ember-data__adapter-4.0.6.tgz", - "integrity": "sha512-vSrx1cqz8jO0cBYwu98SrwFk5s722C+BGpw++NregwQio3g9VbNoymx+HsYeXvsWvGUsoRewxu9K7TwAOJSsvw==", - "dev": true, - "dependencies": { - "@types/ember-data": "*" - } - }, - "node_modules/@types/ember-data__model": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/ember-data__model/-/ember-data__model-4.0.5.tgz", - "integrity": "sha512-zyfHh3tQiMdpbPZ1/RFxi4m9TdwsZxDmVY0e7V1UYp7pWvm/DeqEXqoy3WS9xa/O01xoJFpQtJHyasdXvVTfbg==", - "dev": true, - "dependencies": { - "@types/ember-data": "*" - } - }, - "node_modules/@types/ember-data__serializer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember-data__serializer/-/ember-data__serializer-4.0.6.tgz", - "integrity": "sha512-ebxxySSvTiay1/hgN4fElahSuL0MX+1sMMwx/RQyy7z98ifV8wafW62BwlYtbH44aeTIdcaSBE2pm3R1aP2yUA==", - "dev": true, - "dependencies": { - "@types/ember-data": "*" - } - }, - "node_modules/@types/ember-data__store": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/ember-data__store/-/ember-data__store-4.0.7.tgz", - "integrity": "sha512-0S3Etr32i4aGvhXhZM6CXaosvX8E6c+RCx8pCxUXVdn+SmICm8jqFXsDC6Gnqq4bJeTkf9cglqz46prOVR1Tcg==", - "dev": true, - "dependencies": { - "@types/ember-data": "*" - } - }, "node_modules/@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", @@ -12247,6 +12072,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@warp-drive-types/core-types": { + "version": "0.0.0-alpha.107", + "resolved": "https://registry.npmjs.org/@warp-drive-types/core-types/-/core-types-0.0.0-alpha.107.tgz", + "integrity": "sha512-nUsJplM8y1eTDnrsQ1shq+eJOEZ5476tsRkTE5GeTNha6viyJuvGKoTDhsI8Id/M+CBp8jFz18egYLiC8jShsA==", + "dev": true + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -22284,6 +22115,12 @@ "@ember/string": "^3.0.1" } }, + "node_modules/ember-data-types": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/ember-data-types/-/ember-data-types-5.3.9.tgz", + "integrity": "sha512-Dp7HS756l92pv+5W5zoFM5huIPfZqGVfNofZvf1w0qlRTUFVT/q8KqxFFNAcWvZyZtEqm34WyAlARhfuBgGuXA==", + "dev": true + }, "node_modules/ember-data/node_modules/@types/fs-extra": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz", @@ -55058,6 +54895,66 @@ "dev": true, "requires": {} }, + "@ember-data-types/adapter": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/adapter/-/adapter-5.3.9.tgz", + "integrity": "sha512-soCShQiwEtV3kqGOSPgB6UljFY7NAlWDy06XqiNTPiBBiilPjYG+EJeWwoXbNbWf70XPdWG4ecIJd56Nz/Fhyw==", + "dev": true + }, + "@ember-data-types/graph": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/graph/-/graph-5.3.9.tgz", + "integrity": "sha512-Qo6N+KYZATeheB55dEhQAXzsGVNOtUiLdOfUITAOxvv+wmvbKuGjNfffJ4HuNJBT2ZWB1R6XzCL+YYk2Q+dMyQ==", + "dev": true + }, + "@ember-data-types/json-api": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/json-api/-/json-api-5.3.9.tgz", + "integrity": "sha512-Yi41shKtFyoveIW8NIfyTDCQImDxQqT5OANL2+ZHR/4xnkt9292NOfwFFDwTxGIt3BS/NcfOFUJSRZp3gPONmA==", + "dev": true + }, + "@ember-data-types/legacy-compat": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/legacy-compat/-/legacy-compat-5.3.9.tgz", + "integrity": "sha512-WQKez8tL60bjRUYt2mMjUWZI9FaSSCSKEPTnQSX5t6cIsuC67y3mDt5vmwMEITqw82uV8yXu8J44A1D/bY1aNw==", + "dev": true + }, + "@ember-data-types/model": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/model/-/model-5.3.9.tgz", + "integrity": "sha512-N1KJ/qMdqI4wCV8TcyBGR583dqtqwyFcR5rjP0W2pZZ8khRDk3XROMzOa7wki/BYGkJxwfHxvlFVLRdAP/vF3w==", + "dev": true + }, + "@ember-data-types/request": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/request/-/request-5.3.9.tgz", + "integrity": "sha512-uD3hQCNkSvHFVmKXt4FCJY+GuU/6jL9c6lC5tAD+TMa/C6JrOoJAzeBoWt61xRxtVUcxQB6g4qjm11YsUy5tGw==", + "dev": true + }, + "@ember-data-types/request-utils": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/request-utils/-/request-utils-5.3.9.tgz", + "integrity": "sha512-7Iy23SE8404QD+eH9DuE2R3McW2A6Odsn/wKCwo7gmGyvDZB/5Ca9OOVsm2U9swO2xaQrlB4sE/139jkAji54A==", + "dev": true + }, + "@ember-data-types/serializer": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/serializer/-/serializer-5.3.9.tgz", + "integrity": "sha512-WqzguopBOzm657s1bAGFK3E2O5+nvx2jJRi1kpsYrELxfbXpWCUWit3E9d8FGUqlMYoyBtQWdAwPosjuJTb2/Q==", + "dev": true + }, + "@ember-data-types/store": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/store/-/store-5.3.9.tgz", + "integrity": "sha512-d6iEm6rktkVXmOzhi4QfKlt3dTCVOdSO569RAeDw8Ak3d8zCX3rLu/rcjOnISvGHQ0lVfDG3tHIpgfGpZmb5yg==", + "dev": true + }, + "@ember-data-types/tracking": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@ember-data-types/tracking/-/tracking-5.3.9.tgz", + "integrity": "sha512-4vrPQBo0Hf5TpOuGNMMHWJItqcfuj/oc1RqmEkL9C0Sv60UGnfNLQ994Dsye7CPtjIcIQOdU7/1vhSBqybMgKA==", + "dev": true + }, "@ember-data/adapter": { "version": "4.11.3", "resolved": "https://registry.npmjs.org/@ember-data/adapter/-/adapter-4.11.3.tgz", @@ -62997,230 +62894,6 @@ "@types/node": "*" } }, - "@types/ember": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/ember/-/ember-4.0.11.tgz", - "integrity": "sha512-v7VIex0YILK8fP87LkIfzeeYKNnu74+xwf6U56v6MUDDGfSs9q/6NCxiUfwkxD+z5nQiUcwvfKVokX8qzZFRLw==", - "dev": true, - "requires": { - "@types/ember__application": "*", - "@types/ember__array": "*", - "@types/ember__component": "*", - "@types/ember__controller": "*", - "@types/ember__debug": "*", - "@types/ember__engine": "*", - "@types/ember__error": "*", - "@types/ember__object": "*", - "@types/ember__polyfills": "*", - "@types/ember__routing": "*", - "@types/ember__runloop": "*", - "@types/ember__service": "*", - "@types/ember__string": "*", - "@types/ember__template": "*", - "@types/ember__test": "*", - "@types/ember__utils": "*", - "@types/rsvp": "*" - } - }, - "@types/ember__application": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/ember__application/-/ember__application-4.0.11.tgz", - "integrity": "sha512-U1S7XW0V70nTWbFckWoraJbYGBJK69muP/CsPFLeAuUYHfkkDiwh1SfqgAUN9aHtrEJM5SuSYVYp2YsTI2yLuA==", - "dev": true, - "requires": { - "@glimmer/component": "^1.1.0", - "@types/ember": "*", - "@types/ember__engine": "*", - "@types/ember__object": "*", - "@types/ember__owner": "*", - "@types/ember__routing": "*" - } - }, - "@types/ember__array": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@types/ember__array/-/ember__array-4.0.10.tgz", - "integrity": "sha512-UrhDbopLI3jB0MqV14y8yji2IuPNmeDrtT1PRYJL4CThLHrRkfeYyFvxqvrxWxn0wXKjbbjfH1gOe7BU57QrLQ==", - "dev": true, - "requires": { - "@types/ember": "*", - "@types/ember__object": "*" - } - }, - "@types/ember__component": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@types/ember__component/-/ember__component-4.0.22.tgz", - "integrity": "sha512-m72EtmBN/RxOChXqRsyOg4RR5+AiB4LQ8s1CEKNYAfvANt18m4hjqxtA7QZYLTq2ZjEVJGpdMsrdDuONWjwRSQ==", - "dev": true, - "requires": { - "@types/ember": "*", - "@types/ember__object": "*" - } - }, - "@types/ember__controller": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/@types/ember__controller/-/ember__controller-4.0.12.tgz", - "integrity": "sha512-80rdnSC0UJBqoUX5/vkQcM2xkRdTPTvY0dPXEfY5cC5OZITbcSeRo5qa7ZGhgNBfH6XYyh55Lo/b811LwU3N9w==", - "dev": true, - "requires": { - "@types/ember__object": "*" - } - }, - "@types/ember__debug": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/ember__debug/-/ember__debug-4.0.8.tgz", - "integrity": "sha512-9wF7STmDHDsUxSjyCq2lpMq/03QOPkBQMGJnV8yOBnVZxB6f+FJH/kxaCprdMkUe7iwAPNEC2zrFFx1tzH75Kg==", - "dev": true, - "requires": { - "@types/ember__object": "*", - "@types/ember__owner": "*" - } - }, - "@types/ember__engine": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@types/ember__engine/-/ember__engine-4.0.11.tgz", - "integrity": "sha512-ryR4Q1Xm3kQ3Ap58w10CxV3+vb3hs1cJqi7UZ5IlSdLRql7AbpS6hIjxSQ3EQ4zadeeJ6/D8JJcSwqR7eX3PFA==", - "dev": true, - "requires": { - "@types/ember__object": "*", - "@types/ember__owner": "*" - } - }, - "@types/ember__error": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember__error/-/ember__error-4.0.6.tgz", - "integrity": "sha512-vYrLaGGjHkN14K89Vm8yqB2mkpJQefE5w7QJkkgYyV+smzns1vKlPbvuFevRtoeYNn4u4yY0JyF7HceNkm3H0Q==", - "dev": true - }, - "@types/ember__object": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/@types/ember__object/-/ember__object-4.0.12.tgz", - "integrity": "sha512-ZEpikPjZ02m1QCBiTPTayMJwVwF4UBlHlGDoScRB3IP/SUS1O5mmn1/CnSQDxzzF3ctfmhNuTZzVBBc1Y8OC1A==", - "dev": true, - "requires": { - "@types/ember": "*", - "@types/rsvp": "*" - } - }, - "@types/ember__owner": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/ember__owner/-/ember__owner-4.0.9.tgz", - "integrity": "sha512-iyBda4aUIjBmeiKTKmPow/EJO7xWn8m85CnQTOCqQzTWJyJpgfObbXSHahOHXOfMm279Oa5NlbmS/EontB+XiQ==", - "dev": true - }, - "@types/ember__polyfills": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember__polyfills/-/ember__polyfills-4.0.6.tgz", - "integrity": "sha512-hbds3Qv+oVm/QKIaY1E6atvrCoJTH/MPSl4swOhX6P0RiMB2fOfFCrFSD1mP1KrU1LqpHJ2Rzs7XLe53SWVzgw==", - "dev": true - }, - "@types/ember__routing": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@types/ember__routing/-/ember__routing-4.0.22.tgz", - "integrity": "sha512-qLk9Vd2GMxdlGmX9xbzg4Farths+AQGzYDH901Wo2Nsre+Cwv1Tk1rbCiay2V3ICYZYufytdWT6V++DISF3nvw==", - "dev": true, - "requires": { - "@types/ember": "*", - "@types/ember__controller": "*", - "@types/ember__object": "*", - "@types/ember__service": "*" - } - }, - "@types/ember__runloop": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@types/ember__runloop/-/ember__runloop-4.0.10.tgz", - "integrity": "sha512-9MZfOJBXuUP7RqLjovmzy1yY2xKTxVpqHMapqy6QJ8mjAekRmq9IJ+ni2zJ5CWftyb3Lqu3Eks05CL7fnbhcJA==", - "dev": true, - "requires": { - "@types/ember": "*" - } - }, - "@types/ember__service": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/ember__service/-/ember__service-4.0.9.tgz", - "integrity": "sha512-DrepocL/4hH5YxbDWbxEKMDcAchBPSGGa4g+LEINW1Po81RmSdKw5GZV4UO0mvRWgkdu3EbWUxbTzB4gmbDSeQ==", - "dev": true, - "requires": { - "@types/ember__object": "*" - } - }, - "@types/ember__string": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/ember__string/-/ember__string-3.0.15.tgz", - "integrity": "sha512-SxoaweAJUJKSIt82clIwpi/Fm0IfeisozLnXthnBp/hE2JyVcnOb1wMIbw0CCfzercmyWG1njV45VBqy8SrLDQ==", - "dev": true - }, - "@types/ember__template": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/ember__template/-/ember__template-4.0.7.tgz", - "integrity": "sha512-jv4hhG+8d1zdma+jhbCdJ3Ak7C22YNatGyWWvB3N9zbXq358AAPXaJoyNY8QTDbD/RIR9P6yoRk4u9vLbF6zfA==", - "dev": true - }, - "@types/ember__test": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember__test/-/ember__test-4.0.6.tgz", - "integrity": "sha512-Nswm/epfTepXknT8scZvWyyop1aqJcZcyzY4THGHFcXvYQQfA9rgmgrx6vo9vCJmYHh3jm0TTAIAIfoCvGaX5g==", - "dev": true, - "requires": { - "@types/ember__application": "*" - } - }, - "@types/ember__utils": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/ember__utils/-/ember__utils-4.0.7.tgz", - "integrity": "sha512-qQPBeWRyIPigKnZ68POlkqI5e6XA78Q4G3xHo687wQTcEtfoL/iZyPC4hn70mdijcZq8Hjch2Y3E5yhsEMzK+g==", - "dev": true, - "requires": { - "@types/ember": "*" - } - }, - "@types/ember-data": { - "version": "4.4.16", - "resolved": "https://registry.npmjs.org/@types/ember-data/-/ember-data-4.4.16.tgz", - "integrity": "sha512-plFqPkgw7n4YlkzvApkQAIhvvYTERlx8PeI2J5gSFtMtsKuoaIo8fXm4w22ZdBQtTzeh/kwvpO2WY8R/d5Ttfg==", - "dev": true, - "requires": { - "@types/ember": "*", - "@types/ember__error": "*", - "@types/ember__object": "*", - "@types/rsvp": "*" - } - }, - "@types/ember-data__adapter": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember-data__adapter/-/ember-data__adapter-4.0.6.tgz", - "integrity": "sha512-vSrx1cqz8jO0cBYwu98SrwFk5s722C+BGpw++NregwQio3g9VbNoymx+HsYeXvsWvGUsoRewxu9K7TwAOJSsvw==", - "dev": true, - "requires": { - "@types/ember-data": "*" - } - }, - "@types/ember-data__model": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/ember-data__model/-/ember-data__model-4.0.5.tgz", - "integrity": "sha512-zyfHh3tQiMdpbPZ1/RFxi4m9TdwsZxDmVY0e7V1UYp7pWvm/DeqEXqoy3WS9xa/O01xoJFpQtJHyasdXvVTfbg==", - "dev": true, - "requires": { - "@types/ember-data": "*" - } - }, - "@types/ember-data__serializer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/ember-data__serializer/-/ember-data__serializer-4.0.6.tgz", - "integrity": "sha512-ebxxySSvTiay1/hgN4fElahSuL0MX+1sMMwx/RQyy7z98ifV8wafW62BwlYtbH44aeTIdcaSBE2pm3R1aP2yUA==", - "dev": true, - "requires": { - "@types/ember-data": "*" - } - }, - "@types/ember-data__store": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/ember-data__store/-/ember-data__store-4.0.7.tgz", - "integrity": "sha512-0S3Etr32i4aGvhXhZM6CXaosvX8E6c+RCx8pCxUXVdn+SmICm8jqFXsDC6Gnqq4bJeTkf9cglqz46prOVR1Tcg==", - "dev": true, - "requires": { - "@types/ember-data": "*" - } - }, "@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", @@ -63539,6 +63212,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "@warp-drive-types/core-types": { + "version": "0.0.0-alpha.107", + "resolved": "https://registry.npmjs.org/@warp-drive-types/core-types/-/core-types-0.0.0-alpha.107.tgz", + "integrity": "sha512-nUsJplM8y1eTDnrsQ1shq+eJOEZ5476tsRkTE5GeTNha6viyJuvGKoTDhsI8Id/M+CBp8jFz18egYLiC8jShsA==", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -72251,6 +71930,12 @@ } } }, + "ember-data-types": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/ember-data-types/-/ember-data-types-5.3.9.tgz", + "integrity": "sha512-Dp7HS756l92pv+5W5zoFM5huIPfZqGVfNofZvf1w0qlRTUFVT/q8KqxFFNAcWvZyZtEqm34WyAlARhfuBgGuXA==", + "dev": true + }, "ember-fetch": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/ember-fetch/-/ember-fetch-8.1.2.tgz", diff --git a/package.json b/package.json index c2fb9dcc..ea521c19 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,16 @@ "ember-cli-typescript": "^4.2.1" }, "devDependencies": { + "@ember-data-types/adapter": "^5.3.9", + "@ember-data-types/graph": "^5.3.9", + "@ember-data-types/json-api": "^5.3.9", + "@ember-data-types/legacy-compat": "^5.3.9", + "@ember-data-types/model": "^5.3.9", + "@ember-data-types/request": "^5.3.9", + "@ember-data-types/request-utils": "^5.3.9", + "@ember-data-types/serializer": "^5.3.9", + "@ember-data-types/store": "^5.3.9", + "@ember-data-types/tracking": "^5.3.9", "@ember/optional-features": "^2.1.0", "@ember/string": "^3.1.1", "@ember/test-helpers": "^3.2.0", @@ -48,35 +58,13 @@ "@glimmer/component": "^1.1.2", "@glimmer/tracking": "^1.1.2", "@tsconfig/ember": "^3.0.8", - "@types/ember": "^4.0.11", - "@types/ember__application": "^4.0.11", - "@types/ember__array": "^4.0.10", - "@types/ember__component": "^4.0.22", - "@types/ember__controller": "^4.0.12", - "@types/ember__debug": "^4.0.8", - "@types/ember__engine": "^4.0.11", - "@types/ember__error": "^4.0.6", - "@types/ember__object": "^4.0.12", - "@types/ember__owner": "^4.0.9", - "@types/ember__polyfills": "^4.0.6", - "@types/ember__routing": "^4.0.22", - "@types/ember__runloop": "^4.0.10", - "@types/ember__service": "^4.0.9", - "@types/ember__string": "^3.0.15", - "@types/ember__template": "^4.0.7", - "@types/ember__test": "^4.0.6", - "@types/ember__utils": "^4.0.7", - "@types/ember-data": "^4.4.16", - "@types/ember-data__adapter": "^4.0.6", - "@types/ember-data__model": "^4.0.5", - "@types/ember-data__serializer": "^4.0.6", - "@types/ember-data__store": "^4.0.7", "@types/node": "^20.14.2", "@types/qunit": "^2.19.10", "@types/rsvp": "^4.0.9", "@types/sinon": "^17.0.3", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", + "@warp-drive-types/core-types": "^0.0.0-alpha.107", "broccoli-asset-rev": "^3.0.0", "concurrently": "^8.2.2", "ember-cli": "~5.4.2", @@ -88,6 +76,7 @@ "ember-cli-terser": "^4.0.2", "ember-cli-typescript-blueprints": "^3.0.0", "ember-data": "~4.11.2", + "ember-data-types": "^5.3.9", "ember-fetch": "^8.1.2", "ember-load-initializers": "^2.1.2", "ember-page-title": "^8.0.0", diff --git a/tests/acceptance/features-test.ts b/tests/acceptance/features-test.ts index 1fe7a791..efe792e1 100644 --- a/tests/acceptance/features-test.ts +++ b/tests/acceptance/features-test.ts @@ -69,7 +69,7 @@ module('Acceptance | features', function (hooks) { await waitFor('[data-test-id]', { timeout: 5000 }); assert.dom('[data-test-id="user_a"]').hasText('user_a'); assert.dom('[data-test-name="user_a"]').hasText('user_a'); - assert.dom('[data-test-age="user_a"]').hasNoText(); + assert.dom('[data-test-age="user_a"]').hasText('15'); }); test('should be able to create record with belongs to build reference', async function (assert) { @@ -87,7 +87,7 @@ module('Acceptance | features', function (hooks) { await waitFor('[data-test-id]', { timeout: 5000 }); assert.dom('[data-test-id="user_a"]').hasText('user_a'); assert.dom('[data-test-name="user_a"]').hasText('user_a'); - assert.dom('[data-test-age="user_a"]').hasNoText(); + assert.dom('[data-test-age="user_a"]').hasText('15'); const createdRecord = await getDoc(doc(db, 'posts/new_post')); diff --git a/tests/dummy/app/adapters/application.ts b/tests/dummy/app/adapters/application.ts index fb6c060f..852d75f3 100644 --- a/tests/dummy/app/adapters/application.ts +++ b/tests/dummy/app/adapters/application.ts @@ -1,10 +1,3 @@ import CloudFirestoreAdapter from 'ember-cloud-firestore-adapter/adapters/cloud-firestore-modular'; export default class ApplicationAdapter extends CloudFirestoreAdapter {} - -// DO NOT DELETE: this is how TypeScript knows how to look up your adapters. -declare module 'ember-data/types/registries/adapter' { - export default interface AdapterRegistry { - application: ApplicationAdapter; - } -} diff --git a/tests/dummy/app/controllers/features.ts b/tests/dummy/app/controllers/features.ts index c9374338..ef0585b4 100644 --- a/tests/dummy/app/controllers/features.ts +++ b/tests/dummy/app/controllers/features.ts @@ -13,6 +13,7 @@ import { where, } from 'ember-cloud-firestore-adapter/firebase/firestore'; import type UserModel from '../models/user'; +import type PostModel from '../models/post'; export default class FeaturesController extends Controller { @service @@ -24,7 +25,7 @@ export default class FeaturesController extends Controller { @action public async handleCreateRecordWithIdClick(): Promise { const user = await this.store - .createRecord('user', { + .createRecord('user', { id: 'new', name: 'new_user_created_with_id', age: 25, @@ -37,7 +38,7 @@ export default class FeaturesController extends Controller { @action public async handleCreateRecordWithoutIdClick(): Promise { const user = await this.store - .createRecord('user', { + .createRecord('user', { name: 'new_user_created_without_id', age: 30, }) @@ -48,9 +49,9 @@ export default class FeaturesController extends Controller { @action public async handleCreateRecordWithoutBelongsToRelationship(): Promise { - const user = await this.store.findRecord('user', 'user_a'); + const user = await this.store.findRecord('user', 'user_a'); const post = await this.store - .createRecord('post', { + .createRecord('post', { // No belongs to relationship for Group model author: user, title: 'What does having it all mean to you? (By: Gabe Lewis)', @@ -58,14 +59,14 @@ export default class FeaturesController extends Controller { .save(); const author = await post.get('author'); - this.users = [author]; + this.users = [author!]; } @action public async handleCreateRecordWithBelongsToBuildReference(): Promise { - const user = await this.store.findRecord('user', 'user_a'); + const user = await this.store.findRecord('user', 'user_a'); const post = await this.store - .createRecord('post', { + .createRecord('post', { id: 'new_post', publisher: user, title: 'What does having it all mean to you? (By: Gabe Lewis)', @@ -73,12 +74,12 @@ export default class FeaturesController extends Controller { .save(); const publisher = await post.get('publisher'); - this.users = [publisher]; + this.users = [publisher!]; } @action public async handleUpdateRecordClick(): Promise { - const user = await this.store.findRecord('user', 'user_a'); + const user = await this.store.findRecord('user', 'user_a'); user.set('name', 'updated_user'); @@ -89,9 +90,8 @@ export default class FeaturesController extends Controller { @action public async handleDeleteRecordClick(): Promise { - const users = await this.store.findAll('user'); - // @ts-expect-error array proxy is indeed indexable - const user = users[0]; + const users = await this.store.findAll('user'); + const [user] = users; await user?.destroyRecord(); @@ -100,25 +100,27 @@ export default class FeaturesController extends Controller { @action public async handleFindAllClick(): Promise { - const users = await this.store.findAll('user'); + const users = await this.store.findAll('user'); this.users = users; } @action public async handleFindRecordClick(): Promise { - const user = await this.store.findRecord('user', 'user_a'); + const user = await this.store.findRecord('user', 'user_a'); this.users = [user]; } @action public async handleQuery1Click(): Promise { - const users = await this.store.query('user', { + const users = await this.store.query('user', { + // @ts-expect-error ember data types won't accept function buildReference(db: Firestore) { return collection(db, 'users'); }, + // @ts-expect-error ember data types won't accept function filter(reference: CollectionReference) { return query(reference, where('age', '>=', 15)); }, @@ -129,7 +131,8 @@ export default class FeaturesController extends Controller { @action public async handleQuery2Click(): Promise { - const users = await this.store.query('user', { + const users = await this.store.query('user', { + // @ts-expect-error ember data types won't accept function buildReference(db: Firestore) { return collection(db, 'users/user_a/foobar'); }, diff --git a/tests/dummy/app/models/group.ts b/tests/dummy/app/models/group.ts index 840751f9..57d9b193 100644 --- a/tests/dummy/app/models/group.ts +++ b/tests/dummy/app/models/group.ts @@ -3,8 +3,8 @@ import/no-cycle: off, */ -import type DS from 'ember-data'; -import Model, { attr, hasMany } from '@ember-data/model'; +import Model, { attr, hasMany, type AsyncHasMany } from '@ember-data/model'; +import type { Type } from '@warp-drive/core-types/symbols'; import type { Query } from 'firebase/firestore'; @@ -17,8 +17,9 @@ export default class GroupModel extends Model { public declare name: string; @hasMany('user', { async: true, inverse: 'groups' }) - public declare members: DS.PromiseManyArray; + public declare members: AsyncHasMany; + // @ts-expect-error ember data types won't accept function @hasMany('post', { async: true, inverse: 'group', @@ -28,12 +29,7 @@ export default class GroupModel extends Model { return query(reference, limit(1)); }, }) - public declare posts: DS.PromiseManyArray; -} + public declare posts: AsyncHasMany; -// DO NOT DELETE: this is how TypeScript knows how to look up your models. -declare module 'ember-data/types/registries/model' { - export default interface ModelRegistry { - group: GroupModel; - } + declare [Type]: 'group'; } diff --git a/tests/dummy/app/models/post.ts b/tests/dummy/app/models/post.ts index 6d64e1a6..a091717e 100644 --- a/tests/dummy/app/models/post.ts +++ b/tests/dummy/app/models/post.ts @@ -3,8 +3,8 @@ import/no-cycle: off, */ -import type DS from 'ember-data'; -import Model, { attr, belongsTo } from '@ember-data/model'; +import Model, { attr, belongsTo, type AsyncBelongsTo } from '@ember-data/model'; +import type { Type } from '@warp-drive/core-types/symbols'; import type { Firestore } from 'firebase/firestore'; @@ -21,11 +21,12 @@ export default class PostModel extends Model { public declare createdOn: TimestampTransform; @belongsTo('user', { async: true, inverse: 'posts' }) - public declare author: DS.PromiseObject; + public declare author: AsyncBelongsTo; @belongsTo('group', { async: true, inverse: 'posts' }) - public declare group: DS.PromiseObject; + public declare group: AsyncBelongsTo; + // @ts-expect-error ember data types won't accept function @belongsTo('user', { async: true, inverse: null, @@ -34,12 +35,7 @@ export default class PostModel extends Model { return collection(db, 'publishers'); }, }) - public declare publisher: DS.PromiseObject; -} + public declare publisher: AsyncBelongsTo; -// DO NOT DELETE: this is how TypeScript knows how to look up your models. -declare module 'ember-data/types/registries/model' { - export default interface ModelRegistry { - post: PostModel; - } + declare [Type]: 'post'; } diff --git a/tests/dummy/app/models/user.ts b/tests/dummy/app/models/user.ts index 31820816..0f56a741 100644 --- a/tests/dummy/app/models/user.ts +++ b/tests/dummy/app/models/user.ts @@ -3,8 +3,8 @@ import/no-cycle: off, */ -import type DS from 'ember-data'; -import Model, { attr, hasMany } from '@ember-data/model'; +import Model, { attr, hasMany, type AsyncHasMany } from '@ember-data/model'; +import type { Type } from '@warp-drive/core-types/symbols'; import type GroupModel from './group'; import type PostModel from './post'; @@ -13,16 +13,14 @@ export default class UserModel extends Model { @attr('string') public declare name: string; + @attr('number') + public declare age: number; + @hasMany('group', { async: true, inverse: 'members' }) - public declare groups: DS.PromiseManyArray; + public declare groups: AsyncHasMany; @hasMany('post', { async: true, inverse: 'author' }) - public declare posts: DS.PromiseManyArray; -} + public declare posts: AsyncHasMany; -// DO NOT DELETE: this is how TypeScript knows how to look up your models. -declare module 'ember-data/types/registries/model' { - export default interface ModelRegistry { - user: UserModel; - } + declare [Type]: 'user'; } diff --git a/tests/dummy/app/routes/create-record.ts b/tests/dummy/app/routes/create-record.ts index bb24a344..9856202b 100644 --- a/tests/dummy/app/routes/create-record.ts +++ b/tests/dummy/app/routes/create-record.ts @@ -3,17 +3,19 @@ import Route from '@ember/routing/route'; import type Store from '@ember-data/store'; import type PostModel from '../models/post'; +import type GroupModel from '../models/group'; +import type UserModel from '../models/user'; export default class CreateRecordRoute extends Route { @service public declare store: Store; public async model(): Promise { - const group = await this.store.findRecord('group', 'group_a'); - const author = await this.store.findRecord('user', 'user_a'); + const group = await this.store.findRecord('group', 'group_a'); + const author = await this.store.findRecord('user', 'user_a'); return this.store - .createRecord('post', { + .createRecord('post', { author, group, title: 'What does having it all mean to you? (By: Gabe Lewis)', diff --git a/tests/dummy/app/routes/delete-record.ts b/tests/dummy/app/routes/delete-record.ts index c18da2a3..f9aefd2e 100644 --- a/tests/dummy/app/routes/delete-record.ts +++ b/tests/dummy/app/routes/delete-record.ts @@ -2,12 +2,16 @@ import { service } from '@ember/service'; import Route from '@ember/routing/route'; import type Store from '@ember-data/store'; +import type UserModel from '../models/user'; + export default class DeleteRecordRoute extends Route { @service public declare store: Store; public async beforeModel(): Promise { - const record = this.store.createRecord('user', { name: 'To be deleted' }); + const record = this.store.createRecord('user', { + name: 'To be deleted', + }); await record.save(); await record.destroyRecord(); diff --git a/tests/dummy/app/routes/find-all.ts b/tests/dummy/app/routes/find-all.ts index ced6d17a..b806b61e 100644 --- a/tests/dummy/app/routes/find-all.ts +++ b/tests/dummy/app/routes/find-all.ts @@ -1,5 +1,4 @@ import { service } from '@ember/service'; -import type ArrayProxy from '@ember/array/proxy'; import Route from '@ember/routing/route'; import type Store from '@ember-data/store'; @@ -9,7 +8,7 @@ export default class FindAllRoute extends Route { @service public declare store: Store; - public async model(): Promise> { - return this.store.findAll('group'); + public async model(): Promise { + return this.store.findAll('group'); } } diff --git a/tests/dummy/app/routes/find-record.ts b/tests/dummy/app/routes/find-record.ts index b0cf3248..ae89fcde 100644 --- a/tests/dummy/app/routes/find-record.ts +++ b/tests/dummy/app/routes/find-record.ts @@ -9,7 +9,7 @@ export default class FindRecordRoute extends Route { public declare store: Store; public async model(): Promise { - return this.store.findRecord('group', 'group_a', { + return this.store.findRecord('group', 'group_a', { adapterOptions: { isRealtime: true, }, diff --git a/tests/dummy/app/routes/query.ts b/tests/dummy/app/routes/query.ts index b543bc56..00ebe044 100644 --- a/tests/dummy/app/routes/query.ts +++ b/tests/dummy/app/routes/query.ts @@ -1,5 +1,5 @@ import { service } from '@ember/service'; -import type ArrayProxy from '@ember/array/proxy'; +import type { Collection } from '@ember-data/store/-private/record-arrays/identifier-array'; import Route from '@ember/routing/route'; import type Store from '@ember-data/store'; @@ -17,9 +17,10 @@ export default class QueryRoute extends Route { @service public declare store: Store; - public async model(): Promise> { - return this.store.query('group', { + public async model(): Promise> { + return this.store.query('group', { isRealtime: true, + // @ts-expect-error ember data types won't accept function filter(reference: CollectionReference) { return query(reference, orderBy('name'), limit(1)); }, diff --git a/tests/dummy/app/routes/update-record.ts b/tests/dummy/app/routes/update-record.ts index 465fdf60..e9397cea 100644 --- a/tests/dummy/app/routes/update-record.ts +++ b/tests/dummy/app/routes/update-record.ts @@ -9,7 +9,7 @@ export default class UpdateRecordRoute extends Route { public declare store: Store; public async model(params: { title: string }): Promise { - const post = await this.store.findRecord('post', 'post_a'); + const post = await this.store.findRecord('post', 'post_a'); post.set('title', params.title); await post.save(); diff --git a/tests/dummy/app/serializers/application.ts b/tests/dummy/app/serializers/application.ts index 656530c0..90561356 100644 --- a/tests/dummy/app/serializers/application.ts +++ b/tests/dummy/app/serializers/application.ts @@ -1,10 +1,3 @@ import CloudFirestoreSerializer from 'ember-cloud-firestore-adapter/serializers/cloud-firestore-modular'; export default class ApplicationSerializer extends CloudFirestoreSerializer {} - -// DO NOT DELETE: this is how TypeScript knows how to look up your serializers. -declare module 'ember-data/types/registries/serializer' { - export default interface SerializerRegistry { - application: ApplicationSerializer; - } -} diff --git a/tests/unit/adapters/cloud-firestore-modular-test.ts b/tests/unit/adapters/cloud-firestore-modular-test.ts index aba3d4bf..9d01514e 100644 --- a/tests/unit/adapters/cloud-firestore-modular-test.ts +++ b/tests/unit/adapters/cloud-firestore-modular-test.ts @@ -9,7 +9,8 @@ import { setupTest } from 'ember-qunit'; import EmberObject from '@ember/object'; import Store from '@ember-data/store'; -import type { ModelSchema } from 'ember-data'; +import type { ModelSchema } from '@ember-data/store/types'; +import type { EmptyResourceDocument } from '@warp-drive/core-types/spec/json-api-raw'; import type { CollectionReference, Firestore, @@ -69,7 +70,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { const updateRecordStub = sinon .stub(adapter, 'updateRecord') - .returns('foo' as any); + .returns(Promise.resolve({ foo: 'foo' })); // Act const result = await adapter.createRecord( @@ -79,7 +80,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { ); // Assert - assert.strictEqual(result, 'foo'); + assert.deepEqual(result, { foo: 'foo' }); assert.ok( updateRecordStub.calledWithExactly(store, modelClass, snapshot as any), ); @@ -280,14 +281,14 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { // Arrange const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const modelClass = { modelName: 'user' } as ModelSchema; const adapter = this.owner.lookup( 'adapter:cloud-firestore-modular', ) as CloudFirestoreModularAdapter; // Act - const result = await adapter.findAll(store, modelClass, undefined as any); + const result = await adapter.findAll(store, modelClass, null, {} as any); // Assert assert.deepEqual(result, [ @@ -318,7 +319,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { // Arrange const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const modelClass = { modelName: 'user' } as ModelSchema; const modelId = 'user_a'; const snapshot = {}; @@ -347,7 +348,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { // Arrange const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const modelClass = { modelName: 'user' } as ModelSchema; const modelId = 'user_a'; const snapshot = { @@ -379,7 +380,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const modelClass = { modelName: 'user' } as ModelSchema; const modelId = 'user_100'; const snapshot = {}; @@ -406,7 +407,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { // Arrange const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const snapshot = {}; const url = 'users/user_a'; const relationship = { type: 'user', options: {} }; @@ -419,7 +420,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { store, snapshot as any, url, - relationship, + relationship as any, ); // Assert @@ -444,14 +445,14 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { return { determineRelationshipType: determineRelationshipTypeStub, inverseFor: inverseForStub, - }; + } as unknown as ModelSchema; } }, ); const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const snapshot = { id: 'user_a', modelName: 'user', @@ -476,7 +477,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { store, snapshot as any, url, - relationship, + relationship as any, )) as any; // Assert @@ -497,19 +498,19 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { modelFor() { return { determineRelationshipType: determineRelationshipTypeStub, - }; + } as unknown as ModelSchema; } }, ); const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const snapshot = { modelName: 'user', record: EmberObject.create({ referenceTo: doc(db, 'users/user_a'), - }), + } as any), }; const url = 'users/user_a/friends'; const relationship = { @@ -557,20 +558,20 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { return { determineRelationshipType: determineRelationshipTypeStub, inverseFor: inverseForStub, - }; + } as unknown as ModelSchema; } }, ); const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const snapshot = { id: 'user_a', modelName: 'user', record: EmberObject.create({ id: 'user_a', - }), + } as any), }; const url = 'posts'; const relationship = { @@ -591,7 +592,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { store, snapshot as any, url, - relationship, + relationship as any, )) as any; // Assert @@ -607,9 +608,9 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { // Arrange const store = this.owner.lookup('service:store'); store.normalize = sinon.stub(); - store.push = sinon.stub(); + (store.push as (data: EmptyResourceDocument) => null) = sinon.stub(); const snapshot = { - record: EmberObject.create({ id: 'user_a' }), + record: EmberObject.create({ id: 'user_a' } as any), }; const url = null; const relationship = { @@ -634,7 +635,7 @@ module('Unit | Adapter | cloud firestore modular', function (hooks) { store, snapshot as any, url as any, - relationship, + relationship as any, )) as any; // Assert diff --git a/tests/unit/services/-firestore-data-manager-test.ts b/tests/unit/services/-firestore-data-manager-test.ts index 8f3ea3b1..1b106a95 100644 --- a/tests/unit/services/-firestore-data-manager-test.ts +++ b/tests/unit/services/-firestore-data-manager-test.ts @@ -6,6 +6,7 @@ import RSVP from 'rsvp'; import type { Firestore } from 'firebase/firestore'; import sinon from 'sinon'; +import type { Collection } from '@ember-data/store/-private/record-arrays/identifier-array'; import { collection, @@ -171,7 +172,7 @@ module('Unit | Service | -firestore-data-manager', function (hooks) { recordArray: { update: () => DS.PromiseArray.create({ promise: RSVP.Promise.resolve([]) }), - } as unknown as DS.AdapterPopulatedRecordArray, + } as Collection, }; const firestoreDataManager = this.owner.lookup( 'service:-firestore-data-manager', @@ -201,7 +202,7 @@ module('Unit | Service | -firestore-data-manager', function (hooks) { recordArray: { update: () => DS.PromiseArray.create({ promise: RSVP.Promise.resolve([]) }), - } as unknown as DS.AdapterPopulatedRecordArray, + } as Collection, }; const firestoreDataManager = this.owner.lookup( 'service:-firestore-data-manager', @@ -229,7 +230,7 @@ module('Unit | Service | -firestore-data-manager', function (hooks) { recordArray: { update: () => DS.PromiseArray.create({ promise: RSVP.Promise.resolve([]) }), - } as unknown as DS.AdapterPopulatedRecordArray, + } as Collection, }; const updateSpy = sinon.spy(config.recordArray, 'update'); const firestoreDataManager = this.owner.lookup( @@ -307,6 +308,7 @@ module('Unit | Service | -firestore-data-manager', function (hooks) { sinon .stub(store, 'peekRecord') + // @ts-expect-error method overloads .withArgs('user', 'user_a') .returns({ hasMany: sinon diff --git a/tsconfig.json b/tsconfig.json index c4bed3a0..73ca275e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,21 @@ "ember-cloud-firestore-adapter/test-support": ["addon-test-support"], "ember-cloud-firestore-adapter/test-support/*": ["addon-test-support/*"], "*": ["types/*"] - } + }, + "types": [ + "./node_modules/@ember-data-types/adapter/unstable-preview-types", + "./node_modules/@ember-data-types/graph/unstable-preview-types", + "./node_modules/@ember-data-types/json-api/unstable-preview-types", + "./node_modules/@ember-data-types/legacy-compat/unstable-preview-types", + "./node_modules/@ember-data-types/model/unstable-preview-types", + "./node_modules/@ember-data-types/request-utils/unstable-preview-types", + "./node_modules/@ember-data-types/request/unstable-preview-types", + "./node_modules/@ember-data-types/serializer/unstable-preview-types", + "./node_modules/@ember-data-types/store/unstable-preview-types", + "./node_modules/@ember-data-types/tracking/unstable-preview-types", + "./node_modules/@warp-drive-types/core-types/unstable-preview-types", + "./node_modules/ember-data-types/unstable-preview-types", + "ember-source/types" + ] } } diff --git a/types/dummy/app.d.ts b/types/dummy/app.d.ts index 4d8bb7b1..7ac8d326 100644 --- a/types/dummy/app.d.ts +++ b/types/dummy/app.d.ts @@ -1,3 +1,6 @@ +import 'ember-source/types'; +import 'ember-source/types/preview'; + declare module 'dummy/app' { import Application from '@ember/application'; diff --git a/types/ember-data/types/registries/model.d.ts b/types/ember-data/types/registries/model.d.ts deleted file mode 100644 index c65ed10f..00000000 --- a/types/ember-data/types/registries/model.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint @typescript-eslint/no-explicit-any: off */ - -/** - * Catch-all for ember-data. - */ -export default interface ModelRegistry { - [key: string]: any; -} diff --git a/types/global.d.ts b/types/global.d.ts index 5b6cb811..7c9a3bf0 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -1,2 +1,10 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any declare const FastBoot: { require(moduleName: string): any } | undefined; + +declare module '@ember/service' { + import type { CompatStore } from '@ember-data/legacy-compat'; + + interface Registry { + store: CompatStore; + } +}