Skip to content

Commit 3094041

Browse files
committed
Copy-pasta from #9319
1 parent 690eb1c commit 3094041

File tree

21 files changed

+1242
-22
lines changed

21 files changed

+1242
-22
lines changed

packages/legacy-compat/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
},
5252
"peerDependencies": {
5353
"@ember-data/graph": "workspace:4.12.7",
54-
"@ember-data/json-api": "workspace:4.12.7"
54+
"@ember-data/json-api": "workspace:4.12.7",
55+
"@ember/string": "^3.1.1"
5556
},
5657
"peerDependenciesMeta": {
5758
"@ember-data/graph": {
@@ -74,6 +75,7 @@
7475
"@babel/preset-typescript": "^7.21.4",
7576
"@babel/preset-env": "^7.21.4",
7677
"@babel/runtime": "^7.21.0",
78+
"@ember/string": "^3.1.1",
7779
"@rollup/plugin-babel": "^6.0.3",
7880
"@rollup/plugin-node-resolve": "^15.0.1",
7981
"tslib": "^2.5.0",

packages/legacy-compat/rollup.config.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default {
1717
plugins: [
1818
// These are the modules that users should be able to import from your
1919
// addon. Anything not listed here may get optimized away.
20-
addon.publicEntrypoints(['index.js', '-private.js']),
20+
addon.publicEntrypoints(['index.js', 'builders.js', '-private.js']),
2121

2222
nodeResolve({ extensions: ['.ts'] }),
2323
babel({
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
Builders for migrating from `store` methods to `store.request`.
3+
These builders enable you to migrate your codebase to using the correct syntax for `store.request` while temporarily preserving legacy behaviors.
4+
This is useful for quickly upgrading an entire app to a unified syntax while a longer incremental migration is made to shift off of adapters and serializers.
5+
To that end, these builders are deprecated and will be removed in a future version of Ember Data.
6+
@module @ember-data/legacy-compat/builders
7+
@main @ember-data/legacy-compat/builders
8+
@deprecated
9+
*/
10+
11+
export { findAllBuilder as findAll } from './builders/find-all';
12+
13+
export { findRecordBuilder as findRecord } from './builders/find-record';
14+
15+
export { queryBuilder as query, queryRecordBuilder as queryRecord } from './builders/query';
16+
17+
export { saveRecordBuilder as saveRecord } from './builders/save-record';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* @module @ember-data/legacy-compat/builders
3+
*/
4+
import { assert } from '@ember/debug';
5+
6+
import type { StoreRequestInput } from '@ember-data/store';
7+
import type { FindAllOptions } from '@ember-data/store/-types/q/store';
8+
import type { TypedRecordInstance, TypeFromInstance } from '@warp-drive/core-types/record';
9+
import { SkipCache } from '@warp-drive/core-types/request';
10+
import type { RequestSignature } from '@warp-drive/core-types/symbols';
11+
12+
import { normalizeModelName } from './utils';
13+
14+
type FindAllRequestInput<T extends string = string, RT = unknown[]> = StoreRequestInput & {
15+
op: 'findAll';
16+
data: {
17+
type: T;
18+
options: FindAllBuilderOptions;
19+
};
20+
[RequestSignature]?: RT;
21+
};
22+
23+
type FindAllBuilderOptions = FindAllOptions;
24+
25+
/**
26+
This function builds a request config to perform a `findAll` request for the given type.
27+
When passed to `store.request`, this config will result in the same behavior as a `store.findAll` request.
28+
Additionally, it takes the same options as `store.findAll`.
29+
30+
All `@ember-data/legacy-compat` builders exist to enable you to migrate your codebase to using the correct syntax for `store.request` while temporarily preserving legacy behaviors.
31+
This is useful for quickly upgrading an entire app to a unified syntax while a longer incremental migration is made to shift off of adapters and serializers.
32+
To that end, these builders are deprecated and will be removed in a future version of Ember Data.
33+
34+
@method findAll
35+
@deprecated
36+
@public
37+
@static
38+
@for @ember-data/legacy-compat/builders
39+
@param {string} type the name of the resource
40+
@param {object} query a query to be used by the adapter
41+
@param {FindAllBuilderOptions} [options] optional, may include `adapterOptions` hash which will be passed to adapter.findAll
42+
@return {FindAllRequestInput} request config
43+
*/
44+
export function findAllBuilder<T extends TypedRecordInstance>(
45+
type: TypeFromInstance<T>,
46+
options?: FindAllBuilderOptions
47+
): FindAllRequestInput<TypeFromInstance<T>, T[]>;
48+
export function findAllBuilder(type: string, options?: FindAllBuilderOptions): FindAllRequestInput;
49+
export function findAllBuilder(type: string, options: FindAllBuilderOptions = {}): FindAllRequestInput {
50+
assert(`You need to pass a model name to the findAll builder`, type);
51+
assert(
52+
`Model name passed to the findAll builder must be a dasherized string instead of ${type}`,
53+
typeof type === 'string'
54+
);
55+
56+
return {
57+
op: 'findAll',
58+
data: {
59+
type: normalizeModelName(type),
60+
options: options || {},
61+
},
62+
cacheOptions: { [SkipCache as symbol]: true },
63+
};
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/**
2+
* @module @ember-data/legacy-compat/builders
3+
*/
4+
import { assert } from '@ember/debug';
5+
6+
import type { StoreRequestInput } from '@ember-data/store';
7+
import { constructResource, ensureStringId } from '@ember-data/store/-private';
8+
import type { BaseFinderOptions, FindRecordOptions } from '@ember-data/store/-types/q/store';
9+
import type { TypedRecordInstance, TypeFromInstance } from '@warp-drive/core-types/record';
10+
import { SkipCache } from '@warp-drive/core-types/request';
11+
import type { ResourceIdentifierObject } from '@warp-drive/core-types/spec/raw';
12+
import type { RequestSignature } from '@warp-drive/core-types/symbols';
13+
14+
import { isMaybeIdentifier, normalizeModelName } from './utils';
15+
16+
type FindRecordRequestInput<T extends string = string, RT = unknown> = StoreRequestInput & {
17+
op: 'findRecord';
18+
data: {
19+
record: ResourceIdentifierObject<T>;
20+
options: FindRecordBuilderOptions;
21+
};
22+
[RequestSignature]?: RT;
23+
};
24+
25+
type FindRecordBuilderOptions = Omit<FindRecordOptions, 'preload'>;
26+
27+
/**
28+
This function builds a request config to find the record for a given identifier or type and id combination.
29+
When passed to `store.request`, this config will result in the same behavior as a `store.findRecord` request.
30+
Additionally, it takes the same options as `store.findRecord`, with the exception of `preload` (which is unsupported).
31+
32+
**Example 1**
33+
34+
```ts
35+
import { findRecord } from '@ember-data/legacy-compat/builders';
36+
const { content: post } = await store.request<Post>(findRecord<Post>('post', '1'));
37+
```
38+
39+
**Example 2**
40+
41+
`findRecord` can be called with a single identifier argument instead of the combination
42+
of `type` (modelName) and `id` as separate arguments. You may recognize this combo as
43+
the typical pairing from [JSON:API](https://jsonapi.org/format/#document-resource-object-identification)
44+
45+
```ts
46+
import { findRecord } from '@ember-data/legacy-compat/builders';
47+
const { content: post } = await store.request<Post>(findRecord<Post>({ type: 'post', id }));
48+
```
49+
50+
All `@ember-data/legacy-compat` builders exist to enable you to migrate your codebase to using the correct syntax for `store.request` while temporarily preserving legacy behaviors.
51+
This is useful for quickly upgrading an entire app to a unified syntax while a longer incremental migration is made to shift off of adapters and serializers.
52+
To that end, these builders are deprecated and will be removed in a future version of Ember Data.
53+
54+
@method findRecord
55+
@deprecated
56+
@public
57+
@static
58+
@for @ember-data/legacy-compat/builders
59+
@param {string|object} type - either a string representing the name of the resource or a ResourceIdentifier object containing both the type (a string) and the id (a string) for the record or an lid (a string) of an existing record
60+
@param {string|number|object} id - optional object with options for the request only if the first param is a ResourceIdentifier, else the string id of the record to be retrieved
61+
@param {FindRecordBuilderOptions} [options] - if the first param is a string this will be the optional options for the request. See examples for available options.
62+
@return {FindRecordRequestInput} request config
63+
*/
64+
export function findRecordBuilder<T extends TypedRecordInstance>(
65+
resource: TypeFromInstance<T>,
66+
id: string,
67+
options?: FindRecordBuilderOptions
68+
): FindRecordRequestInput<TypeFromInstance<T>, T>;
69+
export function findRecordBuilder(
70+
resource: string,
71+
id: string,
72+
options?: FindRecordBuilderOptions
73+
): FindRecordRequestInput;
74+
export function findRecordBuilder<T extends TypedRecordInstance>(
75+
resource: ResourceIdentifierObject<TypeFromInstance<T>>,
76+
options?: FindRecordBuilderOptions
77+
): FindRecordRequestInput<TypeFromInstance<T>, T>;
78+
export function findRecordBuilder(
79+
resource: ResourceIdentifierObject,
80+
options?: FindRecordBuilderOptions
81+
): FindRecordRequestInput;
82+
export function findRecordBuilder(
83+
resource: string | ResourceIdentifierObject,
84+
idOrOptions?: string | FindRecordBuilderOptions,
85+
options?: FindRecordBuilderOptions
86+
): FindRecordRequestInput {
87+
assert(
88+
`You need to pass a modelName or resource identifier as the first argument to the findRecord builder`,
89+
resource
90+
);
91+
if (isMaybeIdentifier(resource)) {
92+
options = idOrOptions as BaseFinderOptions | undefined;
93+
} else {
94+
assert(
95+
`You need to pass a modelName or resource identifier as the first argument to the findRecord builder (passed ${resource})`,
96+
typeof resource === 'string'
97+
);
98+
const type = normalizeModelName(resource);
99+
const normalizedId = ensureStringId(idOrOptions as string | number);
100+
resource = constructResource(type, normalizedId);
101+
}
102+
103+
options = options || {};
104+
105+
assert('findRecord builder does not support options.preload', !(options as FindRecordOptions).preload);
106+
107+
return {
108+
op: 'findRecord' as const,
109+
data: {
110+
record: resource,
111+
options,
112+
},
113+
cacheOptions: { [SkipCache as symbol]: true },
114+
};
115+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/**
2+
* @module @ember-data/legacy-compat/builders
3+
*/
4+
import { assert } from '@ember/debug';
5+
6+
import type { StoreRequestInput } from '@ember-data/store';
7+
import type { QueryOptions } from '@ember-data/store/-types/q/store';
8+
import type { TypedRecordInstance, TypeFromInstance } from '@warp-drive/core-types/record';
9+
import { SkipCache } from '@warp-drive/core-types/request';
10+
import type { RequestSignature } from '@warp-drive/core-types/symbols';
11+
12+
import { normalizeModelName } from './utils';
13+
14+
type QueryRequestInput<T extends string = string, RT = unknown[]> = StoreRequestInput & {
15+
op: 'query';
16+
data: {
17+
type: T;
18+
query: Record<string, unknown>;
19+
options: QueryBuilderOptions;
20+
};
21+
[RequestSignature]?: RT;
22+
};
23+
24+
type QueryBuilderOptions = QueryOptions;
25+
26+
/**
27+
This function builds a request config for a given type and query object.
28+
When passed to `store.request`, this config will result in the same behavior as a `store.query` request.
29+
Additionally, it takes the same options as `store.query`.
30+
31+
All `@ember-data/legacy-compat` builders exist to enable you to migrate your codebase to using the correct syntax for `store.request` while temporarily preserving legacy behaviors.
32+
This is useful for quickly upgrading an entire app to a unified syntax while a longer incremental migration is made to shift off of adapters and serializers.
33+
To that end, these builders are deprecated and will be removed in a future version of Ember Data.
34+
35+
@method query
36+
@deprecated
37+
@public
38+
@static
39+
@for @ember-data/legacy-compat/builders
40+
@param {string} type the name of the resource
41+
@param {object} query a query to be used by the adapter
42+
@param {QueryBuilderOptions} [options] optional, may include `adapterOptions` hash which will be passed to adapter.query
43+
@return {QueryRequestInput} request config
44+
*/
45+
export function queryBuilder<T extends TypedRecordInstance>(
46+
type: TypeFromInstance<T>,
47+
query: Record<string, unknown>,
48+
options?: QueryBuilderOptions
49+
): QueryRequestInput<TypeFromInstance<T>, T[]>;
50+
export function queryBuilder(
51+
type: string,
52+
query: Record<string, unknown>,
53+
options?: QueryBuilderOptions
54+
): QueryRequestInput;
55+
export function queryBuilder(
56+
type: string,
57+
query: Record<string, unknown>,
58+
options: QueryBuilderOptions = {}
59+
): QueryRequestInput {
60+
assert(`You need to pass a model name to the query builder`, type);
61+
assert(`You need to pass a query hash to the query builder`, query);
62+
assert(
63+
`Model name passed to the query builder must be a dasherized string instead of ${type}`,
64+
typeof type === 'string'
65+
);
66+
67+
return {
68+
op: 'query' as const,
69+
data: {
70+
type: normalizeModelName(type),
71+
query,
72+
options: options,
73+
},
74+
cacheOptions: { [SkipCache as symbol]: true },
75+
};
76+
}
77+
78+
type QueryRecordRequestInput<T extends string = string, RT = unknown> = StoreRequestInput & {
79+
op: 'queryRecord';
80+
data: {
81+
type: T;
82+
query: Record<string, unknown>;
83+
options: QueryBuilderOptions;
84+
};
85+
[RequestSignature]?: RT;
86+
};
87+
88+
/**
89+
This function builds a request config for a given type and query object.
90+
When passed to `store.request`, this config will result in the same behavior as a `store.queryRecord` request.
91+
Additionally, it takes the same options as `store.queryRecord`.
92+
93+
All `@ember-data/legacy-compat` builders exist to enable you to migrate your codebase to using the correct syntax for `store.request` while temporarily preserving legacy behaviors.
94+
This is useful for quickly upgrading an entire app to a unified syntax while a longer incremental migration is made to shift off of adapters and serializers.
95+
To that end, these builders are deprecated and will be removed in a future version of Ember Data.
96+
97+
@method queryRecord
98+
@deprecated
99+
@public
100+
@static
101+
@for @ember-data/legacy-compat/builders
102+
@param {string} type the name of the resource
103+
@param {object} query a query to be used by the adapter
104+
@param {QueryBuilderOptions} [options] optional, may include `adapterOptions` hash which will be passed to adapter.query
105+
@return {QueryRecordRequestInput} request config
106+
*/
107+
export function queryRecordBuilder<T extends TypedRecordInstance>(
108+
type: TypeFromInstance<T>,
109+
query: Record<string, unknown>,
110+
options?: QueryBuilderOptions
111+
): QueryRecordRequestInput<TypeFromInstance<T>, T | null>;
112+
export function queryRecordBuilder(
113+
type: string,
114+
query: Record<string, unknown>,
115+
options?: QueryBuilderOptions
116+
): QueryRecordRequestInput;
117+
export function queryRecordBuilder(
118+
type: string,
119+
query: Record<string, unknown>,
120+
options?: QueryBuilderOptions
121+
): QueryRecordRequestInput {
122+
assert(`You need to pass a model name to the queryRecord builder`, type);
123+
assert(`You need to pass a query hash to the queryRecord builder`, query);
124+
assert(
125+
`Model name passed to the queryRecord builder must be a dasherized string instead of ${type}`,
126+
typeof type === 'string'
127+
);
128+
129+
return {
130+
op: 'queryRecord',
131+
data: {
132+
type: normalizeModelName(type),
133+
query,
134+
options: options || {},
135+
},
136+
cacheOptions: { [SkipCache as symbol]: true },
137+
};
138+
}

0 commit comments

Comments
 (0)