@iamjulianacosta/mobx-data 1.1.1 → 1.4.0
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.
- package/README.md +273 -102
- package/dist/{CacheHandler-BTU_rYkv.js → CacheHandler-BhfbVHed.js} +17 -20
- package/dist/CacheHandler-BhfbVHed.js.map +1 -0
- package/dist/{CacheHandler-CXgY9IJo.cjs → CacheHandler-Q5VXOgh9.cjs} +2 -2
- package/dist/CacheHandler-Q5VXOgh9.cjs.map +1 -0
- package/dist/EmbeddedRecordsMixin-6mSCXsJ3.js +173 -0
- package/dist/EmbeddedRecordsMixin-6mSCXsJ3.js.map +1 -0
- package/dist/EmbeddedRecordsMixin-BkF7MdbY.cjs +2 -0
- package/dist/EmbeddedRecordsMixin-BkF7MdbY.cjs.map +1 -0
- package/dist/{JsonApiSerializer-wndq5a1n.js → JsonApiSerializer-BV61cFAZ.js} +3 -3
- package/dist/JsonApiSerializer-BV61cFAZ.js.map +1 -0
- package/dist/{JsonApiSerializer-Bc4iQB0d.cjs → JsonApiSerializer-Dt_Y_FIo.cjs} +2 -2
- package/dist/JsonApiSerializer-Dt_Y_FIo.cjs.map +1 -0
- package/dist/JsonSerializer-BzUCyUSf.cjs +2 -0
- package/dist/JsonSerializer-BzUCyUSf.cjs.map +1 -0
- package/dist/JsonSerializer-CFqo6GjC.js +98 -0
- package/dist/JsonSerializer-CFqo6GjC.js.map +1 -0
- package/dist/MdqlMemoryExecutor-BUlsalKm.cjs +2 -0
- package/dist/MdqlMemoryExecutor-BUlsalKm.cjs.map +1 -0
- package/dist/MdqlMemoryExecutor-BWMP31zG.js +127 -0
- package/dist/MdqlMemoryExecutor-BWMP31zG.js.map +1 -0
- package/dist/{MemoryAdapter-ni25N4H0.js → MemoryAdapter-BW1HKixm.js} +2 -2
- package/dist/{MemoryAdapter-ni25N4H0.js.map → MemoryAdapter-BW1HKixm.js.map} +1 -1
- package/dist/{MemoryAdapter-BTK2D64s.cjs → MemoryAdapter-C8iXAa2v.cjs} +2 -2
- package/dist/{MemoryAdapter-BTK2D64s.cjs.map → MemoryAdapter-C8iXAa2v.cjs.map} +1 -1
- package/dist/{ODataAdapter-DAja_jKM.js → ODataAdapter-CeBJblLQ.js} +25 -22
- package/dist/ODataAdapter-CeBJblLQ.js.map +1 -0
- package/dist/{ODataAdapter-lMifLyLD.cjs → ODataAdapter-DdE6MWkG.cjs} +2 -2
- package/dist/ODataAdapter-DdE6MWkG.cjs.map +1 -0
- package/dist/RestAdapter-D7GSrsJo.cjs +2 -0
- package/dist/RestAdapter-D7GSrsJo.cjs.map +1 -0
- package/dist/{RestAdapter-CGWqOR_G.js → RestAdapter-DYUoyV5h.js} +112 -77
- package/dist/RestAdapter-DYUoyV5h.js.map +1 -0
- package/dist/SchemaService-C_pkh-vI.js +180 -0
- package/dist/SchemaService-C_pkh-vI.js.map +1 -0
- package/dist/SchemaService-DbJLoYb9.cjs +2 -0
- package/dist/SchemaService-DbJLoYb9.cjs.map +1 -0
- package/dist/Serializer-Bap9U-kR.cjs +2 -0
- package/dist/Serializer-Bap9U-kR.cjs.map +1 -0
- package/dist/{Serializer-FxJbsZ50.js → Serializer-Ca6w_QNQ.js} +63 -49
- package/dist/Serializer-Ca6w_QNQ.js.map +1 -0
- package/dist/adapter/index.cjs +1 -1
- package/dist/adapter/index.js +2 -2
- package/dist/cache/cache-utils.d.ts +1 -1
- package/dist/cache/cache-utils.d.ts.map +1 -1
- package/dist/createStore-7PecKT54.cjs +2 -0
- package/dist/createStore-7PecKT54.cjs.map +1 -0
- package/dist/createStore-BfmRfZ_2.js +1229 -0
- package/dist/createStore-BfmRfZ_2.js.map +1 -0
- package/dist/date-Bj4O2W1F.js.map +1 -1
- package/dist/date-CRCe-9gf.cjs.map +1 -1
- package/dist/decorators-CKneHgoF.js +56 -0
- package/dist/decorators-CKneHgoF.js.map +1 -0
- package/dist/decorators-DCVYKzrL.cjs +2 -0
- package/dist/decorators-DCVYKzrL.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -90
- package/dist/index.js.map +1 -1
- package/dist/inspector/ConsoleInspector.d.ts +49 -0
- package/dist/inspector/ConsoleInspector.d.ts.map +1 -0
- package/dist/inspector/DevToolsBridge.d.ts +21 -0
- package/dist/inspector/DevToolsBridge.d.ts.map +1 -0
- package/dist/inspector/QueryParser.d.ts +21 -0
- package/dist/inspector/QueryParser.d.ts.map +1 -0
- package/dist/inspector/StoreInspector.d.ts +31 -0
- package/dist/inspector/StoreInspector.d.ts.map +1 -0
- package/dist/inspector/index.cjs +17 -0
- package/dist/inspector/index.cjs.map +1 -0
- package/dist/inspector/index.d.ts +9 -0
- package/dist/inspector/index.d.ts.map +1 -0
- package/dist/inspector/index.js +896 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/inspector/integration.d.ts +15 -0
- package/dist/inspector/integration.d.ts.map +1 -0
- package/dist/inspector/serialization.d.ts +7 -0
- package/dist/inspector/serialization.d.ts.map +1 -0
- package/dist/inspector/types.d.ts +139 -0
- package/dist/inspector/types.d.ts.map +1 -0
- package/dist/json-api/index.cjs +1 -1
- package/dist/json-api/index.js +1 -1
- package/dist/mdql/MdqlMemoryExecutor.d.ts +17 -0
- package/dist/mdql/MdqlMemoryExecutor.d.ts.map +1 -0
- package/dist/mdql/MdqlQueryBuilder.d.ts +38 -0
- package/dist/mdql/MdqlQueryBuilder.d.ts.map +1 -0
- package/dist/mdql/MdqlValidator.d.ts +13 -0
- package/dist/mdql/MdqlValidator.d.ts.map +1 -0
- package/dist/mdql/index.d.ts +6 -0
- package/dist/mdql/index.d.ts.map +1 -0
- package/dist/mdql/types.d.ts +48 -0
- package/dist/mdql/types.d.ts.map +1 -0
- package/dist/model/Model.d.ts +4 -0
- package/dist/model/Model.d.ts.map +1 -1
- package/dist/model/Snapshot.d.ts +2 -0
- package/dist/model/Snapshot.d.ts.map +1 -1
- package/dist/model/index.cjs +1 -1
- package/dist/model/index.js +1 -1
- package/dist/odata/ODataAdapter.d.ts.map +1 -1
- package/dist/odata/index.cjs +1 -1
- package/dist/odata/index.js +1 -1
- package/dist/relationships-BgM0NKdb.cjs +2 -0
- package/dist/relationships-BgM0NKdb.cjs.map +1 -0
- package/dist/{relationships-BEXANmWg.js → relationships-DvSi8fVN.js} +37 -28
- package/dist/relationships-DvSi8fVN.js.map +1 -0
- package/dist/request/CacheHandler.d.ts.map +1 -1
- package/dist/request/index.cjs +1 -1
- package/dist/request/index.js +1 -1
- package/dist/schema/SchemaService.d.ts +38 -1
- package/dist/schema/SchemaService.d.ts.map +1 -1
- package/dist/schema/decorators.d.ts +20 -1
- package/dist/schema/decorators.d.ts.map +1 -1
- package/dist/schema/index.cjs +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +10 -8
- package/dist/schema/types.d.ts +31 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/serializer/JsonSerializer.d.ts +2 -0
- package/dist/serializer/JsonSerializer.d.ts.map +1 -1
- package/dist/serializer/Serializer.d.ts +9 -0
- package/dist/serializer/Serializer.d.ts.map +1 -1
- package/dist/serializer/index.cjs +1 -1
- package/dist/serializer/index.js +6 -5
- package/dist/serializer/index.js.map +1 -1
- package/dist/store/Store.d.ts +3 -0
- package/dist/store/Store.d.ts.map +1 -1
- package/dist/store/createStore.d.ts +12 -0
- package/dist/store/createStore.d.ts.map +1 -0
- package/dist/store/index.cjs +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +5 -4
- package/dist/types-CC2fG3FP.js +8 -0
- package/dist/types-CC2fG3FP.js.map +1 -0
- package/dist/types-DCLy5XYj.cjs +2 -0
- package/dist/types-DCLy5XYj.cjs.map +1 -0
- package/package.json +7 -1
- package/src/cache/cache-utils.ts +4 -4
- package/src/index.ts +3 -0
- package/src/inspector/ConsoleInspector.ts +470 -0
- package/src/inspector/DevToolsBridge.ts +214 -0
- package/src/inspector/QueryParser.ts +343 -0
- package/src/inspector/StoreInspector.ts +162 -0
- package/src/inspector/index.ts +20 -0
- package/src/inspector/integration.ts +56 -0
- package/src/inspector/serialization.ts +100 -0
- package/src/inspector/types.ts +161 -0
- package/src/mdql/MdqlMemoryExecutor.ts +229 -0
- package/src/mdql/MdqlQueryBuilder.ts +170 -0
- package/src/mdql/MdqlValidator.ts +193 -0
- package/src/mdql/index.ts +21 -0
- package/src/mdql/types.ts +107 -0
- package/src/model/Model.ts +15 -0
- package/src/model/Snapshot.ts +3 -0
- package/src/odata/ODataAdapter.ts +4 -1
- package/src/request/CacheHandler.ts +2 -6
- package/src/schema/SchemaService.ts +123 -1
- package/src/schema/decorators.ts +29 -0
- package/src/schema/index.ts +1 -1
- package/src/schema/types.ts +34 -0
- package/src/serializer/JsonSerializer.ts +14 -2
- package/src/serializer/Serializer.ts +24 -1
- package/src/store/Store.ts +61 -18
- package/src/store/createStore.ts +39 -0
- package/src/store/index.ts +1 -0
- package/dist/CacheHandler-BTU_rYkv.js.map +0 -1
- package/dist/CacheHandler-CXgY9IJo.cjs.map +0 -1
- package/dist/EmbeddedRecordsMixin-CBvqNdgC.cjs +0 -2
- package/dist/EmbeddedRecordsMixin-CBvqNdgC.cjs.map +0 -1
- package/dist/EmbeddedRecordsMixin-VoHluHCT.js +0 -261
- package/dist/EmbeddedRecordsMixin-VoHluHCT.js.map +0 -1
- package/dist/JsonApiSerializer-Bc4iQB0d.cjs.map +0 -1
- package/dist/JsonApiSerializer-wndq5a1n.js.map +0 -1
- package/dist/ODataAdapter-DAja_jKM.js.map +0 -1
- package/dist/ODataAdapter-lMifLyLD.cjs.map +0 -1
- package/dist/RestAdapter-1V94stW-.cjs +0 -2
- package/dist/RestAdapter-1V94stW-.cjs.map +0 -1
- package/dist/RestAdapter-CGWqOR_G.js.map +0 -1
- package/dist/SchemaService-DZwkFgZu.js +0 -102
- package/dist/SchemaService-DZwkFgZu.js.map +0 -1
- package/dist/SchemaService-Di_yjVzU.cjs +0 -2
- package/dist/SchemaService-Di_yjVzU.cjs.map +0 -1
- package/dist/Serializer-95gi5edy.cjs +0 -2
- package/dist/Serializer-95gi5edy.cjs.map +0 -1
- package/dist/Serializer-FxJbsZ50.js.map +0 -1
- package/dist/Store-KvjmBTQ9.cjs +0 -2
- package/dist/Store-KvjmBTQ9.cjs.map +0 -1
- package/dist/Store-mvrDLQEZ.js +0 -957
- package/dist/Store-mvrDLQEZ.js.map +0 -1
- package/dist/cache-utils-2lswvJ87.cjs +0 -2
- package/dist/cache-utils-2lswvJ87.cjs.map +0 -1
- package/dist/cache-utils-38Dqu4Qf.js +0 -39
- package/dist/cache-utils-38Dqu4Qf.js.map +0 -1
- package/dist/decorators-HQ1KnRdh.cjs +0 -2
- package/dist/decorators-HQ1KnRdh.cjs.map +0 -1
- package/dist/decorators-Zr35qr6A.js +0 -50
- package/dist/decorators-Zr35qr6A.js.map +0 -1
- package/dist/relationships-B55LBaCW.cjs +0 -2
- package/dist/relationships-B55LBaCW.cjs.map +0 -1
- package/dist/relationships-BEXANmWg.js.map +0 -1
- package/dist/types-C9NB2gRj.js +0 -7
- package/dist/types-C9NB2gRj.js.map +0 -1
- package/dist/types-uWOXMPWW.cjs +0 -2
- package/dist/types-uWOXMPWW.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonSerializer-CFqo6GjC.js","sources":["../src/serializer/JsonSerializer.ts"],"sourcesContent":["/**\r\n * Flat-JSON serializer for simple REST APIs.\r\n *\r\n * `JsonSerializer` expects payloads to be plain JSON objects or arrays with\r\n * no root-key wrapping. It is the lowest-level concrete serializer and the\r\n * base that `RestSerializer` extends.\r\n *\r\n * Normalization:\r\n * - Array payload → `{ data: [NormalizedResource, …] }`\r\n * - Object payload → `{ data: NormalizedResource }`\r\n * - `null` / `undefined` → `{ data: null }`\r\n *\r\n * Serialization:\r\n * - Iterates `@attr` → writes via `serializeAttribute`\r\n * - Iterates `@belongsTo` / `@hasMany` → writes via `serializeBelongsTo` /\r\n * `serializeHasMany`\r\n *\r\n * `normalizeResponse` automatically dispatches to the correct per-operation\r\n * hook (`normalizeFindRecordResponse`, etc.) when a subclass overrides them.\r\n * If no override exists it falls through to `_buildDocument`.\r\n */\r\n\r\nimport 'reflect-metadata';\r\nimport { injectable } from 'tsyringe';\r\nimport { MODEL_OPTIONS_META_KEY, type ModelOptions } from '../schema/types.js';\r\nimport {\r\n Serializer,\r\n type ModelClassMeta,\r\n type NormalizeRequestType,\r\n type NormalizedDocument,\r\n type NormalizedResource,\r\n type SerializerSnapshot,\r\n} from './Serializer.js';\r\n\r\n@injectable()\r\nexport class JsonSerializer extends Serializer {\r\n static dispatchMethodName(\r\n requestType: NormalizeRequestType,\r\n ): keyof Serializer | null {\r\n switch (requestType) {\r\n case 'findRecord':\r\n return 'normalizeFindRecordResponse';\r\n case 'findAll':\r\n return 'normalizeFindAllResponse';\r\n case 'query':\r\n return 'normalizeQueryResponse';\r\n case 'queryRecord':\r\n return 'normalizeQueryRecordResponse';\r\n case 'createRecord':\r\n return 'normalizeCreateRecordResponse';\r\n case 'updateRecord':\r\n return 'normalizeUpdateRecordResponse';\r\n case 'deleteRecord':\r\n return 'normalizeDeleteRecordResponse';\r\n default:\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Normalizes a single flat JSON object into a `NormalizedResource`.\r\n * Returns `null` for absent or non-object payloads.\r\n */\r\n override normalize(\r\n _store: unknown,\r\n modelClass: ModelClassMeta,\r\n payload: unknown,\r\n _prop?: string,\r\n ): NormalizedResource | null {\r\n if (payload === null || payload === undefined) {\r\n return null;\r\n }\r\n if (typeof payload !== 'object') {\r\n return null;\r\n }\r\n const hash = payload as Record<string, unknown>;\r\n const id = this.extractId(modelClass, hash);\r\n\r\n const modelOptions = Reflect.getOwnMetadata(\r\n MODEL_OPTIONS_META_KEY,\r\n modelClass,\r\n ) as ModelOptions | undefined;\r\n const attributes = modelOptions?.discriminator\r\n ? this.extractAllAttributes(modelClass, hash)\r\n : this.extractAttributes(modelClass, hash);\r\n\r\n const relationships = this.extractRelationships(modelClass, hash);\r\n\r\n const resource: NormalizedResource = {\r\n type: modelClass.modelName,\r\n id,\r\n attributes,\r\n };\r\n if (relationships && Object.keys(relationships).length > 0) {\r\n resource.relationships = relationships;\r\n }\r\n return resource;\r\n }\r\n\r\n /**\r\n * Entry point for normalization.\r\n *\r\n * Checks whether a subclass has overridden the relevant per-operation hook\r\n * (e.g. `normalizeFindRecordResponse`). If so, calls it; otherwise falls\r\n * through to `_buildDocument`.\r\n */\r\n override normalizeResponse(\r\n store: unknown,\r\n modelClass: ModelClassMeta,\r\n payload: unknown,\r\n id: string | null,\r\n requestType: NormalizeRequestType,\r\n ): NormalizedDocument {\r\n const methodName = JsonSerializer.dispatchMethodName(requestType);\r\n if (methodName) {\r\n const override = (this as unknown as Record<string, unknown>)[methodName];\r\n const baseImpl = (Serializer.prototype as unknown as Record<string, unknown>)[\r\n methodName\r\n ];\r\n if (typeof override === 'function' && override !== baseImpl) {\r\n return (override as (...args: unknown[]) => NormalizedDocument).call(\r\n this,\r\n store,\r\n modelClass,\r\n payload,\r\n id,\r\n requestType,\r\n );\r\n }\r\n }\r\n return this._buildDocument(store, modelClass, payload, id, requestType);\r\n }\r\n\r\n /**\r\n * Builds a `NormalizedDocument` from a raw payload.\r\n * Arrays are normalized item by item; plain objects are normalized as a\r\n * single resource.\r\n */\r\n protected _buildDocument(\r\n store: unknown,\r\n modelClass: ModelClassMeta,\r\n payload: unknown,\r\n _id: string | null,\r\n _requestType: NormalizeRequestType,\r\n ): NormalizedDocument {\r\n if (payload === null || payload === undefined) {\r\n return { data: null };\r\n }\r\n if (Array.isArray(payload)) {\r\n const data = payload\r\n .map((p) => this.normalize(store, modelClass, p))\r\n .filter((r): r is NormalizedResource => r !== null);\r\n return { data };\r\n }\r\n const data = this.normalize(store, modelClass, payload);\r\n return { data };\r\n }\r\n\r\n /**\r\n * Serializes a snapshot to a flat JSON object.\r\n * Includes `id` when `options.includeId` is `true`.\r\n */\r\n override serialize(\r\n snapshot: SerializerSnapshot,\r\n options?: { includeId?: boolean; clientGeneratedIds?: boolean },\r\n ): Record<string, unknown> {\r\n const json: Record<string, unknown> = {};\r\n if (options?.includeId && snapshot.id !== null) {\r\n json[this.primaryKey] = snapshot.id;\r\n } else if (options?.clientGeneratedIds && snapshot.id === null) {\r\n json[this.primaryKey] = snapshot.clientId;\r\n }\r\n snapshot.eachAttribute((key, meta) => {\r\n this.serializeAttribute(snapshot, json, key, meta);\r\n });\r\n snapshot.eachRelationship((_key, rel) => {\r\n if (rel.kind === 'belongsTo') {\r\n this.serializeBelongsTo(snapshot, json, rel);\r\n } else {\r\n this.serializeHasMany(snapshot, json, rel);\r\n }\r\n });\r\n return json;\r\n }\r\n}\r\n"],"names":["JsonSerializer","Serializer","requestType","_store","modelClass","payload","_prop","hash","id","modelOptions","MODEL_OPTIONS_META_KEY","attributes","relationships","resource","store","methodName","override","baseImpl","_id","_requestType","p","r","data","snapshot","options","json","key","meta","_key","rel","__decorateClass","injectable"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";class n{static executeMany(t,e){let s=t.filter(i=>n.matchesNode(i,e.filters));e.orderBy.length>0&&(s=n.sortRecords(s,e.orderBy));const r=e.offset??0;if(r>0||e.limit!==null){const i=e.limit!==null?r+e.limit:void 0;s=s.slice(r,i)}return s}static executeOne(t,e){return n.executeMany(t,e)[0]??null}static count(t,e){let s=0;for(const r of t)n.matchesNode(r,e.filters)&&s++;return s}static exists(t,e){return t.some(s=>n.matchesNode(s,e.filters))}static compilePredicate(t){return e=>n.matchesNode(e,t.filters)}static matchesNode(t,e){return e.kind==="condition"?n.evaluateCondition(t,e):e.kind==="and"?e.children.every(s=>n.matchesNode(t,s)):e.kind==="or"?e.children.some(s=>n.matchesNode(t,s)):!e.children.some(s=>n.matchesNode(t,s))}static resolveFieldValues(t,e){const s=e.split(".");let r=[t];for(const i of s){const o=[];for(const a of r)if(a!=null)if(Array.isArray(a))for(const c of a)c!=null&&o.push(c[i]);else o.push(a[i]);r=o}return r}static resolveFieldValue(t,e){const s=n.resolveFieldValues(t,e);return s.length===1?s[0]:s.length===0?void 0:s}static evaluateCondition(t,e){const s=n.resolveFieldValues(t,e.field);if(s.length>1)return s.some(i=>n.evaluateSingleCondition(i,e.operator,e.value));const r=s[0];return n.evaluateSingleCondition(r,e.operator,e.value)}static evaluateSingleCondition(t,e,s){switch(e){case"equals":return t===s;case"notEquals":return t!==s;case"in":return Array.isArray(s)&&s.includes(t);case"notIn":return Array.isArray(s)&&!s.includes(t);case"isNull":return t==null;case"isNotNull":return t!=null;case"contains":return typeof t=="string"&&typeof s=="string"&&t.toLowerCase().includes(s.toLowerCase());case"startsWith":return typeof t=="string"&&typeof s=="string"&&t.toLowerCase().startsWith(s.toLowerCase());case"endsWith":return typeof t=="string"&&typeof s=="string"&&t.toLowerCase().endsWith(s.toLowerCase());case"greaterThan":return n.compareValues(t,s)>0;case"greaterThanOrEquals":return n.compareValues(t,s)>=0;case"lessThan":return n.compareValues(t,s)<0;case"lessThanOrEquals":return n.compareValues(t,s)<=0;case"between":{if(!Array.isArray(s)||s.length!==2)return!1;const r=n.compareValues(t,s[0]),i=n.compareValues(t,s[1]);return r>=0&&i<=0}default:return!1}}static compareValues(t,e){return t==null?-1:e==null?1:t instanceof Date&&e instanceof Date?t.getTime()-e.getTime():typeof t=="number"&&typeof e=="number"?t-e:typeof t=="string"&&typeof e=="string"?t.localeCompare(e):String(t).localeCompare(String(e))}static sortRecords(t,e){return[...t].sort((s,r)=>{for(const i of e){const o=n.resolveFieldValue(s,i.field),a=n.resolveFieldValue(r,i.field);if(o===a)continue;if(o==null)return 1;if(a==null)return-1;const c=n.compareValues(o,a);if(c!==0)return i.direction==="desc"?-c:c}return 0})}}exports.MdqlMemoryExecutor=n;
|
|
2
|
+
//# sourceMappingURL=MdqlMemoryExecutor-BUlsalKm.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MdqlMemoryExecutor-BUlsalKm.cjs","sources":["../src/mdql/MdqlMemoryExecutor.ts"],"sourcesContent":["import type { Model } from '@mobx-data/model';\r\nimport type {\r\n MdqlCondition,\r\n MdqlFilterNode,\r\n MdqlQueryObject,\r\n MdqlOrderByClause,\r\n} from './types.js';\r\n\r\nexport class MdqlMemoryExecutor {\r\n static executeMany<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): T[] {\r\n let result = items.filter((record) =>\r\n MdqlMemoryExecutor.matchesNode(record, query.filters),\r\n );\r\n\r\n if (query.orderBy.length > 0) {\r\n result = MdqlMemoryExecutor.sortRecords(result, query.orderBy);\r\n }\r\n\r\n const offset = query.offset ?? 0;\r\n if (offset > 0 || query.limit !== null) {\r\n const end = query.limit !== null ? offset + query.limit : undefined;\r\n result = result.slice(offset, end);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n static executeOne<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): T | null {\r\n const results = MdqlMemoryExecutor.executeMany(items, query);\r\n return results[0] ?? null;\r\n }\r\n\r\n static count<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): number {\r\n let count = 0;\r\n for (const record of items) {\r\n if (MdqlMemoryExecutor.matchesNode(record, query.filters)) {\r\n count++;\r\n }\r\n }\r\n return count;\r\n }\r\n\r\n static exists<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): boolean {\r\n return items.some((record) =>\r\n MdqlMemoryExecutor.matchesNode(record, query.filters),\r\n );\r\n }\r\n\r\n static compilePredicate<T extends Model = Model>(\r\n query: MdqlQueryObject,\r\n ): (record: T) => boolean {\r\n return (record: T) => MdqlMemoryExecutor.matchesNode(record, query.filters);\r\n }\r\n\r\n private static matchesNode(record: Model, node: MdqlFilterNode): boolean {\r\n if (node.kind === 'condition') {\r\n return MdqlMemoryExecutor.evaluateCondition(record, node);\r\n }\r\n\r\n if (node.kind === 'and') {\r\n return node.children.every((child) =>\r\n MdqlMemoryExecutor.matchesNode(record, child),\r\n );\r\n }\r\n\r\n if (node.kind === 'or') {\r\n return node.children.some((child) =>\r\n MdqlMemoryExecutor.matchesNode(record, child),\r\n );\r\n }\r\n\r\n // not\r\n return !node.children.some((child) =>\r\n MdqlMemoryExecutor.matchesNode(record, child),\r\n );\r\n }\r\n\r\n private static resolveFieldValues(record: Model, field: string): unknown[] {\r\n const parts = field.split('.');\r\n let currentValues: unknown[] = [record];\r\n for (const part of parts) {\r\n const nextValues: unknown[] = [];\r\n for (const current of currentValues) {\r\n if (current === null || current === undefined) continue;\r\n if (Array.isArray(current)) {\r\n for (const item of current) {\r\n if (item === null || item === undefined) continue;\r\n nextValues.push((item as Record<string, unknown>)[part]);\r\n }\r\n } else {\r\n nextValues.push((current as Record<string, unknown>)[part]);\r\n }\r\n }\r\n currentValues = nextValues;\r\n }\r\n return currentValues;\r\n }\r\n\r\n private static resolveFieldValue(record: Model, field: string): unknown {\r\n const values = MdqlMemoryExecutor.resolveFieldValues(record, field);\r\n return values.length === 1 ? values[0] : values.length === 0 ? undefined : values;\r\n }\r\n\r\n private static evaluateCondition(record: Model, condition: MdqlCondition): boolean {\r\n const resolvedValues = MdqlMemoryExecutor.resolveFieldValues(record, condition.field);\r\n if (resolvedValues.length > 1) {\r\n return resolvedValues.some((fieldValue) =>\r\n MdqlMemoryExecutor.evaluateSingleCondition(fieldValue, condition.operator, condition.value),\r\n );\r\n }\r\n const fieldValue = resolvedValues[0];\r\n return MdqlMemoryExecutor.evaluateSingleCondition(fieldValue, condition.operator, condition.value);\r\n }\r\n\r\n private static evaluateSingleCondition(fieldValue: unknown, operator: string, value: unknown): boolean {\r\n switch (operator) {\r\n case 'equals':\r\n return fieldValue === value;\r\n\r\n case 'notEquals':\r\n return fieldValue !== value;\r\n\r\n case 'in':\r\n return Array.isArray(value) && value.includes(fieldValue);\r\n\r\n case 'notIn':\r\n return Array.isArray(value) && !value.includes(fieldValue);\r\n\r\n case 'isNull':\r\n return fieldValue === null || fieldValue === undefined;\r\n\r\n case 'isNotNull':\r\n return fieldValue !== null && fieldValue !== undefined;\r\n\r\n case 'contains':\r\n return typeof fieldValue === 'string'\r\n && typeof value === 'string'\r\n && fieldValue.toLowerCase().includes(value.toLowerCase());\r\n\r\n case 'startsWith':\r\n return typeof fieldValue === 'string'\r\n && typeof value === 'string'\r\n && fieldValue.toLowerCase().startsWith(value.toLowerCase());\r\n\r\n case 'endsWith':\r\n return typeof fieldValue === 'string'\r\n && typeof value === 'string'\r\n && fieldValue.toLowerCase().endsWith(value.toLowerCase());\r\n\r\n case 'greaterThan':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) > 0;\r\n\r\n case 'greaterThanOrEquals':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) >= 0;\r\n\r\n case 'lessThan':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) < 0;\r\n\r\n case 'lessThanOrEquals':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) <= 0;\r\n\r\n case 'between': {\r\n if (!Array.isArray(value) || value.length !== 2) return false;\r\n const lower = MdqlMemoryExecutor.compareValues(fieldValue, value[0]);\r\n const upper = MdqlMemoryExecutor.compareValues(fieldValue, value[1]);\r\n return lower >= 0 && upper <= 0;\r\n }\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n private static compareValues(a: unknown, b: unknown): number {\r\n if (a === null || a === undefined) return -1;\r\n if (b === null || b === undefined) return 1;\r\n\r\n if (a instanceof Date && b instanceof Date) {\r\n return a.getTime() - b.getTime();\r\n }\r\n\r\n if (typeof a === 'number' && typeof b === 'number') {\r\n return a - b;\r\n }\r\n\r\n if (typeof a === 'string' && typeof b === 'string') {\r\n return a.localeCompare(b);\r\n }\r\n\r\n return String(a).localeCompare(String(b));\r\n }\r\n\r\n private static sortRecords<T extends Model>(\r\n records: T[],\r\n orderBy: MdqlOrderByClause[],\r\n ): T[] {\r\n return [...records].sort((a, b) => {\r\n for (const clause of orderBy) {\r\n const valueA = MdqlMemoryExecutor.resolveFieldValue(a, clause.field);\r\n const valueB = MdqlMemoryExecutor.resolveFieldValue(b, clause.field);\r\n\r\n if (valueA === valueB) continue;\r\n\r\n // Nulls always sort last regardless of direction\r\n if (valueA === null || valueA === undefined) return 1;\r\n if (valueB === null || valueB === undefined) return -1;\r\n\r\n const comparison = MdqlMemoryExecutor.compareValues(valueA, valueB);\r\n if (comparison !== 0) {\r\n return clause.direction === 'desc' ? -comparison : comparison;\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n }\r\n}\r\n"],"names":["MdqlMemoryExecutor","items","query","result","record","offset","end","count","node","child","field","parts","currentValues","part","nextValues","current","item","values","condition","resolvedValues","fieldValue","operator","value","lower","upper","a","b","records","orderBy","clause","valueA","valueB","comparison"],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
class n {
|
|
2
|
+
static executeMany(t, e) {
|
|
3
|
+
let s = t.filter(
|
|
4
|
+
(i) => n.matchesNode(i, e.filters)
|
|
5
|
+
);
|
|
6
|
+
e.orderBy.length > 0 && (s = n.sortRecords(s, e.orderBy));
|
|
7
|
+
const r = e.offset ?? 0;
|
|
8
|
+
if (r > 0 || e.limit !== null) {
|
|
9
|
+
const i = e.limit !== null ? r + e.limit : void 0;
|
|
10
|
+
s = s.slice(r, i);
|
|
11
|
+
}
|
|
12
|
+
return s;
|
|
13
|
+
}
|
|
14
|
+
static executeOne(t, e) {
|
|
15
|
+
return n.executeMany(t, e)[0] ?? null;
|
|
16
|
+
}
|
|
17
|
+
static count(t, e) {
|
|
18
|
+
let s = 0;
|
|
19
|
+
for (const r of t)
|
|
20
|
+
n.matchesNode(r, e.filters) && s++;
|
|
21
|
+
return s;
|
|
22
|
+
}
|
|
23
|
+
static exists(t, e) {
|
|
24
|
+
return t.some(
|
|
25
|
+
(s) => n.matchesNode(s, e.filters)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
static compilePredicate(t) {
|
|
29
|
+
return (e) => n.matchesNode(e, t.filters);
|
|
30
|
+
}
|
|
31
|
+
static matchesNode(t, e) {
|
|
32
|
+
return e.kind === "condition" ? n.evaluateCondition(t, e) : e.kind === "and" ? e.children.every(
|
|
33
|
+
(s) => n.matchesNode(t, s)
|
|
34
|
+
) : e.kind === "or" ? e.children.some(
|
|
35
|
+
(s) => n.matchesNode(t, s)
|
|
36
|
+
) : !e.children.some(
|
|
37
|
+
(s) => n.matchesNode(t, s)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
static resolveFieldValues(t, e) {
|
|
41
|
+
const s = e.split(".");
|
|
42
|
+
let r = [t];
|
|
43
|
+
for (const i of s) {
|
|
44
|
+
const o = [];
|
|
45
|
+
for (const a of r)
|
|
46
|
+
if (a != null)
|
|
47
|
+
if (Array.isArray(a))
|
|
48
|
+
for (const c of a)
|
|
49
|
+
c != null && o.push(c[i]);
|
|
50
|
+
else
|
|
51
|
+
o.push(a[i]);
|
|
52
|
+
r = o;
|
|
53
|
+
}
|
|
54
|
+
return r;
|
|
55
|
+
}
|
|
56
|
+
static resolveFieldValue(t, e) {
|
|
57
|
+
const s = n.resolveFieldValues(t, e);
|
|
58
|
+
return s.length === 1 ? s[0] : s.length === 0 ? void 0 : s;
|
|
59
|
+
}
|
|
60
|
+
static evaluateCondition(t, e) {
|
|
61
|
+
const s = n.resolveFieldValues(t, e.field);
|
|
62
|
+
if (s.length > 1)
|
|
63
|
+
return s.some(
|
|
64
|
+
(i) => n.evaluateSingleCondition(i, e.operator, e.value)
|
|
65
|
+
);
|
|
66
|
+
const r = s[0];
|
|
67
|
+
return n.evaluateSingleCondition(r, e.operator, e.value);
|
|
68
|
+
}
|
|
69
|
+
static evaluateSingleCondition(t, e, s) {
|
|
70
|
+
switch (e) {
|
|
71
|
+
case "equals":
|
|
72
|
+
return t === s;
|
|
73
|
+
case "notEquals":
|
|
74
|
+
return t !== s;
|
|
75
|
+
case "in":
|
|
76
|
+
return Array.isArray(s) && s.includes(t);
|
|
77
|
+
case "notIn":
|
|
78
|
+
return Array.isArray(s) && !s.includes(t);
|
|
79
|
+
case "isNull":
|
|
80
|
+
return t == null;
|
|
81
|
+
case "isNotNull":
|
|
82
|
+
return t != null;
|
|
83
|
+
case "contains":
|
|
84
|
+
return typeof t == "string" && typeof s == "string" && t.toLowerCase().includes(s.toLowerCase());
|
|
85
|
+
case "startsWith":
|
|
86
|
+
return typeof t == "string" && typeof s == "string" && t.toLowerCase().startsWith(s.toLowerCase());
|
|
87
|
+
case "endsWith":
|
|
88
|
+
return typeof t == "string" && typeof s == "string" && t.toLowerCase().endsWith(s.toLowerCase());
|
|
89
|
+
case "greaterThan":
|
|
90
|
+
return n.compareValues(t, s) > 0;
|
|
91
|
+
case "greaterThanOrEquals":
|
|
92
|
+
return n.compareValues(t, s) >= 0;
|
|
93
|
+
case "lessThan":
|
|
94
|
+
return n.compareValues(t, s) < 0;
|
|
95
|
+
case "lessThanOrEquals":
|
|
96
|
+
return n.compareValues(t, s) <= 0;
|
|
97
|
+
case "between": {
|
|
98
|
+
if (!Array.isArray(s) || s.length !== 2) return !1;
|
|
99
|
+
const r = n.compareValues(t, s[0]), i = n.compareValues(t, s[1]);
|
|
100
|
+
return r >= 0 && i <= 0;
|
|
101
|
+
}
|
|
102
|
+
default:
|
|
103
|
+
return !1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
static compareValues(t, e) {
|
|
107
|
+
return t == null ? -1 : e == null ? 1 : t instanceof Date && e instanceof Date ? t.getTime() - e.getTime() : typeof t == "number" && typeof e == "number" ? t - e : typeof t == "string" && typeof e == "string" ? t.localeCompare(e) : String(t).localeCompare(String(e));
|
|
108
|
+
}
|
|
109
|
+
static sortRecords(t, e) {
|
|
110
|
+
return [...t].sort((s, r) => {
|
|
111
|
+
for (const i of e) {
|
|
112
|
+
const o = n.resolveFieldValue(s, i.field), a = n.resolveFieldValue(r, i.field);
|
|
113
|
+
if (o === a) continue;
|
|
114
|
+
if (o == null) return 1;
|
|
115
|
+
if (a == null) return -1;
|
|
116
|
+
const c = n.compareValues(o, a);
|
|
117
|
+
if (c !== 0)
|
|
118
|
+
return i.direction === "desc" ? -c : c;
|
|
119
|
+
}
|
|
120
|
+
return 0;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
n as M
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=MdqlMemoryExecutor-BWMP31zG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MdqlMemoryExecutor-BWMP31zG.js","sources":["../src/mdql/MdqlMemoryExecutor.ts"],"sourcesContent":["import type { Model } from '@mobx-data/model';\r\nimport type {\r\n MdqlCondition,\r\n MdqlFilterNode,\r\n MdqlQueryObject,\r\n MdqlOrderByClause,\r\n} from './types.js';\r\n\r\nexport class MdqlMemoryExecutor {\r\n static executeMany<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): T[] {\r\n let result = items.filter((record) =>\r\n MdqlMemoryExecutor.matchesNode(record, query.filters),\r\n );\r\n\r\n if (query.orderBy.length > 0) {\r\n result = MdqlMemoryExecutor.sortRecords(result, query.orderBy);\r\n }\r\n\r\n const offset = query.offset ?? 0;\r\n if (offset > 0 || query.limit !== null) {\r\n const end = query.limit !== null ? offset + query.limit : undefined;\r\n result = result.slice(offset, end);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n static executeOne<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): T | null {\r\n const results = MdqlMemoryExecutor.executeMany(items, query);\r\n return results[0] ?? null;\r\n }\r\n\r\n static count<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): number {\r\n let count = 0;\r\n for (const record of items) {\r\n if (MdqlMemoryExecutor.matchesNode(record, query.filters)) {\r\n count++;\r\n }\r\n }\r\n return count;\r\n }\r\n\r\n static exists<T extends Model = Model>(\r\n items: T[],\r\n query: MdqlQueryObject,\r\n ): boolean {\r\n return items.some((record) =>\r\n MdqlMemoryExecutor.matchesNode(record, query.filters),\r\n );\r\n }\r\n\r\n static compilePredicate<T extends Model = Model>(\r\n query: MdqlQueryObject,\r\n ): (record: T) => boolean {\r\n return (record: T) => MdqlMemoryExecutor.matchesNode(record, query.filters);\r\n }\r\n\r\n private static matchesNode(record: Model, node: MdqlFilterNode): boolean {\r\n if (node.kind === 'condition') {\r\n return MdqlMemoryExecutor.evaluateCondition(record, node);\r\n }\r\n\r\n if (node.kind === 'and') {\r\n return node.children.every((child) =>\r\n MdqlMemoryExecutor.matchesNode(record, child),\r\n );\r\n }\r\n\r\n if (node.kind === 'or') {\r\n return node.children.some((child) =>\r\n MdqlMemoryExecutor.matchesNode(record, child),\r\n );\r\n }\r\n\r\n // not\r\n return !node.children.some((child) =>\r\n MdqlMemoryExecutor.matchesNode(record, child),\r\n );\r\n }\r\n\r\n private static resolveFieldValues(record: Model, field: string): unknown[] {\r\n const parts = field.split('.');\r\n let currentValues: unknown[] = [record];\r\n for (const part of parts) {\r\n const nextValues: unknown[] = [];\r\n for (const current of currentValues) {\r\n if (current === null || current === undefined) continue;\r\n if (Array.isArray(current)) {\r\n for (const item of current) {\r\n if (item === null || item === undefined) continue;\r\n nextValues.push((item as Record<string, unknown>)[part]);\r\n }\r\n } else {\r\n nextValues.push((current as Record<string, unknown>)[part]);\r\n }\r\n }\r\n currentValues = nextValues;\r\n }\r\n return currentValues;\r\n }\r\n\r\n private static resolveFieldValue(record: Model, field: string): unknown {\r\n const values = MdqlMemoryExecutor.resolveFieldValues(record, field);\r\n return values.length === 1 ? values[0] : values.length === 0 ? undefined : values;\r\n }\r\n\r\n private static evaluateCondition(record: Model, condition: MdqlCondition): boolean {\r\n const resolvedValues = MdqlMemoryExecutor.resolveFieldValues(record, condition.field);\r\n if (resolvedValues.length > 1) {\r\n return resolvedValues.some((fieldValue) =>\r\n MdqlMemoryExecutor.evaluateSingleCondition(fieldValue, condition.operator, condition.value),\r\n );\r\n }\r\n const fieldValue = resolvedValues[0];\r\n return MdqlMemoryExecutor.evaluateSingleCondition(fieldValue, condition.operator, condition.value);\r\n }\r\n\r\n private static evaluateSingleCondition(fieldValue: unknown, operator: string, value: unknown): boolean {\r\n switch (operator) {\r\n case 'equals':\r\n return fieldValue === value;\r\n\r\n case 'notEquals':\r\n return fieldValue !== value;\r\n\r\n case 'in':\r\n return Array.isArray(value) && value.includes(fieldValue);\r\n\r\n case 'notIn':\r\n return Array.isArray(value) && !value.includes(fieldValue);\r\n\r\n case 'isNull':\r\n return fieldValue === null || fieldValue === undefined;\r\n\r\n case 'isNotNull':\r\n return fieldValue !== null && fieldValue !== undefined;\r\n\r\n case 'contains':\r\n return typeof fieldValue === 'string'\r\n && typeof value === 'string'\r\n && fieldValue.toLowerCase().includes(value.toLowerCase());\r\n\r\n case 'startsWith':\r\n return typeof fieldValue === 'string'\r\n && typeof value === 'string'\r\n && fieldValue.toLowerCase().startsWith(value.toLowerCase());\r\n\r\n case 'endsWith':\r\n return typeof fieldValue === 'string'\r\n && typeof value === 'string'\r\n && fieldValue.toLowerCase().endsWith(value.toLowerCase());\r\n\r\n case 'greaterThan':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) > 0;\r\n\r\n case 'greaterThanOrEquals':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) >= 0;\r\n\r\n case 'lessThan':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) < 0;\r\n\r\n case 'lessThanOrEquals':\r\n return MdqlMemoryExecutor.compareValues(fieldValue, value) <= 0;\r\n\r\n case 'between': {\r\n if (!Array.isArray(value) || value.length !== 2) return false;\r\n const lower = MdqlMemoryExecutor.compareValues(fieldValue, value[0]);\r\n const upper = MdqlMemoryExecutor.compareValues(fieldValue, value[1]);\r\n return lower >= 0 && upper <= 0;\r\n }\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n private static compareValues(a: unknown, b: unknown): number {\r\n if (a === null || a === undefined) return -1;\r\n if (b === null || b === undefined) return 1;\r\n\r\n if (a instanceof Date && b instanceof Date) {\r\n return a.getTime() - b.getTime();\r\n }\r\n\r\n if (typeof a === 'number' && typeof b === 'number') {\r\n return a - b;\r\n }\r\n\r\n if (typeof a === 'string' && typeof b === 'string') {\r\n return a.localeCompare(b);\r\n }\r\n\r\n return String(a).localeCompare(String(b));\r\n }\r\n\r\n private static sortRecords<T extends Model>(\r\n records: T[],\r\n orderBy: MdqlOrderByClause[],\r\n ): T[] {\r\n return [...records].sort((a, b) => {\r\n for (const clause of orderBy) {\r\n const valueA = MdqlMemoryExecutor.resolveFieldValue(a, clause.field);\r\n const valueB = MdqlMemoryExecutor.resolveFieldValue(b, clause.field);\r\n\r\n if (valueA === valueB) continue;\r\n\r\n // Nulls always sort last regardless of direction\r\n if (valueA === null || valueA === undefined) return 1;\r\n if (valueB === null || valueB === undefined) return -1;\r\n\r\n const comparison = MdqlMemoryExecutor.compareValues(valueA, valueB);\r\n if (comparison !== 0) {\r\n return clause.direction === 'desc' ? -comparison : comparison;\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n }\r\n}\r\n"],"names":["MdqlMemoryExecutor","items","query","result","record","offset","end","count","node","child","field","parts","currentValues","part","nextValues","current","item","values","condition","resolvedValues","fieldValue","operator","value","lower","upper","a","b","records","orderBy","clause","valueA","valueB","comparison"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { injectable as d } from "tsyringe";
|
|
2
|
-
import { A as f } from "./RestAdapter-
|
|
2
|
+
import { A as f } from "./RestAdapter-DYUoyV5h.js";
|
|
3
3
|
var p = Object.getOwnPropertyDescriptor, y = (s, t, e, r) => {
|
|
4
4
|
for (var n = r > 1 ? void 0 : r ? p(t, e) : t, o = s.length - 1, i; o >= 0; o--)
|
|
5
5
|
(i = s[o]) && (n = i(n) || n);
|
|
@@ -120,4 +120,4 @@ c = y([
|
|
|
120
120
|
export {
|
|
121
121
|
c as M
|
|
122
122
|
};
|
|
123
|
-
//# sourceMappingURL=MemoryAdapter-
|
|
123
|
+
//# sourceMappingURL=MemoryAdapter-BW1HKixm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemoryAdapter-ni25N4H0.js","sources":["../src/adapter/MemoryAdapter.ts"],"sourcesContent":["/**\n * In-memory adapter for testing and server-side rendering.\n *\n * `MemoryAdapter` stores records in plain `Map` structures with no network I/O.\n * It implements the full adapter interface (findRecord, findAll, findMany, query,\n * queryRecord, createRecord, updateRecord, deleteRecord) so it can serve as a\n * drop-in replacement for `RestAdapter` in unit tests or SSR hydration scenarios.\n *\n * Use `seed()` to pre-populate data and `reset()` to clear all state between\n * test cases.\n */\n\nimport { injectable } from 'tsyringe';\nimport { Adapter, type AdapterSnapshot } from './Adapter.js';\n\ninterface MemoryRecord {\n id: string;\n type: string;\n attributes: Record<string, unknown>;\n}\n\n@injectable()\nexport class MemoryAdapter extends Adapter {\n private storage: Map<string, Map<string, MemoryRecord>> = new Map();\n\n private nextId: Map<string, number> = new Map();\n\n private getCollection(modelName: string): Map<string, MemoryRecord> {\n let collection = this.storage.get(modelName);\n if (!collection) {\n collection = new Map();\n this.storage.set(modelName, collection);\n }\n return collection;\n }\n\n private generateId(modelName: string): string {\n const current = this.nextId.get(modelName) ?? 1;\n this.nextId.set(modelName, current + 1);\n return String(current);\n }\n\n /**\n * Pre-populates the adapter with records for a given model type.\n * Auto-increments the internal ID counter to avoid collisions with\n * subsequently created records.\n *\n * @param modelName - The model type to seed.\n * @param records - Array of plain objects; each must have an `id` key.\n */\n seed(modelName: string, records: Array<{ id: string; [key: string]: unknown }>): void {\n const collection = this.getCollection(modelName);\n for (const record of records) {\n const { id, ...attributes } = record;\n collection.set(id, { id, type: modelName, attributes });\n const numId = Number(id);\n if (!Number.isNaN(numId)) {\n const current = this.nextId.get(modelName) ?? 1;\n if (numId >= current) {\n this.nextId.set(modelName, numId + 1);\n }\n }\n }\n }\n\n /** Clears all stored records and resets ID counters. */\n reset(): void {\n this.storage.clear();\n this.nextId.clear();\n }\n\n override async findRecord(\n _store: unknown,\n modelName: string,\n id: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const record = collection.get(id);\n if (!record) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n return { data: { id: record.id, type: record.type, attributes: { ...record.attributes } } };\n }\n\n override async findAll(\n _store: unknown,\n modelName: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = Array.from(collection.values()).map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n override async findMany(\n _store: unknown,\n modelName: string,\n ids: string[],\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = ids\n .map((id) => collection.get(id))\n .filter((record): record is MemoryRecord => record !== undefined)\n .map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Filters records by exact attribute match on all query keys. */\n override async query(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const entries = Array.from(collection.values());\n const filtered = entries.filter((record) => {\n for (const [key, value] of Object.entries(query)) {\n if (record.attributes[key] !== value) {\n return false;\n }\n }\n return true;\n });\n const data = filtered.map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Returns the first record matching the query, or `null`. */\n override async queryRecord(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const result = await this.query(_store, modelName, query) as { data: unknown[] };\n return { data: result.data[0] ?? null };\n }\n\n private static safeAssign(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): void {\n for (const [key, value] of Object.entries(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n target[key] = value;\n }\n }\n\n override async createRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const id = this.generateId(modelName);\n const attributes: Record<string, unknown> = {};\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(attributes, record._data);\n }\n const entry: MemoryRecord = { id, type: modelName, attributes };\n this.getCollection(modelName).set(id, entry);\n return { data: { id, type: modelName, attributes: { ...attributes } } };\n }\n\n override async updateRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot update a record without an id');\n }\n const collection = this.getCollection(modelName);\n const existing = collection.get(id);\n if (!existing) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(existing.attributes, record._data);\n }\n return { data: { id, type: modelName, attributes: { ...existing.attributes } } };\n }\n\n override async deleteRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot delete a record without an id');\n }\n this.getCollection(modelName).delete(id);\n return null;\n }\n}\n"],"names":["MemoryAdapter","Adapter","modelName","collection","current","records","record","id","attributes","numId","_store","ids","query","key","value","target","source","snapshot","entry","existing","__decorateClass","injectable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MemoryAdapter-BW1HKixm.js","sources":["../src/adapter/MemoryAdapter.ts"],"sourcesContent":["/**\n * In-memory adapter for testing and server-side rendering.\n *\n * `MemoryAdapter` stores records in plain `Map` structures with no network I/O.\n * It implements the full adapter interface (findRecord, findAll, findMany, query,\n * queryRecord, createRecord, updateRecord, deleteRecord) so it can serve as a\n * drop-in replacement for `RestAdapter` in unit tests or SSR hydration scenarios.\n *\n * Use `seed()` to pre-populate data and `reset()` to clear all state between\n * test cases.\n */\n\nimport { injectable } from 'tsyringe';\nimport { Adapter, type AdapterSnapshot } from './Adapter.js';\n\ninterface MemoryRecord {\n id: string;\n type: string;\n attributes: Record<string, unknown>;\n}\n\n@injectable()\nexport class MemoryAdapter extends Adapter {\n private storage: Map<string, Map<string, MemoryRecord>> = new Map();\n\n private nextId: Map<string, number> = new Map();\n\n private getCollection(modelName: string): Map<string, MemoryRecord> {\n let collection = this.storage.get(modelName);\n if (!collection) {\n collection = new Map();\n this.storage.set(modelName, collection);\n }\n return collection;\n }\n\n private generateId(modelName: string): string {\n const current = this.nextId.get(modelName) ?? 1;\n this.nextId.set(modelName, current + 1);\n return String(current);\n }\n\n /**\n * Pre-populates the adapter with records for a given model type.\n * Auto-increments the internal ID counter to avoid collisions with\n * subsequently created records.\n *\n * @param modelName - The model type to seed.\n * @param records - Array of plain objects; each must have an `id` key.\n */\n seed(modelName: string, records: Array<{ id: string; [key: string]: unknown }>): void {\n const collection = this.getCollection(modelName);\n for (const record of records) {\n const { id, ...attributes } = record;\n collection.set(id, { id, type: modelName, attributes });\n const numId = Number(id);\n if (!Number.isNaN(numId)) {\n const current = this.nextId.get(modelName) ?? 1;\n if (numId >= current) {\n this.nextId.set(modelName, numId + 1);\n }\n }\n }\n }\n\n /** Clears all stored records and resets ID counters. */\n reset(): void {\n this.storage.clear();\n this.nextId.clear();\n }\n\n override async findRecord(\n _store: unknown,\n modelName: string,\n id: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const record = collection.get(id);\n if (!record) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n return { data: { id: record.id, type: record.type, attributes: { ...record.attributes } } };\n }\n\n override async findAll(\n _store: unknown,\n modelName: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = Array.from(collection.values()).map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n override async findMany(\n _store: unknown,\n modelName: string,\n ids: string[],\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = ids\n .map((id) => collection.get(id))\n .filter((record): record is MemoryRecord => record !== undefined)\n .map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Filters records by exact attribute match on all query keys. */\n override async query(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const entries = Array.from(collection.values());\n const filtered = entries.filter((record) => {\n for (const [key, value] of Object.entries(query)) {\n if (record.attributes[key] !== value) {\n return false;\n }\n }\n return true;\n });\n const data = filtered.map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Returns the first record matching the query, or `null`. */\n override async queryRecord(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const result = await this.query(_store, modelName, query) as { data: unknown[] };\n return { data: result.data[0] ?? null };\n }\n\n private static safeAssign(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): void {\n for (const [key, value] of Object.entries(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n target[key] = value;\n }\n }\n\n override async createRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const id = this.generateId(modelName);\n const attributes: Record<string, unknown> = {};\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(attributes, record._data);\n }\n const entry: MemoryRecord = { id, type: modelName, attributes };\n this.getCollection(modelName).set(id, entry);\n return { data: { id, type: modelName, attributes: { ...attributes } } };\n }\n\n override async updateRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot update a record without an id');\n }\n const collection = this.getCollection(modelName);\n const existing = collection.get(id);\n if (!existing) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(existing.attributes, record._data);\n }\n return { data: { id, type: modelName, attributes: { ...existing.attributes } } };\n }\n\n override async deleteRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot delete a record without an id');\n }\n this.getCollection(modelName).delete(id);\n return null;\n }\n}\n"],"names":["MemoryAdapter","Adapter","modelName","collection","current","records","record","id","attributes","numId","_store","ids","query","key","value","target","source","snapshot","entry","existing","__decorateClass","injectable"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const l=require("tsyringe"),y=require("./RestAdapter-
|
|
2
|
-
//# sourceMappingURL=MemoryAdapter-
|
|
1
|
+
"use strict";const l=require("tsyringe"),y=require("./RestAdapter-D7GSrsJo.cjs");var p=Object.getOwnPropertyDescriptor,f=(c,s,t,e)=>{for(var r=e>1?void 0:e?p(s,t):s,n=c.length-1,o;n>=0;n--)(o=c[n])&&(r=o(r)||r);return r};exports.MemoryAdapter=class extends y.Adapter{constructor(){super(...arguments),this.storage=new Map,this.nextId=new Map}getCollection(s){let t=this.storage.get(s);return t||(t=new Map,this.storage.set(s,t)),t}generateId(s){const t=this.nextId.get(s)??1;return this.nextId.set(s,t+1),String(t)}seed(s,t){const e=this.getCollection(s);for(const r of t){const{id:n,...o}=r;e.set(n,{id:n,type:s,attributes:o});const i=Number(n);if(!Number.isNaN(i)){const a=this.nextId.get(s)??1;i>=a&&this.nextId.set(s,i+1)}}}reset(){this.storage.clear(),this.nextId.clear()}async findRecord(s,t,e){const n=this.getCollection(t).get(e);if(!n)throw Object.assign(new Error(`Record not found: ${t}:${e}`),{status:404});return{data:{id:n.id,type:n.type,attributes:{...n.attributes}}}}async findAll(s,t){const e=this.getCollection(t);return{data:Array.from(e.values()).map(n=>({id:n.id,type:n.type,attributes:{...n.attributes}}))}}async findMany(s,t,e){const r=this.getCollection(t);return{data:e.map(o=>r.get(o)).filter(o=>o!==void 0).map(o=>({id:o.id,type:o.type,attributes:{...o.attributes}}))}}async query(s,t,e){const r=this.getCollection(t);return{data:Array.from(r.values()).filter(a=>{for(const[u,d]of Object.entries(e))if(a.attributes[u]!==d)return!1;return!0}).map(a=>({id:a.id,type:a.type,attributes:{...a.attributes}}))}}async queryRecord(s,t,e){return{data:(await this.query(s,t,e)).data[0]??null}}static safeAssign(s,t){for(const[e,r]of Object.entries(t))e==="__proto__"||e==="constructor"||e==="prototype"||(s[e]=r)}async createRecord(s,t,e){const r=this.generateId(t),n={},o=e.record;o._data&&exports.MemoryAdapter.safeAssign(n,o._data);const i={id:r,type:t,attributes:n};return this.getCollection(t).set(r,i),{data:{id:r,type:t,attributes:{...n}}}}async updateRecord(s,t,e){const{id:r}=e;if(!r)throw new Error("Cannot update a record without an id");const o=this.getCollection(t).get(r);if(!o)throw Object.assign(new Error(`Record not found: ${t}:${r}`),{status:404});const i=e.record;return i._data&&exports.MemoryAdapter.safeAssign(o.attributes,i._data),{data:{id:r,type:t,attributes:{...o.attributes}}}}async deleteRecord(s,t,e){const{id:r}=e;if(!r)throw new Error("Cannot delete a record without an id");return this.getCollection(t).delete(r),null}};exports.MemoryAdapter=f([l.injectable()],exports.MemoryAdapter);
|
|
2
|
+
//# sourceMappingURL=MemoryAdapter-C8iXAa2v.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemoryAdapter-BTK2D64s.cjs","sources":["../src/adapter/MemoryAdapter.ts"],"sourcesContent":["/**\n * In-memory adapter for testing and server-side rendering.\n *\n * `MemoryAdapter` stores records in plain `Map` structures with no network I/O.\n * It implements the full adapter interface (findRecord, findAll, findMany, query,\n * queryRecord, createRecord, updateRecord, deleteRecord) so it can serve as a\n * drop-in replacement for `RestAdapter` in unit tests or SSR hydration scenarios.\n *\n * Use `seed()` to pre-populate data and `reset()` to clear all state between\n * test cases.\n */\n\nimport { injectable } from 'tsyringe';\nimport { Adapter, type AdapterSnapshot } from './Adapter.js';\n\ninterface MemoryRecord {\n id: string;\n type: string;\n attributes: Record<string, unknown>;\n}\n\n@injectable()\nexport class MemoryAdapter extends Adapter {\n private storage: Map<string, Map<string, MemoryRecord>> = new Map();\n\n private nextId: Map<string, number> = new Map();\n\n private getCollection(modelName: string): Map<string, MemoryRecord> {\n let collection = this.storage.get(modelName);\n if (!collection) {\n collection = new Map();\n this.storage.set(modelName, collection);\n }\n return collection;\n }\n\n private generateId(modelName: string): string {\n const current = this.nextId.get(modelName) ?? 1;\n this.nextId.set(modelName, current + 1);\n return String(current);\n }\n\n /**\n * Pre-populates the adapter with records for a given model type.\n * Auto-increments the internal ID counter to avoid collisions with\n * subsequently created records.\n *\n * @param modelName - The model type to seed.\n * @param records - Array of plain objects; each must have an `id` key.\n */\n seed(modelName: string, records: Array<{ id: string; [key: string]: unknown }>): void {\n const collection = this.getCollection(modelName);\n for (const record of records) {\n const { id, ...attributes } = record;\n collection.set(id, { id, type: modelName, attributes });\n const numId = Number(id);\n if (!Number.isNaN(numId)) {\n const current = this.nextId.get(modelName) ?? 1;\n if (numId >= current) {\n this.nextId.set(modelName, numId + 1);\n }\n }\n }\n }\n\n /** Clears all stored records and resets ID counters. */\n reset(): void {\n this.storage.clear();\n this.nextId.clear();\n }\n\n override async findRecord(\n _store: unknown,\n modelName: string,\n id: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const record = collection.get(id);\n if (!record) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n return { data: { id: record.id, type: record.type, attributes: { ...record.attributes } } };\n }\n\n override async findAll(\n _store: unknown,\n modelName: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = Array.from(collection.values()).map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n override async findMany(\n _store: unknown,\n modelName: string,\n ids: string[],\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = ids\n .map((id) => collection.get(id))\n .filter((record): record is MemoryRecord => record !== undefined)\n .map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Filters records by exact attribute match on all query keys. */\n override async query(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const entries = Array.from(collection.values());\n const filtered = entries.filter((record) => {\n for (const [key, value] of Object.entries(query)) {\n if (record.attributes[key] !== value) {\n return false;\n }\n }\n return true;\n });\n const data = filtered.map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Returns the first record matching the query, or `null`. */\n override async queryRecord(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const result = await this.query(_store, modelName, query) as { data: unknown[] };\n return { data: result.data[0] ?? null };\n }\n\n private static safeAssign(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): void {\n for (const [key, value] of Object.entries(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n target[key] = value;\n }\n }\n\n override async createRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const id = this.generateId(modelName);\n const attributes: Record<string, unknown> = {};\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(attributes, record._data);\n }\n const entry: MemoryRecord = { id, type: modelName, attributes };\n this.getCollection(modelName).set(id, entry);\n return { data: { id, type: modelName, attributes: { ...attributes } } };\n }\n\n override async updateRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot update a record without an id');\n }\n const collection = this.getCollection(modelName);\n const existing = collection.get(id);\n if (!existing) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(existing.attributes, record._data);\n }\n return { data: { id, type: modelName, attributes: { ...existing.attributes } } };\n }\n\n override async deleteRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot delete a record without an id');\n }\n this.getCollection(modelName).delete(id);\n return null;\n }\n}\n"],"names":["MemoryAdapter","Adapter","modelName","collection","current","records","record","id","attributes","numId","_store","ids","query","key","value","target","source","snapshot","entry","existing","__decorateClass","injectable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MemoryAdapter-C8iXAa2v.cjs","sources":["../src/adapter/MemoryAdapter.ts"],"sourcesContent":["/**\n * In-memory adapter for testing and server-side rendering.\n *\n * `MemoryAdapter` stores records in plain `Map` structures with no network I/O.\n * It implements the full adapter interface (findRecord, findAll, findMany, query,\n * queryRecord, createRecord, updateRecord, deleteRecord) so it can serve as a\n * drop-in replacement for `RestAdapter` in unit tests or SSR hydration scenarios.\n *\n * Use `seed()` to pre-populate data and `reset()` to clear all state between\n * test cases.\n */\n\nimport { injectable } from 'tsyringe';\nimport { Adapter, type AdapterSnapshot } from './Adapter.js';\n\ninterface MemoryRecord {\n id: string;\n type: string;\n attributes: Record<string, unknown>;\n}\n\n@injectable()\nexport class MemoryAdapter extends Adapter {\n private storage: Map<string, Map<string, MemoryRecord>> = new Map();\n\n private nextId: Map<string, number> = new Map();\n\n private getCollection(modelName: string): Map<string, MemoryRecord> {\n let collection = this.storage.get(modelName);\n if (!collection) {\n collection = new Map();\n this.storage.set(modelName, collection);\n }\n return collection;\n }\n\n private generateId(modelName: string): string {\n const current = this.nextId.get(modelName) ?? 1;\n this.nextId.set(modelName, current + 1);\n return String(current);\n }\n\n /**\n * Pre-populates the adapter with records for a given model type.\n * Auto-increments the internal ID counter to avoid collisions with\n * subsequently created records.\n *\n * @param modelName - The model type to seed.\n * @param records - Array of plain objects; each must have an `id` key.\n */\n seed(modelName: string, records: Array<{ id: string; [key: string]: unknown }>): void {\n const collection = this.getCollection(modelName);\n for (const record of records) {\n const { id, ...attributes } = record;\n collection.set(id, { id, type: modelName, attributes });\n const numId = Number(id);\n if (!Number.isNaN(numId)) {\n const current = this.nextId.get(modelName) ?? 1;\n if (numId >= current) {\n this.nextId.set(modelName, numId + 1);\n }\n }\n }\n }\n\n /** Clears all stored records and resets ID counters. */\n reset(): void {\n this.storage.clear();\n this.nextId.clear();\n }\n\n override async findRecord(\n _store: unknown,\n modelName: string,\n id: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const record = collection.get(id);\n if (!record) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n return { data: { id: record.id, type: record.type, attributes: { ...record.attributes } } };\n }\n\n override async findAll(\n _store: unknown,\n modelName: string,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = Array.from(collection.values()).map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n override async findMany(\n _store: unknown,\n modelName: string,\n ids: string[],\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const data = ids\n .map((id) => collection.get(id))\n .filter((record): record is MemoryRecord => record !== undefined)\n .map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Filters records by exact attribute match on all query keys. */\n override async query(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const collection = this.getCollection(modelName);\n const entries = Array.from(collection.values());\n const filtered = entries.filter((record) => {\n for (const [key, value] of Object.entries(query)) {\n if (record.attributes[key] !== value) {\n return false;\n }\n }\n return true;\n });\n const data = filtered.map((record) => ({\n id: record.id,\n type: record.type,\n attributes: { ...record.attributes },\n }));\n return { data };\n }\n\n /** Returns the first record matching the query, or `null`. */\n override async queryRecord(\n _store: unknown,\n modelName: string,\n query: Record<string, unknown>,\n ): Promise<unknown> {\n const result = await this.query(_store, modelName, query) as { data: unknown[] };\n return { data: result.data[0] ?? null };\n }\n\n private static safeAssign(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): void {\n for (const [key, value] of Object.entries(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n target[key] = value;\n }\n }\n\n override async createRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const id = this.generateId(modelName);\n const attributes: Record<string, unknown> = {};\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(attributes, record._data);\n }\n const entry: MemoryRecord = { id, type: modelName, attributes };\n this.getCollection(modelName).set(id, entry);\n return { data: { id, type: modelName, attributes: { ...attributes } } };\n }\n\n override async updateRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot update a record without an id');\n }\n const collection = this.getCollection(modelName);\n const existing = collection.get(id);\n if (!existing) {\n throw Object.assign(\n new Error(`Record not found: ${modelName}:${id}`),\n { status: 404 },\n );\n }\n const record = snapshot.record as { _data?: Record<string, unknown> };\n if (record._data) {\n MemoryAdapter.safeAssign(existing.attributes, record._data);\n }\n return { data: { id, type: modelName, attributes: { ...existing.attributes } } };\n }\n\n override async deleteRecord(\n _store: unknown,\n modelName: string,\n snapshot: AdapterSnapshot,\n ): Promise<unknown> {\n const { id } = snapshot;\n if (!id) {\n throw new Error('Cannot delete a record without an id');\n }\n this.getCollection(modelName).delete(id);\n return null;\n }\n}\n"],"names":["MemoryAdapter","Adapter","modelName","collection","current","records","record","id","attributes","numId","_store","ids","query","key","value","target","source","snapshot","entry","existing","__decorateClass","injectable"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { injectable as u } from "tsyringe";
|
|
2
2
|
import h from "pluralize";
|
|
3
|
-
import { R as l, p } from "./RestAdapter-
|
|
4
|
-
var y = Object.getOwnPropertyDescriptor,
|
|
5
|
-
for (var
|
|
6
|
-
(a = t[n]) && (
|
|
7
|
-
return
|
|
3
|
+
import { R as l, c as p } from "./RestAdapter-DYUoyV5h.js";
|
|
4
|
+
var y = Object.getOwnPropertyDescriptor, _ = (t, r, e, o) => {
|
|
5
|
+
for (var s = o > 1 ? void 0 : o ? y(r, e) : r, n = t.length - 1, a; n >= 0; n--)
|
|
6
|
+
(a = t[n]) && (s = a(s) || s);
|
|
7
|
+
return s;
|
|
8
8
|
};
|
|
9
9
|
const d = /* @__PURE__ */ new Set([
|
|
10
10
|
"$filter",
|
|
@@ -73,15 +73,15 @@ let i = class extends l {
|
|
|
73
73
|
* Builds a `$filter=id eq X or id eq Y` expression so only one HTTP round-trip
|
|
74
74
|
* is needed regardless of how many ids are requested.
|
|
75
75
|
*/
|
|
76
|
-
async findMany(t, r, e,
|
|
77
|
-
const
|
|
76
|
+
async findMany(t, r, e, o) {
|
|
77
|
+
const s = this.buildURL(r, e, o, "findMany"), n = e.map((c) => `id eq ${this.encodeKey(c)}`).join(" or "), a = `${s}?${this._toQueryString({ $filter: n })}`;
|
|
78
78
|
return this._fetchJSON(a, {
|
|
79
79
|
method: "GET",
|
|
80
80
|
headers: this.defaultHeaders()
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
async query(t, r, e) {
|
|
84
|
-
const
|
|
84
|
+
const o = this.buildURL(r, null, null, "query", e), s = this._normalizeQuery(e), n = `${o}${this._appendQuery(s)}`;
|
|
85
85
|
return this._fetchJSON(n, {
|
|
86
86
|
method: "GET",
|
|
87
87
|
headers: this.defaultHeaders()
|
|
@@ -92,7 +92,7 @@ let i = class extends l {
|
|
|
92
92
|
* The caller is responsible for picking the first element from the returned `value` array.
|
|
93
93
|
*/
|
|
94
94
|
async queryRecord(t, r, e) {
|
|
95
|
-
const
|
|
95
|
+
const o = this.buildURL(r, null, null, "queryRecord", e), s = { ...this._normalizeQuery(e), $top: 1 }, n = `${o}${this._appendQuery(s)}`;
|
|
96
96
|
return this._fetchJSON(n, {
|
|
97
97
|
method: "GET",
|
|
98
98
|
headers: this.defaultHeaders()
|
|
@@ -100,8 +100,8 @@ let i = class extends l {
|
|
|
100
100
|
}
|
|
101
101
|
/** Sends a PATCH request (partial update) as required by the OData v4 spec. */
|
|
102
102
|
async updateRecord(t, r, e) {
|
|
103
|
-
const
|
|
104
|
-
return this._fetchJSON(
|
|
103
|
+
const o = this.buildURL(r, e.id, e, "updateRecord");
|
|
104
|
+
return this._fetchJSON(o, {
|
|
105
105
|
method: "PATCH",
|
|
106
106
|
headers: this.mutationHeaders(),
|
|
107
107
|
body: JSON.stringify(this._serializeSnapshot(e))
|
|
@@ -109,10 +109,10 @@ let i = class extends l {
|
|
|
109
109
|
}
|
|
110
110
|
/** Sends a PATCH request with only the changed attributes (partial update). */
|
|
111
111
|
async patchRecord(t, r, e) {
|
|
112
|
-
const
|
|
113
|
-
for (const [a, [, c]] of Object.entries(
|
|
112
|
+
const o = this.buildURL(r, e.id, e, "updateRecord"), s = e.changedAttributes(), n = {};
|
|
113
|
+
for (const [a, [, c]] of Object.entries(s))
|
|
114
114
|
n[a] = c;
|
|
115
|
-
return this._fetchJSON(
|
|
115
|
+
return this._fetchJSON(o, {
|
|
116
116
|
method: "PATCH",
|
|
117
117
|
headers: this.mutationHeaders(),
|
|
118
118
|
body: JSON.stringify(n)
|
|
@@ -120,8 +120,11 @@ let i = class extends l {
|
|
|
120
120
|
}
|
|
121
121
|
/** Extracts the raw attribute map from the snapshot's internal record. */
|
|
122
122
|
_serializeSnapshot(t) {
|
|
123
|
-
const e = t.record._data,
|
|
124
|
-
|
|
123
|
+
const e = t.record._data, o = {};
|
|
124
|
+
if (e)
|
|
125
|
+
for (const s of Object.keys(e))
|
|
126
|
+
s === "__proto__" || s === "constructor" || s === "prototype" || (o[s] = e[s]);
|
|
127
|
+
return o;
|
|
125
128
|
}
|
|
126
129
|
/**
|
|
127
130
|
* Normalises a query hash so every OData system option has its `$` prefix.
|
|
@@ -131,15 +134,15 @@ let i = class extends l {
|
|
|
131
134
|
*/
|
|
132
135
|
_normalizeQuery(t) {
|
|
133
136
|
const r = {};
|
|
134
|
-
for (const [e,
|
|
135
|
-
|
|
137
|
+
for (const [e, o] of Object.entries(t))
|
|
138
|
+
o != null && (d.has(e) ? r[e] = o : d.has(`$${e}`) ? r[`$${e}`] = o : r[e] = o);
|
|
136
139
|
return r;
|
|
137
140
|
}
|
|
138
141
|
/** Serialises a key→value map to a `key=value&…` query string (percent-encoded). */
|
|
139
142
|
_toQueryString(t) {
|
|
140
143
|
const r = [];
|
|
141
|
-
for (const [e,
|
|
142
|
-
|
|
144
|
+
for (const [e, o] of Object.entries(t))
|
|
145
|
+
o != null && r.push(`${encodeURIComponent(e)}=${encodeURIComponent(String(o))}`);
|
|
143
146
|
return r.join("&");
|
|
144
147
|
}
|
|
145
148
|
/** Returns `?key=value&…` when the query is non-empty, or an empty string. */
|
|
@@ -148,10 +151,10 @@ let i = class extends l {
|
|
|
148
151
|
return r ? `?${r}` : "";
|
|
149
152
|
}
|
|
150
153
|
};
|
|
151
|
-
i =
|
|
154
|
+
i = _([
|
|
152
155
|
u()
|
|
153
156
|
], i);
|
|
154
157
|
export {
|
|
155
158
|
i as O
|
|
156
159
|
};
|
|
157
|
-
//# sourceMappingURL=ODataAdapter-
|
|
160
|
+
//# sourceMappingURL=ODataAdapter-CeBJblLQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ODataAdapter-CeBJblLQ.js","sources":["../src/odata/ODataAdapter.ts"],"sourcesContent":["import { injectable } from 'tsyringe';\r\nimport pluralize from 'pluralize';\r\nimport { pascalCase } from 'change-case';\r\nimport { RestAdapter } from '@mobx-data/adapter';\r\nimport type { AdapterSnapshot } from '@mobx-data/adapter';\r\n\r\n/** All OData v4 system query option names (both bare and $-prefixed forms are checked). */\r\nconst ODATA_SYSTEM_QUERY_OPTIONS = new Set([\r\n '$filter',\r\n '$select',\r\n '$orderby',\r\n '$top',\r\n '$skip',\r\n '$expand',\r\n '$count',\r\n '$search',\r\n '$format',\r\n '$skiptoken',\r\n]);\r\n\r\n/**\r\n * OData v4 adapter.\r\n *\r\n * Extends `RestAdapter` with OData-specific conventions:\r\n * - Entity-set names are PascalCase plural (`user` → `Users`).\r\n * - Single-entity URLs use key-in-parentheses syntax (`Users(1)`, `Users('abc')`).\r\n * - Mutations use PATCH instead of PUT.\r\n * - Accept / Content-Type headers carry the `odata.metadata=minimal` parameter.\r\n * - System query options (`$filter`, `$expand`, etc.) are passed through verbatim;\r\n * bare names are auto-prefixed (`filter` → `$filter`).\r\n */\r\n@injectable()\r\nexport class ODataAdapter extends RestAdapter {\r\n /** OData protocol version sent in `OData-Version` and `OData-MaxVersion` headers. */\r\n odataVersion: string = '4.0';\r\n\r\n static isNumericKey(id: string): boolean {\r\n return /^-?\\d+(?:\\.\\d+)?$/.test(id);\r\n }\r\n\r\n static escapeODataString(value: string): string {\r\n return value.replace(/'/g, \"''\");\r\n }\r\n\r\n override defaultHeaders(): Record<string, string> {\r\n return {\r\n Accept: 'application/json;odata.metadata=minimal',\r\n 'OData-Version': this.odataVersion,\r\n 'OData-MaxVersion': this.odataVersion,\r\n ...this.headers,\r\n };\r\n }\r\n\r\n override mutationHeaders(): Record<string, string> {\r\n return {\r\n 'Content-Type': 'application/json;odata.metadata=minimal',\r\n ...this.defaultHeaders(),\r\n };\r\n }\r\n\r\n /**\r\n * Maps a camelCase/dasherized model name to a PascalCase plural entity-set name.\r\n * @example `pathForType('orderItem')` → `'OrderItems'`\r\n */\r\n override pathForType(modelName: string): string {\r\n return pascalCase(pluralize.plural(modelName));\r\n }\r\n\r\n /**\r\n * Encodes a record id as an OData key literal.\r\n * Numeric ids are returned bare (`1`); string ids are single-quoted with\r\n * inner apostrophes escaped (`o'brien` → `'o''brien'`).\r\n *\r\n * Override this method when the service uses a non-default key format (e.g. GUIDs).\r\n */\r\n encodeKey(id: string): string {\r\n if (ODataAdapter.isNumericKey(id)) {\r\n return id;\r\n }\r\n return `'${ODataAdapter.escapeODataString(id)}'`;\r\n }\r\n\r\n override urlForFindRecord(\r\n id: string,\r\n modelName: string,\r\n _snapshot: AdapterSnapshot,\r\n ): string {\r\n return this._composeURL(`${this.pathForType(modelName)}(${this.encodeKey(id)})`);\r\n }\r\n\r\n override urlForUpdateRecord(\r\n id: string,\r\n modelName: string,\r\n _snapshot: AdapterSnapshot,\r\n ): string {\r\n return this._composeURL(`${this.pathForType(modelName)}(${this.encodeKey(id)})`);\r\n }\r\n\r\n override urlForDeleteRecord(\r\n id: string,\r\n modelName: string,\r\n _snapshot: AdapterSnapshot,\r\n ): string {\r\n return this._composeURL(`${this.pathForType(modelName)}(${this.encodeKey(id)})`);\r\n }\r\n\r\n /**\r\n * Fetches multiple records by id using a single request.\r\n * Builds a `$filter=id eq X or id eq Y` expression so only one HTTP round-trip\r\n * is needed regardless of how many ids are requested.\r\n */\r\n override async findMany(\r\n _store: unknown,\r\n modelName: string,\r\n ids: string[],\r\n snapshots: AdapterSnapshot[],\r\n ): Promise<unknown> {\r\n const base = this.buildURL(modelName, ids, snapshots, 'findMany');\r\n const filter = ids.map((id) => `id eq ${this.encodeKey(id)}`).join(' or ');\r\n const url = `${base}?${this._toQueryString({ $filter: filter })}`;\r\n return this._fetchJSON(url, {\r\n method: 'GET',\r\n headers: this.defaultHeaders(),\r\n });\r\n }\r\n\r\n override async query(\r\n _store: unknown,\r\n modelName: string,\r\n query: Record<string, unknown>,\r\n ): Promise<unknown> {\r\n const base = this.buildURL(modelName, null, null, 'query', query);\r\n const normalized = this._normalizeQuery(query);\r\n const url = `${base}${this._appendQuery(normalized)}`;\r\n return this._fetchJSON(url, {\r\n method: 'GET',\r\n headers: this.defaultHeaders(),\r\n });\r\n }\r\n\r\n /**\r\n * Queries for a single record by appending `$top=1` to whatever filter is provided.\r\n * The caller is responsible for picking the first element from the returned `value` array.\r\n */\r\n override async queryRecord(\r\n _store: unknown,\r\n modelName: string,\r\n query: Record<string, unknown>,\r\n ): Promise<unknown> {\r\n const base = this.buildURL(modelName, null, null, 'queryRecord', query);\r\n const normalized = { ...this._normalizeQuery(query), $top: 1 };\r\n const url = `${base}${this._appendQuery(normalized)}`;\r\n return this._fetchJSON(url, {\r\n method: 'GET',\r\n headers: this.defaultHeaders(),\r\n });\r\n }\r\n\r\n /** Sends a PATCH request (partial update) as required by the OData v4 spec. */\r\n override async updateRecord(\r\n _store: unknown,\r\n modelName: string,\r\n snapshot: AdapterSnapshot,\r\n ): Promise<unknown> {\r\n const url = this.buildURL(modelName, snapshot.id, snapshot, 'updateRecord');\r\n return this._fetchJSON(url, {\r\n method: 'PATCH',\r\n headers: this.mutationHeaders(),\r\n body: JSON.stringify(this._serializeSnapshot(snapshot)),\r\n });\r\n }\r\n\r\n /** Sends a PATCH request with only the changed attributes (partial update). */\r\n override async patchRecord(\r\n _store: unknown,\r\n modelName: string,\r\n snapshot: AdapterSnapshot,\r\n ): Promise<unknown> {\r\n const url = this.buildURL(modelName, snapshot.id, snapshot, 'updateRecord');\r\n const changed = snapshot.changedAttributes();\r\n const partial: Record<string, unknown> = {};\r\n for (const [key, [, current]] of Object.entries(changed)) {\r\n partial[key] = current;\r\n }\r\n return this._fetchJSON(url, {\r\n method: 'PATCH',\r\n headers: this.mutationHeaders(),\r\n body: JSON.stringify(partial),\r\n });\r\n }\r\n\r\n /** Extracts the raw attribute map from the snapshot's internal record. */\r\n protected _serializeSnapshot(snapshot: AdapterSnapshot): Record<string, unknown> {\r\n const record = snapshot.record as { _data?: Record<string, unknown> };\r\n const data = record._data;\r\n const body: Record<string, unknown> = {};\r\n if (data) {\r\n for (const key of Object.keys(data)) {\r\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\r\n body[key] = data[key];\r\n }\r\n }\r\n return body;\r\n }\r\n\r\n /**\r\n * Normalises a query hash so every OData system option has its `$` prefix.\r\n * Bare names (`filter`, `top`, `expand`) are prefixed automatically.\r\n * Custom (non-system) keys are forwarded verbatim.\r\n * `null` and `undefined` values are dropped.\r\n */\r\n protected _normalizeQuery(\r\n query: Record<string, unknown>,\r\n ): Record<string, unknown> {\r\n const normalized: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(query)) {\r\n if (value === undefined || value === null) {\r\n continue;\r\n }\r\n if (ODATA_SYSTEM_QUERY_OPTIONS.has(key)) {\r\n normalized[key] = value;\r\n } else if (ODATA_SYSTEM_QUERY_OPTIONS.has(`$${key}`)) {\r\n normalized[`$${key}`] = value;\r\n } else {\r\n normalized[key] = value;\r\n }\r\n }\r\n return normalized;\r\n }\r\n\r\n /** Serialises a key→value map to a `key=value&…` query string (percent-encoded). */\r\n protected _toQueryString(query: Record<string, unknown>): string {\r\n const parts: string[] = [];\r\n for (const [key, value] of Object.entries(query)) {\r\n if (value === undefined || value === null) {\r\n continue;\r\n }\r\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\r\n }\r\n return parts.join('&');\r\n }\r\n\r\n /** Returns `?key=value&…` when the query is non-empty, or an empty string. */\r\n protected _appendQuery(query: Record<string, unknown>): string {\r\n const queryString = this._toQueryString(query);\r\n return queryString ? `?${queryString}` : '';\r\n }\r\n}\r\n"],"names":["ODATA_SYSTEM_QUERY_OPTIONS","ODataAdapter","RestAdapter","id","value","modelName","pascalCase","pluralize","_snapshot","_store","ids","snapshots","base","filter","url","query","normalized","snapshot","changed","partial","key","current","data","body","parts","queryString","__decorateClass","injectable"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const h=require("tsyringe"),l=require("pluralize"),d=require("./RestAdapter-
|
|
2
|
-
//# sourceMappingURL=ODataAdapter-
|
|
1
|
+
"use strict";const h=require("tsyringe"),l=require("pluralize"),d=require("./RestAdapter-D7GSrsJo.cjs");var p=Object.getOwnPropertyDescriptor,y=(n,t,r,e)=>{for(var s=e>1?void 0:e?p(t,r):t,a=n.length-1,o;a>=0;a--)(o=n[a])&&(s=o(s)||s);return s};const u=new Set(["$filter","$select","$orderby","$top","$skip","$expand","$count","$search","$format","$skiptoken"]);exports.ODataAdapter=class extends d.RestAdapter{constructor(){super(...arguments),this.odataVersion="4.0"}static isNumericKey(t){return/^-?\d+(?:\.\d+)?$/.test(t)}static escapeODataString(t){return t.replace(/'/g,"''")}defaultHeaders(){return{Accept:"application/json;odata.metadata=minimal","OData-Version":this.odataVersion,"OData-MaxVersion":this.odataVersion,...this.headers}}mutationHeaders(){return{"Content-Type":"application/json;odata.metadata=minimal",...this.defaultHeaders()}}pathForType(t){return d.pascalCase(l.plural(t))}encodeKey(t){return exports.ODataAdapter.isNumericKey(t)?t:`'${exports.ODataAdapter.escapeODataString(t)}'`}urlForFindRecord(t,r,e){return this._composeURL(`${this.pathForType(r)}(${this.encodeKey(t)})`)}urlForUpdateRecord(t,r,e){return this._composeURL(`${this.pathForType(r)}(${this.encodeKey(t)})`)}urlForDeleteRecord(t,r,e){return this._composeURL(`${this.pathForType(r)}(${this.encodeKey(t)})`)}async findMany(t,r,e,s){const a=this.buildURL(r,e,s,"findMany"),o=e.map(c=>`id eq ${this.encodeKey(c)}`).join(" or "),i=`${a}?${this._toQueryString({$filter:o})}`;return this._fetchJSON(i,{method:"GET",headers:this.defaultHeaders()})}async query(t,r,e){const s=this.buildURL(r,null,null,"query",e),a=this._normalizeQuery(e),o=`${s}${this._appendQuery(a)}`;return this._fetchJSON(o,{method:"GET",headers:this.defaultHeaders()})}async queryRecord(t,r,e){const s=this.buildURL(r,null,null,"queryRecord",e),a={...this._normalizeQuery(e),$top:1},o=`${s}${this._appendQuery(a)}`;return this._fetchJSON(o,{method:"GET",headers:this.defaultHeaders()})}async updateRecord(t,r,e){const s=this.buildURL(r,e.id,e,"updateRecord");return this._fetchJSON(s,{method:"PATCH",headers:this.mutationHeaders(),body:JSON.stringify(this._serializeSnapshot(e))})}async patchRecord(t,r,e){const s=this.buildURL(r,e.id,e,"updateRecord"),a=e.changedAttributes(),o={};for(const[i,[,c]]of Object.entries(a))o[i]=c;return this._fetchJSON(s,{method:"PATCH",headers:this.mutationHeaders(),body:JSON.stringify(o)})}_serializeSnapshot(t){const e=t.record._data,s={};if(e)for(const a of Object.keys(e))a==="__proto__"||a==="constructor"||a==="prototype"||(s[a]=e[a]);return s}_normalizeQuery(t){const r={};for(const[e,s]of Object.entries(t))s!=null&&(u.has(e)?r[e]=s:u.has(`$${e}`)?r[`$${e}`]=s:r[e]=s);return r}_toQueryString(t){const r=[];for(const[e,s]of Object.entries(t))s!=null&&r.push(`${encodeURIComponent(e)}=${encodeURIComponent(String(s))}`);return r.join("&")}_appendQuery(t){const r=this._toQueryString(t);return r?`?${r}`:""}};exports.ODataAdapter=y([h.injectable()],exports.ODataAdapter);
|
|
2
|
+
//# sourceMappingURL=ODataAdapter-DdE6MWkG.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ODataAdapter-DdE6MWkG.cjs","sources":["../src/odata/ODataAdapter.ts"],"sourcesContent":["import { injectable } from 'tsyringe';\r\nimport pluralize from 'pluralize';\r\nimport { pascalCase } from 'change-case';\r\nimport { RestAdapter } from '@mobx-data/adapter';\r\nimport type { AdapterSnapshot } from '@mobx-data/adapter';\r\n\r\n/** All OData v4 system query option names (both bare and $-prefixed forms are checked). */\r\nconst ODATA_SYSTEM_QUERY_OPTIONS = new Set([\r\n '$filter',\r\n '$select',\r\n '$orderby',\r\n '$top',\r\n '$skip',\r\n '$expand',\r\n '$count',\r\n '$search',\r\n '$format',\r\n '$skiptoken',\r\n]);\r\n\r\n/**\r\n * OData v4 adapter.\r\n *\r\n * Extends `RestAdapter` with OData-specific conventions:\r\n * - Entity-set names are PascalCase plural (`user` → `Users`).\r\n * - Single-entity URLs use key-in-parentheses syntax (`Users(1)`, `Users('abc')`).\r\n * - Mutations use PATCH instead of PUT.\r\n * - Accept / Content-Type headers carry the `odata.metadata=minimal` parameter.\r\n * - System query options (`$filter`, `$expand`, etc.) are passed through verbatim;\r\n * bare names are auto-prefixed (`filter` → `$filter`).\r\n */\r\n@injectable()\r\nexport class ODataAdapter extends RestAdapter {\r\n /** OData protocol version sent in `OData-Version` and `OData-MaxVersion` headers. */\r\n odataVersion: string = '4.0';\r\n\r\n static isNumericKey(id: string): boolean {\r\n return /^-?\\d+(?:\\.\\d+)?$/.test(id);\r\n }\r\n\r\n static escapeODataString(value: string): string {\r\n return value.replace(/'/g, \"''\");\r\n }\r\n\r\n override defaultHeaders(): Record<string, string> {\r\n return {\r\n Accept: 'application/json;odata.metadata=minimal',\r\n 'OData-Version': this.odataVersion,\r\n 'OData-MaxVersion': this.odataVersion,\r\n ...this.headers,\r\n };\r\n }\r\n\r\n override mutationHeaders(): Record<string, string> {\r\n return {\r\n 'Content-Type': 'application/json;odata.metadata=minimal',\r\n ...this.defaultHeaders(),\r\n };\r\n }\r\n\r\n /**\r\n * Maps a camelCase/dasherized model name to a PascalCase plural entity-set name.\r\n * @example `pathForType('orderItem')` → `'OrderItems'`\r\n */\r\n override pathForType(modelName: string): string {\r\n return pascalCase(pluralize.plural(modelName));\r\n }\r\n\r\n /**\r\n * Encodes a record id as an OData key literal.\r\n * Numeric ids are returned bare (`1`); string ids are single-quoted with\r\n * inner apostrophes escaped (`o'brien` → `'o''brien'`).\r\n *\r\n * Override this method when the service uses a non-default key format (e.g. GUIDs).\r\n */\r\n encodeKey(id: string): string {\r\n if (ODataAdapter.isNumericKey(id)) {\r\n return id;\r\n }\r\n return `'${ODataAdapter.escapeODataString(id)}'`;\r\n }\r\n\r\n override urlForFindRecord(\r\n id: string,\r\n modelName: string,\r\n _snapshot: AdapterSnapshot,\r\n ): string {\r\n return this._composeURL(`${this.pathForType(modelName)}(${this.encodeKey(id)})`);\r\n }\r\n\r\n override urlForUpdateRecord(\r\n id: string,\r\n modelName: string,\r\n _snapshot: AdapterSnapshot,\r\n ): string {\r\n return this._composeURL(`${this.pathForType(modelName)}(${this.encodeKey(id)})`);\r\n }\r\n\r\n override urlForDeleteRecord(\r\n id: string,\r\n modelName: string,\r\n _snapshot: AdapterSnapshot,\r\n ): string {\r\n return this._composeURL(`${this.pathForType(modelName)}(${this.encodeKey(id)})`);\r\n }\r\n\r\n /**\r\n * Fetches multiple records by id using a single request.\r\n * Builds a `$filter=id eq X or id eq Y` expression so only one HTTP round-trip\r\n * is needed regardless of how many ids are requested.\r\n */\r\n override async findMany(\r\n _store: unknown,\r\n modelName: string,\r\n ids: string[],\r\n snapshots: AdapterSnapshot[],\r\n ): Promise<unknown> {\r\n const base = this.buildURL(modelName, ids, snapshots, 'findMany');\r\n const filter = ids.map((id) => `id eq ${this.encodeKey(id)}`).join(' or ');\r\n const url = `${base}?${this._toQueryString({ $filter: filter })}`;\r\n return this._fetchJSON(url, {\r\n method: 'GET',\r\n headers: this.defaultHeaders(),\r\n });\r\n }\r\n\r\n override async query(\r\n _store: unknown,\r\n modelName: string,\r\n query: Record<string, unknown>,\r\n ): Promise<unknown> {\r\n const base = this.buildURL(modelName, null, null, 'query', query);\r\n const normalized = this._normalizeQuery(query);\r\n const url = `${base}${this._appendQuery(normalized)}`;\r\n return this._fetchJSON(url, {\r\n method: 'GET',\r\n headers: this.defaultHeaders(),\r\n });\r\n }\r\n\r\n /**\r\n * Queries for a single record by appending `$top=1` to whatever filter is provided.\r\n * The caller is responsible for picking the first element from the returned `value` array.\r\n */\r\n override async queryRecord(\r\n _store: unknown,\r\n modelName: string,\r\n query: Record<string, unknown>,\r\n ): Promise<unknown> {\r\n const base = this.buildURL(modelName, null, null, 'queryRecord', query);\r\n const normalized = { ...this._normalizeQuery(query), $top: 1 };\r\n const url = `${base}${this._appendQuery(normalized)}`;\r\n return this._fetchJSON(url, {\r\n method: 'GET',\r\n headers: this.defaultHeaders(),\r\n });\r\n }\r\n\r\n /** Sends a PATCH request (partial update) as required by the OData v4 spec. */\r\n override async updateRecord(\r\n _store: unknown,\r\n modelName: string,\r\n snapshot: AdapterSnapshot,\r\n ): Promise<unknown> {\r\n const url = this.buildURL(modelName, snapshot.id, snapshot, 'updateRecord');\r\n return this._fetchJSON(url, {\r\n method: 'PATCH',\r\n headers: this.mutationHeaders(),\r\n body: JSON.stringify(this._serializeSnapshot(snapshot)),\r\n });\r\n }\r\n\r\n /** Sends a PATCH request with only the changed attributes (partial update). */\r\n override async patchRecord(\r\n _store: unknown,\r\n modelName: string,\r\n snapshot: AdapterSnapshot,\r\n ): Promise<unknown> {\r\n const url = this.buildURL(modelName, snapshot.id, snapshot, 'updateRecord');\r\n const changed = snapshot.changedAttributes();\r\n const partial: Record<string, unknown> = {};\r\n for (const [key, [, current]] of Object.entries(changed)) {\r\n partial[key] = current;\r\n }\r\n return this._fetchJSON(url, {\r\n method: 'PATCH',\r\n headers: this.mutationHeaders(),\r\n body: JSON.stringify(partial),\r\n });\r\n }\r\n\r\n /** Extracts the raw attribute map from the snapshot's internal record. */\r\n protected _serializeSnapshot(snapshot: AdapterSnapshot): Record<string, unknown> {\r\n const record = snapshot.record as { _data?: Record<string, unknown> };\r\n const data = record._data;\r\n const body: Record<string, unknown> = {};\r\n if (data) {\r\n for (const key of Object.keys(data)) {\r\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\r\n body[key] = data[key];\r\n }\r\n }\r\n return body;\r\n }\r\n\r\n /**\r\n * Normalises a query hash so every OData system option has its `$` prefix.\r\n * Bare names (`filter`, `top`, `expand`) are prefixed automatically.\r\n * Custom (non-system) keys are forwarded verbatim.\r\n * `null` and `undefined` values are dropped.\r\n */\r\n protected _normalizeQuery(\r\n query: Record<string, unknown>,\r\n ): Record<string, unknown> {\r\n const normalized: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(query)) {\r\n if (value === undefined || value === null) {\r\n continue;\r\n }\r\n if (ODATA_SYSTEM_QUERY_OPTIONS.has(key)) {\r\n normalized[key] = value;\r\n } else if (ODATA_SYSTEM_QUERY_OPTIONS.has(`$${key}`)) {\r\n normalized[`$${key}`] = value;\r\n } else {\r\n normalized[key] = value;\r\n }\r\n }\r\n return normalized;\r\n }\r\n\r\n /** Serialises a key→value map to a `key=value&…` query string (percent-encoded). */\r\n protected _toQueryString(query: Record<string, unknown>): string {\r\n const parts: string[] = [];\r\n for (const [key, value] of Object.entries(query)) {\r\n if (value === undefined || value === null) {\r\n continue;\r\n }\r\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\r\n }\r\n return parts.join('&');\r\n }\r\n\r\n /** Returns `?key=value&…` when the query is non-empty, or an empty string. */\r\n protected _appendQuery(query: Record<string, unknown>): string {\r\n const queryString = this._toQueryString(query);\r\n return queryString ? `?${queryString}` : '';\r\n }\r\n}\r\n"],"names":["ODATA_SYSTEM_QUERY_OPTIONS","ODataAdapter","RestAdapter","id","value","modelName","pascalCase","pluralize","_snapshot","_store","ids","snapshots","base","filter","url","query","normalized","snapshot","changed","partial","key","current","data","body","parts","queryString","__decorateClass","injectable"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const y=require("tsyringe"),F=require("pluralize"),i=Symbol("response-headers");function b(c){const e=c["cache-control"];if(e){if(/no-store/i.test(e)||/no-cache/i.test(e))return 0;const t=/s-maxage=(\d+)/i.exec(e);if(t)return parseInt(t[1],10)*1e3;const s=/max-age=(\d+)/i.exec(e);if(s)return parseInt(s[1],10)*1e3}const r=c.expires;if(r){const t=new Date(r).getTime();if(!Number.isNaN(t))return Math.max(0,t-Date.now())}return null}function L(c){return c!==null&&typeof c=="object"?c[i]??null:null}function h(c,e){c!==null&&typeof c=="object"&&Object.defineProperty(c,i,{value:e,enumerable:!1,writable:!1,configurable:!1})}const U=new RegExp("([\\p{Ll}\\d])(\\p{Lu})","gu"),m=new RegExp("(\\p{Lu})([\\p{Lu}][\\p{Ll}])","gu"),S=new RegExp("(\\d)\\p{Ll}|(\\p{L})\\d","u"),A=/[^\p{L}\d]+/giu,l="$1\0$2",d="";function f(c){let e=c.trim();e=e.replace(U,l).replace(m,l),e=e.replace(A,"\0");let r=0,t=e.length;for(;e.charAt(r)==="\0";)r++;if(r===t)return[];for(;e.charAt(t-1)==="\0";)t--;return e.slice(r,t).split(/\0/g)}function T(c){const e=f(c);for(let r=0;r<e.length;r++){const t=e[r],s=S.exec(t);if(s){const n=s.index+(s[1]??s[2]).length;e.splice(r,1,t.slice(0,n),t.slice(n))}}return e}function E(c,e){const[r,t,s]=p(c,e);return r+t.map(R(e==null?void 0:e.locale)).join((e==null?void 0:e.delimiter)??" ")+s}function g(c,e){const[r,t,s]=p(c,e),n=R(e==null?void 0:e.locale),a=C(e==null?void 0:e.locale),o=O(n,a);return r+t.map(o).join("")+s}function x(c,e){return E(c,{delimiter:"-",...e})}function R(c){return c===!1?e=>e.toLowerCase():e=>e.toLocaleLowerCase(c)}function C(c){return e=>e.toLocaleUpperCase(c)}function O(c,e){return(r,t)=>{const s=r[0];return(t>0&&s>="0"&&s<="9"?"_"+s:e(s))+c(r.slice(1))}}function p(c,e={}){const r=e.split??(e.separateNumbers?T:f),t=e.prefixCharacters??d,s=e.suffixCharacters??d;let n=0,a=c.length;for(;n<c.length;){const o=c.charAt(n);if(!t.includes(o))break;n++}for(;a>n;){const o=a-1,u=c.charAt(o);if(!s.includes(u))break;a=o}return[c.slice(0,n),r(c.slice(n,a)),c.slice(a)]}class _{constructor(){this.namespace="",this.host="",this.headers={},this.coalesceFindRequests=!1}patchRecord(e,r,t){return this.updateRecord(e,r,t)}pathForType(e){return F.plural(x(e))}_composeURL(e){const r=this.namespace.replace(/^\/+|\/+$/g,""),t=this.host?this.host.replace(/\/+$/,""):"",s=[];return t&&s.push(t),r&&s.push(r),s.push(e),t?s.join("/"):`/${s.filter(Boolean).join("/")}`}buildURL(e,r,t,s,n={}){switch(s){case"findRecord":return this.urlForFindRecord(r,e,t);case"findAll":return this.urlForFindAll(e,t??[]);case"findMany":return this.urlForFindMany(r??[],e,t??[]);case"query":return this.urlForQuery(n,e);case"queryRecord":return this.urlForQueryRecord(n,e);case"createRecord":return this.urlForCreateRecord(e,t);case"updateRecord":return this.urlForUpdateRecord(r,e,t);case"deleteRecord":return this.urlForDeleteRecord(r,e,t)}}urlForFindRecord(e,r,t){return this._composeURL(`${this.pathForType(r)}/${encodeURIComponent(e)}`)}urlForFindAll(e,r){return this._composeURL(this.pathForType(e))}urlForFindMany(e,r,t){return this._composeURL(this.pathForType(r))}urlForQuery(e,r){return this._composeURL(this.pathForType(r))}urlForQueryRecord(e,r){return this._composeURL(this.pathForType(r))}urlForCreateRecord(e,r){return this._composeURL(this.pathForType(e))}urlForUpdateRecord(e,r,t){return this._composeURL(`${this.pathForType(r)}/${encodeURIComponent(e)}`)}urlForDeleteRecord(e,r,t){return this._composeURL(`${this.pathForType(r)}/${encodeURIComponent(e)}`)}groupRecordsForFindMany(e,r){return[r]}shouldReloadRecord(e,r){return!1}shouldBackgroundReloadRecord(e,r){return!0}shouldReloadAll(e,r){return!1}shouldBackgroundReloadAll(e,r){return!0}}var $=Object.getOwnPropertyDescriptor,P=(c,e,r,t)=>{for(var s=t>1?void 0:t?$(e,r):e,n=c.length-1,a;n>=0;n--)(a=c[n])&&(s=a(s)||s);return s};exports.RestAdapter=class extends _{static serializeSnapshotToObject(e){const r={},s=e.record._data;if(s)for(const[n,a]of Object.entries(s))n==="__proto__"||n==="constructor"||n==="prototype"||(r[n]=a);return r}static toQueryString(e){const r=[];for(const[t,s]of Object.entries(e))s!=null&&r.push(`${encodeURIComponent(t)}=${encodeURIComponent(String(s))}`);return r.length>0?`?${r.join("&")}`:""}defaultHeaders(){return{Accept:"application/json",...this.headers}}mutationHeaders(){return{"Content-Type":"application/json",...this.defaultHeaders()}}async _fetchJSON(e,r){const t=await fetch(e,r);if(!t.ok){let a=null;try{a=await t.json()}catch{}throw Object.assign(new Error(`Request failed: ${t.status}`),{status:t.status,body:a})}if(t.status===204)return null;const s=await t.text();if(!s)return null;let n;try{n=JSON.parse(s)}catch{n=s}if(n!==null&&typeof n=="object"){const a={};t.headers.forEach((o,u)=>{a[u.toLowerCase()]=o}),h(n,a)}return n}async findRecord(e,r,t,s,n){let a=this.buildURL(r,t,s,"findRecord");return n!=null&&n.include&&(a+=`${a.includes("?")?"&":"?"}include=${encodeURIComponent(n.include)}`),this._fetchJSON(a,{method:"GET",headers:this.defaultHeaders()})}async findAll(e,r,t,s,n){let a=this.buildURL(r,null,s,"findAll");return n!=null&&n.include&&(a+=`${a.includes("?")?"&":"?"}include=${encodeURIComponent(n.include)}`),this._fetchJSON(a,{method:"GET",headers:this.defaultHeaders()})}async findMany(e,r,t,s){const n=this.buildURL(r,t,s,"findMany"),a=n.includes("?")?"&":"?",o=`${n}${a}ids=${t.map(encodeURIComponent).join(",")}`;return this._fetchJSON(o,{method:"GET",headers:this.defaultHeaders()})}async query(e,r,t){const n=`${this.buildURL(r,null,null,"query",t)}${exports.RestAdapter.toQueryString(t)}`;return this._fetchJSON(n,{method:"GET",headers:this.defaultHeaders()})}async queryRecord(e,r,t){const n=`${this.buildURL(r,null,null,"queryRecord",t)}${exports.RestAdapter.toQueryString(t)}`;return this._fetchJSON(n,{method:"GET",headers:this.defaultHeaders()})}async createRecord(e,r,t){const s=this.buildURL(r,null,t,"createRecord");return this._fetchJSON(s,{method:"POST",headers:this.mutationHeaders(),body:JSON.stringify(exports.RestAdapter.serializeSnapshotToObject(t))})}async updateRecord(e,r,t){const s=this.buildURL(r,t.id,t,"updateRecord");return this._fetchJSON(s,{method:"PUT",headers:this.mutationHeaders(),body:JSON.stringify(exports.RestAdapter.serializeSnapshotToObject(t))})}async patchRecord(e,r,t){const s=this.buildURL(r,t.id,t,"updateRecord"),n=t.changedAttributes(),a={};for(const[o,[,u]]of Object.entries(n))a[o]=u;return this._fetchJSON(s,{method:"PATCH",headers:this.mutationHeaders(),body:JSON.stringify(a)})}async deleteRecord(e,r,t){const s=this.buildURL(r,t.id,t,"deleteRecord");return this._fetchJSON(s,{method:"DELETE",headers:this.defaultHeaders()})}};exports.RestAdapter=P([y.injectable()],exports.RestAdapter);exports.Adapter=_;exports.RESPONSE_HEADERS=i;exports.attachResponseHeaders=h;exports.extractResponseHeaders=L;exports.parseCacheTTLFromHeaders=b;exports.pascalCase=g;
|
|
2
|
+
//# sourceMappingURL=RestAdapter-D7GSrsJo.cjs.map
|