@warp-drive/legacy 5.10.0-alpha.10 → 5.10.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +84 -8
  2. package/blueprints/adapter/files/__root__/__path__/__name__.js +1 -1
  3. package/blueprints/adapter/index.js +8 -4
  4. package/blueprints/adapter-test/index.js +0 -2
  5. package/blueprints/adapter-test/qunit-files/__root__/__path__/__test__.js +1 -1
  6. package/blueprints/model/files/__root__/__path__/__name__.js +1 -1
  7. package/blueprints/model/index.js +9 -3
  8. package/blueprints/model-test/index.js +0 -2
  9. package/blueprints/model-test/qunit-files/__root__/__path__/__test__.js +1 -1
  10. package/blueprints/serializer/files/__root__/__path__/__name__.js +1 -1
  11. package/blueprints/serializer/index.js +8 -4
  12. package/blueprints/serializer-test/index.js +0 -2
  13. package/blueprints/serializer-test/qunit-files/__root__/__path__/__test__.js +1 -1
  14. package/blueprints/transform/files/__root__/__path__/__name__.js +1 -1
  15. package/blueprints/transform/index.js +6 -1
  16. package/blueprints/transform-test/index.js +0 -2
  17. package/blueprints/transform-test/qunit-files/__root__/__path__/__test__.js +1 -1
  18. package/dist/adapter/json-api.d.ts +1 -1
  19. package/dist/adapter/json-api.js +1 -1
  20. package/dist/adapter/json-api.js.map +1 -1
  21. package/dist/index.js +1 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/unpkg/dev/adapter/json-api.js +1 -1
  24. package/dist/unpkg/dev/adapter/json-api.js.map +1 -1
  25. package/dist/unpkg/dev/index.js +1 -0
  26. package/dist/unpkg/dev/index.js.map +1 -1
  27. package/dist/unpkg/dev-deprecated/adapter/json-api.js +1 -1
  28. package/dist/unpkg/dev-deprecated/adapter/json-api.js.map +1 -1
  29. package/dist/unpkg/dev-deprecated/index.js +1 -0
  30. package/dist/unpkg/dev-deprecated/index.js.map +1 -1
  31. package/dist/unpkg/prod/adapter/json-api.js +1 -1
  32. package/dist/unpkg/prod/adapter/json-api.js.map +1 -1
  33. package/dist/unpkg/prod/index.js +1 -0
  34. package/dist/unpkg/prod/index.js.map +1 -1
  35. package/dist/unpkg/prod-deprecated/adapter/json-api.js +1 -1
  36. package/dist/unpkg/prod-deprecated/adapter/json-api.js.map +1 -1
  37. package/dist/unpkg/prod-deprecated/index.js +1 -0
  38. package/dist/unpkg/prod-deprecated/index.js.map +1 -1
  39. package/package.json +11 -8
package/README.md CHANGED
@@ -8,13 +8,11 @@
8
8
  />
9
9
  </p>
10
10
 
11
- ![NPM Stable Version](https://img.shields.io/npm/v/ember-data/latest?label=version&style=flat&color=fdb155)
12
- ![NPM Downloads](https://img.shields.io/npm/dm/ember-data.svg?style=flat&color=fdb155)
11
+ ![NPM Stable Version](https://img.shields.io/npm/v/%40warp-drive%2Flegacy/latest?label=version&style=flat&color=fdb155)
12
+ ![NPM Downloads](https://img.shields.io/npm/dm/%40warp-drive%2Flegacy.svg?style=flat&color=fdb155)
13
13
  ![License](https://img.shields.io/github/license/warp-drive-data/warp-drive.svg?style=flat&color=fdb155)
14
- [![EmberJS Discord Community Server](https://img.shields.io/badge/EmberJS-grey?logo=discord&logoColor=fdb155)](https://discord.gg/zT3asNS
15
- )
16
- [![WarpDrive Discord Server](https://img.shields.io/badge/WarpDrive-grey?logo=discord&logoColor=fdb155)](https://discord.gg/PHBbnWJx5S
17
- )
14
+ [![EmberJS Discord Community Server](https://img.shields.io/badge/EmberJS-grey?logo=discord&logoColor=fdb155)](https://discord.gg/zT3asNS)
15
+ [![WarpDrive Discord Server](https://img.shields.io/badge/WarpDrive-grey?logo=discord&logoColor=fdb155)](https://discord.gg/PHBbnWJx5S)
18
16
 
19
17
  # @warp-drive/legacy
20
18
 
@@ -28,13 +26,31 @@ Decommissioned Features from <em>Warp</em><strong>Drive</strong> that your App m
28
26
 
29
27
  > [!WARNING]
30
28
  > This package provides support for older ***Warp*Drive** features that have been
31
- > deprecated and removed from [@warp-drive/core](https://canary.warp-drive.io/api/@warp-drive/core/).
29
+ > deprecated and removed from [@warp-drive/core](https://warp-drive.io/api/@warp-drive/core/).
32
30
  >
33
31
  > **Projects using these features should refactor away from them with urgency**
34
32
 
33
+ ## Usage
34
+
35
+ `useLegacyStore` produces a Store class with the legacy features switched on:
36
+
37
+ ```ts
38
+ import { useLegacyStore } from '@warp-drive/legacy';
39
+ import { JSONAPICache } from '@warp-drive/json-api';
40
+
41
+ export default useLegacyStore({
42
+ // false: relationships still resolve via adapters, not links
43
+ linksMode: false,
44
+ // true: keep the legacy request methods and adapter/serializer infrastructure
45
+ legacyRequests: true,
46
+ cache: JSONAPICache,
47
+ schemas: [],
48
+ });
49
+ ```
50
+
35
51
  ## Documentation
36
52
 
37
- *Get Started* → [Guides](https://docs.warp-drive.io)
53
+ *Get Started* → [Guides](https://warp-drive.io/guides/)
38
54
 
39
55
 
40
56
  <br>
@@ -48,3 +64,63 @@ Refer to the [Code of Conduct](https://github.com/warp-drive-data/warp-drive/blo
48
64
  ### License
49
65
 
50
66
  This project is licensed under the [MIT License](LICENSE.md).
67
+
68
+ ### ♥️ Credits
69
+
70
+ <details>
71
+ <summary>Brought to you with ♥️ love by <a href="https://emberjs.com" title="EmberJS">🐹 Ember</a></summary>
72
+
73
+ <style type="text/css">
74
+ img.project-logo {
75
+ padding: 0 5em 1em 5em;
76
+ width: 100px;
77
+ border-bottom: 2px solid #bbb;
78
+ margin: 0 auto;
79
+ display: block;
80
+ }
81
+ details > summary {
82
+ font-size: 1.1rem;
83
+ line-height: 1rem;
84
+ margin-bottom: 1rem;
85
+ }
86
+ details {
87
+ font-size: 1rem;
88
+ }
89
+ details > summary strong {
90
+ display: inline-block;
91
+ padding: .2rem 0;
92
+ color: #000;
93
+ border-bottom: 3px solid #bbb;
94
+ }
95
+
96
+ details > details {
97
+ margin-left: 2rem;
98
+ }
99
+ details > details > summary {
100
+ font-size: 1rem;
101
+ line-height: 1rem;
102
+ margin-bottom: 1rem;
103
+ }
104
+ details > details > summary strong {
105
+ display: inline-block;
106
+ padding: .2rem 0;
107
+ color: #555;
108
+ border-bottom: 2px solid #555;
109
+ }
110
+ details > details {
111
+ font-size: .85rem;
112
+ }
113
+
114
+ @media (prefers-color-scheme: dark) {
115
+ details > summary strong {
116
+ color: #fff;
117
+ }
118
+ }
119
+ @media (prefers-color-scheme: dark) {
120
+ details > details > summary strong {
121
+ color: #afaba0;
122
+ border-bottom: 2px solid #afaba0;
123
+ }
124
+ }
125
+ </style>
126
+ </details>
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1,10 +1,10 @@
1
+ const path = require('path');
2
+
1
3
  module.exports = {
2
4
  description: 'Generates an ember-data Adapter.',
3
5
 
4
6
  availableOptions: [{ name: 'base-class', type: String }],
5
7
 
6
- root: __dirname,
7
-
8
8
  async locals(options) {
9
9
  const { generateAdapterSource } = await import('warp-drive/generators/adapter');
10
10
 
@@ -15,9 +15,13 @@ module.exports = {
15
15
  cwd: options.project.root,
16
16
  isAddon,
17
17
  baseClass: options.baseClass,
18
- packageName: '@warp-drive/legacy/adapter',
19
- importStyle: 'named',
18
+ packageName: this.packageName ?? '@warp-drive/legacy/adapter',
19
+ importStyle: this.importStyle ?? 'named',
20
20
  }),
21
21
  };
22
22
  },
23
+
24
+ filesPath() {
25
+ return path.join(__dirname, 'files');
26
+ },
23
27
  };
@@ -6,8 +6,6 @@ module.exports = {
6
6
  return false;
7
7
  },
8
8
 
9
- root: __dirname,
10
-
11
9
  fileMapTokens() {
12
10
  return {
13
11
  __root__() {
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1,10 +1,10 @@
1
+ const path = require('path');
2
+
1
3
  module.exports = {
2
4
  description: 'Generates an ember-data Model.',
3
5
 
4
6
  anonymousOptions: ['name', 'attr:type'],
5
7
 
6
- root: __dirname,
7
-
8
8
  async locals(options) {
9
9
  const { generateModelSource } = await import('warp-drive/generators/model');
10
10
 
@@ -15,7 +15,13 @@ module.exports = {
15
15
  });
16
16
 
17
17
  return {
18
- content: generateModelSource(options.entity.name, rawAttrs, { packageName: '@warp-drive/legacy/model' }),
18
+ content: generateModelSource(options.entity.name, rawAttrs, {
19
+ packageName: this.packageName ?? '@warp-drive/legacy/model',
20
+ }),
19
21
  };
20
22
  },
23
+
24
+ filesPath() {
25
+ return path.join(__dirname, 'files');
26
+ },
21
27
  };
@@ -6,8 +6,6 @@ module.exports = {
6
6
  return false;
7
7
  },
8
8
 
9
- root: __dirname,
10
-
11
9
  fileMapTokens() {
12
10
  return {
13
11
  __root__() {
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1,10 +1,10 @@
1
+ const path = require('path');
2
+
1
3
  module.exports = {
2
4
  description: 'Generates an ember-data Serializer.',
3
5
 
4
6
  availableOptions: [{ name: 'base-class', type: String }],
5
7
 
6
- root: __dirname,
7
-
8
8
  async locals(options) {
9
9
  const { generateSerializerSource } = await import('warp-drive/generators/serializer');
10
10
 
@@ -15,9 +15,13 @@ module.exports = {
15
15
  cwd: options.project.root,
16
16
  isAddon,
17
17
  baseClass: options.baseClass,
18
- packageName: '@warp-drive/legacy/serializer',
19
- importStyle: 'named',
18
+ packageName: this.packageName ?? '@warp-drive/legacy/serializer',
19
+ importStyle: this.importStyle ?? 'named',
20
20
  }),
21
21
  };
22
22
  },
23
+
24
+ filesPath() {
25
+ return path.join(__dirname, 'files');
26
+ },
23
27
  };
@@ -6,8 +6,6 @@ module.exports = {
6
6
  return false;
7
7
  },
8
8
 
9
- root: __dirname,
10
-
11
9
  fileMapTokens() {
12
10
  return {
13
11
  __root__() {
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -1,6 +1,7 @@
1
+ const path = require('path');
2
+
1
3
  module.exports = {
2
4
  description: 'Generates an ember-data Transform.',
3
- root: __dirname,
4
5
 
5
6
  async locals(options) {
6
7
  const { generateTransformSource } = await import('warp-drive/generators/transform');
@@ -9,4 +10,8 @@ module.exports = {
9
10
  content: generateTransformSource(options.entity.name),
10
11
  };
11
12
  },
13
+
14
+ filesPath() {
15
+ return path.join(__dirname, 'files');
16
+ },
12
17
  };
@@ -6,8 +6,6 @@ module.exports = {
6
6
  return false;
7
7
  },
8
8
 
9
- root: __dirname,
10
-
11
9
  fileMapTokens() {
12
10
  return {
13
11
  __root__() {
@@ -1 +1 @@
1
- <%- content %>
1
+ <%= content %>
@@ -13,7 +13,7 @@ If starting a new app or thinking of implementing a new adapter, consider writin
13
13
  {@link Handler} instead to be used with the {@link RequestManager}
14
14
  :::
15
15
 
16
- The `JSONAPIAdapter` is an adapter whichtransforms the store's
16
+ The `JSONAPIAdapter` is an adapter which transforms the store's
17
17
  requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).
18
18
 
19
19
  ## JSON API Conventions
@@ -13,7 +13,7 @@ If starting a new app or thinking of implementing a new adapter, consider writin
13
13
  {@link Handler} instead to be used with the {@link RequestManager}
14
14
  :::
15
15
 
16
- The `JSONAPIAdapter` is an adapter whichtransforms the store's
16
+ The `JSONAPIAdapter` is an adapter which transforms the store's
17
17
  requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).
18
18
 
19
19
  ## JSON API Conventions
@@ -1 +1 @@
1
- {"version":3,"file":"json-api.js","names":["dasherize","pluralize","serializeIntoHash","RESTAdapter","macroCondition","getGlobalConfig","JSONAPIAdapter","_defaultContentType","ajaxOptions","url","type","options","hash","headers","coalesceFindRequests","_coalesceFindRequests","value","findMany","store","ids","snapshots","buildURL","modelName","ajax","data","filter","id","join","pathForType","dasherized","updateRecord","schema","snapshot","WarpDrive","env","DEBUG","test","Error","length","buildQuery","query","include","normalizedInclude","Array","isArray"],"sources":["../../src/adapter/json-api.ts"],"sourcesContent":["// oxlint-disable-next-line no-unused-vars\nimport type { RequestManager, Store } from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\n// oxlint-disable-next-line no-unused-vars\nimport type { Handler } from '@warp-drive/core/request';\nimport type { ModelSchema } from '@warp-drive/core/types';\nimport type { HTTPMethod } from '@warp-drive/core/types/request';\nimport { dasherize, pluralize } from '@warp-drive/utilities/string';\n\nimport type { AdapterPayload } from '../compat.ts';\nimport type { Snapshot, SnapshotRecordArray } from '../compat/-private.ts';\nimport { serializeIntoHash } from './-private.ts';\nimport type { FetchRequestInit, JQueryRequestInit, QueryState } from './rest.ts';\nimport { RESTAdapter } from './rest.ts';\n/**\n ## Overview\n\n :::danger\n ⚠️ **This is LEGACY documentation** for a feature that is no longer encouraged to be used.\n If starting a new app or thinking of implementing a new adapter, consider writing a\n {@link Handler} instead to be used with the {@link RequestManager}\n :::\n\n The `JSONAPIAdapter` is an adapter whichtransforms the store's\n requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).\n\n ## JSON API Conventions\n\n The JSONAPIAdapter uses JSON API conventions for building the URL\n for a record and selecting the HTTP verb to use with a request. The\n actions you can take on a record map onto the following URLs in the\n JSON API adapter:\n\n<table>\n <tr>\n <th>\n Action\n </th>\n <th>\n HTTP Verb\n </th>\n <th>\n URL\n </th>\n </tr>\n <tr>\n <th>\n `store.findRecord('post', 123)`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n `store.findAll('post')`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Update `postRecord.save()`\n </th>\n <td>\n PATCH\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n Create `store.createRecord('post').save()`\n </th>\n <td>\n POST\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Delete `postRecord.destroyRecord()`\n </th>\n <td>\n DELETE\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n</table>\n\n ## Success and failure\n\n The JSONAPIAdapter will consider a success any response with a\n status code of the 2xx family (\"Success\"), as well as 304 (\"Not\n Modified\"). Any other status code will be considered a failure.\n\n On success, the request promise will be resolved with the full\n response payload.\n\n Failed responses with status code 422 (\"Unprocessable Entity\") will\n be considered \"invalid\". The response will be discarded, except for\n the `errors` key. The request promise will be rejected with a\n `InvalidError`. This error object will encapsulate the saved\n `errors` value.\n\n Any other status codes will be treated as an adapter error. The\n request promise will be rejected, similarly to the invalid case,\n but with an instance of `AdapterError` instead.\n\n ### Endpoint path customization\n\n Endpoint paths can be prefixed with a `namespace` by setting the\n namespace property on the adapter:\n\n ```js [app/adapters/application.js]\n import { JSONAPIAdapter } from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n namespace = 'api/1';\n }\n ```\n Requests for the `person` model would now target `/api/1/people/1`.\n\n ### Host customization\n\n An adapter can target other hosts by setting the `host` property.\n\n ```js [app/adapters/application.js]\n import JSONAPIAdapter from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n host = 'https://api.example.com';\n }\n ```\n\n Requests for the `person` model would now target\n `https://api.example.com/people/1`.\n\n @since 1.13.0\n @class JSONAPIAdapter\n @public\n @constructor\n*/\nclass JSONAPIAdapter extends RESTAdapter {\n /**\n * The `Content-Type` header used when serializing request bodies\n * that don't otherwise specify one.\n */\n _defaultContentType = 'application/vnd.api+json';\n\n /**\n @private\n @param {String} url\n @param {String} type The request type GET, POST, PUT, DELETE etc.\n @param {Object} options\n @return {Object}\n */\n ajaxOptions(\n url: string,\n type: HTTPMethod,\n options: JQueryAjaxSettings | RequestInit = {}\n ): JQueryRequestInit | FetchRequestInit {\n const hash = super.ajaxOptions(url, type, options) as FetchRequestInit;\n const headers: HeadersInit = (hash.headers = hash.headers || {});\n headers['Accept'] = (headers['Accept'] as string) || 'application/vnd.api+json';\n\n return hash;\n }\n\n /**\n By default the JSONAPIAdapter will send each find request coming from a `store.find`\n or from accessing a relationship separately to the server. If your server supports passing\n ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests\n within a single runloop.\n\n For example, if you have an initial payload of:\n\n ```javascript\n {\n data: {\n id: 1,\n type: 'post',\n relationship: {\n comments: {\n data: [\n { id: 1, type: 'comment' },\n { id: 2, type: 'comment' }\n ]\n }\n }\n }\n }\n ```\n\n By default calling `post.comments` will trigger the following requests(assuming the\n comments haven't been loaded before):\n\n ```\n GET /comments/1\n GET /comments/2\n ```\n\n If you set coalesceFindRequests to `true` it will instead trigger the following request:\n\n ```\n GET /comments?filter[id]=1,2\n ```\n\n Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`\n relationships accessed within the same runloop. If you set `coalesceFindRequests: true`\n\n ```javascript\n store.findRecord('comment', 1);\n store.findRecord('comment', 2);\n ```\n\n will also send a request to: `GET /comments?filter[id]=1,2`\n\n Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app\n `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.\n\n @property coalesceFindRequests\n @public\n @type {Boolean}\n */\n get coalesceFindRequests() {\n const coalesceFindRequests = this._coalesceFindRequests;\n if (typeof coalesceFindRequests === 'boolean') {\n return coalesceFindRequests;\n }\n return (this._coalesceFindRequests = false);\n }\n\n set coalesceFindRequests(value: boolean) {\n this._coalesceFindRequests = value;\n }\n\n findMany(store: Store, type: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<AdapterPayload> {\n const url = this.buildURL(type.modelName, ids, snapshots, 'findMany');\n return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } });\n }\n\n /**\n * Determines the pathname for a given type.\n *\n * Unlike the base `BuildURLMixin` implementation, dasherizes (rather\n * than camelizes) the type name before pluralizing it, per the\n * {json:api} convention for member names.\n */\n pathForType(modelName: string): string {\n const dasherized = dasherize(modelName);\n return pluralize(dasherized);\n }\n\n updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload> {\n const data = serializeIntoHash(store, schema, snapshot);\n const type = snapshot.modelName;\n const id = snapshot.id;\n assert(`Attempted to update the ${type} record, but the record has no id`, typeof id === 'string' && id.length > 0);\n\n const url = this.buildURL(type, id, snapshot, 'updateRecord');\n\n return this.ajax(url, 'PATCH', { data: data });\n }\n\n /**\n Used by `findAll` and `findRecord` to build the query's `data` hash\n supplied to the ajax method.\n\n @since 2.5.0\n @public\n @param {Snapshot} snapshot\n @return {Object}\n */\n buildQuery(snapshot: Snapshot | SnapshotRecordArray): QueryState {\n const query: QueryState = {};\n\n if (snapshot) {\n const { include } = snapshot;\n const normalizedInclude = Array.isArray(include) ? include.join(',') : include;\n\n if (normalizedInclude) {\n query.include = normalizedInclude;\n }\n }\n\n return query;\n }\n}\n\nexport { JSONAPIAdapter };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JA,IAAMM,iBAAN,cAA6BH,YAAY;;;;;CAKvCI,sBAAsB;;;;;;;;CAStBC,YACEC,KACAC,MACAC,UAA4C,CAAC,GACP;EACtC,MAAMC,OAAO,MAAMJ,YAAYC,KAAKC,MAAMC,OAAO;EACjD,MAAME,UAAwBD,KAAKC,UAAUD,KAAKC,WAAW,CAAC;EAC9DA,QAAQ,YAAaA,QAAQ,aAAwB;EAErD,OAAOD;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DA,IAAIE,uBAAuB;EACzB,MAAMA,uBAAuB,KAAKC;EAClC,IAAI,OAAOD,yBAAyB,WAClC,OAAOA;EAET,OAAQ,KAAKC,wBAAwB;CACvC;CAEA,IAAID,qBAAqBE,OAAgB;EACvC,KAAKD,wBAAwBC;CAC/B;CAEAC,SAASC,OAAcR,MAAmBS,KAAeC,WAAgD;EACvG,MAAMX,MAAM,KAAKY,SAASX,KAAKY,WAAWH,KAAKC,WAAW,UAAU;EACpE,OAAO,KAAKG,KAAKd,KAAK,OAAO,EAAEe,MAAM,EAAEC,QAAQ,EAAEC,IAAIP,IAAIQ,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC;CAC1E;;;;;;;;CASAC,YAAYN,WAA2B;EACrC,MAAMO,aAAa7B,UAAUsB,SAAS;EACtC,OAAOrB,UAAU4B,UAAU;CAC7B;CAEAC,aAAaZ,OAAca,QAAqBC,UAA6C;EAC3F,MAAMR,OAAOtB,kBAAkBgB,OAAOa,QAAQC,QAAQ;EACtD,MAAMtB,OAAOsB,SAASV;EACtB,MAAMI,KAAKM,SAASN;EACpBtB,eAAAC,gBAAA,CAAA,CAAA4B,UAAAC,IAAAC,KAAA,OAAAC,SAAA;GAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MAAO,2BAA2B3B,KAAI,kCAAmC;EAAA,EAAA,CAAE,OAAOgB,OAAO,YAAYA,GAAGY,SAAS,CAAC;EAElH,MAAM7B,MAAM,KAAKY,SAASX,MAAMgB,IAAIM,UAAU,cAAc;EAE5D,OAAO,KAAKT,KAAKd,KAAK,SAAS,EAAQe,KAAK,CAAC;CAC/C;;;;;;;;;CAWAe,WAAWP,UAAsD;EAC/D,MAAMQ,QAAoB,CAAC;EAE3B,IAAIR,UAAU;GACZ,MAAM,EAAES,YAAYT;GACpB,MAAMU,oBAAoBC,MAAMC,QAAQH,OAAO,IAAIA,QAAQd,KAAK,GAAG,IAAIc;GAEvE,IAAIC,mBACFF,MAAMC,UAAUC;EAEpB;EAEA,OAAOF;CACT;AACF"}
1
+ {"version":3,"file":"json-api.js","names":["dasherize","pluralize","serializeIntoHash","RESTAdapter","macroCondition","getGlobalConfig","JSONAPIAdapter","_defaultContentType","ajaxOptions","url","type","options","hash","headers","coalesceFindRequests","_coalesceFindRequests","value","findMany","store","ids","snapshots","buildURL","modelName","ajax","data","filter","id","join","pathForType","dasherized","updateRecord","schema","snapshot","WarpDrive","env","DEBUG","test","Error","length","buildQuery","query","include","normalizedInclude","Array","isArray"],"sources":["../../src/adapter/json-api.ts"],"sourcesContent":["// oxlint-disable-next-line no-unused-vars\nimport type { RequestManager, Store } from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\n// oxlint-disable-next-line no-unused-vars\nimport type { Handler } from '@warp-drive/core/request';\nimport type { ModelSchema } from '@warp-drive/core/types';\nimport type { HTTPMethod } from '@warp-drive/core/types/request';\nimport { dasherize, pluralize } from '@warp-drive/utilities/string';\n\nimport type { AdapterPayload } from '../compat.ts';\nimport type { Snapshot, SnapshotRecordArray } from '../compat/-private.ts';\nimport { serializeIntoHash } from './-private.ts';\nimport type { FetchRequestInit, JQueryRequestInit, QueryState } from './rest.ts';\nimport { RESTAdapter } from './rest.ts';\n/**\n ## Overview\n\n :::danger\n ⚠️ **This is LEGACY documentation** for a feature that is no longer encouraged to be used.\n If starting a new app or thinking of implementing a new adapter, consider writing a\n {@link Handler} instead to be used with the {@link RequestManager}\n :::\n\n The `JSONAPIAdapter` is an adapter which transforms the store's\n requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).\n\n ## JSON API Conventions\n\n The JSONAPIAdapter uses JSON API conventions for building the URL\n for a record and selecting the HTTP verb to use with a request. The\n actions you can take on a record map onto the following URLs in the\n JSON API adapter:\n\n<table>\n <tr>\n <th>\n Action\n </th>\n <th>\n HTTP Verb\n </th>\n <th>\n URL\n </th>\n </tr>\n <tr>\n <th>\n `store.findRecord('post', 123)`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n `store.findAll('post')`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Update `postRecord.save()`\n </th>\n <td>\n PATCH\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n Create `store.createRecord('post').save()`\n </th>\n <td>\n POST\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Delete `postRecord.destroyRecord()`\n </th>\n <td>\n DELETE\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n</table>\n\n ## Success and failure\n\n The JSONAPIAdapter will consider a success any response with a\n status code of the 2xx family (\"Success\"), as well as 304 (\"Not\n Modified\"). Any other status code will be considered a failure.\n\n On success, the request promise will be resolved with the full\n response payload.\n\n Failed responses with status code 422 (\"Unprocessable Entity\") will\n be considered \"invalid\". The response will be discarded, except for\n the `errors` key. The request promise will be rejected with a\n `InvalidError`. This error object will encapsulate the saved\n `errors` value.\n\n Any other status codes will be treated as an adapter error. The\n request promise will be rejected, similarly to the invalid case,\n but with an instance of `AdapterError` instead.\n\n ### Endpoint path customization\n\n Endpoint paths can be prefixed with a `namespace` by setting the\n namespace property on the adapter:\n\n ```js [app/adapters/application.js]\n import { JSONAPIAdapter } from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n namespace = 'api/1';\n }\n ```\n Requests for the `person` model would now target `/api/1/people/1`.\n\n ### Host customization\n\n An adapter can target other hosts by setting the `host` property.\n\n ```js [app/adapters/application.js]\n import JSONAPIAdapter from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n host = 'https://api.example.com';\n }\n ```\n\n Requests for the `person` model would now target\n `https://api.example.com/people/1`.\n\n @since 1.13.0\n @class JSONAPIAdapter\n @public\n @constructor\n*/\nclass JSONAPIAdapter extends RESTAdapter {\n /**\n * The `Content-Type` header used when serializing request bodies\n * that don't otherwise specify one.\n */\n _defaultContentType = 'application/vnd.api+json';\n\n /**\n @private\n @param {String} url\n @param {String} type The request type GET, POST, PUT, DELETE etc.\n @param {Object} options\n @return {Object}\n */\n ajaxOptions(\n url: string,\n type: HTTPMethod,\n options: JQueryAjaxSettings | RequestInit = {}\n ): JQueryRequestInit | FetchRequestInit {\n const hash = super.ajaxOptions(url, type, options) as FetchRequestInit;\n const headers: HeadersInit = (hash.headers = hash.headers || {});\n headers['Accept'] = (headers['Accept'] as string) || 'application/vnd.api+json';\n\n return hash;\n }\n\n /**\n By default the JSONAPIAdapter will send each find request coming from a `store.find`\n or from accessing a relationship separately to the server. If your server supports passing\n ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests\n within a single runloop.\n\n For example, if you have an initial payload of:\n\n ```javascript\n {\n data: {\n id: 1,\n type: 'post',\n relationship: {\n comments: {\n data: [\n { id: 1, type: 'comment' },\n { id: 2, type: 'comment' }\n ]\n }\n }\n }\n }\n ```\n\n By default calling `post.comments` will trigger the following requests(assuming the\n comments haven't been loaded before):\n\n ```\n GET /comments/1\n GET /comments/2\n ```\n\n If you set coalesceFindRequests to `true` it will instead trigger the following request:\n\n ```\n GET /comments?filter[id]=1,2\n ```\n\n Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`\n relationships accessed within the same runloop. If you set `coalesceFindRequests: true`\n\n ```javascript\n store.findRecord('comment', 1);\n store.findRecord('comment', 2);\n ```\n\n will also send a request to: `GET /comments?filter[id]=1,2`\n\n Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app\n `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.\n\n @property coalesceFindRequests\n @public\n @type {Boolean}\n */\n get coalesceFindRequests() {\n const coalesceFindRequests = this._coalesceFindRequests;\n if (typeof coalesceFindRequests === 'boolean') {\n return coalesceFindRequests;\n }\n return (this._coalesceFindRequests = false);\n }\n\n set coalesceFindRequests(value: boolean) {\n this._coalesceFindRequests = value;\n }\n\n findMany(store: Store, type: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<AdapterPayload> {\n const url = this.buildURL(type.modelName, ids, snapshots, 'findMany');\n return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } });\n }\n\n /**\n * Determines the pathname for a given type.\n *\n * Unlike the base `BuildURLMixin` implementation, dasherizes (rather\n * than camelizes) the type name before pluralizing it, per the\n * {json:api} convention for member names.\n */\n pathForType(modelName: string): string {\n const dasherized = dasherize(modelName);\n return pluralize(dasherized);\n }\n\n updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload> {\n const data = serializeIntoHash(store, schema, snapshot);\n const type = snapshot.modelName;\n const id = snapshot.id;\n assert(`Attempted to update the ${type} record, but the record has no id`, typeof id === 'string' && id.length > 0);\n\n const url = this.buildURL(type, id, snapshot, 'updateRecord');\n\n return this.ajax(url, 'PATCH', { data: data });\n }\n\n /**\n Used by `findAll` and `findRecord` to build the query's `data` hash\n supplied to the ajax method.\n\n @since 2.5.0\n @public\n @param {Snapshot} snapshot\n @return {Object}\n */\n buildQuery(snapshot: Snapshot | SnapshotRecordArray): QueryState {\n const query: QueryState = {};\n\n if (snapshot) {\n const { include } = snapshot;\n const normalizedInclude = Array.isArray(include) ? include.join(',') : include;\n\n if (normalizedInclude) {\n query.include = normalizedInclude;\n }\n }\n\n return query;\n }\n}\n\nexport { JSONAPIAdapter };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JA,IAAMM,iBAAN,cAA6BH,YAAY;;;;;CAKvCI,sBAAsB;;;;;;;;CAStBC,YACEC,KACAC,MACAC,UAA4C,CAAC,GACP;EACtC,MAAMC,OAAO,MAAMJ,YAAYC,KAAKC,MAAMC,OAAO;EACjD,MAAME,UAAwBD,KAAKC,UAAUD,KAAKC,WAAW,CAAC;EAC9DA,QAAQ,YAAaA,QAAQ,aAAwB;EAErD,OAAOD;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DA,IAAIE,uBAAuB;EACzB,MAAMA,uBAAuB,KAAKC;EAClC,IAAI,OAAOD,yBAAyB,WAClC,OAAOA;EAET,OAAQ,KAAKC,wBAAwB;CACvC;CAEA,IAAID,qBAAqBE,OAAgB;EACvC,KAAKD,wBAAwBC;CAC/B;CAEAC,SAASC,OAAcR,MAAmBS,KAAeC,WAAgD;EACvG,MAAMX,MAAM,KAAKY,SAASX,KAAKY,WAAWH,KAAKC,WAAW,UAAU;EACpE,OAAO,KAAKG,KAAKd,KAAK,OAAO,EAAEe,MAAM,EAAEC,QAAQ,EAAEC,IAAIP,IAAIQ,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC;CAC1E;;;;;;;;CASAC,YAAYN,WAA2B;EACrC,MAAMO,aAAa7B,UAAUsB,SAAS;EACtC,OAAOrB,UAAU4B,UAAU;CAC7B;CAEAC,aAAaZ,OAAca,QAAqBC,UAA6C;EAC3F,MAAMR,OAAOtB,kBAAkBgB,OAAOa,QAAQC,QAAQ;EACtD,MAAMtB,OAAOsB,SAASV;EACtB,MAAMI,KAAKM,SAASN;EACpBtB,eAAAC,gBAAA,CAAA,CAAA4B,UAAAC,IAAAC,KAAA,OAAAC,SAAA;GAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MAAO,2BAA2B3B,KAAI,kCAAmC;EAAA,EAAA,CAAE,OAAOgB,OAAO,YAAYA,GAAGY,SAAS,CAAC;EAElH,MAAM7B,MAAM,KAAKY,SAASX,MAAMgB,IAAIM,UAAU,cAAc;EAE5D,OAAO,KAAKT,KAAKd,KAAK,SAAS,EAAQe,KAAK,CAAC;CAC/C;;;;;;;;;CAWAe,WAAWP,UAAsD;EAC/D,MAAMQ,QAAoB,CAAC;EAE3B,IAAIR,UAAU;GACZ,MAAM,EAAES,YAAYT;GACpB,MAAMU,oBAAoBC,MAAMC,QAAQH,OAAO,IAAIA,QAAQd,KAAK,GAAG,IAAIc;GAEvE,IAAIC,mBACFF,MAAMC,UAAUC;EAEpB;EAEA,OAAOF;CACT;AACF"}
package/dist/index.js CHANGED
@@ -232,6 +232,7 @@ function useLegacyStore(options, StoreKlass = Store) {
232
232
  return modelFor.call(this, type) || (options.modelFragments ? fragmentsModelFor.call(this, type) : false) || super.modelFor(type);
233
233
  }
234
234
  adapterFor(modelName, _allowMissing) {
235
+ if (options.linksMode && _allowMissing) return;
235
236
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
236
237
  if (!test) throw new Error(`useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`);
237
238
  })(!options.linksMode);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["CacheHandler","Fetch","recordIdentifierFor","RequestManager","Store","instantiateRecord","registerDerivations","SchemaService","teardownRecord","DefaultCachePolicy","adapterFor","cleanup","LegacyNetworkHandler","normalize","pushPayload","serializeRecord","serializerFor","EmberArrayLikeExtension","EmberObjectArrayExtension","EmberObjectExtension","instantiateModel","modelFor","teardownModel","FragmentArrayExtension","FragmentExtension","fragmentsModelFor","releaseLegacySupport","DelegatingSchemaService","registerLegacyDerivations","restoreDeprecatedStoreBehaviors","macroCondition","getGlobalConfig","useLegacyStore","options","StoreKlass","WarpDrive","env","DEBUG","test","Error","linksMode","legacyRequests","BaseKlass","LegacyConfiguredStore","constructor","createArgs","requestManager","Object","defineProperty","configurable","enumerable","get","handlersOption","handlers","use","filter","Boolean","useCache","set","value","lifetimes","policy","apiCacheHardExpires","apiCacheSoftExpires","constraints","headers","Expires","createSchemaService","schema","schemas","registerResources","traits","trait","registerTrait","derivations","derivation","registerDerivation","transformations","transformation","registerTransformation","hashFns","hashFn","registerHashFn","CAUTION_MEGA_DANGER_ZONE_extensions","extension","CAUTION_MEGA_DANGER_ZONE_registerExtension","modelFragments","createCache","capabilities","cache","key","isDelegated","call","record","type","assertType","klass","modelName","_allowMissing","args","destroy","hasResource"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @module\n * @mergeModuleWith <project>\n */\n\nimport {\n CacheHandler,\n Fetch,\n recordIdentifierFor,\n RequestManager,\n Store,\n type StoreSetupOptions,\n} from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\nimport { instantiateRecord, registerDerivations, SchemaService, teardownRecord } from '@warp-drive/core/reactive';\nimport type { Handler } from '@warp-drive/core/request';\nimport { DefaultCachePolicy } from '@warp-drive/core/store';\nimport type { CacheCapabilitiesManager, ModelSchema, ResourceKey } from '@warp-drive/core/types';\nimport type { Cache } from '@warp-drive/core/types/cache';\nimport type { TypeFromInstance } from '@warp-drive/core/types/record';\n// oxlint-disable-next-line no-unused-vars\nimport type { RequestInfo } from '@warp-drive/core/types/request';\nimport type { ObjectSchema, ResourceSchema } from '@warp-drive/core/types/schema/fields';\n\nimport type { MinimumAdapterInterface } from './compat';\nimport {\n adapterFor,\n cleanup,\n LegacyNetworkHandler,\n normalize,\n pushPayload,\n serializeRecord,\n serializerFor,\n} from './compat';\nimport { EmberArrayLikeExtension, EmberObjectArrayExtension, EmberObjectExtension } from './compat/extensions';\nimport type Model from './model';\nimport { instantiateRecord as instantiateModel, modelFor, teardownRecord as teardownModel } from './model';\nimport { FragmentArrayExtension, FragmentExtension } from './model-fragments';\nimport { fragmentsModelFor } from './model-fragments/hooks/model-for';\nimport { releaseLegacySupport } from './model/-private/legacy-relationships-support';\nimport { DelegatingSchemaService, registerDerivations as registerLegacyDerivations } from './model/migration-support';\nimport { restoreDeprecatedStoreBehaviors } from './store';\n\ninterface _LegacyStoreSetupOptions<T extends Cache> extends Omit<StoreSetupOptions<T>, 'schemas'> {\n /**\n * The {@link ResourceSchema | ResourceSchemas} or {@link ObjectSchema | ObjectSchemas} of entities\n * migrated to no longer use {@link Model}.\n *\n * :::caution\n * {@link Model} is still able to be used directly as a source of schema when using {@link useLegacyStore},\n * however, its reliance on EmberObject, classic computeds and resolver behaviors mean that Model\n * will stop working when these things are deprecated in Ember.\n * :::\n */\n schemas?: Array<ResourceSchema | ObjectSchema>;\n\n /**\n * Whether to include support for ModelFragments migrations.\n *\n * @default false\n */\n modelFragments?: boolean;\n}\n\n/**\n * Setup options for a legacy store configured to use `Model` with `linksMode`\n * enabled, meaning no legacy adapter/serializer request infrastructure is required.\n *\n * @public\n */\nexport interface LegacyModelStoreSetupOptions<T extends Cache> extends _LegacyStoreSetupOptions<T> {\n /**\n * If true, it is presumed that no requests require use of the LegacyNetworkHandler\n * and associated adapters/serializer methods.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n linksMode: true;\n /**\n * if true, all legacy request methods and supporting infrastructure will\n * be available on the store.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n legacyRequests?: false;\n}\n\n/**\n * Setup options for a legacy store configured to use `Model` along with the\n * legacy adapter/serializer network layer, but without the deprecated\n * `store.findRecord`/`findAll`/`query`/etc. request methods.\n *\n * @public\n */\nexport interface LegacyModelAndNetworkStoreSetupOptions<T extends Cache> extends _LegacyStoreSetupOptions<T> {\n /**\n * If true, it is presumed that no requests require use of the LegacyNetworkHandler\n * and associated adapters/serializer methods.\n *\n * @default false\n */\n linksMode: false;\n /**\n * if true, all legacy request methods and supporting infrastructure will\n * be available on the store.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n legacyRequests?: false;\n}\n\n/**\n * Setup options for a legacy store configured to use `Model` along with the\n * legacy adapter/serializer network layer and the deprecated\n * `store.findRecord`/`findAll`/`query`/etc. request methods.\n *\n * @public\n */\nexport interface LegacyModelAndNetworkAndRequestStoreSetupOptions<T extends Cache> extends _LegacyStoreSetupOptions<T> {\n /**\n * If true, it is presumed that no requests require use of the LegacyNetworkHandler\n * and associated adapters/serializer methods.\n *\n * @default false\n */\n linksMode: false;\n /**\n * if true, all legacy request methods and supporting infrastructure will\n * be available on the store.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n legacyRequests: true;\n}\n\n//export type ConfiguredStore<T = unknown> = typeof Store;\n\n/**\n * The available options when setting up the legacy store,\n * one of:\n *\n * - {@link LegacyModelStoreSetupOptions}\n * - {@link LegacyModelAndNetworkStoreSetupOptions}\n * - {@link LegacyModelAndNetworkAndRequestStoreSetupOptions}\n */\nexport type LegacyStoreSetupOptions<T extends Cache = Cache> =\n | LegacyModelStoreSetupOptions<T>\n | LegacyModelAndNetworkStoreSetupOptions<T>\n | LegacyModelAndNetworkAndRequestStoreSetupOptions<T>;\n\nexport declare class ConfiguredStore<\n T extends {\n /**\n * The {@link Cache} implementation this store was configured with.\n */\n cache: Cache;\n },\n> extends Store {\n // get cache(): T extends OptionsWithCache<infer R> ? R : never;\n createCache(capabilities: CacheCapabilitiesManager): T['cache'];\n}\n\n/**\n * Use the legacy store with the given options.\n *\n * See {@link LegacyStoreSetupOptions} for details on the available options.\n *\n * ```ts\n * import { useLegacyStore } from '@warp-drive/legacy';\n * import { JSONAPICache } from '@warp-drive/json-api';\n *\n * export default useLegacyStore({\n * linksMode: false,\n * legacyRequests: true,\n * cache: JSONAPICache,\n * schemas: [],\n * });\n * ```\n *\n * ### Adding Stateful Handlers\n *\n * A request {@link Handler} is sometimes more than a plain object or class\n * with a `request` method — it may need access to a stateful dependency such\n * as an Ember service (an auth token, a feature-flags service, an i18n\n * helper, etc.).\n *\n * A plain class handler that only relies on Ember's `@service` decorator will\n * not work here on its own: the handler is never instantiated *through*\n * Ember's container (it's just `new`'d up), so it has no owner and its\n * `@service` injections would fail to resolve.\n *\n * Instead, give `handlers` a function. It receives the {@link Store} instance\n * being configured, which by the time the function runs already has an owner\n * assigned. Use `getOwner`/`setOwner` from `@ember/owner` to transfer that\n * owner onto your handler instance before returning it, exactly as you would\n * when constructing any other DI-aware object outside of the container:\n *\n * ```ts\n * import { getOwner, setOwner } from '@ember/owner';\n * import { service } from '@ember/service';\n * import { useLegacyStore } from '@warp-drive/legacy';\n * import type { NextFn } from '@warp-drive/core/request';\n * import type { RequestContext } from '@warp-drive/core/types/request';\n * import { JSONAPICache } from '@warp-drive/json-api';\n *\n * class AuthHandler {\n * @service session;\n *\n * request<T>(context: RequestContext, next: NextFn<T>) {\n * const headers = new Headers(context.request.headers);\n * headers.append('Authorization', `Bearer ${this.session.accessToken}`);\n * return next(Object.assign({}, context.request, { headers }));\n * }\n * }\n *\n * export default useLegacyStore({\n * linksMode: false,\n * legacyRequests: true,\n * cache: JSONAPICache,\n * handlers: (store) => {\n * const authHandler = new AuthHandler();\n * setOwner(authHandler, getOwner(store)!);\n * return [authHandler];\n * },\n * });\n * ```\n *\n * The `handlers` function is invoked lazily and only once per store instance,\n * the first time `store.requestManager` is accessed, so it is safe to do\n * owner-dependent setup like this inside of it.\n *\n * ### Accessing the Store from a Handler's Context\n *\n * If a handler only needs to read something *off of the store itself*\n * (its cache, or a property/service you've attached to a custom store\n * subclass) rather than an unrelated Ember service, there is a second,\n * simpler option that requires no DI/`setOwner` wiring at all.\n *\n * Every request issued via {@link Store.request | store.request(...)}\n * automatically carries the originating store along as\n * {@link RequestInfo.store | context.request.store}. Any handler — a plain\n * object, a function-built handler, or a class — can read it directly,\n * without needing the `handlers` callback form shown above:\n *\n * ```ts\n * import { useLegacyStore } from '@warp-drive/legacy';\n * import type { NextFn } from '@warp-drive/core/request';\n * import type { RequestContext } from '@warp-drive/core/types/request';\n * import { JSONAPICache } from '@warp-drive/json-api';\n *\n * const LoggingHandler = {\n * request<T>(context: RequestContext, next: NextFn<T>) {\n * // only present when the request was made via `store.request(...)`\n * const store = context.request.store;\n * if (store) {\n * console.log(`[${store.constructor.name}] ${context.request.url ?? ''}`);\n * }\n * return next(context.request);\n * },\n * };\n *\n * export default useLegacyStore({\n * linksMode: false,\n * legacyRequests: true,\n * cache: JSONAPICache,\n * handlers: [LoggingHandler],\n * });\n * ```\n *\n * The trade-off versus the `getOwner`/`setOwner` pattern above is that\n * `context.request.store` is only populated for requests issued via\n * `store.request(...)`; a request made directly against a\n * {@link RequestManager} won't have it set unless the caller supplies it\n * explicitly, so a handler relying on it should treat it as optional (as\n * `LoggingHandler` does above).\n */\nexport function useLegacyStore<T extends Cache>(\n options: LegacyModelStoreSetupOptions<T>,\n StoreKlass?: typeof Store\n): typeof ConfiguredStore<{ cache: T }>;\nexport function useLegacyStore<T extends Cache>(\n options: LegacyModelAndNetworkStoreSetupOptions<T>,\n StoreKlass?: typeof Store\n): typeof ConfiguredStore<{ cache: T }>;\nexport function useLegacyStore<T extends Cache>(\n options: LegacyModelAndNetworkAndRequestStoreSetupOptions<T>,\n StoreKlass?: typeof Store\n): typeof ConfiguredStore<{ cache: T }>;\nexport function useLegacyStore<T extends Cache>(\n options: LegacyStoreSetupOptions<T>,\n StoreKlass: typeof Store = Store\n): typeof ConfiguredStore<{ cache: T }> {\n assert(`If legacyRequests is true, linksMode must be false`, !(options.linksMode && options.legacyRequests));\n // we extend the store to ensure we don't leak our prototype overrides to other stores below.\n class BaseKlass extends StoreKlass {}\n class LegacyConfiguredStore extends BaseKlass {\n constructor(createArgs?: unknown) {\n super(createArgs);\n // installed via defineProperty (rather than a class field/accessor) so that\n // this lazy override of the inherited `requestManager` field does not\n // conflict with the documented pattern of assigning it directly on\n // consumer-authored Store subclasses. The setter preserves the ability\n // to replace `requestManager` outright after construction.\n let requestManager: RequestManager | undefined;\n Object.defineProperty(this, 'requestManager', {\n configurable: true,\n enumerable: true,\n get: (): RequestManager => {\n if (!requestManager) {\n const handlersOption = options.handlers;\n const handlers = typeof handlersOption === 'function' ? handlersOption(this) : (handlersOption ?? []);\n requestManager = new RequestManager()\n .use([options.linksMode ? null : LegacyNetworkHandler, ...handlers, Fetch].filter(Boolean) as Handler[])\n .useCache(CacheHandler);\n }\n return requestManager;\n },\n set: (value: RequestManager): void => {\n requestManager = value;\n },\n });\n }\n\n lifetimes =\n options.policy ??\n new DefaultCachePolicy({\n apiCacheHardExpires: 15 * 60 * 1000, // 15 minutes\n apiCacheSoftExpires: 1 * 30 * 1000, // 30 seconds\n constraints: {\n headers: {\n 'X-WarpDrive-Expires': true,\n 'Cache-Control': true,\n Expires: true,\n },\n },\n });\n\n createSchemaService(): DelegatingSchemaService {\n // prepare for PolarisMode\n const schema = new SchemaService();\n registerDerivations(schema);\n if (options.schemas) schema.registerResources(options.schemas);\n\n if (options.traits) {\n for (const trait of options.traits) {\n schema.registerTrait(trait);\n }\n }\n\n if (options.derivations) {\n for (const derivation of options.derivations) {\n schema.registerDerivation(derivation);\n }\n }\n\n if (options.transformations) {\n for (const transformation of options.transformations) {\n schema.registerTransformation(transformation);\n }\n }\n\n if (options.hashFns) {\n for (const hashFn of options.hashFns) {\n schema.registerHashFn(hashFn);\n }\n }\n\n if (options.CAUTION_MEGA_DANGER_ZONE_extensions) {\n for (const extension of options.CAUTION_MEGA_DANGER_ZONE_extensions) {\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(extension);\n }\n }\n\n // Add support for LegacyMode ReactiveResource with Maximal coverage\n // for upgrading from 4.x\n registerLegacyDerivations(schema);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(EmberArrayLikeExtension);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(EmberObjectArrayExtension);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(EmberObjectExtension);\n\n // add support for fragments\n if (options.modelFragments) {\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension?.(FragmentExtension);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension?.(FragmentArrayExtension);\n }\n\n // Add fallback for Models\n return new DelegatingSchemaService(this, schema);\n }\n\n createCache(capabilities: CacheCapabilitiesManager) {\n // oxlint-disable-next-line new-cap\n return new options.cache(capabilities);\n }\n\n instantiateRecord(key: ResourceKey, createArgs?: Record<string, unknown>) {\n if (this.schema.isDelegated(key)) {\n return instantiateModel.call(this, key, createArgs);\n }\n return instantiateRecord(this, key, createArgs);\n }\n\n teardownRecord(record: unknown): void {\n const key = recordIdentifierFor(record);\n if (this.schema.isDelegated(key)) {\n return teardownModel.call(this, record as Model);\n }\n releaseLegacySupport(key);\n return teardownRecord(record);\n }\n\n modelFor<InstanceType>(type: TypeFromInstance<InstanceType>): ModelSchema<InstanceType>;\n modelFor(type: string): ModelSchema;\n modelFor(type: string): ModelSchema {\n assertType(this.schema, type);\n\n const klass =\n // prefer real models if present\n (modelFor.call(this, type) as ModelSchema) ||\n // fallback to ShimModelClass specific to fragments if fragments support in use\n (options.modelFragments ? (fragmentsModelFor.call(this, type) as ModelSchema) : false) ||\n // fallback to ShimModelClass\n super.modelFor(type);\n\n return klass;\n }\n\n adapterFor(this: Store, modelName: string): MinimumAdapterInterface;\n adapterFor(this: Store, modelName: string, _allowMissing: true): MinimumAdapterInterface | undefined;\n adapterFor(this: Store, modelName: string, _allowMissing?: true): MinimumAdapterInterface | undefined {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n // @ts-expect-error\n return adapterFor.call(this, modelName, _allowMissing);\n }\n\n serializerFor(this: Store, ...args: Parameters<typeof serializerFor>): ReturnType<typeof serializerFor> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return serializerFor.call(this, ...args);\n }\n\n pushPayload(this: Store, ...args: Parameters<typeof pushPayload>): ReturnType<typeof pushPayload> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return pushPayload.call(this, ...args);\n }\n\n normalize(this: Store, ...args: Parameters<typeof normalize>): ReturnType<typeof normalize> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return normalize.call(this, ...args);\n }\n\n serializeRecord(this: Store, ...args: Parameters<typeof serializeRecord>): ReturnType<typeof serializeRecord> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return serializeRecord.call(this, ...args);\n }\n\n destroy() {\n if (!options.linksMode) {\n cleanup.call(this);\n }\n super.destroy();\n }\n }\n\n if (options.legacyRequests) {\n restoreDeprecatedStoreBehaviors(BaseKlass);\n }\n\n return LegacyConfiguredStore;\n}\n\nfunction assertType(schema: DelegatingSchemaService, type: string) {\n assert(`Expected type ${type} to be a valid ResourceType`, schema.hasResource({ type }));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["CacheHandler","Fetch","recordIdentifierFor","RequestManager","Store","instantiateRecord","registerDerivations","SchemaService","teardownRecord","DefaultCachePolicy","adapterFor","cleanup","LegacyNetworkHandler","normalize","pushPayload","serializeRecord","serializerFor","EmberArrayLikeExtension","EmberObjectArrayExtension","EmberObjectExtension","instantiateModel","modelFor","teardownModel","FragmentArrayExtension","FragmentExtension","fragmentsModelFor","releaseLegacySupport","DelegatingSchemaService","registerLegacyDerivations","restoreDeprecatedStoreBehaviors","macroCondition","getGlobalConfig","useLegacyStore","options","StoreKlass","WarpDrive","env","DEBUG","test","Error","linksMode","legacyRequests","BaseKlass","LegacyConfiguredStore","constructor","createArgs","requestManager","Object","defineProperty","configurable","enumerable","get","handlersOption","handlers","use","filter","Boolean","useCache","set","value","lifetimes","policy","apiCacheHardExpires","apiCacheSoftExpires","constraints","headers","Expires","createSchemaService","schema","schemas","registerResources","traits","trait","registerTrait","derivations","derivation","registerDerivation","transformations","transformation","registerTransformation","hashFns","hashFn","registerHashFn","CAUTION_MEGA_DANGER_ZONE_extensions","extension","CAUTION_MEGA_DANGER_ZONE_registerExtension","modelFragments","createCache","capabilities","cache","key","isDelegated","call","record","type","assertType","klass","modelName","_allowMissing","undefined","args","destroy","hasResource"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @module\n * @mergeModuleWith <project>\n */\n\nimport {\n CacheHandler,\n Fetch,\n recordIdentifierFor,\n RequestManager,\n Store,\n type StoreSetupOptions,\n} from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\nimport { instantiateRecord, registerDerivations, SchemaService, teardownRecord } from '@warp-drive/core/reactive';\nimport type { Handler } from '@warp-drive/core/request';\nimport { DefaultCachePolicy } from '@warp-drive/core/store';\nimport type { CacheCapabilitiesManager, ModelSchema, ResourceKey } from '@warp-drive/core/types';\nimport type { Cache } from '@warp-drive/core/types/cache';\nimport type { TypeFromInstance } from '@warp-drive/core/types/record';\n// oxlint-disable-next-line no-unused-vars\nimport type { RequestInfo } from '@warp-drive/core/types/request';\nimport type { ObjectSchema, ResourceSchema } from '@warp-drive/core/types/schema/fields';\n\nimport type { MinimumAdapterInterface } from './compat';\nimport {\n adapterFor,\n cleanup,\n LegacyNetworkHandler,\n normalize,\n pushPayload,\n serializeRecord,\n serializerFor,\n} from './compat';\nimport { EmberArrayLikeExtension, EmberObjectArrayExtension, EmberObjectExtension } from './compat/extensions';\nimport type Model from './model';\nimport { instantiateRecord as instantiateModel, modelFor, teardownRecord as teardownModel } from './model';\nimport { FragmentArrayExtension, FragmentExtension } from './model-fragments';\nimport { fragmentsModelFor } from './model-fragments/hooks/model-for';\nimport { releaseLegacySupport } from './model/-private/legacy-relationships-support';\nimport { DelegatingSchemaService, registerDerivations as registerLegacyDerivations } from './model/migration-support';\nimport { restoreDeprecatedStoreBehaviors } from './store';\n\ninterface _LegacyStoreSetupOptions<T extends Cache> extends Omit<StoreSetupOptions<T>, 'schemas'> {\n /**\n * The {@link ResourceSchema | ResourceSchemas} or {@link ObjectSchema | ObjectSchemas} of entities\n * migrated to no longer use {@link Model}.\n *\n * :::caution\n * {@link Model} is still able to be used directly as a source of schema when using {@link useLegacyStore},\n * however, its reliance on EmberObject, classic computeds and resolver behaviors mean that Model\n * will stop working when these things are deprecated in Ember.\n * :::\n */\n schemas?: Array<ResourceSchema | ObjectSchema>;\n\n /**\n * Whether to include support for ModelFragments migrations.\n *\n * @default false\n */\n modelFragments?: boolean;\n}\n\n/**\n * Setup options for a legacy store configured to use `Model` with `linksMode`\n * enabled, meaning no legacy adapter/serializer request infrastructure is required.\n *\n * @public\n */\nexport interface LegacyModelStoreSetupOptions<T extends Cache> extends _LegacyStoreSetupOptions<T> {\n /**\n * If true, it is presumed that no requests require use of the LegacyNetworkHandler\n * and associated adapters/serializer methods.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n linksMode: true;\n /**\n * if true, all legacy request methods and supporting infrastructure will\n * be available on the store.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n legacyRequests?: false;\n}\n\n/**\n * Setup options for a legacy store configured to use `Model` along with the\n * legacy adapter/serializer network layer, but without the deprecated\n * `store.findRecord`/`findAll`/`query`/etc. request methods.\n *\n * @public\n */\nexport interface LegacyModelAndNetworkStoreSetupOptions<T extends Cache> extends _LegacyStoreSetupOptions<T> {\n /**\n * If true, it is presumed that no requests require use of the LegacyNetworkHandler\n * and associated adapters/serializer methods.\n *\n * @default false\n */\n linksMode: false;\n /**\n * if true, all legacy request methods and supporting infrastructure will\n * be available on the store.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n legacyRequests?: false;\n}\n\n/**\n * Setup options for a legacy store configured to use `Model` along with the\n * legacy adapter/serializer network layer and the deprecated\n * `store.findRecord`/`findAll`/`query`/etc. request methods.\n *\n * @public\n */\nexport interface LegacyModelAndNetworkAndRequestStoreSetupOptions<T extends Cache> extends _LegacyStoreSetupOptions<T> {\n /**\n * If true, it is presumed that no requests require use of the LegacyNetworkHandler\n * and associated adapters/serializer methods.\n *\n * @default false\n */\n linksMode: false;\n /**\n * if true, all legacy request methods and supporting infrastructure will\n * be available on the store.\n *\n * If legacyRequests is true, {@link linksMode} must be false\n *\n * @default false\n */\n legacyRequests: true;\n}\n\n//export type ConfiguredStore<T = unknown> = typeof Store;\n\n/**\n * The available options when setting up the legacy store,\n * one of:\n *\n * - {@link LegacyModelStoreSetupOptions}\n * - {@link LegacyModelAndNetworkStoreSetupOptions}\n * - {@link LegacyModelAndNetworkAndRequestStoreSetupOptions}\n */\nexport type LegacyStoreSetupOptions<T extends Cache = Cache> =\n | LegacyModelStoreSetupOptions<T>\n | LegacyModelAndNetworkStoreSetupOptions<T>\n | LegacyModelAndNetworkAndRequestStoreSetupOptions<T>;\n\nexport declare class ConfiguredStore<\n T extends {\n /**\n * The {@link Cache} implementation this store was configured with.\n */\n cache: Cache;\n },\n> extends Store {\n // get cache(): T extends OptionsWithCache<infer R> ? R : never;\n createCache(capabilities: CacheCapabilitiesManager): T['cache'];\n}\n\n/**\n * Use the legacy store with the given options.\n *\n * See {@link LegacyStoreSetupOptions} for details on the available options.\n *\n * ```ts\n * import { useLegacyStore } from '@warp-drive/legacy';\n * import { JSONAPICache } from '@warp-drive/json-api';\n *\n * export default useLegacyStore({\n * linksMode: false,\n * legacyRequests: true,\n * cache: JSONAPICache,\n * schemas: [],\n * });\n * ```\n *\n * ### Adding Stateful Handlers\n *\n * A request {@link Handler} is sometimes more than a plain object or class\n * with a `request` method — it may need access to a stateful dependency such\n * as an Ember service (an auth token, a feature-flags service, an i18n\n * helper, etc.).\n *\n * A plain class handler that only relies on Ember's `@service` decorator will\n * not work here on its own: the handler is never instantiated *through*\n * Ember's container (it's just `new`'d up), so it has no owner and its\n * `@service` injections would fail to resolve.\n *\n * Instead, give `handlers` a function. It receives the {@link Store} instance\n * being configured, which by the time the function runs already has an owner\n * assigned. Use `getOwner`/`setOwner` from `@ember/owner` to transfer that\n * owner onto your handler instance before returning it, exactly as you would\n * when constructing any other DI-aware object outside of the container:\n *\n * ```ts\n * import { getOwner, setOwner } from '@ember/owner';\n * import { service } from '@ember/service';\n * import { useLegacyStore } from '@warp-drive/legacy';\n * import type { NextFn } from '@warp-drive/core/request';\n * import type { RequestContext } from '@warp-drive/core/types/request';\n * import { JSONAPICache } from '@warp-drive/json-api';\n *\n * class AuthHandler {\n * @service session;\n *\n * request<T>(context: RequestContext, next: NextFn<T>) {\n * const headers = new Headers(context.request.headers);\n * headers.append('Authorization', `Bearer ${this.session.accessToken}`);\n * return next(Object.assign({}, context.request, { headers }));\n * }\n * }\n *\n * export default useLegacyStore({\n * linksMode: false,\n * legacyRequests: true,\n * cache: JSONAPICache,\n * handlers: (store) => {\n * const authHandler = new AuthHandler();\n * setOwner(authHandler, getOwner(store)!);\n * return [authHandler];\n * },\n * });\n * ```\n *\n * The `handlers` function is invoked lazily and only once per store instance,\n * the first time `store.requestManager` is accessed, so it is safe to do\n * owner-dependent setup like this inside of it.\n *\n * ### Accessing the Store from a Handler's Context\n *\n * If a handler only needs to read something *off of the store itself*\n * (its cache, or a property/service you've attached to a custom store\n * subclass) rather than an unrelated Ember service, there is a second,\n * simpler option that requires no DI/`setOwner` wiring at all.\n *\n * Every request issued via {@link Store.request | store.request(...)}\n * automatically carries the originating store along as\n * {@link RequestInfo.store | context.request.store}. Any handler — a plain\n * object, a function-built handler, or a class — can read it directly,\n * without needing the `handlers` callback form shown above:\n *\n * ```ts\n * import { useLegacyStore } from '@warp-drive/legacy';\n * import type { NextFn } from '@warp-drive/core/request';\n * import type { RequestContext } from '@warp-drive/core/types/request';\n * import { JSONAPICache } from '@warp-drive/json-api';\n *\n * const LoggingHandler = {\n * request<T>(context: RequestContext, next: NextFn<T>) {\n * // only present when the request was made via `store.request(...)`\n * const store = context.request.store;\n * if (store) {\n * console.log(`[${store.constructor.name}] ${context.request.url ?? ''}`);\n * }\n * return next(context.request);\n * },\n * };\n *\n * export default useLegacyStore({\n * linksMode: false,\n * legacyRequests: true,\n * cache: JSONAPICache,\n * handlers: [LoggingHandler],\n * });\n * ```\n *\n * The trade-off versus the `getOwner`/`setOwner` pattern above is that\n * `context.request.store` is only populated for requests issued via\n * `store.request(...)`; a request made directly against a\n * {@link RequestManager} won't have it set unless the caller supplies it\n * explicitly, so a handler relying on it should treat it as optional (as\n * `LoggingHandler` does above).\n */\nexport function useLegacyStore<T extends Cache>(\n options: LegacyModelStoreSetupOptions<T>,\n StoreKlass?: typeof Store\n): typeof ConfiguredStore<{ cache: T }>;\nexport function useLegacyStore<T extends Cache>(\n options: LegacyModelAndNetworkStoreSetupOptions<T>,\n StoreKlass?: typeof Store\n): typeof ConfiguredStore<{ cache: T }>;\nexport function useLegacyStore<T extends Cache>(\n options: LegacyModelAndNetworkAndRequestStoreSetupOptions<T>,\n StoreKlass?: typeof Store\n): typeof ConfiguredStore<{ cache: T }>;\nexport function useLegacyStore<T extends Cache>(\n options: LegacyStoreSetupOptions<T>,\n StoreKlass: typeof Store = Store\n): typeof ConfiguredStore<{ cache: T }> {\n assert(`If legacyRequests is true, linksMode must be false`, !(options.linksMode && options.legacyRequests));\n // we extend the store to ensure we don't leak our prototype overrides to other stores below.\n class BaseKlass extends StoreKlass {}\n class LegacyConfiguredStore extends BaseKlass {\n constructor(createArgs?: unknown) {\n super(createArgs);\n // installed via defineProperty (rather than a class field/accessor) so that\n // this lazy override of the inherited `requestManager` field does not\n // conflict with the documented pattern of assigning it directly on\n // consumer-authored Store subclasses. The setter preserves the ability\n // to replace `requestManager` outright after construction.\n let requestManager: RequestManager | undefined;\n Object.defineProperty(this, 'requestManager', {\n configurable: true,\n enumerable: true,\n get: (): RequestManager => {\n if (!requestManager) {\n const handlersOption = options.handlers;\n const handlers = typeof handlersOption === 'function' ? handlersOption(this) : (handlersOption ?? []);\n requestManager = new RequestManager()\n .use([options.linksMode ? null : LegacyNetworkHandler, ...handlers, Fetch].filter(Boolean) as Handler[])\n .useCache(CacheHandler);\n }\n return requestManager;\n },\n set: (value: RequestManager): void => {\n requestManager = value;\n },\n });\n }\n\n lifetimes =\n options.policy ??\n new DefaultCachePolicy({\n apiCacheHardExpires: 15 * 60 * 1000, // 15 minutes\n apiCacheSoftExpires: 1 * 30 * 1000, // 30 seconds\n constraints: {\n headers: {\n 'X-WarpDrive-Expires': true,\n 'Cache-Control': true,\n Expires: true,\n },\n },\n });\n\n createSchemaService(): DelegatingSchemaService {\n // prepare for PolarisMode\n const schema = new SchemaService();\n registerDerivations(schema);\n if (options.schemas) schema.registerResources(options.schemas);\n\n if (options.traits) {\n for (const trait of options.traits) {\n schema.registerTrait(trait);\n }\n }\n\n if (options.derivations) {\n for (const derivation of options.derivations) {\n schema.registerDerivation(derivation);\n }\n }\n\n if (options.transformations) {\n for (const transformation of options.transformations) {\n schema.registerTransformation(transformation);\n }\n }\n\n if (options.hashFns) {\n for (const hashFn of options.hashFns) {\n schema.registerHashFn(hashFn);\n }\n }\n\n if (options.CAUTION_MEGA_DANGER_ZONE_extensions) {\n for (const extension of options.CAUTION_MEGA_DANGER_ZONE_extensions) {\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(extension);\n }\n }\n\n // Add support for LegacyMode ReactiveResource with Maximal coverage\n // for upgrading from 4.x\n registerLegacyDerivations(schema);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(EmberArrayLikeExtension);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(EmberObjectArrayExtension);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension(EmberObjectExtension);\n\n // add support for fragments\n if (options.modelFragments) {\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension?.(FragmentExtension);\n schema.CAUTION_MEGA_DANGER_ZONE_registerExtension?.(FragmentArrayExtension);\n }\n\n // Add fallback for Models\n return new DelegatingSchemaService(this, schema);\n }\n\n createCache(capabilities: CacheCapabilitiesManager) {\n // oxlint-disable-next-line new-cap\n return new options.cache(capabilities);\n }\n\n instantiateRecord(key: ResourceKey, createArgs?: Record<string, unknown>) {\n if (this.schema.isDelegated(key)) {\n return instantiateModel.call(this, key, createArgs);\n }\n return instantiateRecord(this, key, createArgs);\n }\n\n teardownRecord(record: unknown): void {\n const key = recordIdentifierFor(record);\n if (this.schema.isDelegated(key)) {\n return teardownModel.call(this, record as Model);\n }\n releaseLegacySupport(key);\n return teardownRecord(record);\n }\n\n modelFor<InstanceType>(type: TypeFromInstance<InstanceType>): ModelSchema<InstanceType>;\n modelFor(type: string): ModelSchema;\n modelFor(type: string): ModelSchema {\n assertType(this.schema, type);\n\n const klass =\n // prefer real models if present\n (modelFor.call(this, type) as ModelSchema) ||\n // fallback to ShimModelClass specific to fragments if fragments support in use\n (options.modelFragments ? (fragmentsModelFor.call(this, type) as ModelSchema) : false) ||\n // fallback to ShimModelClass\n super.modelFor(type);\n\n return klass;\n }\n\n adapterFor(this: Store, modelName: string): MinimumAdapterInterface;\n adapterFor(this: Store, modelName: string, _allowMissing: true): MinimumAdapterInterface | undefined;\n adapterFor(this: Store, modelName: string, _allowMissing?: true): MinimumAdapterInterface | undefined {\n // createRecord asks for an adapter with _allowMissing to offer id generation;\n // linksMode has no adapters, so that soft lookup finds none.\n if (options.linksMode && _allowMissing) {\n return undefined;\n }\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n // @ts-expect-error\n return adapterFor.call(this, modelName, _allowMissing);\n }\n\n serializerFor(this: Store, ...args: Parameters<typeof serializerFor>): ReturnType<typeof serializerFor> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return serializerFor.call(this, ...args);\n }\n\n pushPayload(this: Store, ...args: Parameters<typeof pushPayload>): ReturnType<typeof pushPayload> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return pushPayload.call(this, ...args);\n }\n\n normalize(this: Store, ...args: Parameters<typeof normalize>): ReturnType<typeof normalize> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return normalize.call(this, ...args);\n }\n\n serializeRecord(this: Store, ...args: Parameters<typeof serializeRecord>): ReturnType<typeof serializeRecord> {\n assert(\n `useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`,\n !options.linksMode\n );\n return serializeRecord.call(this, ...args);\n }\n\n destroy() {\n if (!options.linksMode) {\n cleanup.call(this);\n }\n super.destroy();\n }\n }\n\n if (options.legacyRequests) {\n restoreDeprecatedStoreBehaviors(BaseKlass);\n }\n\n return LegacyConfiguredStore;\n}\n\nfunction assertType(schema: DelegatingSchemaService, type: string) {\n assert(`Expected type ${type} to be a valid ResourceType`, schema.hasResource({ type }));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwSA,SAAgBgC,eACdC,SACAC,aAA2B9B,OACW;CACtC0B,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;EAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MAAO,oDAAoD;CAAA,EAAA,CAAE,EAAEN,QAAQO,aAAaP,QAAQQ,eAAe;CAE3G,MAAMC,kBAAkBR,WAAW,CAAA;CACnC,MAAMS,8BAA8BD,UAAU;EAC5CE,YAAYC,YAAsB;GAChC,MAAMA,UAAU;GAMhB,IAAIC;GACJC,OAAOC,eAAe,MAAM,kBAAkB;IAC5CC,cAAc;IACdC,YAAY;IACZC,WAA2B;KACzB,IAAI,CAACL,gBAAgB;MACnB,MAAMM,iBAAiBnB,QAAQoB;MAC/B,MAAMA,WAAW,OAAOD,mBAAmB,aAAaA,eAAe,IAAI,IAAKA,kBAAkB,CAAA;MAClGN,iBAAiB,IAAI3C,eAAe,CAAC,CAClCmD,IAAI;OAACrB,QAAQO,YAAY,OAAO5B;OAAsB,GAAGyC;OAAUpD;MAAK,CAAC,CAACsD,OAAOC,OAAO,CAAc,CAAC,CACvGC,SAASzD,YAAY;KAC1B;KACA,OAAO8C;IACT;IACAY,MAAMC,UAAgC;KACpCb,iBAAiBa;IACnB;GACF,CAAC;EACH;EAEAC,YACE3B,QAAQ4B,UACR,IAAIpD,mBAAmB;GACrBqD,qBAAqB;GACrBC,qBAAqB;GACrBC,aAAa,EACXC,SAAS;IACP,uBAAuB;IACvB,iBAAiB;IACjBC,SAAS;GACX,EACF;EACF,CAAC;EAEHC,sBAA+C;GAE7C,MAAMC,SAAS,IAAI7D,cAAc;GACjCD,oBAAoB8D,MAAM;GAC1B,IAAInC,QAAQoC,SAASD,OAAOE,kBAAkBrC,QAAQoC,OAAO;GAE7D,IAAIpC,QAAQsC,QACV,KAAK,MAAMC,SAASvC,QAAQsC,QAC1BH,OAAOK,cAAcD,KAAK;GAI9B,IAAIvC,QAAQyC,aACV,KAAK,MAAMC,cAAc1C,QAAQyC,aAC/BN,OAAOQ,mBAAmBD,UAAU;GAIxC,IAAI1C,QAAQ4C,iBACV,KAAK,MAAMC,kBAAkB7C,QAAQ4C,iBACnCT,OAAOW,uBAAuBD,cAAc;GAIhD,IAAI7C,QAAQ+C,SACV,KAAK,MAAMC,UAAUhD,QAAQ+C,SAC3BZ,OAAOc,eAAeD,MAAM;GAIhC,IAAIhD,QAAQkD,qCACV,KAAK,MAAMC,aAAanD,QAAQkD,qCAC9Bf,OAAOiB,2CAA2CD,SAAS;GAM/DxD,sBAA0BwC,MAAM;GAChCA,OAAOiB,2CAA2CpE,uBAAuB;GACzEmD,OAAOiB,2CAA2CnE,yBAAyB;GAC3EkD,OAAOiB,2CAA2ClE,oBAAoB;GAGtE,IAAIc,QAAQqD,gBAAgB;IAC1BlB,OAAOiB,6CAA6C7D,iBAAiB;IACrE4C,OAAOiB,6CAA6C9D,sBAAsB;GAC5E;GAGA,OAAO,IAAII,wBAAwB,MAAMyC,MAAM;EACjD;EAEAmB,YAAYC,cAAwC;GAElD,OAAO,IAAIvD,QAAQwD,MAAMD,YAAY;EACvC;EAEAnF,kBAAkBqF,KAAkB7C,YAAsC;GACxE,IAAI,KAAKuB,OAAOuB,YAAYD,GAAG,GAC7B,OAAOtE,oBAAiBwE,KAAK,MAAMF,KAAK7C,UAAU;GAEpD,OAAOxC,kBAAkB,MAAMqF,KAAK7C,UAAU;EAChD;EAEArC,eAAeqF,QAAuB;GACpC,MAAMH,MAAMxF,oBAAoB2F,MAAM;GACtC,IAAI,KAAKzB,OAAOuB,YAAYD,GAAG,GAC7B,OAAOpE,iBAAcsE,KAAK,MAAMC,MAAe;GAEjDnE,qBAAqBgE,GAAG;GACxB,OAAOlF,eAAeqF,MAAM;EAC9B;EAIAxE,SAASyE,MAA2B;GAClCC,WAAW,KAAK3B,QAAQ0B,IAAI;GAU5B,OANGzE,SAASuE,KAAK,MAAME,IAAI,MAExB7D,QAAQqD,iBAAkB7D,kBAAkBmE,KAAK,MAAME,IAAI,IAAoB,UAEhF,MAAMzE,SAASyE,IAAI;EAGvB;EAIApF,WAAwBuF,WAAmBC,eAA2D;GAGpG,IAAIjE,QAAQO,aAAa0D,eACvB;GAEFpE,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;IAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MACE,mIAAmI;GAAA,EAAA,CACnI,CAACN,QAAQO,SAAS;GAGpB,OAAO9B,WAAWkF,KAAK,MAAMK,WAAWC,aAAa;EACvD;EAEAlF,cAA2B,GAAGoF,MAA0E;GACtGtE,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;IAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MACE,mIAAmI;GAAA,EAAA,CACnI,CAACN,QAAQO,SAAS;GAEpB,OAAOxB,cAAc4E,KAAK,MAAM,GAAGQ,IAAI;EACzC;EAEAtF,YAAyB,GAAGsF,MAAsE;GAChGtE,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;IAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MACE,mIAAmI;GAAA,EAAA,CACnI,CAACN,QAAQO,SAAS;GAEpB,OAAO1B,YAAY8E,KAAK,MAAM,GAAGQ,IAAI;EACvC;EAEAvF,UAAuB,GAAGuF,MAAkE;GAC1FtE,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;IAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MACE,mIAAmI;GAAA,EAAA,CACnI,CAACN,QAAQO,SAAS;GAEpB,OAAO3B,UAAU+E,KAAK,MAAM,GAAGQ,IAAI;EACrC;EAEArF,gBAA6B,GAAGqF,MAA8E;GAC5GtE,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;IAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MACE,mIAAmI;GAAA,EAAA,CACnI,CAACN,QAAQO,SAAS;GAEpB,OAAOzB,gBAAgB6E,KAAK,MAAM,GAAGQ,IAAI;EAC3C;EAEAC,UAAU;GACR,IAAI,CAACpE,QAAQO,WACX7B,QAAQiF,KAAK,IAAI;GAEnB,MAAMS,QAAQ;EAChB;CACF;CAEA,IAAIpE,QAAQQ,gBACVZ,gCAAgCa,SAAS;CAG3C,OAAOC;AACT;AAEA,SAASoD,WAAW3B,QAAiC0B,MAAc;CACjEhE,eAAAC,gBAAA,CAAA,CAAAI,UAAAC,IAAAC,KAAA,OAAAC,SAAA;EAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MAAO,iBAAiBuD,KAAI,4BAA6B;CAAA,EAAA,CAAE1B,OAAOkC,YAAY,EAAER,KAAK,CAAC,CAAC;AACzF"}
@@ -12,7 +12,7 @@ If starting a new app or thinking of implementing a new adapter, consider writin
12
12
  {@link Handler} instead to be used with the {@link RequestManager}
13
13
  :::
14
14
 
15
- The `JSONAPIAdapter` is an adapter whichtransforms the store's
15
+ The `JSONAPIAdapter` is an adapter which transforms the store's
16
16
  requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).
17
17
 
18
18
  ## JSON API Conventions
@@ -1 +1 @@
1
- {"version":3,"file":"json-api.js","names":["dasherize","pluralize","serializeIntoHash","RESTAdapter","JSONAPIAdapter","_defaultContentType","ajaxOptions","url","type","options","hash","headers","coalesceFindRequests","_coalesceFindRequests","value","findMany","store","ids","snapshots","buildURL","modelName","ajax","data","filter","id","join","pathForType","dasherized","updateRecord","schema","snapshot","test","Error","length","buildQuery","query","include","normalizedInclude","Array","isArray"],"sources":["../../../../src/adapter/json-api.ts"],"sourcesContent":["// oxlint-disable-next-line no-unused-vars\nimport type { RequestManager, Store } from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\n// oxlint-disable-next-line no-unused-vars\nimport type { Handler } from '@warp-drive/core/request';\nimport type { ModelSchema } from '@warp-drive/core/types';\nimport type { HTTPMethod } from '@warp-drive/core/types/request';\nimport { dasherize, pluralize } from '@warp-drive/utilities/string';\n\nimport type { AdapterPayload } from '../compat.ts';\nimport type { Snapshot, SnapshotRecordArray } from '../compat/-private.ts';\nimport { serializeIntoHash } from './-private.ts';\nimport type { FetchRequestInit, JQueryRequestInit, QueryState } from './rest.ts';\nimport { RESTAdapter } from './rest.ts';\n/**\n ## Overview\n\n :::danger\n ⚠️ **This is LEGACY documentation** for a feature that is no longer encouraged to be used.\n If starting a new app or thinking of implementing a new adapter, consider writing a\n {@link Handler} instead to be used with the {@link RequestManager}\n :::\n\n The `JSONAPIAdapter` is an adapter whichtransforms the store's\n requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).\n\n ## JSON API Conventions\n\n The JSONAPIAdapter uses JSON API conventions for building the URL\n for a record and selecting the HTTP verb to use with a request. The\n actions you can take on a record map onto the following URLs in the\n JSON API adapter:\n\n<table>\n <tr>\n <th>\n Action\n </th>\n <th>\n HTTP Verb\n </th>\n <th>\n URL\n </th>\n </tr>\n <tr>\n <th>\n `store.findRecord('post', 123)`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n `store.findAll('post')`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Update `postRecord.save()`\n </th>\n <td>\n PATCH\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n Create `store.createRecord('post').save()`\n </th>\n <td>\n POST\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Delete `postRecord.destroyRecord()`\n </th>\n <td>\n DELETE\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n</table>\n\n ## Success and failure\n\n The JSONAPIAdapter will consider a success any response with a\n status code of the 2xx family (\"Success\"), as well as 304 (\"Not\n Modified\"). Any other status code will be considered a failure.\n\n On success, the request promise will be resolved with the full\n response payload.\n\n Failed responses with status code 422 (\"Unprocessable Entity\") will\n be considered \"invalid\". The response will be discarded, except for\n the `errors` key. The request promise will be rejected with a\n `InvalidError`. This error object will encapsulate the saved\n `errors` value.\n\n Any other status codes will be treated as an adapter error. The\n request promise will be rejected, similarly to the invalid case,\n but with an instance of `AdapterError` instead.\n\n ### Endpoint path customization\n\n Endpoint paths can be prefixed with a `namespace` by setting the\n namespace property on the adapter:\n\n ```js [app/adapters/application.js]\n import { JSONAPIAdapter } from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n namespace = 'api/1';\n }\n ```\n Requests for the `person` model would now target `/api/1/people/1`.\n\n ### Host customization\n\n An adapter can target other hosts by setting the `host` property.\n\n ```js [app/adapters/application.js]\n import JSONAPIAdapter from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n host = 'https://api.example.com';\n }\n ```\n\n Requests for the `person` model would now target\n `https://api.example.com/people/1`.\n\n @since 1.13.0\n @class JSONAPIAdapter\n @public\n @constructor\n*/\nclass JSONAPIAdapter extends RESTAdapter {\n /**\n * The `Content-Type` header used when serializing request bodies\n * that don't otherwise specify one.\n */\n _defaultContentType = 'application/vnd.api+json';\n\n /**\n @private\n @param {String} url\n @param {String} type The request type GET, POST, PUT, DELETE etc.\n @param {Object} options\n @return {Object}\n */\n ajaxOptions(\n url: string,\n type: HTTPMethod,\n options: JQueryAjaxSettings | RequestInit = {}\n ): JQueryRequestInit | FetchRequestInit {\n const hash = super.ajaxOptions(url, type, options) as FetchRequestInit;\n const headers: HeadersInit = (hash.headers = hash.headers || {});\n headers['Accept'] = (headers['Accept'] as string) || 'application/vnd.api+json';\n\n return hash;\n }\n\n /**\n By default the JSONAPIAdapter will send each find request coming from a `store.find`\n or from accessing a relationship separately to the server. If your server supports passing\n ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests\n within a single runloop.\n\n For example, if you have an initial payload of:\n\n ```javascript\n {\n data: {\n id: 1,\n type: 'post',\n relationship: {\n comments: {\n data: [\n { id: 1, type: 'comment' },\n { id: 2, type: 'comment' }\n ]\n }\n }\n }\n }\n ```\n\n By default calling `post.comments` will trigger the following requests(assuming the\n comments haven't been loaded before):\n\n ```\n GET /comments/1\n GET /comments/2\n ```\n\n If you set coalesceFindRequests to `true` it will instead trigger the following request:\n\n ```\n GET /comments?filter[id]=1,2\n ```\n\n Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`\n relationships accessed within the same runloop. If you set `coalesceFindRequests: true`\n\n ```javascript\n store.findRecord('comment', 1);\n store.findRecord('comment', 2);\n ```\n\n will also send a request to: `GET /comments?filter[id]=1,2`\n\n Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app\n `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.\n\n @property coalesceFindRequests\n @public\n @type {Boolean}\n */\n get coalesceFindRequests() {\n const coalesceFindRequests = this._coalesceFindRequests;\n if (typeof coalesceFindRequests === 'boolean') {\n return coalesceFindRequests;\n }\n return (this._coalesceFindRequests = false);\n }\n\n set coalesceFindRequests(value: boolean) {\n this._coalesceFindRequests = value;\n }\n\n findMany(store: Store, type: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<AdapterPayload> {\n const url = this.buildURL(type.modelName, ids, snapshots, 'findMany');\n return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } });\n }\n\n /**\n * Determines the pathname for a given type.\n *\n * Unlike the base `BuildURLMixin` implementation, dasherizes (rather\n * than camelizes) the type name before pluralizing it, per the\n * {json:api} convention for member names.\n */\n pathForType(modelName: string): string {\n const dasherized = dasherize(modelName);\n return pluralize(dasherized);\n }\n\n updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload> {\n const data = serializeIntoHash(store, schema, snapshot);\n const type = snapshot.modelName;\n const id = snapshot.id;\n assert(`Attempted to update the ${type} record, but the record has no id`, typeof id === 'string' && id.length > 0);\n\n const url = this.buildURL(type, id, snapshot, 'updateRecord');\n\n return this.ajax(url, 'PATCH', { data: data });\n }\n\n /**\n Used by `findAll` and `findRecord` to build the query's `data` hash\n supplied to the ajax method.\n\n @since 2.5.0\n @public\n @param {Snapshot} snapshot\n @return {Object}\n */\n buildQuery(snapshot: Snapshot | SnapshotRecordArray): QueryState {\n const query: QueryState = {};\n\n if (snapshot) {\n const { include } = snapshot;\n const normalizedInclude = Array.isArray(include) ? include.join(',') : include;\n\n if (normalizedInclude) {\n query.include = normalizedInclude;\n }\n }\n\n return query;\n }\n}\n\nexport { JSONAPIAdapter };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JA,IAAMI,iBAAN,cAA6BD,YAAY;;;;;CAKvCE,sBAAsB;;;;;;;;CAStBC,YACEC,KACAC,MACAC,UAA4C,CAAC,GACP;EACtC,MAAMC,OAAO,MAAMJ,YAAYC,KAAKC,MAAMC,OAAO;EACjD,MAAME,UAAwBD,KAAKC,UAAUD,KAAKC,WAAW,CAAC;EAC9DA,QAAQ,YAAaA,QAAQ,aAAwB;EAErD,OAAOD;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DA,IAAIE,uBAAuB;EACzB,MAAMA,uBAAuB,KAAKC;EAClC,IAAI,OAAOD,yBAAyB,WAClC,OAAOA;EAET,OAAQ,KAAKC,wBAAwB;CACvC;CAEA,IAAID,qBAAqBE,OAAgB;EACvC,KAAKD,wBAAwBC;CAC/B;CAEAC,SAASC,OAAcR,MAAmBS,KAAeC,WAAgD;EACvG,MAAMX,MAAM,KAAKY,SAASX,KAAKY,WAAWH,KAAKC,WAAW,UAAU;EACpE,OAAO,KAAKG,KAAKd,KAAK,OAAO,EAAEe,MAAM,EAAEC,QAAQ,EAAEC,IAAIP,IAAIQ,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC;CAC1E;;;;;;;;CASAC,YAAYN,WAA2B;EACrC,MAAMO,aAAa3B,UAAUoB,SAAS;EACtC,OAAOnB,UAAU0B,UAAU;CAC7B;CAEAC,aAAaZ,OAAca,QAAqBC,UAA6C;EAC3F,MAAMR,OAAOpB,kBAAkBc,OAAOa,QAAQC,QAAQ;EACtD,MAAMtB,OAAOsB,SAASV;EACtB,MAAMI,KAAKM,SAASN;EACpB,EAAAO,SAAA;GAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MAAO,2BAA2BxB,KAAI,kCAAmC;EAAA,EAAA,CAAE,OAAOgB,OAAO,YAAYA,GAAGS,SAAS,CAAC;EAElH,MAAM1B,MAAM,KAAKY,SAASX,MAAMgB,IAAIM,UAAU,cAAc;EAE5D,OAAO,KAAKT,KAAKd,KAAK,SAAS,EAAQe,KAAK,CAAC;CAC/C;;;;;;;;;CAWAY,WAAWJ,UAAsD;EAC/D,MAAMK,QAAoB,CAAC;EAE3B,IAAIL,UAAU;GACZ,MAAM,EAAEM,YAAYN;GACpB,MAAMO,oBAAoBC,MAAMC,QAAQH,OAAO,IAAIA,QAAQX,KAAK,GAAG,IAAIW;GAEvE,IAAIC,mBACFF,MAAMC,UAAUC;EAEpB;EAEA,OAAOF;CACT;AACF"}
1
+ {"version":3,"file":"json-api.js","names":["dasherize","pluralize","serializeIntoHash","RESTAdapter","JSONAPIAdapter","_defaultContentType","ajaxOptions","url","type","options","hash","headers","coalesceFindRequests","_coalesceFindRequests","value","findMany","store","ids","snapshots","buildURL","modelName","ajax","data","filter","id","join","pathForType","dasherized","updateRecord","schema","snapshot","test","Error","length","buildQuery","query","include","normalizedInclude","Array","isArray"],"sources":["../../../../src/adapter/json-api.ts"],"sourcesContent":["// oxlint-disable-next-line no-unused-vars\nimport type { RequestManager, Store } from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\n// oxlint-disable-next-line no-unused-vars\nimport type { Handler } from '@warp-drive/core/request';\nimport type { ModelSchema } from '@warp-drive/core/types';\nimport type { HTTPMethod } from '@warp-drive/core/types/request';\nimport { dasherize, pluralize } from '@warp-drive/utilities/string';\n\nimport type { AdapterPayload } from '../compat.ts';\nimport type { Snapshot, SnapshotRecordArray } from '../compat/-private.ts';\nimport { serializeIntoHash } from './-private.ts';\nimport type { FetchRequestInit, JQueryRequestInit, QueryState } from './rest.ts';\nimport { RESTAdapter } from './rest.ts';\n/**\n ## Overview\n\n :::danger\n ⚠️ **This is LEGACY documentation** for a feature that is no longer encouraged to be used.\n If starting a new app or thinking of implementing a new adapter, consider writing a\n {@link Handler} instead to be used with the {@link RequestManager}\n :::\n\n The `JSONAPIAdapter` is an adapter which transforms the store's\n requests into HTTP requests that follow the [JSON API format](http://jsonapi.org/format/).\n\n ## JSON API Conventions\n\n The JSONAPIAdapter uses JSON API conventions for building the URL\n for a record and selecting the HTTP verb to use with a request. The\n actions you can take on a record map onto the following URLs in the\n JSON API adapter:\n\n<table>\n <tr>\n <th>\n Action\n </th>\n <th>\n HTTP Verb\n </th>\n <th>\n URL\n </th>\n </tr>\n <tr>\n <th>\n `store.findRecord('post', 123)`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n `store.findAll('post')`\n </th>\n <td>\n GET\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Update `postRecord.save()`\n </th>\n <td>\n PATCH\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n <tr>\n <th>\n Create `store.createRecord('post').save()`\n </th>\n <td>\n POST\n </td>\n <td>\n /posts\n </td>\n </tr>\n <tr>\n <th>\n Delete `postRecord.destroyRecord()`\n </th>\n <td>\n DELETE\n </td>\n <td>\n /posts/123\n </td>\n </tr>\n</table>\n\n ## Success and failure\n\n The JSONAPIAdapter will consider a success any response with a\n status code of the 2xx family (\"Success\"), as well as 304 (\"Not\n Modified\"). Any other status code will be considered a failure.\n\n On success, the request promise will be resolved with the full\n response payload.\n\n Failed responses with status code 422 (\"Unprocessable Entity\") will\n be considered \"invalid\". The response will be discarded, except for\n the `errors` key. The request promise will be rejected with a\n `InvalidError`. This error object will encapsulate the saved\n `errors` value.\n\n Any other status codes will be treated as an adapter error. The\n request promise will be rejected, similarly to the invalid case,\n but with an instance of `AdapterError` instead.\n\n ### Endpoint path customization\n\n Endpoint paths can be prefixed with a `namespace` by setting the\n namespace property on the adapter:\n\n ```js [app/adapters/application.js]\n import { JSONAPIAdapter } from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n namespace = 'api/1';\n }\n ```\n Requests for the `person` model would now target `/api/1/people/1`.\n\n ### Host customization\n\n An adapter can target other hosts by setting the `host` property.\n\n ```js [app/adapters/application.js]\n import JSONAPIAdapter from '@warp-drive/legacy/adapter/json-api';\n\n export default class ApplicationAdapter extends JSONAPIAdapter {\n host = 'https://api.example.com';\n }\n ```\n\n Requests for the `person` model would now target\n `https://api.example.com/people/1`.\n\n @since 1.13.0\n @class JSONAPIAdapter\n @public\n @constructor\n*/\nclass JSONAPIAdapter extends RESTAdapter {\n /**\n * The `Content-Type` header used when serializing request bodies\n * that don't otherwise specify one.\n */\n _defaultContentType = 'application/vnd.api+json';\n\n /**\n @private\n @param {String} url\n @param {String} type The request type GET, POST, PUT, DELETE etc.\n @param {Object} options\n @return {Object}\n */\n ajaxOptions(\n url: string,\n type: HTTPMethod,\n options: JQueryAjaxSettings | RequestInit = {}\n ): JQueryRequestInit | FetchRequestInit {\n const hash = super.ajaxOptions(url, type, options) as FetchRequestInit;\n const headers: HeadersInit = (hash.headers = hash.headers || {});\n headers['Accept'] = (headers['Accept'] as string) || 'application/vnd.api+json';\n\n return hash;\n }\n\n /**\n By default the JSONAPIAdapter will send each find request coming from a `store.find`\n or from accessing a relationship separately to the server. If your server supports passing\n ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests\n within a single runloop.\n\n For example, if you have an initial payload of:\n\n ```javascript\n {\n data: {\n id: 1,\n type: 'post',\n relationship: {\n comments: {\n data: [\n { id: 1, type: 'comment' },\n { id: 2, type: 'comment' }\n ]\n }\n }\n }\n }\n ```\n\n By default calling `post.comments` will trigger the following requests(assuming the\n comments haven't been loaded before):\n\n ```\n GET /comments/1\n GET /comments/2\n ```\n\n If you set coalesceFindRequests to `true` it will instead trigger the following request:\n\n ```\n GET /comments?filter[id]=1,2\n ```\n\n Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`\n relationships accessed within the same runloop. If you set `coalesceFindRequests: true`\n\n ```javascript\n store.findRecord('comment', 1);\n store.findRecord('comment', 2);\n ```\n\n will also send a request to: `GET /comments?filter[id]=1,2`\n\n Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app\n `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.\n\n @property coalesceFindRequests\n @public\n @type {Boolean}\n */\n get coalesceFindRequests() {\n const coalesceFindRequests = this._coalesceFindRequests;\n if (typeof coalesceFindRequests === 'boolean') {\n return coalesceFindRequests;\n }\n return (this._coalesceFindRequests = false);\n }\n\n set coalesceFindRequests(value: boolean) {\n this._coalesceFindRequests = value;\n }\n\n findMany(store: Store, type: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<AdapterPayload> {\n const url = this.buildURL(type.modelName, ids, snapshots, 'findMany');\n return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } });\n }\n\n /**\n * Determines the pathname for a given type.\n *\n * Unlike the base `BuildURLMixin` implementation, dasherizes (rather\n * than camelizes) the type name before pluralizing it, per the\n * {json:api} convention for member names.\n */\n pathForType(modelName: string): string {\n const dasherized = dasherize(modelName);\n return pluralize(dasherized);\n }\n\n updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload> {\n const data = serializeIntoHash(store, schema, snapshot);\n const type = snapshot.modelName;\n const id = snapshot.id;\n assert(`Attempted to update the ${type} record, but the record has no id`, typeof id === 'string' && id.length > 0);\n\n const url = this.buildURL(type, id, snapshot, 'updateRecord');\n\n return this.ajax(url, 'PATCH', { data: data });\n }\n\n /**\n Used by `findAll` and `findRecord` to build the query's `data` hash\n supplied to the ajax method.\n\n @since 2.5.0\n @public\n @param {Snapshot} snapshot\n @return {Object}\n */\n buildQuery(snapshot: Snapshot | SnapshotRecordArray): QueryState {\n const query: QueryState = {};\n\n if (snapshot) {\n const { include } = snapshot;\n const normalizedInclude = Array.isArray(include) ? include.join(',') : include;\n\n if (normalizedInclude) {\n query.include = normalizedInclude;\n }\n }\n\n return query;\n }\n}\n\nexport { JSONAPIAdapter };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JA,IAAMI,iBAAN,cAA6BD,YAAY;;;;;CAKvCE,sBAAsB;;;;;;;;CAStBC,YACEC,KACAC,MACAC,UAA4C,CAAC,GACP;EACtC,MAAMC,OAAO,MAAMJ,YAAYC,KAAKC,MAAMC,OAAO;EACjD,MAAME,UAAwBD,KAAKC,UAAUD,KAAKC,WAAW,CAAC;EAC9DA,QAAQ,YAAaA,QAAQ,aAAwB;EAErD,OAAOD;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DA,IAAIE,uBAAuB;EACzB,MAAMA,uBAAuB,KAAKC;EAClC,IAAI,OAAOD,yBAAyB,WAClC,OAAOA;EAET,OAAQ,KAAKC,wBAAwB;CACvC;CAEA,IAAID,qBAAqBE,OAAgB;EACvC,KAAKD,wBAAwBC;CAC/B;CAEAC,SAASC,OAAcR,MAAmBS,KAAeC,WAAgD;EACvG,MAAMX,MAAM,KAAKY,SAASX,KAAKY,WAAWH,KAAKC,WAAW,UAAU;EACpE,OAAO,KAAKG,KAAKd,KAAK,OAAO,EAAEe,MAAM,EAAEC,QAAQ,EAAEC,IAAIP,IAAIQ,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC;CAC1E;;;;;;;;CASAC,YAAYN,WAA2B;EACrC,MAAMO,aAAa3B,UAAUoB,SAAS;EACtC,OAAOnB,UAAU0B,UAAU;CAC7B;CAEAC,aAAaZ,OAAca,QAAqBC,UAA6C;EAC3F,MAAMR,OAAOpB,kBAAkBc,OAAOa,QAAQC,QAAQ;EACtD,MAAMtB,OAAOsB,SAASV;EACtB,MAAMI,KAAKM,SAASN;EACpB,EAAAO,SAAA;GAAA,IAAA,CAAAA,MAAA,MAAA,IAAAC,MAAO,2BAA2BxB,KAAI,kCAAmC;EAAA,EAAA,CAAE,OAAOgB,OAAO,YAAYA,GAAGS,SAAS,CAAC;EAElH,MAAM1B,MAAM,KAAKY,SAASX,MAAMgB,IAAIM,UAAU,cAAc;EAE5D,OAAO,KAAKT,KAAKd,KAAK,SAAS,EAAQe,KAAK,CAAC;CAC/C;;;;;;;;;CAWAY,WAAWJ,UAAsD;EAC/D,MAAMK,QAAoB,CAAC;EAE3B,IAAIL,UAAU;GACZ,MAAM,EAAEM,YAAYN;GACpB,MAAMO,oBAAoBC,MAAMC,QAAQH,OAAO,IAAIA,QAAQX,KAAK,GAAG,IAAIW;GAEvE,IAAIC,mBACFF,MAAMC,UAAUC;EAEpB;EAEA,OAAOF;CACT;AACF"}
@@ -231,6 +231,7 @@ function useLegacyStore(options, StoreKlass = Store) {
231
231
  return modelFor.call(this, type) || (options.modelFragments ? fragmentsModelFor.call(this, type) : false) || super.modelFor(type);
232
232
  }
233
233
  adapterFor(modelName, _allowMissing) {
234
+ if (options.linksMode && _allowMissing) return;
234
235
  ((test) => {
235
236
  if (!test) throw new Error(`useLegacyStore was setup in linksMode. linksMode assumes that all requests have been migrated away from adapters and serializers.`);
236
237
  })(!options.linksMode);