@warp-drive/json-api 5.9.0-beta.0 → 5.9.0-beta.1
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/CHANGELOG.md +109 -0
- package/README.md +1 -1
- package/declarations/index.d.ts +514 -4
- package/declarations/index.d.ts.map +1 -0
- package/dist/index.js +2426 -3118
- package/dist/index.js.map +1 -0
- package/dist/unpkg/dev/index.js +2482 -3223
- package/dist/unpkg/dev/index.js.map +1 -0
- package/dist/unpkg/dev-deprecated/index.js +2457 -3184
- package/dist/unpkg/dev-deprecated/index.js.map +1 -0
- package/dist/unpkg/prod/index.js +1269 -1813
- package/dist/unpkg/prod/index.js.map +1 -0
- package/dist/unpkg/prod-deprecated/index.js +1269 -1813
- package/dist/unpkg/prod-deprecated/index.js.map +1 -0
- package/package.json +11 -11
- package/declarations/-private/cache.d.ts +0 -454
- package/declarations/-private/validate-document-fields.d.ts +0 -3
- package/declarations/-private/validator/1.1/7.1_top-level-document-members.d.ts +0 -1
- package/declarations/-private/validator/1.1/7.2_resource-objects.d.ts +0 -1
- package/declarations/-private/validator/1.1/links.d.ts +0 -1
- package/declarations/-private/validator/index.d.ts +0 -4
- package/declarations/-private/validator/utils.d.ts +0 -75
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["Fuse","jsonToAst","inspectType","obj","Array","isArray","proto","Object","getPrototypeOf","prototype","constructor","name","isSimpleObject","RELATIONSHIP_FIELD_KINDS","Reporter","capabilities","contextDocument","errors","maxLines","contextLines","maxOccurrencesPerGroup","maxDistinctIssues","jsonStr","_jsonStr","undefined","JSON","stringify","content","ast","_ast","loc","strict","linkage","unknownType","unknownAttribute","unknownRelationship","enforceReachable","_presence","presence","primaryResources","Map","includedResources","allResources","doc","data","i","length","addResourceToMap","included","all","searchTypes","type","_typeFilter","allTypes","schema","resourceTypes","result","search","_fieldFilters","searchFields","field","has","allFields","fields","allCacheFields","cacheFields","attrs","from","values","filter","isRemoteField","map","v","set","get","getLocation","path","kind","priorNode","node","segment","children","childNode","child","find","childCandidate","key","value","error","message","push","warn","info","hasExtension","extensionName","REGISTERED_EXTENSIONS","getExtension","report","colorize","lines","split","sort","a","b","end","line","column","compareType","counts","warning","contextStr","request","method","url","groups","group","activeErrors","Set","recurrenceNoteFor","shownGroupCount","hiddenGroupCount","hiddenOccurrenceCount","showCount","Math","min","add","extra","errorMap","errorsForLine","MERGE_GAP","activeLines","keys","ranges","start","max","lastRange","firstRange","lastRangeOverall","chunks","text","colors","renderedCount","nextLine","lineColors","chunk","pushSkipMarker","gap","LINE_SIZE","String","r","rangeStart","rangeEnd","padEnd","symbol","padStart","repeat","lastRenderedRange","forEach","index","prefix","chunkString","join","console","log","isMetaDocument","Error","isErrorDocument","isPushedDocument","logPotentialMatches","matches","item","potentialMatches","match","getRemoteField","getSourceKeyMismatch","sourceKey","resource","location","id","checkResourceInMap","checkResourcePresent","graphFor","isBelongsTo","peekGraph","assertPrivateCapabilities","isRequestKey","isResourceKey","logGroup","validateDocumentFields","validateDocument","isErrorDocument","isMetaDocument","isImplicit","relationship","definition","EMPTY_ITERATOR","iterator","next","done","value","undefined","makeCache","id","remoteAttrs","localAttrs","defaultAttrs","inflightAttrs","changes","errors","isNew","isDeleted","isDeletionCommitted","JSONAPICache","constructor","capabilities","version","_capabilities","__cache","Map","__graph","__destroyedCache","__documents","put","doc","_putDocument","jsonApiDoc","content","included","i","length","cacheKeyManager","putOne","Array","isArray","data","identifiers","push","identifier","resourceDocument","fromStructuredError","fromBaseDocument","request","getOrCreateDocumentIdentifier","lid","hasExisting","has","set","notifyChange","op","parentIdentifier","options","parentField","field","record","name","patch","_store","_join","operation","patchCache","mutate","mutation","update","peek","peeked","__safePeek","type","attributes","structuredClone","Object","assign","relationships","rels","get","keys","forEach","key","rel","getData","store","attrs","getCacheFields","attr","defaultValue","getDefaultValue","document","peekRequest","peekRemoteState","upsert","calculateChanges","_cbs","result","_run","cacheUpsert","fork","Error","merge","_cache","diff","dump","hydrate","stream","clientDidCreate","cached","_createCache","createOptions","fields","graph","propertyNames","propertyValue","fieldType","kind","setAttr","state","hasReceivedData","isEmpty","willCommit","_context","didCommit","committedIdentifier","payload","responseIsCollection","hasMultipleIdentifiers","commitWasRejected","commitDidError","unloadRecord","storeWrapper","unload","removeFromRecordArray","removed","__peek","relatedIdentifiers","_allRelatedIdentifiers","areAllModelsUnloaded","relatedIdentifier","disconnectRecord","delete","size","setTimeout","clear","getAttr","isSimplePath","attribute","attrSchema","schemaHasLegacyDefaultValueFn","create","path","basePath","current","getRemoteAttr","currentAttr","existing","existingAttr","currentLocal","nextLink","existingStr","JSON","stringify","newStr","changedAttrs","hasChangedAttrs","rollbackAttrs","dirtyKeys","notifyAttributes","Set","changedRelationships","getChanged","hasChangedRelationships","hasChanged","rollbackRelationships","rollback","getRelationship","getRemoteRelationship","getRemoteData","setIsDeleted","getErrors","cache","allowDestroyed","resource","addResourceToDocument","shouldNotify","asDoc","index","splice","concat","removeResourceFromDocument","toRemove","indexOf","wrapper","hasRecord","getLocalState","localState","additions","getRemoteState","remoteState","schema","hasLegacyDefaultValueFn","transform","transformation","calculateChangedKeys","updates","changedKeys","original","add","cacheIsEmpty","_isEmpty","recordIsLoaded","filterDeleted","_isLoading","req","getRequestStateService","isLoaded","getPendingRequestsForRecord","some","r","setupRelationships","relationshipData","isRelationship","patchLocalAttributes","changedRemoteKeys","hasAppliedPatch","mutatedKeys","asOp","peekResourceKey","updateRecordIdentifier","getOrCreateRecordIdentifier","_directlyRelatedIdentifiersIterable","originating","initializedRelationships","initializedRelationshipsArr","j","k","findNext","array","queue","seen","shift","obj","copyLinksAndMeta","errorDoc","error","title","message","target","source","links","meta","existed","isLoading","isUpdate","from","Cache","isRecord","isDocument","cacheFields","existingId","newCanonicalAttributes"],"sources":["../../../src/-private/validator/utils.ts","../../../src/-private/cache.ts"],"sourcesContent":["import type { FuseResult } from 'fuse.js';\nimport Fuse from 'fuse.js';\nimport type { ArrayNode, ObjectNode } from 'json-to-ast';\nimport jsonToAst from 'json-to-ast';\n\nimport { JSON_API_CACHE_VALIDATION_ERRORS } from '@warp-drive/core/build-config/canary-features';\nimport { assert } from '@warp-drive/core/build-config/macros';\nimport type { CacheCapabilitiesManager, SchemaService } from '@warp-drive/core/types';\nimport type {\n StructuredDataDocument,\n StructuredDocument,\n StructuredErrorDocument,\n} from '@warp-drive/core/types/request';\nimport type { FieldSchema } from '@warp-drive/core/types/schema/fields';\nimport type {\n ResourceDataDocument,\n ResourceDocument,\n ResourceErrorDocument,\n ResourceMetaDocument,\n} from '@warp-drive/core/types/spec/document';\nimport type { ResourceObject } from '@warp-drive/core/types/spec/json-api-raw';\n\nexport function inspectType(obj: unknown): string {\n if (obj === null) {\n return 'null';\n }\n if (Array.isArray(obj)) {\n return 'array';\n }\n if (typeof obj === 'object') {\n const proto = Object.getPrototypeOf(obj) as unknown;\n if (proto === null) {\n return 'object';\n }\n if (proto === Object.prototype) {\n return 'object';\n }\n return `object (${(proto as object).constructor?.name})`;\n }\n if (typeof obj === 'function') {\n return 'function';\n }\n if (typeof obj === 'string') {\n return 'string';\n }\n if (typeof obj === 'number') {\n return 'number';\n }\n if (typeof obj === 'boolean') {\n return 'boolean';\n }\n if (typeof obj === 'symbol') {\n return 'symbol';\n }\n if (typeof obj === 'bigint') {\n return 'bigint';\n }\n if (typeof obj === 'undefined') {\n return 'undefined';\n }\n return 'unknown';\n}\n\nexport function isSimpleObject(obj: unknown): obj is Record<string, unknown> {\n if (obj === null) {\n return false;\n }\n if (Array.isArray(obj)) {\n return false;\n }\n if (typeof obj !== 'object') {\n return false;\n }\n\n const proto = Object.getPrototypeOf(obj) as unknown;\n if (proto === null) {\n return true;\n }\n if (proto === Object.prototype) {\n return true;\n }\n return false;\n}\n\nexport const RELATIONSHIP_FIELD_KINDS: string[] = ['belongsTo', 'hasMany', 'resource', 'collection'];\nexport type PathLike = Array<string | number>;\ninterface ErrorReport {\n path: PathLike;\n message: string;\n loc: {\n start: { line: number; column: number; offset: number };\n end: { line: number; column: number; offset: number };\n };\n type: 'error' | 'warning' | 'info';\n kind: 'key' | 'value';\n}\n\nexport interface ResourcePresence {\n data: Map<string, Map<string, ResourceInfo[]>>;\n included: Map<string, Map<string, ResourceInfo[]>>;\n all: Map<string, Map<string, ResourceInfo[]>>;\n}\n\nexport interface ResourceInfo {\n data: ResourceObject;\n /**\n * null if the only primary data member\n */\n index: number | null;\n location: 'data' | 'included';\n}\n\nexport class Reporter {\n capabilities: CacheCapabilitiesManager;\n contextDocument: StructuredDocument<ResourceDocument>;\n errors: ErrorReport[] = [];\n\n /**\n * The maximum number of source lines the reporter will annotate and emit\n * in a single `console.log` call when producing a report. Documents with\n * more lines than this are chunked across multiple calls so that no\n * single call ever has to spread an unbounded number of colorization\n * args (which can exceed engine call-argument/stack limits for very\n * large payloads).\n */\n maxLines = 500;\n\n /**\n * The number of source lines to show before/after each reported line when\n * annotating the document. Stretches of source between annotated lines\n * that are larger than this get collapsed into a single\n * `... N lines skipped ...` marker rather than printed in full.\n */\n contextLines = 2;\n\n /**\n * The number of occurrences of an identical error message to annotate\n * inline before collapsing the rest. When a message recurs beyond this\n * count, the last shown occurrence's annotation is suffixed with\n * `(recurs N more times)` and the remaining occurrences are omitted from\n * the printed document entirely (though they still count toward the\n * totals in the summary line).\n */\n maxOccurrencesPerGroup = 1;\n\n /**\n * The number of distinct error messages to annotate inline before\n * refusing to show any more. Once this many distinct messages have been\n * shown, further distinct messages are omitted entirely and rolled up\n * into a single trailing `... and N more distinct issues ... not shown`\n * line so nothing is dropped silently.\n */\n maxDistinctIssues = 50;\n\n declare _ast: ReturnType<typeof jsonToAst> | undefined;\n declare _jsonStr: string | undefined;\n\n // lazy: only parse the document into a string/AST if we actually need to\n // locate an error, warning, or info within it. Clean documents (the vast\n // majority) never pay this cost.\n get jsonStr(): string {\n if (this._jsonStr === undefined) {\n this._jsonStr = JSON.stringify(this.contextDocument.content, null, 2);\n }\n return this._jsonStr;\n }\n\n get ast(): ReturnType<typeof jsonToAst> {\n if (!this._ast) {\n this._ast = jsonToAst(this.jsonStr, { loc: true });\n }\n return this._ast;\n }\n\n // TODO @runspired make this configurable to consuming apps before\n // activating by default\n strict = {\n linkage: true,\n unknownType: true,\n unknownAttribute: true,\n unknownRelationship: true,\n enforceReachable: true,\n };\n\n _presence: ResourcePresence | null = null;\n\n get presence(): ResourcePresence {\n if (this._presence) {\n return this._presence;\n }\n\n const primaryResources = new Map<string, Map<string, ResourceInfo[]>>();\n const includedResources = new Map<string, Map<string, ResourceInfo[]>>();\n const allResources = new Map<string, Map<string, ResourceInfo[]>>();\n\n const doc = this.contextDocument.content;\n if (doc) {\n if ('data' in doc && doc.data) {\n if (Array.isArray(doc.data)) {\n for (let i = 0; i < doc.data.length; i++) {\n addResourceToMap(primaryResources, doc.data[i], i, 'data');\n addResourceToMap(allResources, doc.data[i], i, 'data');\n }\n } else {\n addResourceToMap(primaryResources, doc.data, null, 'data');\n addResourceToMap(allResources, doc.data, null, 'data');\n }\n }\n }\n\n if (doc && 'included' in doc && Array.isArray(doc.included)) {\n for (let i = 0; i < doc.included.length; i++) {\n addResourceToMap(includedResources, doc.included[i], i, 'included');\n addResourceToMap(allResources, doc.included[i], i, 'included');\n }\n }\n\n this._presence = {\n data: primaryResources,\n included: includedResources,\n all: allResources,\n };\n return this._presence;\n }\n\n constructor(capabilities: CacheCapabilitiesManager, doc: StructuredDocument<ResourceDocument>) {\n this.capabilities = capabilities;\n this.contextDocument = doc;\n }\n\n declare _typeFilter: Fuse<string> | undefined;\n searchTypes(type: string): FuseResult<string>[] {\n if (!this._typeFilter) {\n const allTypes = this.schema.resourceTypes();\n this._typeFilter = new Fuse(allTypes);\n }\n const result = this._typeFilter.search(type);\n return result;\n }\n\n _fieldFilters: Map<string, Fuse<string>> = new Map();\n searchFields(type: string, field: string): FuseResult<string>[] {\n if (!this._fieldFilters.has(type)) {\n const allFields = this.schema.fields({ type });\n const allCacheFields = this.schema.cacheFields?.({ type }) ?? allFields;\n const attrs = Array.from(allCacheFields.values())\n .filter(isRemoteField)\n .map((v) => v.name);\n this._fieldFilters.set(type, new Fuse(attrs));\n }\n const result = this._fieldFilters.get(type)!.search(field);\n return result;\n }\n\n get schema(): SchemaService {\n return this.capabilities.schema;\n }\n\n getLocation(\n path: PathLike,\n kind: 'key' | 'value'\n ): {\n start: { line: number; column: number; offset: number };\n end: { line: number; column: number; offset: number };\n } {\n if (path.length === 0) {\n return this.ast.loc!;\n }\n\n let priorNode = this.ast as ObjectNode | ArrayNode;\n let node = this.ast as ObjectNode | ArrayNode;\n for (const segment of path) {\n //\n // handle array paths\n //\n if (typeof segment === 'number') {\n assert(`Because the segment is a number, expected a node of type Array`, node.type === 'Array');\n\n if (node.children && node.children[segment]) {\n priorNode = node;\n const childNode = node.children[segment];\n\n if (childNode.type === 'Object' || childNode.type === 'Array') {\n node = childNode;\n } else {\n // set to the closest node we can find\n return node.loc!;\n }\n } else {\n // set to the closest node we can find\n // as we had no children\n return priorNode.loc!;\n }\n\n //\n // handle object paths\n //\n } else {\n assert(`Because the segment is a string, expected a node of type Object`, node.type === 'Object');\n\n const child = node.children.find((childCandidate) => {\n if (childCandidate.type === 'Property') {\n return childCandidate.key.type === 'Identifier' && childCandidate.key.value === segment;\n }\n return false;\n });\n\n if (child) {\n if (child.value.type === 'Object' || child.value.type === 'Array') {\n priorNode = node;\n node = child.value;\n } else {\n // set to the closest node we can find\n return kind === 'key' ? child.key.loc! : child.value.loc!;\n }\n } else {\n // set to the closest node we can find\n return priorNode.loc!;\n }\n }\n }\n\n return node.loc!;\n }\n\n error(path: PathLike, message: string, kind: 'key' | 'value' = 'key'): void {\n const loc = this.getLocation(path, kind);\n this.errors.push({ path, message, loc, type: 'error', kind });\n }\n\n warn(path: PathLike, message: string, kind: 'key' | 'value' = 'key'): void {\n const loc = this.getLocation(path, kind);\n this.errors.push({ path, message, loc, type: 'warning', kind });\n }\n\n info(path: PathLike, message: string, kind: 'key' | 'value' = 'key'): void {\n const loc = this.getLocation(path, kind);\n this.errors.push({ path, message, loc, type: 'info', kind });\n }\n\n hasExtension(extensionName: string): boolean {\n return REGISTERED_EXTENSIONS.has(extensionName);\n }\n\n getExtension(extensionName: string): ReporterFn | undefined {\n return REGISTERED_EXTENSIONS.get(extensionName);\n }\n\n report(colorize = true): void {\n // sort the errors by line, then by column, then by type\n const { errors } = this;\n\n if (!errors.length) {\n return;\n }\n\n const lines = this.jsonStr.split('\\n');\n\n errors.sort((a, b) => {\n return a.loc.end.line < b.loc.end.line\n ? -1\n : a.loc.end.column < b.loc.end.column\n ? -1\n : compareType(a.type, b.type);\n });\n\n // counts reflect every error/warning/info regardless of whether it ends\n // up annotated inline below, so the header total is always accurate.\n const counts = {\n error: 0,\n warning: 0,\n info: 0,\n };\n for (const error of errors) {\n counts[error.type]++;\n }\n const contextStr = `${counts.error} errors and ${counts.warning} warnings found in the {json:api} document returned by ${this.contextDocument.request?.method ?? 'GET'} ${this.contextDocument.request?.url}`;\n\n // group identical messages together so repeats can be collapsed down to\n // a representative sample instead of printed in full.\n const groups = new Map<string, ErrorReport[]>();\n for (const error of errors) {\n let group = groups.get(error.message);\n if (!group) {\n group = [];\n groups.set(error.message, group);\n }\n group.push(error);\n }\n\n const activeErrors = new Set<ErrorReport>();\n const recurrenceNoteFor = new Map<ErrorReport, number>();\n let shownGroupCount = 0;\n let hiddenGroupCount = 0;\n let hiddenOccurrenceCount = 0;\n\n for (const group of groups.values()) {\n if (shownGroupCount < this.maxDistinctIssues) {\n shownGroupCount++;\n const showCount = Math.min(this.maxOccurrencesPerGroup, group.length);\n for (let i = 0; i < showCount; i++) {\n activeErrors.add(group[i]);\n }\n const extra = group.length - showCount;\n if (extra > 0) {\n recurrenceNoteFor.set(group[showCount - 1], extra);\n }\n } else {\n hiddenGroupCount++;\n hiddenOccurrenceCount += group.length;\n }\n }\n\n // store the active (to-be-annotated) errors in a map by line\n const errorMap = new Map<number, ErrorReport[]>();\n for (const error of activeErrors) {\n const line = error.loc.end.line;\n let errorsForLine = errorMap.get(line);\n if (!errorsForLine) {\n errorsForLine = [];\n errorMap.set(line, errorsForLine);\n }\n errorsForLine.push(error);\n }\n\n // determine which stretches of source to display: a window of\n // `contextLines` around every active error line, merging windows that\n // are close enough together that a skip marker wouldn't save anything.\n const MERGE_GAP = 3;\n const activeLines = Array.from(errorMap.keys()).sort((a, b) => a - b);\n const ranges: [number, number][] = [];\n for (const line of activeLines) {\n const start = Math.max(1, line - this.contextLines);\n const end = Math.min(lines.length, line + this.contextLines);\n const lastRange = ranges[ranges.length - 1];\n if (lastRange && start <= lastRange[1] + MERGE_GAP + 1) {\n lastRange[1] = Math.max(lastRange[1], end);\n } else {\n ranges.push([start, end]);\n }\n }\n\n // extend the first/last range to the document boundary when the\n // leading/trailing stretch is too small for a skip marker to be worth it\n const firstRange = ranges[0];\n if (firstRange && firstRange[0] - 1 <= MERGE_GAP + 1) {\n firstRange[0] = 1;\n }\n const lastRangeOverall = ranges[ranges.length - 1];\n if (lastRangeOverall && lines.length - lastRangeOverall[1] <= MERGE_GAP + 1) {\n lastRangeOverall[1] = lines.length;\n }\n\n // render into chunks so that no single `console.log` call has to spread\n // more than `this.maxLines` worth of rendered lines as colorization\n // args.\n const chunks: { text: string[]; colors: string[] }[] = [{ text: [], colors: [] }];\n let renderedCount = 0;\n const nextLine = (text: string, lineColors: string[]) => {\n if (renderedCount > 0 && renderedCount % this.maxLines === 0) {\n chunks.push({ text: [], colors: [] });\n }\n const chunk = chunks[chunks.length - 1];\n chunk.text.push(text);\n chunk.colors.push(...lineColors);\n renderedCount++;\n };\n\n const pushSkipMarker = (gap: number) => {\n nextLine(\n colorize\n ? `%c... ${gap} line${gap === 1 ? '' : 's'} skipped (no errors) ...%c`\n : `... ${gap} line${gap === 1 ? '' : 's'} skipped (no errors) ...`,\n ['color: grey; font-style: italic;', 'color: inherit; background-color: transparent;']\n );\n };\n\n const LINE_SIZE = String(lines.length).length;\n for (let r = 0; r < ranges.length; r++) {\n const [rangeStart, rangeEnd] = ranges[r];\n\n if (r === 0) {\n if (rangeStart > 1) {\n pushSkipMarker(rangeStart - 1);\n }\n } else {\n const gap = rangeStart - ranges[r - 1][1] - 1;\n if (gap > 0) {\n pushSkipMarker(gap);\n }\n }\n\n for (let i = rangeStart; i <= rangeEnd; i++) {\n const line = lines[i - 1];\n nextLine(\n colorize\n ? `${String(i).padEnd(LINE_SIZE, ' ')} \\t%c${line}%c`\n : `${String(i).padEnd(LINE_SIZE, ' ')} \\t${line}`,\n [`color: grey; background-color: transparent;`, `color: inherit; background-color: transparent;`]\n );\n\n if (errorMap.has(i)) {\n for (const error of errorMap.get(i)!) {\n const { loc } = error;\n const start = loc.end.line === loc.start.line ? loc.start.column - 1 : loc.end.column - 1;\n const end = loc.end.column - 1;\n const symbol = error.type === 'error' ? '❌' : error.type === 'warning' ? '⚠️' : 'ℹ️';\n const extra = recurrenceNoteFor.get(error);\n const message = extra\n ? `${error.message} (recurs ${extra} more time${extra === 1 ? '' : 's'})`\n : error.message;\n nextLine(\n colorize\n ? `${''.padStart(LINE_SIZE, ' ') + symbol}\\t${' '.repeat(start)}%c^${'~'.repeat(end - start)} %c//%c ${message}%c`\n : `${''.padStart(LINE_SIZE, ' ') + symbol}\\t${' '.repeat(start)}^${'~'.repeat(end - start)} // ${message}`,\n [\n error.type === 'error' ? 'color: red;' : error.type === 'warning' ? 'color: orange;' : 'color: blue;',\n 'color: grey;',\n error.type === 'error' ? 'color: red;' : error.type === 'warning' ? 'color: orange;' : 'color: blue;',\n 'color: inherit; background-color: transparent;',\n ]\n );\n }\n }\n }\n }\n\n const lastRenderedRange = ranges[ranges.length - 1];\n if (lastRenderedRange && lastRenderedRange[1] < lines.length) {\n pushSkipMarker(lines.length - lastRenderedRange[1]);\n }\n\n if (hiddenGroupCount > 0) {\n nextLine(\n colorize\n ? `%c... and ${hiddenGroupCount} more distinct issue${hiddenGroupCount === 1 ? '' : 's'} (${hiddenOccurrenceCount} occurrence${hiddenOccurrenceCount === 1 ? '' : 's'}) not shown ...%c`\n : `... and ${hiddenGroupCount} more distinct issues (${hiddenOccurrenceCount} occurrences) not shown ...`,\n ['color: grey; font-style: italic;', 'color: inherit; background-color: transparent;']\n );\n }\n\n chunks.forEach((chunk, index) => {\n const prefix = index === 0 ? `${contextStr}\\n\\n` : '';\n const chunkString = prefix + chunk.text.join('\\n');\n // eslint-disable-next-line no-console, @typescript-eslint/no-unused-expressions\n colorize ? console.log(chunkString, ...chunk.colors) : console.log(chunkString);\n });\n\n if (JSON_API_CACHE_VALIDATION_ERRORS) {\n if (counts.error > 0) {\n throw new Error(contextStr);\n }\n }\n }\n}\n\n// we always want to sort errors first, then warnings, then info\nfunction compareType(a: 'error' | 'warning' | 'info', b: 'error' | 'warning' | 'info') {\n if (a === b) {\n return 0;\n }\n if (a === 'error') {\n return -1;\n }\n if (b === 'error') {\n return 1;\n }\n if (a === 'warning') {\n return -1;\n }\n if (b === 'warning') {\n return 1;\n }\n return 0;\n}\n\ntype ReporterFn = (reporter: Reporter, path: PathLike) => void;\nconst REGISTERED_EXTENSIONS = new Map<string, ReporterFn>();\n\nexport function isMetaDocument(\n doc: StructuredDocument<ResourceDocument>\n): doc is StructuredDataDocument<ResourceMetaDocument> {\n return (\n !(doc instanceof Error) &&\n doc.content &&\n !('data' in doc.content) &&\n !('included' in doc.content) &&\n 'meta' in doc.content\n );\n}\n\nexport function isErrorDocument(\n doc: StructuredDocument<ResourceDocument>\n): doc is StructuredErrorDocument<ResourceErrorDocument> {\n return doc instanceof Error;\n}\n\nexport function isPushedDocument(doc: unknown): doc is { content: ResourceDataDocument } {\n return !!doc && typeof doc === 'object' && 'content' in doc && !('request' in doc) && !('response' in doc);\n}\n\nexport function logPotentialMatches(matches: FuseResult<string>[], kind: string): string {\n if (matches.length === 0) {\n return '';\n }\n\n if (matches.length === 1) {\n return ` Did you mean this available ${kind} \"${matches[0].item}\"?`;\n }\n\n const potentialMatches = matches.map((match) => match.item).join('\", \"');\n return ` Did you mean one of these available ${kind}s: \"${potentialMatches}\"?`;\n}\n\nfunction isRemoteField(v: FieldSchema): boolean {\n return !(v.kind === '@local' || v.kind === 'alias' || v.kind === 'derived');\n}\n\nexport function getRemoteField(fields: Map<string, FieldSchema>, key: string): FieldSchema | undefined {\n const field = fields.get(key);\n if (!field) {\n return undefined;\n }\n if (!isRemoteField(field)) {\n return undefined;\n }\n return field;\n}\n\n/**\n * Detects the common mistake of providing a field's `name` in a payload\n * when the field's schema defines a `sourceKey` that should be used instead.\n *\n * @internal\n */\nexport function getSourceKeyMismatch(\n fields: Map<string, FieldSchema>,\n key: string\n): { field: FieldSchema; sourceKey: string } | undefined {\n const field = getRemoteField(fields, key);\n if (!field) {\n return undefined;\n }\n const sourceKey = 'sourceKey' in field ? field.sourceKey : undefined;\n if (sourceKey && sourceKey !== key) {\n return { field, sourceKey };\n }\n return undefined;\n}\n\nfunction addResourceToMap(\n map: Map<string, Map<string, ResourceInfo[]>>,\n resource: ResourceObject,\n index: number | null,\n location: 'data' | 'included'\n): void {\n if (!map.has(resource.type)) {\n map.set(resource.type, new Map());\n }\n if (!map.get(resource.type)!.has(resource.id!)) {\n map.get(resource.type)!.set(resource.id!, []);\n }\n map.get(resource.type)!.get(resource.id!)!.push({ data: resource, index, location });\n}\n\nexport function checkResourceInMap(\n map: Map<string, Map<string, ResourceInfo[]>>,\n resource: { type: string; id: string }\n): boolean {\n return map.has(resource.type) && map.get(resource.type)!.has(resource.id);\n}\n\nexport function checkResourcePresent(presence: ResourcePresence, resource: { type: string; id: string }): boolean {\n return checkResourceInMap(presence.data, resource) || checkResourceInMap(presence.included, resource);\n}\n","import type { NotifyKeys, Store } from '@warp-drive/core';\nimport { LOG_CACHE } from '@warp-drive/core/build-config/debugging';\nimport { DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE } from '@warp-drive/core/build-config/deprecations';\nimport { DEBUG } from '@warp-drive/core/build-config/env';\nimport { assert } from '@warp-drive/core/build-config/macros';\nimport type { CollectionEdge, Graph, GraphEdge, ImplicitEdge, ResourceEdge } from '@warp-drive/core/graph/-private';\nimport { graphFor, isBelongsTo, peekGraph } from '@warp-drive/core/graph/-private';\nimport { assertPrivateCapabilities, isRequestKey, isResourceKey, logGroup } from '@warp-drive/core/store/-private';\nimport type { CacheCapabilitiesManager } from '@warp-drive/core/types';\nimport type { Cache, ChangedAttributesHash, RelationshipDiff } from '@warp-drive/core/types/cache';\nimport type { Change } from '@warp-drive/core/types/cache/change';\nimport type {\n AddResourceOperation,\n AddToDocumentOperation,\n AddToResourceRelationshipOperation,\n Op,\n Operation,\n RemoveDocumentOperation,\n RemoveFromDocumentOperation,\n RemoveFromResourceRelationshipOperation,\n RemoveResourceOperation,\n UpdateResourceFieldOperation,\n UpdateResourceOperation,\n UpdateResourceRelationshipOperation,\n} from '@warp-drive/core/types/cache/operations';\nimport type { CollectionRelationship, ResourceRelationship } from '@warp-drive/core/types/cache/relationship';\nimport type { LocalRelationshipOperation } from '@warp-drive/core/types/graph';\nimport type { PersistedResourceKey, RequestKey, ResourceKey } from '@warp-drive/core/types/identifier';\nimport type { ObjectValue, Value } from '@warp-drive/core/types/json/raw';\nimport type {\n ImmutableRequestInfo,\n RequestContext,\n StructuredDataDocument,\n StructuredDocument,\n StructuredErrorDocument,\n} from '@warp-drive/core/types/request';\nimport type {\n CacheableFieldSchema,\n CollectionField,\n FieldSchema,\n IdentityField,\n LegacyHasManyField,\n LegacyRelationshipField,\n ResourceField,\n} from '@warp-drive/core/types/schema/fields';\nimport type {\n CollectionResourceDataDocument,\n ResourceDataDocument,\n ResourceDocument,\n ResourceErrorDocument,\n ResourceMetaDocument,\n SingleResourceDataDocument,\n} from '@warp-drive/core/types/spec/document';\nimport type { ApiError } from '@warp-drive/core/types/spec/error';\nimport type {\n CollectionResourceDocument,\n ExistingResourceObject,\n ResourceObject,\n SingleResourceDocument,\n SingleResourceRelationship,\n} from '@warp-drive/core/types/spec/json-api-raw';\n\nimport { validateDocumentFields } from './validate-document-fields.ts';\nimport { validateDocument } from './validator/index.ts';\nimport { isErrorDocument, isMetaDocument } from './validator/utils.ts';\n\ntype CacheKeyManager = Store['cacheKeyManager'];\n\nfunction isImplicit(relationship: GraphEdge): relationship is ImplicitEdge {\n return relationship.definition.isImplicit;\n}\n\nconst EMPTY_ITERATOR = {\n iterator() {\n return {\n next() {\n return { done: true, value: undefined };\n },\n };\n },\n};\n\ninterface CachedResource {\n id: string | null;\n remoteAttrs: Record<string, Value | undefined> | null;\n localAttrs: Record<string, Value | undefined> | null;\n defaultAttrs: Record<string, Value | undefined> | null;\n inflightAttrs: Record<string, Value | undefined> | null;\n changes: Record<string, [Value | undefined, Value]> | null;\n errors: ApiError[] | null;\n isNew: boolean;\n isDeleted: boolean;\n isDeletionCommitted: boolean;\n\n /**\n * debugging only\n *\n * @internal\n */\n inflightRelationships?: Record<string, unknown> | null;\n}\n\nfunction makeCache(): CachedResource {\n return {\n id: null,\n remoteAttrs: null,\n localAttrs: null,\n defaultAttrs: null,\n inflightAttrs: null,\n changes: null,\n errors: null,\n isNew: false,\n isDeleted: false,\n isDeletionCommitted: false,\n };\n}\n\n/**\n * ```ts\n * import { JSONAPICache } from '@warp-drive/json-api';\n * ```\n *\n * A {@link Cache} implementation tuned for [{json:api}](https://jsonapi.org/)\n *\n * @categoryDescription Cache Management\n * APIs for primary cache management functionality\n * @categoryDescription Cache Forking\n * APIs that support Cache Forking\n * @categoryDescription SSR Support\n * APIs that support SSR functionality\n * @categoryDescription Resource Lifecycle\n * APIs that support management of resource data\n * @categoryDescription Resource Data\n * APIs that support granular field level management of resource data\n * @categoryDescription Resource State\n * APIs that support managing Resource states\n *\n * @public\n */\nexport class JSONAPICache implements Cache {\n /**\n * The Cache Version that this implementation implements.\n *\n * @public\n */\n declare version: '2';\n\n /** @internal */\n declare _capabilities: CacheCapabilitiesManager;\n /** @internal */\n declare __cache: Map<ResourceKey, CachedResource>;\n /** @internal */\n declare __destroyedCache: Map<ResourceKey, CachedResource>;\n /** @internal */\n declare __documents: Map<string, StructuredDocument<ResourceDocument>>;\n /** @internal */\n declare __graph: Graph;\n\n constructor(capabilities: CacheCapabilitiesManager) {\n this.version = '2';\n this._capabilities = capabilities;\n this.__cache = new Map();\n this.__graph = graphFor(capabilities);\n this.__destroyedCache = new Map();\n this.__documents = new Map();\n }\n\n ////////// ================ //////////\n ////////// Cache Management //////////\n ////////// ================ //////////\n\n /**\n * Cache the response to a request\n *\n * Implements `Cache.put`.\n *\n * Expects a StructuredDocument whose `content` member is a JsonApiDocument.\n *\n * ```js\n * cache.put({\n * request: { url: 'https://api.example.com/v1/user/1' },\n * content: {\n * data: {\n * type: 'user',\n * id: '1',\n * attributes: {\n * name: 'Chris'\n * }\n * }\n * }\n * })\n * ```\n *\n * > **Note**\n * > The nested `content` and `data` members are not a mistake. This is because\n * > there are two separate concepts involved here, the `StructuredDocument` which contains\n * > the context of a given Request that has been issued with the returned contents as its\n * > `content` property, and a `JSON:API Document` which is the json contents returned by\n * > this endpoint and which uses its `data` property to signify which resources are the\n * > primary resources associated with the request.\n *\n * StructuredDocument's with urls will be cached as full documents with\n * associated resource membership order and contents preserved but linked\n * into the cache.\n *\n * @category Cache Management\n * @public\n */\n put<T extends SingleResourceDocument>(doc: StructuredDataDocument<T>): SingleResourceDataDocument;\n put<T extends CollectionResourceDocument>(doc: StructuredDataDocument<T>): CollectionResourceDataDocument;\n put<T extends ResourceErrorDocument>(doc: StructuredErrorDocument<T>): ResourceErrorDocument;\n put<T extends ResourceMetaDocument>(doc: StructuredDataDocument<T>): ResourceMetaDocument;\n put(doc: StructuredDocument<ResourceDocument>): ResourceDocument {\n if (DEBUG) {\n validateDocument(this._capabilities, doc);\n }\n\n if (isErrorDocument(doc)) {\n return this._putDocument(doc, undefined, undefined);\n } else if (isMetaDocument(doc)) {\n return this._putDocument(doc, undefined, undefined);\n }\n\n const jsonApiDoc = doc.content as SingleResourceDocument | CollectionResourceDocument;\n const included = jsonApiDoc.included;\n let i: number, length: number;\n const { cacheKeyManager } = this._capabilities;\n\n if (DEBUG) {\n validateDocumentFields(this._capabilities.schema, jsonApiDoc);\n }\n\n if (LOG_CACHE) {\n const Counts = new Map();\n let totalCount = 0;\n if (included) {\n for (i = 0, length = included.length; i < length; i++) {\n const type = included[i].type;\n Counts.set(type, (Counts.get(type) || 0) + 1);\n totalCount++;\n }\n }\n if (Array.isArray(jsonApiDoc.data)) {\n for (i = 0, length = jsonApiDoc.data.length; i < length; i++) {\n const type = jsonApiDoc.data[i].type;\n Counts.set(type, (Counts.get(type) || 0) + 1);\n totalCount++;\n }\n } else if (jsonApiDoc.data) {\n const type = jsonApiDoc.data.type;\n Counts.set(type, (Counts.get(type) || 0) + 1);\n totalCount++;\n }\n\n logGroup(\n 'cache',\n 'put',\n '<@document>',\n doc.content?.lid || doc.request?.url || 'unknown-request',\n `(${totalCount}) records`,\n ''\n );\n let str = `\\tContent Counts:`;\n Counts.forEach((count, type) => {\n str += `\\n\\t\\t${type}: ${count} record${count > 1 ? 's' : ''}`;\n });\n if (Counts.size === 0) {\n str += `\\t(empty)`;\n }\n // eslint-disable-next-line no-console\n console.log(str);\n // eslint-disable-next-line no-console\n console.log({\n lid: doc.content?.lid,\n content: structuredClone(doc.content),\n // we may need a specialized copy here\n request: doc.request, // structuredClone(doc.request),\n response: doc.response, // structuredClone(doc.response),\n });\n // eslint-disable-next-line no-console\n console.groupEnd();\n }\n\n if (included) {\n for (i = 0, length = included.length; i < length; i++) {\n included[i] = putOne(this, cacheKeyManager, included[i]);\n }\n }\n\n if (Array.isArray(jsonApiDoc.data)) {\n length = jsonApiDoc.data.length;\n const identifiers: PersistedResourceKey[] = [];\n\n for (i = 0; i < length; i++) {\n identifiers.push(putOne(this, cacheKeyManager, jsonApiDoc.data[i]));\n }\n return this._putDocument(\n doc as StructuredDataDocument<CollectionResourceDocument>,\n identifiers,\n included as PersistedResourceKey[]\n );\n }\n\n if (jsonApiDoc.data === null) {\n return this._putDocument(\n doc as StructuredDataDocument<SingleResourceDocument>,\n null,\n included as PersistedResourceKey[]\n );\n }\n\n const identifier = putOne(this, cacheKeyManager, jsonApiDoc.data);\n return this._putDocument(\n doc as StructuredDataDocument<SingleResourceDocument>,\n identifier,\n included as PersistedResourceKey[]\n );\n }\n\n /** @internal */\n private _putDocument<T extends ResourceErrorDocument>(\n doc: StructuredErrorDocument<T>,\n data: undefined,\n included: undefined\n ): ResourceErrorDocument;\n /** @internal */\n private _putDocument<T extends ResourceMetaDocument>(\n doc: StructuredDataDocument<T>,\n data: undefined,\n included: undefined\n ): ResourceMetaDocument;\n /** @internal */\n private _putDocument<T extends SingleResourceDocument>(\n doc: StructuredDataDocument<T>,\n data: PersistedResourceKey | null,\n included: PersistedResourceKey[] | undefined\n ): SingleResourceDataDocument;\n /** @internal */\n private _putDocument<T extends CollectionResourceDocument>(\n doc: StructuredDataDocument<T>,\n data: PersistedResourceKey[],\n included: PersistedResourceKey[] | undefined\n ): CollectionResourceDataDocument;\n /** @internal */\n private _putDocument<T extends ResourceDocument>(\n doc: StructuredDocument<T>,\n data: PersistedResourceKey[] | PersistedResourceKey | null | undefined,\n included: PersistedResourceKey[] | undefined\n ): SingleResourceDataDocument | CollectionResourceDataDocument | ResourceErrorDocument | ResourceMetaDocument {\n // @ts-expect-error narrowing within is just horrible in TS :/\n const resourceDocument: SingleResourceDataDocument | CollectionResourceDataDocument | ResourceErrorDocument =\n isErrorDocument(doc) ? fromStructuredError(doc) : fromBaseDocument(doc);\n\n if (data !== undefined) {\n (resourceDocument as ResourceDataDocument).data = data;\n }\n\n if (included !== undefined) {\n assert(`There should not be included data on an Error document`, !isErrorDocument(doc));\n assert(`There should not be included data on a Meta document`, !isMetaDocument(doc));\n (resourceDocument as ResourceDataDocument).included = included;\n }\n\n const request = doc.request as ImmutableRequestInfo | undefined;\n const identifier = request ? this._capabilities.cacheKeyManager.getOrCreateDocumentIdentifier(request) : null;\n\n if (identifier) {\n resourceDocument.lid = identifier.lid;\n\n // @ts-expect-error\n doc.content = resourceDocument;\n const hasExisting = this.__documents.has(identifier.lid);\n this.__documents.set(identifier.lid, doc as StructuredDocument<ResourceDocument>);\n\n this._capabilities.notifyChange(identifier, hasExisting ? 'updated' : 'added', null);\n }\n\n if (doc.request?.op === 'findHasMany') {\n const parentIdentifier = doc.request.options?.identifier as ResourceKey | undefined;\n const parentField = doc.request.options?.field as LegacyHasManyField | undefined;\n assert(`Expected a hasMany field`, parentField?.kind === 'hasMany');\n assert(\n `Expected a parent identifier for a findHasMany request`,\n parentIdentifier && isResourceKey(parentIdentifier)\n );\n if (parentField && parentIdentifier) {\n this.__graph.push({\n op: 'updateRelationship',\n record: parentIdentifier,\n field: parentField.name,\n value: resourceDocument,\n });\n }\n }\n\n return resourceDocument;\n }\n\n /**\n * Update the \"remote\" or \"canonical\" (persisted) state of the Cache\n * by merging new information into the existing state.\n *\n * @category Cache Management\n * @public\n * @param op the operation or list of operations to perform\n */\n patch(op: Operation | Operation[]): void {\n if (Array.isArray(op)) {\n if (LOG_CACHE) {\n logGroup('cache', 'patch', '<BATCH>', String(op.length) + ' operations', '', '');\n }\n\n assertPrivateCapabilities(this._capabilities);\n this._capabilities._store._join(() => {\n for (const operation of op) {\n patchCache(this, operation);\n }\n });\n\n if (LOG_CACHE) {\n // eslint-disable-next-line no-console\n console.groupEnd();\n }\n } else {\n patchCache(this, op);\n }\n }\n\n /**\n * Update the \"local\" or \"current\" (unpersisted) state of the Cache\n *\n * @category Cache Management\n * @public\n */\n mutate(mutation: LocalRelationshipOperation): void {\n if (LOG_CACHE) {\n logGroup('cache', 'mutate', mutation.record.type, mutation.record.lid, mutation.field, mutation.op);\n try {\n const _data = JSON.parse(JSON.stringify(mutation)) as object;\n // eslint-disable-next-line no-console\n console.log(_data);\n } catch {\n // eslint-disable-next-line no-console\n console.log(mutation);\n }\n }\n this.__graph.update(mutation, false);\n\n if (LOG_CACHE) {\n // eslint-disable-next-line no-console\n console.groupEnd();\n }\n }\n\n /**\n * Peek resource data from the Cache.\n *\n * In development, if the return value\n * is JSON the return value\n * will be deep-cloned and deep-frozen\n * to prevent mutation thereby enforcing cache\n * Immutability.\n *\n * This form of peek is useful for implementations\n * that want to feed raw-data from cache to the UI\n * or which want to interact with a blob of data\n * directly from the presentation cache.\n *\n * An implementation might want to do this because\n * de-referencing records which read from their own\n * blob is generally safer because the record does\n * not require retainining connections to the Store\n * and Cache to present data on a per-field basis.\n *\n * This generally takes the place of `getAttr` as\n * an API and may even take the place of `getRelationship`\n * depending on implementation specifics, though this\n * latter usage is less recommended due to the advantages\n * of the Graph handling necessary entanglements and\n * notifications for relational data.\n *\n * :::warning\n * It is not recommended to use the return value as\n * a serialized representation of the resource both\n * due to it containing local mutations and because\n * it may contain additional fields not recognized\n * by the {json:api} API implementation such as `lid` and\n * the various internal WarpDrive bookkeeping fields.\n * :::\n *\n * @category Cache Management\n * @public\n */\n peek(identifier: ResourceKey): ResourceObject | null;\n peek(identifier: RequestKey): ResourceDocument | null;\n peek(identifier: RequestKey | ResourceKey): ResourceObject | ResourceDocument | null {\n if (isResourceKey(identifier)) {\n const peeked = this.__safePeek(identifier, false);\n\n if (!peeked) {\n return null;\n }\n\n const { type, id, lid } = identifier;\n const attributes = structuredClone(\n Object.assign({}, peeked.remoteAttrs, peeked.inflightAttrs, peeked.localAttrs)\n ) as ObjectValue;\n const relationships: ResourceObject['relationships'] = {};\n\n const rels = this.__graph.identifiers.get(identifier);\n if (rels) {\n Object.keys(rels).forEach((key) => {\n const rel = rels[key];\n if (rel.definition.isImplicit) {\n return;\n } else {\n relationships[key] = this.__graph.getData(identifier, key);\n }\n });\n }\n\n assertPrivateCapabilities(this._capabilities);\n const store = this._capabilities._store;\n const attrs = getCacheFields(this, identifier);\n attrs.forEach((attr, key) => {\n if (key in attributes && attributes[key] !== undefined) {\n return;\n }\n const defaultValue = getDefaultValue(attr, identifier, store);\n\n if (defaultValue !== undefined) {\n attributes[key] = defaultValue;\n }\n });\n\n return {\n type,\n id,\n lid,\n attributes,\n relationships,\n };\n }\n\n const document = this.peekRequest(identifier);\n\n if (document) {\n if ('content' in document) return document.content!;\n }\n return null;\n }\n\n /**\n * Peek the remote resource data from the Cache.\n *\n * @category Cache Management\n * @public\n */\n peekRemoteState(identifier: ResourceKey): ResourceObject | null;\n peekRemoteState(identifier: RequestKey): ResourceDocument | null;\n peekRemoteState(identifier: RequestKey | ResourceKey): ResourceObject | ResourceDocument | null {\n if (isResourceKey(identifier)) {\n const peeked = this.__safePeek(identifier, false);\n\n if (!peeked) {\n return null;\n }\n\n const { type, id, lid } = identifier;\n const attributes = structuredClone(peeked.remoteAttrs) as ObjectValue;\n const relationships: ResourceObject['relationships'] = {};\n\n const rels = this.__graph.identifiers.get(identifier);\n if (rels) {\n Object.keys(rels).forEach((key) => {\n const rel = rels[key];\n if (rel.definition.isImplicit) {\n return;\n } else {\n relationships[key] = structuredClone(this.__graph.getData(identifier, key));\n }\n });\n }\n\n assertPrivateCapabilities(this._capabilities);\n const store = this._capabilities._store;\n const attrs = getCacheFields(this, identifier);\n attrs.forEach((attr, key) => {\n if (key in attributes && attributes[key] !== undefined) {\n return;\n }\n const defaultValue = getDefaultValue(attr, identifier, store);\n\n if (defaultValue !== undefined) {\n attributes[key] = defaultValue;\n }\n });\n\n return {\n type,\n id,\n lid,\n attributes,\n relationships,\n };\n }\n\n const document = this.peekRequest(identifier);\n\n if (document) {\n if ('content' in document) return document.content!;\n }\n return null;\n }\n\n /**\n * Peek the Cache for the existing request data associated with\n * a cacheable request.\n *\n * This is effectively the reverse of `put` for a request in\n * that it will return the the request, response, and content\n * whereas `peek` will return just the `content`.\n *\n * @category Cache Management\n * @public\n */\n peekRequest(identifier: RequestKey): StructuredDocument<ResourceDocument> | null {\n return this.__documents.get(identifier.lid) || null;\n }\n\n /**\n * Push resource data from a remote source into the cache for this identifier\n *\n * @category Cache Management\n * @public\n * @return if `calculateChanges` is true then calculated key changes should be returned\n */\n upsert(identifier: ResourceKey, data: ExistingResourceObject, calculateChanges?: boolean): void | string[] {\n assertPrivateCapabilities(this._capabilities);\n const store = this._capabilities._store;\n if (!store._cbs) {\n let result: void | string[] = undefined;\n\n store._run(() => {\n result = cacheUpsert(this, identifier, data, calculateChanges);\n });\n return result;\n }\n\n return cacheUpsert(this, identifier, data, calculateChanges);\n }\n\n ////////// ============= //////////\n ////////// Cache Forking //////////\n ////////// ============= //////////\n\n /**\n * Create a fork of the cache from the current state.\n *\n * Applications should typically not call this method themselves,\n * preferring instead to fork at the Store level, which will\n * utilize this method to fork the cache.\n *\n * @category Cache Forking\n * @private\n */\n fork(): Promise<Cache> {\n throw new Error(`Not Implemented`);\n }\n\n /**\n * Merge a fork back into a parent Cache.\n *\n * Applications should typically not call this method themselves,\n * preferring instead to merge at the Store level, which will\n * utilize this method to merge the caches.\n *\n * @category Cache Forking\n * @private\n */\n merge(_cache: Cache): Promise<void> {\n throw new Error(`Not Implemented`);\n }\n\n /**\n * Generate the list of changes applied to all\n * record in the store.\n *\n * Each individual resource or document that has\n * been mutated should be described as an individual\n * `Change` entry in the returned array.\n *\n * A `Change` is described by an object containing up to\n * three properties: (1) the `identifier` of the entity that\n * changed; (2) the `op` code of that change being one of\n * `upsert` or `remove`, and if the op is `upsert` a `patch`\n * containing the data to merge into the cache for the given\n * entity.\n *\n * This `patch` is opaque to the Store but should be understood\n * by the Cache and may expect to be utilized by an Adapter\n * when generating data during a `save` operation.\n *\n * It is generally recommended that the `patch` contain only\n * the updated state, ignoring fields that are unchanged\n *\n * ```ts\n * interface Change {\n * identifier: ResourceKey | RequestKey;\n * op: 'upsert' | 'remove';\n * patch?: unknown;\n * }\n * ```\n *\n * @category Cache Forking\n * @private\n */\n diff(): Promise<Change[]> {\n throw new Error(`Not Implemented`);\n }\n\n ////////// =========== //////////\n ////////// SSR Support //////////\n ////////// =========== //////////\n\n /**\n * Serialize the entire contents of the Cache into a Stream\n * which may be fed back into a new instance of the same Cache\n * via `cache.hydrate`.\n *\n * @category SSR Support\n * @private\n */\n dump(): Promise<ReadableStream<unknown>> {\n throw new Error(`Not Implemented`);\n }\n\n /**\n * hydrate a Cache from a Stream with content previously serialized\n * from another instance of the same Cache, resolving when hydration\n * is complete.\n *\n * This method should expect to be called both in the context of restoring\n * the Cache during application rehydration after SSR **AND** at unknown\n * times during the lifetime of an already booted application when it is\n * desired to bulk-load additional information into the cache. This latter\n * behavior supports optimizing pre/fetching of data for route transitions\n * via data-only SSR modes.\n *\n * @category SSR Support\n * @private\n */\n hydrate(stream: ReadableStream<unknown>): Promise<void> {\n throw new Error('Not Implemented');\n }\n\n ////////// ================== //////////\n ////////// Resource Lifecycle //////////\n ////////// ================== //////////\n\n /**\n * [LIFECYCLE] Signal to the cache that a new record has been instantiated on the client\n *\n * It returns properties from options that should be set on the record during the create\n * process. This return value behavior is deprecated.\n *\n * @category Resource Lifecycle\n * @public\n */\n clientDidCreate(identifier: ResourceKey, options?: Record<string, Value>): Record<string, unknown> {\n if (LOG_CACHE) {\n try {\n const _data = options ? (JSON.parse(JSON.stringify(options)) as object) : options;\n // eslint-disable-next-line no-console\n console.log(`WarpDrive | Mutation - clientDidCreate ${identifier.lid}`, _data);\n } catch {\n // eslint-disable-next-line no-console\n console.log(`WarpDrive | Mutation - clientDidCreate ${identifier.lid}`, options);\n }\n }\n const cached = this._createCache(identifier);\n cached.isNew = true;\n const createOptions: Record<string, unknown> = {};\n\n if (options !== undefined) {\n const fields = getCacheFields(this, identifier);\n const graph = this.__graph;\n const propertyNames = Object.keys(options);\n\n for (let i = 0; i < propertyNames.length; i++) {\n const name = propertyNames[i];\n const propertyValue = options[name];\n\n if (name === 'id') {\n continue;\n }\n\n const fieldType: FieldSchema | undefined = fields.get(name);\n const kind = fieldType !== undefined ? ('kind' in fieldType ? fieldType.kind : 'attribute') : null;\n let relationship: ResourceEdge | CollectionEdge;\n\n switch (kind) {\n case 'attribute':\n this.setAttr(identifier, name, propertyValue);\n createOptions[name] = propertyValue;\n break;\n case 'belongsTo':\n this.mutate({\n op: 'replaceRelatedRecord',\n field: name,\n record: identifier,\n value: propertyValue as ResourceKey | null,\n });\n relationship = graph.get(identifier, name) as ResourceEdge;\n relationship.state.hasReceivedData = true;\n relationship.state.isEmpty = false;\n break;\n case 'hasMany':\n this.mutate({\n op: 'replaceRelatedRecords',\n field: name,\n record: identifier,\n value: propertyValue as unknown as ResourceKey[],\n });\n relationship = graph.get(identifier, name) as CollectionEdge;\n relationship.state.hasReceivedData = true;\n relationship.state.isEmpty = false;\n break;\n default:\n // reflect back (pass-thru) unknown properties\n createOptions[name] = propertyValue;\n }\n }\n }\n\n this._capabilities.notifyChange(identifier, 'added', null);\n\n return createOptions;\n }\n\n /**\n * [LIFECYCLE] Signals to the cache that a resource\n * will be part of a save transaction.\n *\n * @category Resource Lifecycle\n * @public\n */\n willCommit(identifier: ResourceKey | ResourceKey[], _context: RequestContext | null): void {\n if (Array.isArray(identifier)) {\n for (const key of identifier) {\n willCommit(this, key);\n }\n } else {\n willCommit(this, identifier);\n }\n }\n\n /**\n * [LIFECYCLE] Signals to the cache that a resource\n * was successfully updated as part of a save transaction.\n *\n * @category Resource Lifecycle\n * @public\n */\n didCommit(\n committedIdentifier: ResourceKey,\n result: StructuredDataDocument<SingleResourceDataDocument> | null\n ): SingleResourceDataDocument;\n didCommit(\n committedIdentifier: ResourceKey[],\n result: StructuredDataDocument<SingleResourceDataDocument> | null\n ): SingleResourceDataDocument;\n didCommit(\n committedIdentifier: ResourceKey[],\n result: StructuredDataDocument<CollectionResourceDataDocument> | null\n ): CollectionResourceDataDocument;\n didCommit(\n committedIdentifier: ResourceKey | ResourceKey[],\n result: StructuredDataDocument<SingleResourceDataDocument | CollectionResourceDataDocument> | null\n ): CollectionResourceDataDocument | SingleResourceDataDocument {\n const payload = result ? result.content : null;\n const operation = result?.request?.op ?? null;\n const data = payload && payload.data;\n\n if (LOG_CACHE) {\n try {\n const payloadCopy: unknown = payload ? JSON.parse(JSON.stringify(payload)) : payload;\n // eslint-disable-next-line no-console\n console.log(`WarpDrive | Payload - ${operation}`, payloadCopy);\n } catch {\n // eslint-disable-next-line no-console\n console.log(`WarpDrive | Payload - ${operation}`, payload);\n }\n }\n\n const responseIsCollection = Array.isArray(data);\n const hasMultipleIdentifiers = Array.isArray(committedIdentifier) && committedIdentifier.length > 1;\n\n if (Array.isArray(committedIdentifier)) {\n // if we get back an array of primary data, we treat each\n // entry as a separate commit for each identifier\n assert(\n `Expected the array of primary data to match the array of committed identifiers`,\n !hasMultipleIdentifiers || !responseIsCollection || data.length === committedIdentifier.length\n );\n if (responseIsCollection) {\n for (let i = 0; i < committedIdentifier.length; i++) {\n const identifier = committedIdentifier[i];\n didCommit(this, identifier, data[i] ?? null, operation);\n }\n // but if we get back no data or a single entry, we apply\n // the change back to the original identifier\n } else {\n for (let i = 0; i < committedIdentifier.length; i++) {\n const identifier = committedIdentifier[i];\n didCommit(this, identifier, i === 0 ? data : null, operation);\n }\n }\n } else {\n didCommit(this, committedIdentifier, data as ExistingResourceObject | null, operation);\n }\n\n const included = payload && payload.included;\n const { cacheKeyManager } = this._capabilities;\n if (included) {\n for (let i = 0, length = included.length; i < length; i++) {\n putOne(this, cacheKeyManager, included[i]);\n }\n }\n\n return hasMultipleIdentifiers && responseIsCollection\n ? {\n data: committedIdentifier as PersistedResourceKey[],\n }\n : {\n data: (Array.isArray(committedIdentifier)\n ? committedIdentifier[0]\n : committedIdentifier) as PersistedResourceKey,\n };\n }\n\n /**\n * [LIFECYCLE] Signals to the cache that a resource\n * was update via a save transaction failed.\n *\n * @category Resource Lifecycle\n * @public\n */\n commitWasRejected(identifier: ResourceKey | ResourceKey[], errors?: ApiError[]): void {\n if (Array.isArray(identifier)) {\n for (let i = 0; i < identifier.length; i++) {\n commitDidError(this, identifier[i], errors && i === 0 ? errors : null);\n }\n return;\n }\n\n return commitDidError(this, identifier, errors || null);\n }\n\n /**\n * [LIFECYCLE] Signals to the cache that all data for a resource\n * should be cleared.\n *\n * This method is a candidate to become a mutation\n *\n * @category Resource Lifecycle\n * @public\n */\n unloadRecord(identifier: ResourceKey): void {\n const storeWrapper = this._capabilities;\n // TODO this is necessary because\n // we maintain memebership inside InstanceCache\n // for peekAll, so even though we haven't created\n // any data we think this exists.\n // TODO can we eliminate that membership now?\n if (!this.__cache.has(identifier)) {\n // the graph may still need to unload identity\n peekGraph(storeWrapper)?.unload(identifier);\n return;\n }\n const removeFromRecordArray = !this.isDeletionCommitted(identifier);\n let removed = false;\n const cached = this.__peek(identifier, false);\n\n if (cached.isNew || cached.isDeletionCommitted) {\n peekGraph(storeWrapper)?.push({\n op: 'deleteRecord',\n record: identifier,\n isNew: cached.isNew,\n });\n } else {\n peekGraph(storeWrapper)?.unload(identifier);\n }\n\n // effectively clearing these is ensuring that\n // we report as `isEmpty` during teardown.\n cached.localAttrs = null;\n cached.remoteAttrs = null;\n cached.defaultAttrs = null;\n cached.inflightAttrs = null;\n\n const relatedIdentifiers = _allRelatedIdentifiers(storeWrapper, identifier);\n if (areAllModelsUnloaded(storeWrapper, relatedIdentifiers)) {\n for (let i = 0; i < relatedIdentifiers.length; ++i) {\n const relatedIdentifier = relatedIdentifiers[i];\n storeWrapper.notifyChange(relatedIdentifier, 'removed', null);\n removed = true;\n storeWrapper.disconnectRecord(relatedIdentifier);\n }\n }\n\n this.__cache.delete(identifier);\n this.__destroyedCache.set(identifier, cached);\n\n /*\n * The destroy cache is a hack to prevent applications\n * from blowing up during teardown. Accessing state\n * on a destroyed record is not safe, but historically\n * was possible due to a combination of teardown timing\n * and retention of cached state directly on the\n * record itself.\n *\n * Once we have deprecated accessing state on a destroyed\n * instance we may remove this. The timing isn't a huge deal\n * as momentarily retaining the objects outside the bounds\n * of a test won't cause issues.\n */\n if (this.__destroyedCache.size === 1) {\n // TODO do we still need this?\n setTimeout(() => {\n this.__destroyedCache.clear();\n }, 100);\n }\n\n if (!removed && removeFromRecordArray) {\n storeWrapper.notifyChange(identifier, 'removed', null);\n }\n }\n\n ////////// ============= //////////\n ////////// Resource Data //////////\n ////////// ============= //////////\n\n /**\n * Retrieve the data for an attribute from the cache\n * with local mutations applied.\n *\n * @category Resource Data\n * @public\n */\n getAttr(identifier: ResourceKey, attr: string | string[]): Value | undefined {\n const isSimplePath = !Array.isArray(attr) || attr.length === 1;\n if (Array.isArray(attr) && attr.length === 1) {\n attr = attr[0];\n }\n\n if (isSimplePath) {\n const attribute = attr as string;\n const cached = this.__peek(identifier, true);\n assert(\n `Cannot retrieve attributes for identifier ${String(identifier)} as it is not present in the cache`,\n cached\n );\n\n // in Prod we try to recover when accessing something that\n // doesn't exist\n if (!cached) {\n return undefined;\n }\n\n if (cached.localAttrs && attribute in cached.localAttrs) {\n return cached.localAttrs[attribute];\n } else if (cached.inflightAttrs && attribute in cached.inflightAttrs) {\n return cached.inflightAttrs[attribute];\n } else if (cached.remoteAttrs && attribute in cached.remoteAttrs) {\n return cached.remoteAttrs[attribute];\n } else if (cached.defaultAttrs && attribute in cached.defaultAttrs) {\n return cached.defaultAttrs[attribute];\n } else {\n const attrSchema = getCacheFields(this, identifier).get(attribute);\n\n assertPrivateCapabilities(this._capabilities);\n const defaultValue = getDefaultValue(attrSchema, identifier, this._capabilities._store);\n if (schemaHasLegacyDefaultValueFn(attrSchema)) {\n cached.defaultAttrs = cached.defaultAttrs || (Object.create(null) as Record<string, Value>);\n cached.defaultAttrs[attribute] = defaultValue;\n }\n return defaultValue;\n }\n }\n\n // TODO @runspired consider whether we need a defaultValue cache in ReactiveResource\n // like we do for the simple case above.\n const path: string[] = attr as string[];\n const cached = this.__peek(identifier, true);\n const basePath = path[0];\n let current = cached.localAttrs && basePath in cached.localAttrs ? cached.localAttrs[basePath] : undefined;\n if (current === undefined) {\n current = cached.inflightAttrs && basePath in cached.inflightAttrs ? cached.inflightAttrs[basePath] : undefined;\n }\n if (current === undefined) {\n current = cached.remoteAttrs && basePath in cached.remoteAttrs ? cached.remoteAttrs[basePath] : undefined;\n }\n if (current === undefined) {\n return undefined;\n }\n for (let i = 1; i < path.length; i++) {\n current = (current as ObjectValue)[path[i]];\n if (current === undefined) {\n return undefined;\n }\n }\n return current;\n }\n\n /**\n * Retrieve the remote data for an attribute from the cache\n *\n * @category Resource Data\n * @public\n */\n getRemoteAttr(identifier: ResourceKey, attr: string | string[]): Value | undefined {\n const isSimplePath = !Array.isArray(attr) || attr.length === 1;\n if (Array.isArray(attr) && attr.length === 1) {\n attr = attr[0];\n }\n\n if (isSimplePath) {\n const attribute = attr as string;\n const cached = this.__peek(identifier, true);\n assert(\n `Cannot retrieve remote attributes for identifier ${String(identifier)} as it is not present in the cache`,\n cached\n );\n\n // in Prod we try to recover when accessing something that\n // doesn't exist\n if (!cached) {\n return undefined;\n }\n\n if (cached.remoteAttrs && attribute in cached.remoteAttrs) {\n return cached.remoteAttrs[attribute];\n\n // we still show defaultValues in the case of a remoteAttr access\n } else if (cached.defaultAttrs && attribute in cached.defaultAttrs) {\n return cached.defaultAttrs[attribute];\n } else {\n const attrSchema = getCacheFields(this, identifier).get(attribute);\n\n assertPrivateCapabilities(this._capabilities);\n const defaultValue = getDefaultValue(attrSchema, identifier, this._capabilities._store);\n if (schemaHasLegacyDefaultValueFn(attrSchema)) {\n cached.defaultAttrs = cached.defaultAttrs || (Object.create(null) as Record<string, Value>);\n cached.defaultAttrs[attribute] = defaultValue;\n }\n return defaultValue;\n }\n }\n\n // TODO @runspired consider whether we need a defaultValue cache in ReactiveResource\n // like we do for the simple case above.\n const path: string[] = attr as string[];\n const cached = this.__peek(identifier, true);\n const basePath = path[0];\n let current = cached.remoteAttrs && basePath in cached.remoteAttrs ? cached.remoteAttrs[basePath] : undefined;\n\n if (current === undefined) {\n return undefined;\n }\n\n for (let i = 1; i < path.length; i++) {\n current = (current as ObjectValue)[path[i]];\n if (current === undefined) {\n return undefined;\n }\n }\n return current;\n }\n\n /**\n * Mutate the data for an attribute in the cache\n *\n * This method is a candidate to become a mutation\n *\n * @category Resource Data\n * @public\n */\n setAttr(identifier: ResourceKey, attr: string | string[], value: Value): void {\n // this assert works to ensure we have a non-empty string and/or a non-empty array\n assert('setAttr must receive at least one attribute path', attr.length > 0);\n const isSimplePath = !Array.isArray(attr) || attr.length === 1;\n\n if (Array.isArray(attr) && attr.length === 1) {\n attr = attr[0];\n }\n\n if (isSimplePath) {\n const cached = this.__peek(identifier, false);\n const currentAttr = attr as string;\n const existing =\n cached.inflightAttrs && currentAttr in cached.inflightAttrs\n ? cached.inflightAttrs[currentAttr]\n : cached.remoteAttrs && currentAttr in cached.remoteAttrs\n ? cached.remoteAttrs[currentAttr]\n : undefined;\n\n if (existing !== value) {\n cached.localAttrs = cached.localAttrs || (Object.create(null) as Record<string, Value>);\n cached.localAttrs[currentAttr] = value;\n cached.changes = cached.changes || (Object.create(null) as Record<string, [Value, Value]>);\n cached.changes[currentAttr] = [existing, value];\n } else if (cached.localAttrs) {\n delete cached.localAttrs[currentAttr];\n delete cached.changes![currentAttr];\n }\n\n if (cached.defaultAttrs && currentAttr in cached.defaultAttrs) {\n delete cached.defaultAttrs[currentAttr];\n }\n\n this._capabilities.notifyChange(identifier, 'attributes', currentAttr);\n return;\n }\n\n // get current value from local else inflight else remote\n // structuredClone current if not local (or always?)\n // traverse path, update value at path\n // notify change at first link in path.\n // second pass optimization is change notifyChange signature to take an array path\n\n // guaranteed that we have path of at least 2 in length\n const path: string[] = attr as string[];\n\n const cached = this.__peek(identifier, false);\n\n // get existing cache record for base path\n const basePath = path[0];\n const existing =\n cached.inflightAttrs && basePath in cached.inflightAttrs\n ? cached.inflightAttrs[basePath]\n : cached.remoteAttrs && basePath in cached.remoteAttrs\n ? cached.remoteAttrs[basePath]\n : undefined;\n\n let existingAttr;\n if (existing) {\n existingAttr = (existing as ObjectValue)[path[1]];\n\n for (let i = 2; i < path.length; i++) {\n // the specific change we're making is at path[length - 1]\n existingAttr = (existingAttr as ObjectValue)[path[i]];\n }\n }\n\n if (existingAttr !== value) {\n cached.localAttrs = cached.localAttrs || (Object.create(null) as Record<string, Value>);\n cached.localAttrs[basePath] = cached.localAttrs[basePath] || structuredClone(existing);\n cached.changes = cached.changes || (Object.create(null) as Record<string, [Value, Value]>);\n let currentLocal = cached.localAttrs[basePath] as ObjectValue;\n let nextLink = 1;\n\n while (nextLink < path.length - 1) {\n currentLocal = currentLocal[path[nextLink++]] as ObjectValue;\n }\n currentLocal[path[nextLink]] = value as ObjectValue;\n\n cached.changes[basePath] = [existing, cached.localAttrs[basePath] as ObjectValue];\n\n // since we initiaize the value as basePath as a clone of the value at the remote basePath\n // then in theory we can use JSON.stringify to compare the two values as key insertion order\n // ought to be consistent.\n // we try/catch this because users have a habit of doing \"Bad Things\"TM wherein the cache contains\n // stateful values that are not JSON serializable correctly such as Dates.\n // in the case that we error, we fallback to not removing the local value\n // so that any changes we don't understand are preserved. Thse objects would then sometimes\n // appear to be dirty unnecessarily, and for folks that open an issue we can guide them\n // to make their cache data less stateful.\n } else if (cached.localAttrs) {\n try {\n if (!existing) {\n return;\n }\n const existingStr = JSON.stringify(existing);\n const newStr = JSON.stringify(cached.localAttrs[basePath]);\n\n if (existingStr !== newStr) {\n delete cached.localAttrs[basePath];\n delete cached.changes![basePath];\n }\n } catch {\n // noop\n }\n }\n\n this._capabilities.notifyChange(identifier, 'attributes', basePath);\n }\n\n /**\n * Query the cache for the changed attributes of a resource.\n *\n * @category Resource Data\n * @public\n * @return `{ '<field>': ['<old>', '<new>'] }`\n */\n changedAttrs(identifier: ResourceKey): ChangedAttributesHash {\n const cached = this.__peek(identifier, false);\n assert(\n `Cannot retrieve changed attributes for identifier ${String(identifier)} as it is not present in the cache`,\n cached\n );\n\n // in Prod we try to recover when accessing something that\n // doesn't exist\n if (!cached) {\n return Object.create(null) as ChangedAttributesHash;\n }\n\n // TODO freeze in dev\n return cached.changes || (Object.create(null) as ChangedAttributesHash);\n }\n\n /**\n * Query the cache for whether any mutated attributes exist\n *\n * @category Resource Data\n * @public\n */\n hasChangedAttrs(identifier: ResourceKey): boolean {\n const cached = this.__peek(identifier, true);\n assert(\n `Cannot retrieve changed attributes for identifier ${String(identifier)} as it is not present in the cache`,\n cached\n );\n\n // in Prod we try to recover when accessing something that\n // doesn't exist\n if (!cached) {\n return false;\n }\n\n return (\n (cached.inflightAttrs !== null && Object.keys(cached.inflightAttrs).length > 0) ||\n (cached.localAttrs !== null && Object.keys(cached.localAttrs).length > 0)\n );\n }\n\n /**\n * Tell the cache to discard any uncommitted mutations to attributes\n *\n * This method is a candidate to become a mutation\n *\n * @category Resource Data\n * @public\n * @return the names of fields that were restored\n */\n rollbackAttrs(identifier: ResourceKey): string[] {\n const cached = this.__peek(identifier, false);\n let dirtyKeys: string[] | undefined;\n cached.isDeleted = false;\n\n if (cached.localAttrs !== null) {\n dirtyKeys = Object.keys(cached.localAttrs);\n cached.localAttrs = null;\n cached.changes = null;\n }\n\n if (cached.isNew) {\n // > Note: Graph removal handled by unloadRecord\n cached.isDeletionCommitted = true;\n cached.isDeleted = true;\n cached.isNew = false;\n }\n\n cached.inflightAttrs = null;\n cached.defaultAttrs = null;\n\n if (cached.errors) {\n cached.errors = null;\n this._capabilities.notifyChange(identifier, 'errors', null);\n }\n\n this._capabilities.notifyChange(identifier, 'state', null);\n\n if (dirtyKeys && dirtyKeys.length) {\n // `dirtyKeys` is a plain array here (from `Object.keys`), but\n // `notifyAttributes`/`notifyChange`/`notify` batch as a `Set<string>`,\n // so wrap it before handing it off.\n notifyAttributes(this._capabilities, identifier, new Set(dirtyKeys));\n }\n\n return dirtyKeys || [];\n }\n\n /**\n * Query the cache for the changes to relationships of a resource.\n *\n * Returns a map of relationship names to RelationshipDiff objects.\n *\n * ```ts\n * type RelationshipDiff =\n | {\n kind: 'collection';\n remoteState: ResourceKey[];\n additions: Set<ResourceKey>;\n removals: Set<ResourceKey>;\n localState: ResourceKey[];\n reordered: boolean;\n }\n | {\n kind: 'resource';\n remoteState: ResourceKey | null;\n localState: ResourceKey | null;\n };\n ```\n *\n * @category Resource Data\n * @public\n */\n changedRelationships(identifier: ResourceKey): Map<string, RelationshipDiff> {\n return this.__graph.getChanged(identifier);\n }\n\n /**\n * Query the cache for whether any mutated relationships exist\n *\n * @category Resource Data\n * @public\n */\n hasChangedRelationships(identifier: ResourceKey): boolean {\n return this.__graph.hasChanged(identifier);\n }\n\n /**\n * Tell the cache to discard any uncommitted mutations to relationships.\n *\n * This will also discard the change on any appropriate inverses.\n *\n * This method is a candidate to become a mutation\n *\n * @category Resource Data\n * @public\n * @return the names of relationships that were restored\n */\n rollbackRelationships(identifier: ResourceKey): string[] {\n assertPrivateCapabilities(this._capabilities);\n let result!: string[];\n\n this._capabilities._store._join(() => {\n result = this.__graph.rollback(identifier);\n });\n return result;\n }\n\n /**\n * Query the cache for the current state of a relationship property\n *\n * @category Resource Data\n * @public\n * @return resource relationship object\n */\n getRelationship(identifier: ResourceKey, field: string): ResourceRelationship | CollectionRelationship {\n return this.__graph.getData(identifier, field);\n }\n\n /**\n * Query the cache for the remote state of a relationship property\n *\n * @category Resource Data\n * @public\n * @return resource relationship object\n */\n getRemoteRelationship(identifier: ResourceKey, field: string): ResourceRelationship | CollectionRelationship {\n return this.__graph.getRemoteData(identifier, field);\n }\n\n ////////// ============== //////////\n ////////// Resource State //////////\n ////////// ============== //////////\n\n /**\n * Update the cache state for the given resource to be marked\n * as locally deleted, or remove such a mark.\n *\n * This method is a candidate to become a mutation\n *\n * @category Resource State\n * @public\n */\n setIsDeleted(identifier: ResourceKey, isDeleted: boolean): void {\n const cached = this.__peek(identifier, false);\n cached.isDeleted = isDeleted;\n // > Note: Graph removal for isNew handled by unloadRecord\n this._capabilities.notifyChange(identifier, 'state', null);\n }\n\n /**\n * Query the cache for any validation errors applicable to the given resource.\n *\n * @category Resource State\n * @public\n */\n getErrors(identifier: ResourceKey): ApiError[] {\n return this.__peek(identifier, true).errors || [];\n }\n\n /**\n * Query the cache for whether a given resource has any available data\n *\n * @category Resource State\n * @public\n */\n isEmpty(identifier: ResourceKey): boolean {\n const cached = this.__safePeek(identifier, true);\n return cached ? cached.remoteAttrs === null && cached.inflightAttrs === null && cached.localAttrs === null : true;\n }\n\n /**\n * Query the cache for whether a given resource was created locally and not\n * yet persisted.\n *\n * @category Resource State\n * @public\n */\n isNew(identifier: ResourceKey): boolean {\n // TODO can we assert here?\n return this.__safePeek(identifier, true)?.isNew || false;\n }\n\n /**\n * Query the cache for whether a given resource is marked as deleted (but not\n * necessarily persisted yet).\n *\n * @category Resource State\n * @public\n */\n isDeleted(identifier: ResourceKey): boolean {\n // TODO can we assert here?\n return this.__safePeek(identifier, true)?.isDeleted || false;\n }\n\n /**\n * Query the cache for whether a given resource has been deleted and that deletion\n * has also been persisted.\n *\n * @category Resource State\n * @public\n */\n isDeletionCommitted(identifier: ResourceKey): boolean {\n // TODO can we assert here?\n return this.__safePeek(identifier, true)?.isDeletionCommitted || false;\n }\n\n /**\n * Private method used to populate an entry for the identifier\n *\n * @internal\n */\n _createCache(identifier: ResourceKey): CachedResource {\n assert(`Expected no resource data to yet exist in the cache`, !this.__cache.has(identifier));\n const cache = makeCache();\n this.__cache.set(identifier, cache);\n return cache;\n }\n\n /**\n * Peek whether we have cached resource data matching the identifier\n * without asserting if the resource data is missing.\n *\n * @internal\n */\n __safePeek(identifier: ResourceKey, allowDestroyed: boolean): CachedResource | undefined {\n let resource = this.__cache.get(identifier);\n if (!resource && allowDestroyed) {\n resource = this.__destroyedCache.get(identifier);\n }\n return resource;\n }\n\n /**\n * Peek whether we have cached resource data matching the identifier\n * Asserts if the resource data is missing.\n *\n * @internal\n */\n __peek(identifier: ResourceKey, allowDestroyed: boolean): CachedResource {\n const resource = this.__safePeek(identifier, allowDestroyed);\n assert(\n `Expected Cache to have a resource entry for the identifier ${String(identifier)} but none was found`,\n resource\n );\n return resource;\n }\n}\n\nfunction addResourceToDocument(cache: JSONAPICache, op: AddToDocumentOperation): void {\n assert(`Expected field to be either 'data' or 'included'`, op.field === 'data' || op.field === 'included');\n\n const doc = cache.__documents.get(op.record.lid);\n assert(`Expected to have a cached document on which to perform the add operation`, doc);\n assert(`Expected to have content on the document`, doc.content);\n const { content } = doc;\n\n if (op.field === 'data') {\n let shouldNotify = false;\n assert(`Expected to have a data property on the document`, 'data' in content);\n asDoc<ResourceDataDocument>(content);\n\n // if data is not an array, we set the data property directly\n if (!Array.isArray(content.data)) {\n assert(`Expected to have a single record as the operation value`, op.value && !Array.isArray(op.value));\n shouldNotify = content.data !== op.value;\n if (shouldNotify) content.data = op.value;\n assert(\n `The value '${op.value.lid}' cannot be added from the data of document '${op.record.lid}' as it is already the current value '${content.data ? content.data.lid : '<null>'}'`,\n shouldNotify\n );\n } else {\n assert(`Expected to have a non-null operation value`, op.value);\n\n if (Array.isArray(op.value)) {\n if (op.index !== undefined) {\n // for collections, because we allow duplicates we are always changed.\n shouldNotify = true;\n content.data.splice(op.index, 0, ...op.value);\n } else {\n // for collections, because we allow duplicates we are always changed.\n shouldNotify = true;\n content.data.push(...op.value);\n }\n } else {\n if (op.index !== undefined) {\n // for collections, because we allow duplicates we are always changed.\n shouldNotify = true;\n content.data.splice(op.index, 0, op.value);\n } else {\n // for collections, because we allow duplicates we are always changed.\n shouldNotify = true;\n content.data.push(op.value);\n }\n }\n }\n\n // notify\n if (shouldNotify) cache._capabilities.notifyChange(op.record, 'updated', null);\n return;\n }\n\n asDoc<ResourceDataDocument>(content);\n content.included = content.included || [];\n\n assert(`Expected to have a non-null operation value`, op.value);\n if (Array.isArray(op.value)) {\n // included is not allowed to have duplicates, so we do a dirty check here\n assert(\n `included should not contain duplicate members`,\n new Set([...content.included, ...op.value]).size === content.included.length + op.value.length\n );\n content.included = content.included.concat(op.value);\n } else {\n // included is not allowed to have duplicates, so we do a dirty check here\n assert(`included should not contain duplicate members`, content.included.includes(op.value) === false);\n content.included.push(op.value);\n }\n\n // we don't notify in the included case because this is not reactively\n // exposed. We should possibly consider doing so though for subscribers\n}\n\nfunction removeResourceFromDocument(cache: JSONAPICache, op: RemoveFromDocumentOperation): void {\n assert(`Expected field to be either 'data' or 'included'`, op.field === 'data' || op.field === 'included');\n\n const doc = cache.__documents.get(op.record.lid);\n assert(`Expected to have a cached document on which to perform the remove operation`, doc);\n assert(`Expected to have content on the document`, doc.content);\n const { content } = doc;\n\n if (op.field === 'data') {\n let shouldNotify = false;\n assert(`Expected to have a data property on the document`, 'data' in content);\n asDoc<ResourceDataDocument>(content);\n\n // if data is not an array, we set the data property directly\n if (!Array.isArray(content.data)) {\n assert(`Expected to have a single record as the operation value`, op.value && !Array.isArray(op.value));\n shouldNotify = content.data === op.value;\n // we only remove the value if it was our existing value\n if (shouldNotify) content.data = null;\n assert(\n `The value '${op.value.lid}' cannot be removed from the data of document '${op.record.lid}' as it is not the current value '${content.data ? content.data.lid : '<null>'}'`,\n shouldNotify\n );\n } else {\n assert(`Expected to have a non-null operation value`, op.value);\n const toRemove = Array.isArray(op.value) ? op.value : [op.value];\n\n for (let i = 0; i < toRemove.length; i++) {\n const value = toRemove[i];\n if (op.index !== undefined) {\n // in production we want to recover gracefully\n // so we fallback to first-index-of\n const index: number =\n op.index < content.data.length && content.data[op.index] === value ? op.index : content.data.indexOf(value);\n\n assert(\n `Mismatched Index: Expected index '${op.index}' to contain the value '${value.lid}' but that value is at index '${index}'`,\n op.index < content.data.length && content.data[op.index] === value\n );\n\n if (index !== -1) {\n // we remove the first occurrence of the value\n shouldNotify = true;\n content.data.splice(index, 1);\n }\n } else {\n // we remove the first occurrence of the value\n const index = content.data.indexOf(value);\n if (index !== -1) {\n shouldNotify = true;\n content.data.splice(index, 1);\n }\n }\n }\n }\n\n // notify\n if (shouldNotify) cache._capabilities.notifyChange(op.record, 'updated', null);\n } else {\n asDoc<ResourceDataDocument>(content);\n content.included = content.included || [];\n\n assert(`Expected to have a non-null operation value`, op.value);\n const toRemove = Array.isArray(op.value) ? op.value : [op.value];\n for (const identifier of toRemove) {\n assert(\n `attempted to remove a value from included that was not present in the included array`,\n content.included.includes(identifier)\n );\n const index = content.included.indexOf(identifier);\n assert(\n `The value '${identifier.lid}' cannot be removed from the included of document '${op.record.lid}' as it is not present`,\n index !== -1\n );\n if (index !== -1) {\n content.included.splice(index, 1);\n }\n }\n\n // we don't notify in the included case because this is not reactively\n // exposed. We should possibly consider doing so though for subscribers\n }\n}\n\nfunction areAllModelsUnloaded(wrapper: CacheCapabilitiesManager, identifiers: ResourceKey[]): boolean {\n for (let i = 0; i < identifiers.length; ++i) {\n const identifier = identifiers[i];\n if (wrapper.hasRecord(identifier)) {\n return false;\n }\n }\n return true;\n}\n\nfunction getLocalState(rel: CollectionEdge | ResourceEdge): ResourceKey[] {\n if (isBelongsTo(rel)) {\n return rel.localState ? [rel.localState] : [];\n }\n return rel.additions ? [...rel.additions] : [];\n}\n\nfunction getRemoteState(rel: CollectionEdge | ResourceEdge) {\n if (isBelongsTo(rel)) {\n return rel.remoteState ? [rel.remoteState] : [];\n }\n return rel.remoteState;\n}\n\nfunction schemaHasLegacyDefaultValueFn(schema: Exclude<CacheableFieldSchema, IdentityField> | undefined): boolean {\n if (!schema) return false;\n return hasLegacyDefaultValueFn(schema.options);\n}\n\nfunction hasLegacyDefaultValueFn(options: object | undefined): options is { defaultValue: () => Value } {\n return !!options && typeof (options as { defaultValue: () => Value }).defaultValue === 'function';\n}\n\nfunction getDefaultValue(\n schema: Exclude<CacheableFieldSchema, IdentityField> | undefined,\n identifier: ResourceKey,\n store: Store\n): Value | undefined {\n const options = schema?.options;\n\n if (!schema || (!options && !schema.type)) {\n return;\n }\n\n if (schema.kind !== 'attribute' && schema.kind !== 'field') {\n return;\n }\n\n // legacy support for defaultValues that are functions\n if (hasLegacyDefaultValueFn(options)) {\n // If anyone opens an issue for args not working right, we'll restore + deprecate it via a Proxy\n // that lazily instantiates the record. We don't want to provide any args here\n // because in a non @ember-data/model world they don't make sense.\n return options.defaultValue();\n // legacy support for defaultValues that are primitives\n } else if (options && 'defaultValue' in options) {\n const defaultValue = options.defaultValue;\n assert(\n `Non primitive defaultValues are not supported because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`,\n typeof defaultValue !== 'object' || defaultValue === null\n );\n return defaultValue as Value;\n\n // new style transforms\n } else if (schema.kind !== 'attribute' && schema.type) {\n const transform = store.schema.transformation(schema);\n\n if (transform?.defaultValue) {\n return transform.defaultValue((options as ObjectValue) || null, identifier);\n }\n }\n}\n\nfunction notifyAttributes(storeWrapper: CacheCapabilitiesManager, identifier: ResourceKey, keys?: NotifyKeys) {\n if (!keys) {\n storeWrapper.notifyChange(identifier, 'attributes', null);\n return;\n }\n\n // deliver as a single batch instead of one `notifyChange` call per key: this\n // still results in one notification per key being delivered to subscribers\n // (in insertion order), but pays the per-call overhead (subscriber lookups,\n // buffer scheduling, etc) only once for the whole record instead of once\n // per changed attribute. This matters because this path runs once per\n // resource during a push/upsert, so with N records each having M changed\n // attributes the naive per-key approach costs O(N*M) in overhead alone.\n //\n // `keys` is handed off exactly as received. For the `calculateChangedKeys`\n // callers it is already the `Set<string>` they built, so no conversion\n // happens on this path; only `rollbackAttrs`'s naturally-array `dirtyKeys`\n // needs to be wrapped in a `Set` before reaching here.\n storeWrapper.notifyChange(identifier, 'attributes', keys);\n}\n\n/*\n TODO @deprecate IGOR DAVID\n There seems to be a potential bug here, where we will return keys that are not\n in the schema\n */\nfunction calculateChangedKeys(\n cached: CachedResource,\n updates: Exclude<ExistingResourceObject['attributes'], undefined>,\n fields: ReturnType<Store['schema']['fields']>\n): Set<string> {\n const changedKeys = new Set<string>();\n const keys = Object.keys(updates);\n const length = keys.length;\n const localAttrs = cached.localAttrs;\n\n const original: Record<string, unknown> = Object.assign(\n Object.create(null) as Record<string, unknown>,\n cached.remoteAttrs,\n cached.inflightAttrs\n );\n\n for (let i = 0; i < length; i++) {\n const key = keys[i];\n if (!fields.has(key)) {\n continue;\n }\n\n const value = updates[key];\n\n // A value in localAttrs means the user has a local change to\n // this attribute. We never override this value when merging\n // updates from the backend so we should not sent a change\n // notification if the server value differs from the original.\n if (localAttrs && localAttrs[key] !== undefined) {\n continue;\n }\n\n if (original[key] !== value) {\n changedKeys.add(key);\n }\n }\n\n return changedKeys;\n}\n\nfunction cacheIsEmpty(cached: CachedResource | undefined): boolean {\n return !cached || (cached.remoteAttrs === null && cached.inflightAttrs === null && cached.localAttrs === null);\n}\n\nfunction _isEmpty(peeked: CachedResource | undefined): boolean {\n if (!peeked) {\n return true;\n }\n const isNew = peeked.isNew;\n const isDeleted = peeked.isDeleted;\n const isEmpty = cacheIsEmpty(peeked);\n\n return (!isNew || isDeleted) && isEmpty;\n}\n\nfunction recordIsLoaded(cached: CachedResource | undefined, filterDeleted = false): boolean {\n if (!cached) {\n return false;\n }\n const isNew = cached.isNew;\n const isEmpty = cacheIsEmpty(cached);\n\n // if we are new we must consider ourselves loaded\n if (isNew) {\n return !cached.isDeleted;\n }\n // even if we have a past request, if we are now empty we are not loaded\n // typically this is true after an unloadRecord call\n\n // if we are not empty, not new && we have a fulfilled request then we are loaded\n // we should consider allowing for something to be loaded that is simply \"not empty\".\n // which is how RecordState currently handles this case; however, RecordState is buggy\n // in that it does not account for unloading.\n return filterDeleted && cached.isDeletionCommitted ? false : !isEmpty;\n}\n\nfunction _isLoading(\n peeked: CachedResource | undefined,\n capabilities: CacheCapabilitiesManager,\n identifier: ResourceKey\n): boolean {\n assertPrivateCapabilities(capabilities);\n // TODO refactor things such that the cache is not required to know\n // about isLoading\n const req = capabilities._store.getRequestStateService();\n // const fulfilled = req.getLastRequestForRecord(identifier);\n const isLoaded = recordIsLoaded(peeked);\n\n return (\n !isLoaded &&\n // fulfilled === null &&\n req.getPendingRequestsForRecord(identifier).some((r) => r.type === 'query')\n );\n}\n\nfunction setupRelationships(\n graph: Graph,\n fields: ReturnType<Store['schema']['fields']>,\n identifier: ResourceKey,\n data: ExistingResourceObject\n) {\n for (const name in data.relationships!) {\n const relationshipData = data.relationships[name];\n const field = fields.get(name);\n // TODO consider asserting if the relationship is not in the schema\n // we intentionally ignore relationships that are not in the schema\n if (!relationshipData || !field || !isRelationship(field)) continue;\n\n graph.push({\n op: 'updateRelationship',\n record: identifier,\n field: name,\n value: relationshipData,\n });\n }\n}\n\nfunction isRelationship(field: FieldSchema): field is LegacyRelationshipField | CollectionField | ResourceField {\n const { kind } = field;\n return kind === 'hasMany' || kind === 'belongsTo' || kind === 'resource' || kind === 'collection';\n}\n\nfunction patchLocalAttributes(cached: CachedResource, changedRemoteKeys?: Set<string>): boolean {\n const { localAttrs, remoteAttrs, inflightAttrs, defaultAttrs, changes } = cached;\n if (!localAttrs) {\n cached.changes = null;\n return false;\n }\n let hasAppliedPatch = false;\n const mutatedKeys = Object.keys(localAttrs);\n\n for (let i = 0, length = mutatedKeys.length; i < length; i++) {\n const attr = mutatedKeys[i];\n const existing =\n inflightAttrs && attr in inflightAttrs\n ? inflightAttrs[attr]\n : remoteAttrs && attr in remoteAttrs\n ? remoteAttrs[attr]\n : undefined;\n\n if (existing === localAttrs[attr]) {\n hasAppliedPatch = true;\n\n // if the local change is committed, then\n // the remoteKeyChange is no longer relevant\n changedRemoteKeys?.delete(attr);\n\n delete localAttrs[attr];\n delete changes![attr];\n }\n\n if (defaultAttrs && attr in defaultAttrs) {\n delete defaultAttrs[attr];\n }\n }\n return hasAppliedPatch;\n}\n\nfunction asDoc<T extends ResourceDocument>(doc: unknown): asserts doc is T {}\nfunction asOp<T extends Op>(doc: unknown): asserts doc is T {}\n\nfunction putOne(\n cache: JSONAPICache,\n identifiers: CacheKeyManager,\n resource: ExistingResourceObject\n): PersistedResourceKey {\n assert(\n `You must include an 'id' for the resource data ${resource.type}`,\n resource.id !== null && resource.id !== undefined && resource.id !== ''\n );\n assert(\n `Missing Resource Type: received resource data with a type '${resource.type}' but no schema could be found with that name.`,\n cache._capabilities.schema.hasResource(resource)\n );\n let identifier: ResourceKey | undefined = identifiers.peekResourceKey(resource);\n\n if (identifier) {\n identifier = identifiers.updateRecordIdentifier(identifier, resource);\n } else {\n identifier = identifiers.getOrCreateRecordIdentifier(resource);\n }\n cache.upsert(identifier, resource, cache._capabilities.hasRecord(identifier));\n // even if the identifier was not \"existing\" before, it is now\n return identifier as PersistedResourceKey;\n}\n\n/*\n Iterates over the set of internal models reachable from `this` across exactly one\n relationship.\n */\nfunction _directlyRelatedIdentifiersIterable(storeWrapper: CacheCapabilitiesManager, originating: ResourceKey) {\n const graph = peekGraph(storeWrapper);\n const initializedRelationships = graph?.identifiers.get(originating);\n\n if (!initializedRelationships) {\n return EMPTY_ITERATOR;\n }\n\n const initializedRelationshipsArr: Array<CollectionEdge | ResourceEdge> = [];\n Object.keys(initializedRelationships).forEach((key) => {\n const rel = initializedRelationships[key];\n if (rel && !isImplicit(rel)) {\n initializedRelationshipsArr.push(rel);\n }\n });\n\n let i = 0;\n let j = 0;\n let k = 0;\n\n const findNext = (): ResourceKey | undefined => {\n while (i < initializedRelationshipsArr.length) {\n while (j < 2) {\n const relatedIdentifiers =\n j === 0 ? getLocalState(initializedRelationshipsArr[i]) : getRemoteState(initializedRelationshipsArr[i]);\n while (k < relatedIdentifiers.length) {\n const relatedIdentifier = relatedIdentifiers[k++];\n if (relatedIdentifier !== null) {\n return relatedIdentifier;\n }\n }\n k = 0;\n j++;\n }\n j = 0;\n i++;\n }\n return undefined;\n };\n\n return {\n iterator() {\n return {\n next: (): { value: ResourceKey | undefined; done: boolean } => {\n const value = findNext();\n return { value, done: value === undefined };\n },\n };\n },\n };\n}\n\n/*\n Computes the set of Identifiers reachable from this Identifier.\n\n Reachability is determined over the relationship graph (ie a graph where\n nodes are identifiers and edges are belongs to or has many\n relationships).\n\n Returns an array including `this` and all identifiers reachable\n from `this.identifier`.\n */\nfunction _allRelatedIdentifiers(storeWrapper: CacheCapabilitiesManager, originating: ResourceKey): ResourceKey[] {\n const array: ResourceKey[] = [];\n const queue: ResourceKey[] = [];\n const seen = new Set();\n queue.push(originating);\n while (queue.length > 0) {\n const identifier = queue.shift()!;\n array.push(identifier);\n seen.add(identifier);\n\n const iterator = _directlyRelatedIdentifiersIterable(storeWrapper, originating).iterator();\n for (let obj = iterator.next(); !obj.done; obj = iterator.next()) {\n const relatedIdentifier = obj.value;\n if (relatedIdentifier && !seen.has(relatedIdentifier)) {\n seen.add(relatedIdentifier);\n queue.push(relatedIdentifier);\n }\n }\n }\n\n return array;\n}\n\nfunction fromBaseDocument(doc: StructuredDocument<ResourceDocument>): Partial<ResourceDocument> {\n const resourceDocument = {} as Partial<ResourceDocument>;\n const jsonApiDoc = doc.content;\n if (jsonApiDoc) {\n copyLinksAndMeta(resourceDocument, jsonApiDoc);\n }\n return resourceDocument;\n}\n\nfunction fromStructuredError(doc: StructuredErrorDocument<ResourceErrorDocument>): ResourceErrorDocument {\n const errorDoc: ResourceErrorDocument = {} as ResourceErrorDocument;\n\n if (doc.content) {\n copyLinksAndMeta(errorDoc, doc.content);\n\n if ('errors' in doc.content) {\n errorDoc.errors = doc.content.errors;\n } else if (typeof doc.error === 'object' && 'errors' in doc.error) {\n errorDoc.errors = doc.error.errors as Array<object>;\n } else {\n errorDoc.errors = [{ title: doc.message }];\n }\n }\n\n return errorDoc;\n}\n\nfunction copyLinksAndMeta(target: { links?: unknown; meta?: unknown }, source: object) {\n if ('links' in source) {\n target.links = source.links;\n }\n if ('meta' in source) {\n target.meta = source.meta;\n }\n}\n\nfunction cacheUpsert(\n cache: JSONAPICache,\n identifier: ResourceKey,\n data: ExistingResourceObject,\n calculateChanges?: boolean\n) {\n let changedKeys: Set<string> | undefined;\n const peeked = cache.__safePeek(identifier, false);\n const existed = !!peeked;\n const cached = peeked || cache._createCache(identifier);\n\n const isLoading = /*#__NOINLINE__*/ _isLoading(peeked, cache._capabilities, identifier) || !recordIsLoaded(peeked);\n const isUpdate = /*#__NOINLINE__*/ !_isEmpty(peeked) && !isLoading;\n\n if (LOG_CACHE) {\n logGroup(\n 'cache',\n 'upsert',\n identifier.type,\n identifier.lid,\n existed ? 'merged' : 'inserted',\n calculateChanges ? 'has-subscription' : ''\n );\n try {\n const _data = JSON.parse(JSON.stringify(data)) as object;\n\n // eslint-disable-next-line no-console\n console.log(_data);\n } catch {\n // eslint-disable-next-line no-console\n console.log(data);\n }\n }\n\n if (cached.isNew) {\n cached.isNew = false;\n cache._capabilities.notifyChange(identifier, 'identity', null);\n cache._capabilities.notifyChange(identifier, 'state', null);\n }\n\n const fields = getCacheFields(cache, identifier);\n\n // if no cache entry existed, no record exists / property has been accessed\n // and thus we do not need to notify changes to any properties.\n if (calculateChanges && existed && data.attributes) {\n changedKeys = calculateChangedKeys(cached, data.attributes, fields);\n }\n\n cached.remoteAttrs = Object.assign(\n cached.remoteAttrs || (Object.create(null) as Record<string, unknown>),\n data.attributes\n );\n\n if (cached.localAttrs) {\n if (patchLocalAttributes(cached, changedKeys)) {\n cache._capabilities.notifyChange(identifier, 'state', null);\n }\n }\n\n if (!isUpdate) {\n cache._capabilities.notifyChange(identifier, 'added', null);\n }\n\n if (data.id) {\n cached.id = data.id;\n }\n\n if (data.relationships) {\n setupRelationships(cache.__graph, fields, identifier, data);\n }\n\n if (changedKeys?.size) {\n notifyAttributes(cache._capabilities, identifier, changedKeys);\n }\n\n if (LOG_CACHE) {\n // eslint-disable-next-line no-console\n console.groupEnd();\n }\n\n return changedKeys?.size ? Array.from(changedKeys) : undefined;\n}\n\nfunction patchCache(Cache: JSONAPICache, op: Operation): void {\n const isRecord = isResourceKey(op.record);\n const isDocument = !isRecord && isRequestKey(op.record);\n\n assert(`Expected Cache.patch op.record to be a record or document identifier`, isRecord || isDocument);\n\n if (LOG_CACHE) {\n logGroup(\n 'cache',\n 'patch',\n isRecord ? (op.record as ResourceKey).type : '<@document>',\n op.record.lid,\n op.op,\n 'field' in op ? op.field : op.op === 'mergeIdentifiers' ? op.value.lid : ''\n );\n try {\n const _data = JSON.parse(JSON.stringify(op)) as object;\n // eslint-disable-next-line no-console\n console.log(_data);\n } catch {\n // eslint-disable-next-line no-console\n console.log(op);\n }\n }\n\n switch (op.op) {\n case 'mergeIdentifiers': {\n const cache = Cache.__cache.get(op.record);\n if (cache) {\n Cache.__cache.set(op.value, cache);\n Cache.__cache.delete(op.record);\n }\n Cache.__graph.update(op, true);\n break;\n }\n case 'update': {\n if (isRecord) {\n if ('field' in op) {\n const field = getCacheFields(Cache, op.record).get(op.field);\n assert(`Expected ${op.field} to be a field on ${op.record.type}`, field);\n if (isRelationship(field)) {\n asOp<UpdateResourceRelationshipOperation>(op);\n Cache.__graph.push(op);\n } else {\n asOp<UpdateResourceFieldOperation>(op);\n Cache.upsert(\n op.record,\n {\n type: op.record.type,\n id: op.record.id,\n attributes: {\n [op.field]: op.value,\n },\n },\n Cache._capabilities.hasRecord(op.record)\n );\n }\n } else {\n asOp<UpdateResourceOperation>(op);\n Cache.upsert(op.record, op.value, Cache._capabilities.hasRecord(op.record));\n }\n } else {\n assert(`Update operations on documents is not supported`, false);\n }\n break;\n }\n case 'add': {\n if (isRecord) {\n if ('field' in op) {\n asOp<AddToResourceRelationshipOperation>(op);\n Cache.__graph.push(op);\n } else {\n asOp<AddResourceOperation>(op);\n Cache.upsert(op.record, op.value, Cache._capabilities.hasRecord(op.record));\n }\n } else {\n assert(`Expected a field in the add operation`, 'field' in op);\n asOp<AddToDocumentOperation>(op);\n addResourceToDocument(Cache, op);\n }\n break;\n }\n case 'remove': {\n if (isRecord) {\n if ('field' in op) {\n asOp<RemoveFromResourceRelationshipOperation>(op);\n Cache.__graph.push(op);\n } else {\n asOp<RemoveResourceOperation>(op);\n const cached = Cache.__safePeek(op.record, false);\n if (cached) {\n cached.isDeleted = true;\n cached.isDeletionCommitted = true;\n Cache.unloadRecord(op.record);\n } else {\n peekGraph(Cache._capabilities)?.push({\n op: 'deleteRecord',\n record: op.record,\n isNew: false,\n });\n }\n }\n } else {\n if ('field' in op) {\n assert(`Expected a field in the remove operation`, 'field' in op);\n\n asOp<RemoveFromDocumentOperation>(op);\n removeResourceFromDocument(Cache, op);\n } else {\n asOp<RemoveDocumentOperation>(op);\n // TODO @runspired teardown associated state ... notify subscribers etc.\n // This likely means that the instance cache needs to handle\n // holding onto reactive documents instead of the CacheHandler\n // and use a subscription to remove them.\n // Cache.__documents.delete(op.record.lid);\n assert(`Removing documents from the cache is not yet supported`, false);\n }\n }\n break;\n }\n default:\n assert(`Unhandled cache.patch operation ${(op as unknown as Op).op}`);\n }\n\n if (LOG_CACHE) {\n // eslint-disable-next-line no-console\n console.groupEnd();\n }\n}\n\nfunction getCacheFields(\n cache: JSONAPICache,\n identifier: ResourceKey\n): Map<string, Exclude<CacheableFieldSchema, IdentityField>> {\n if (cache._capabilities.schema.cacheFields) {\n const result = cache._capabilities.schema.cacheFields(identifier);\n if (result) {\n return result;\n }\n }\n\n // the model schema service cannot process fields that are not cache fields\n return cache._capabilities.schema.fields(identifier) as unknown as Map<\n string,\n Exclude<CacheableFieldSchema, IdentityField>\n >;\n}\n\nfunction commitDidError(cache: JSONAPICache, identifier: ResourceKey, errors: ApiError[] | null): void {\n const cached = cache.__peek(identifier, false);\n if (cached.inflightAttrs) {\n const keys = Object.keys(cached.inflightAttrs);\n if (keys.length > 0) {\n const attrs = (cached.localAttrs =\n cached.localAttrs || (Object.create(null) as Record<string, Value | undefined>));\n for (let i = 0; i < keys.length; i++) {\n if (attrs[keys[i]] === undefined) {\n attrs[keys[i]] = cached.inflightAttrs[keys[i]];\n }\n }\n }\n cached.inflightAttrs = null;\n }\n if (errors) {\n cached.errors = errors;\n }\n cache._capabilities.notifyChange(identifier, 'errors', null);\n}\n\nfunction didCommit(\n cache: JSONAPICache,\n committedIdentifier: ResourceKey,\n data: ExistingResourceObject | null,\n op: string | null\n): void {\n if (!data) {\n assert(\n `Your ${committedIdentifier.type} record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.`,\n committedIdentifier.id\n );\n }\n\n const { cacheKeyManager } = cache._capabilities;\n const existingId = committedIdentifier.id;\n const identifier: ResourceKey =\n op !== 'deleteRecord' && data\n ? cacheKeyManager.updateRecordIdentifier(committedIdentifier, data)\n : committedIdentifier;\n\n const cached = cache.__peek(identifier, false);\n if (cached.isDeleted || op === 'deleteRecord') {\n cache.__graph.push({\n op: 'deleteRecord',\n record: identifier,\n isNew: false,\n });\n cached.isDeleted = true;\n cached.isDeletionCommitted = true;\n cache._capabilities.notifyChange(identifier, 'removed', null);\n // TODO @runspired should we early exit here?\n }\n\n if (DEBUG) {\n if (cached.isNew && !identifier.id && (typeof data?.id !== 'string' || data.id.length > 0)) {\n const error = new Error(`Expected an id ${String(identifier)} in response ${JSON.stringify(data)}`);\n //@ts-expect-error\n error.isAdapterError = true;\n //@ts-expect-error\n error.code = 'InvalidError';\n throw error;\n }\n }\n\n const fields = getCacheFields(cache, identifier);\n cached.isNew = false;\n let newCanonicalAttributes: ExistingResourceObject['attributes'];\n if (data) {\n if (data.id && !cached.id) {\n cached.id = data.id;\n }\n if (identifier === committedIdentifier && identifier.id !== existingId) {\n cache._capabilities.notifyChange(identifier, 'identity', null);\n }\n\n assert(\n `Expected the ID received for the primary '${identifier.type}' resource being saved to match the current id '${cached.id}' but received '${identifier.id}'.`,\n identifier.id === cached.id\n );\n\n if (data.relationships) {\n if (DEBUG) {\n if (!DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE) {\n // assert against bad API behavior where a belongsTo relationship\n // is saved but the return payload indicates a different final state.\n fields.forEach((field, name) => {\n if (field.kind === 'belongsTo') {\n const relationshipData = data.relationships![name]?.data;\n if (relationshipData !== undefined) {\n const inFlightData = cached.inflightRelationships?.[name] as SingleResourceRelationship;\n if (!inFlightData || !('data' in inFlightData)) {\n return;\n }\n const actualData = relationshipData\n ? cache._capabilities.cacheKeyManager.getOrCreateRecordIdentifier(relationshipData)\n : null;\n assert(\n `Expected the resource relationship '<${identifier.type}>.${name}' on ${\n identifier.lid\n } to be saved as ${inFlightData.data ? inFlightData.data.lid : '<null>'} but it was saved as ${\n actualData ? actualData.lid : '<null>'\n }`,\n inFlightData.data === actualData\n );\n }\n }\n });\n cached.inflightRelationships = null;\n }\n }\n setupRelationships(cache.__graph, fields, identifier, data);\n }\n newCanonicalAttributes = data.attributes;\n }\n const changedKeys = newCanonicalAttributes && calculateChangedKeys(cached, newCanonicalAttributes, fields);\n\n cached.remoteAttrs = Object.assign(\n cached.remoteAttrs || (Object.create(null) as Record<string, unknown>),\n cached.inflightAttrs,\n newCanonicalAttributes\n );\n cached.inflightAttrs = null;\n patchLocalAttributes(cached, changedKeys);\n\n if (cached.errors) {\n cached.errors = null;\n cache._capabilities.notifyChange(identifier, 'errors', null);\n }\n\n if (changedKeys?.size) notifyAttributes(cache._capabilities, identifier, changedKeys);\n cache._capabilities.notifyChange(identifier, 'state', null);\n}\n\nfunction willCommit(cache: JSONAPICache, identifier: ResourceKey): void {\n const cached = cache.__peek(identifier, false);\n\n /*\n if we have multiple saves in flight at once then\n we have information loss no matter what. This\n attempts to lose the least information.\n\n If we were to clear inflightAttrs, previous requests\n would not be able to use it during their didCommit.\n\n If we upsert inflightattrs, previous requests incorrectly\n see more recent inflight changes as part of their own and\n will incorrectly mark the new state as the correct remote state.\n\n We choose this latter behavior to avoid accidentally removing\n earlier changes.\n\n If apps do not want this behavior they can either\n - chain save requests serially vs allowing concurrent saves\n - move to using a request handler that caches the inflight state\n on a per-request basis\n - change their save requests to only send a \"PATCH\" instead of a \"PUT\"\n so that only latest changes are involved in each request, and then also\n ensure that the API or their handler reflects only those changes back\n for upsert into the cache.\n */\n if (cached.inflightAttrs) {\n if (cached.localAttrs) {\n Object.assign(cached.inflightAttrs, cached.localAttrs);\n }\n } else {\n cached.inflightAttrs = cached.localAttrs;\n }\n cached.localAttrs = null;\n\n if (DEBUG) {\n if (!DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE) {\n // save off info about saved relationships\n const fields = getCacheFields(cache, identifier);\n fields.forEach((schema, name) => {\n if (schema.kind === 'belongsTo') {\n if (cache.__graph._isDirty(identifier, name)) {\n const relationshipData = cache.__graph.getData(identifier, name);\n const inFlight = (cached.inflightRelationships =\n cached.inflightRelationships || (Object.create(null) as Record<string, unknown>));\n inFlight[name] = relationshipData;\n }\n }\n });\n }\n }\n}\n"],"mappings":";;;;;;AAmkBA,SAAgBoK,eACdzH,KACqD;CACrD,OACE,EAAEA,eAAe0H,UACjB1H,IAAIhB,WACJ,EAAE,UAAUgB,IAAIhB,YAChB,EAAE,cAAcgB,IAAIhB,YACpB,UAAUgB,IAAIhB;AAElB;AAEA,SAAgB2I,gBACd3H,KACuD;CACvD,OAAOA,eAAe0H;AACxB;;;;AC/gBA,SAAS2B,WAAWC,cAAuD;CACzE,OAAOA,aAAaC,WAAWF;AACjC;AAEA,MAAMG,iBAAiB,EACrBC,WAAW;CACT,OAAO,EACLC,OAAO;EACL,OAAO;GAAEC,MAAM;GAAMC,OAAOC;EAAU;CACxC,EACF;AACF,EACF;AAsBA,SAASC,YAA4B;CACnC,OAAO;EACLC,IAAI;EACJC,aAAa;EACbC,YAAY;EACZC,cAAc;EACdC,eAAe;EACfC,SAAS;EACTC,QAAQ;EACRC,OAAO;EACPC,WAAW;EACXC,qBAAqB;CACvB;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAaC,eAAb,MAA2C;;;;;;;;;;;CAmBzCC,YAAYC,cAAwC;EAClD,KAAKC,UAAU;EACf,KAAKC,gBAAgBF;EACrB,KAAKG,0BAAU,IAAIC,IAAI;EACvB,KAAKC,UAAUtC,SAASiC,YAAY;EACpC,KAAKM,mCAAmB,IAAIF,IAAI;EAChC,KAAKG,8BAAc,IAAIH,IAAI;CAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CAI,IAAIC,KAA6D;EAK/D,IAAIjC,gBAAgBiC,GAAG,GACrB,OAAO,KAAKC,aAAaD,KAAKvB,QAAWA,MAAS;OAC7C,IAAIT,eAAegC,GAAG,GAC3B,OAAO,KAAKC,aAAaD,KAAKvB,QAAWA,MAAS;EAGpD,MAAMyB,aAAaF,IAAIG;EACvB,MAAMC,WAAWF,WAAWE;EAC5B,IAAIC,GAAWC;EACf,MAAM,EAAEC,oBAAoB,KAAKd;EAyDjC,IAAIW,UACF,KAAKC,IAAI,GAAGC,SAASF,SAASE,QAAQD,IAAIC,QAAQD,KAChDD,SAASC,KAAKG,OAAO,MAAMD,iBAAiBH,SAASC,EAAE;EAI3D,IAAII,MAAMC,QAAQR,WAAWS,IAAI,GAAG;GAClCL,SAASJ,WAAWS,KAAKL;GACzB,MAAMM,cAAsC,CAAA;GAE5C,KAAKP,IAAI,GAAGA,IAAIC,QAAQD,KACtBO,YAAYC,KAAKL,OAAO,MAAMD,iBAAiBL,WAAWS,KAAKN,EAAE,CAAC;GAEpE,OAAO,KAAKJ,aACVD,KACAY,aACAR,QACF;EACF;EAEA,IAAIF,WAAWS,SAAS,MACtB,OAAO,KAAKV,aACVD,KACA,MACAI,QACF;EAGF,MAAMU,aAAaN,OAAO,MAAMD,iBAAiBL,WAAWS,IAAI;EAChE,OAAO,KAAKV,aACVD,KACAc,YACAV,QACF;CACF;;;;;;CA2BQH,aACND,KACAW,MACAP,UAC4G;EAE5G,MAAMW,mBACJhD,gBAAgBiC,GAAG,IAAIgB,oBAAoBhB,GAAG,IAAIiB,iBAAiBjB,GAAG;EAExE,IAAIW,SAASlC,QACVsC,iBAA0CJ,OAAOA;EAGpD,IAAIP,aAAa3B,QAGdsC,iBAA0CX,WAAWA;EAGxD,MAAMc,UAAUlB,IAAIkB;EACpB,MAAMJ,aAAaI,UAAU,KAAKzB,cAAcc,gBAAgBY,8BAA8BD,OAAO,IAAI;EAEzG,IAAIJ,YAAY;GACdC,iBAAiBK,MAAMN,WAAWM;GAGlCpB,IAAIG,UAAUY;GACd,MAAMM,cAAc,KAAKvB,YAAYwB,IAAIR,WAAWM,GAAG;GACvD,KAAKtB,YAAYyB,IAAIT,WAAWM,KAAKpB,GAA2C;GAEhF,KAAKP,cAAc+B,aAAaV,YAAYO,cAAc,YAAY,SAAS,IAAI;EACrF;EAEA,IAAIrB,IAAIkB,SAASO,OAAO,eAAe;GACrC,MAAMC,mBAAmB1B,IAAIkB,QAAQS,SAASb;GAC9C,MAAMc,cAAc5B,IAAIkB,QAAQS,SAASE;GAMzC,IAAID,eAAeF,kBACjB,KAAK9B,QAAQiB,KAAK;IAChBY,IAAI;IACJK,QAAQJ;IACRG,OAAOD,YAAYG;IACnBvD,OAAOuC;GACT,CAAC;EAEL;EAEA,OAAOA;CACT;;;;;;;;;CAUAiB,MAAMP,IAAmC;EACvC,IAAIhB,MAAMC,QAAQe,EAAE,GAAG;GAKrBhE,0BAA0B,KAAKgC,aAAa;GAC5C,KAAKA,cAAcwC,OAAOC,YAAY;IACpC,KAAK,MAAMC,aAAaV,IACtBW,WAAW,MAAMD,SAAS;GAE9B,CAAC;EAMH,OACEC,WAAW,MAAMX,EAAE;CAEvB;;;;;;;CAQAY,OAAOC,UAA4C;EAYjD,KAAK1C,QAAQ2C,OAAOD,UAAU,KAAK;CAMrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CAE,KAAK1B,YAAgF;EACnF,IAAInD,cAAcmD,UAAU,GAAG;GAC7B,MAAM2B,SAAS,KAAKC,WAAW5B,YAAY,KAAK;GAEhD,IAAI,CAAC2B,QACH,OAAO;GAGT,MAAM,EAAEE,MAAMhE,IAAIyC,QAAQN;GAC1B,MAAM8B,aAAaC,gBACjBC,OAAOC,OAAO,CAAC,GAAGN,OAAO7D,aAAa6D,OAAO1D,eAAe0D,OAAO5D,UAAU,CAC/E;GACA,MAAMmE,gBAAiD,CAAC;GAExD,MAAMC,OAAO,KAAKrD,QAAQgB,YAAYsC,IAAIpC,UAAU;GACpD,IAAImC,MACFH,OAAOK,KAAKF,IAAI,CAAC,CAACG,SAASC,QAAQ;IAEjC,IADYJ,KAAKI,IACV,CAAClF,WAAWF,YACjB;SAEA+E,cAAcK,OAAO,KAAKzD,QAAQ2D,QAAQzC,YAAYuC,GAAG;GAE7D,CAAC;GAGH5F,0BAA0B,KAAKgC,aAAa;GAC5C,MAAM+D,QAAQ,KAAK/D,cAAcwC;GAEjCwB,AADcC,eAAe,MAAM5C,UACnC2C,CAAK,CAACL,SAASO,MAAMN,QAAQ;IAC3B,IAAIA,OAAOT,cAAcA,WAAWS,SAAS5E,QAC3C;IAEF,MAAMmF,eAAeC,gBAAgBF,MAAM7C,YAAY0C,KAAK;IAE5D,IAAII,iBAAiBnF,QACnBmE,WAAWS,OAAOO;GAEtB,CAAC;GAED,OAAO;IACLjB;IACAhE;IACAyC;IACAwB;IACAI;GACF;EACF;EAEA,MAAMc,WAAW,KAAKC,YAAYjD,UAAU;EAE5C,IAAIgD,UACF;OAAI,aAAaA,UAAU,OAAOA,SAAS3D;EAAO;EAEpD,OAAO;CACT;;;;;;;CAUA6D,gBAAgBlD,YAAgF;EAC9F,IAAInD,cAAcmD,UAAU,GAAG;GAC7B,MAAM2B,SAAS,KAAKC,WAAW5B,YAAY,KAAK;GAEhD,IAAI,CAAC2B,QACH,OAAO;GAGT,MAAM,EAAEE,MAAMhE,IAAIyC,QAAQN;GAC1B,MAAM8B,aAAaC,gBAAgBJ,OAAO7D,WAAW;GACrD,MAAMoE,gBAAiD,CAAC;GAExD,MAAMC,OAAO,KAAKrD,QAAQgB,YAAYsC,IAAIpC,UAAU;GACpD,IAAImC,MACFH,OAAOK,KAAKF,IAAI,CAAC,CAACG,SAASC,QAAQ;IAEjC,IADYJ,KAAKI,IACV,CAAClF,WAAWF,YACjB;SAEA+E,cAAcK,OAAOR,gBAAgB,KAAKjD,QAAQ2D,QAAQzC,YAAYuC,GAAG,CAAC;GAE9E,CAAC;GAGH5F,0BAA0B,KAAKgC,aAAa;GAC5C,MAAM+D,QAAQ,KAAK/D,cAAcwC;GAEjCwB,AADcC,eAAe,MAAM5C,UACnC2C,CAAK,CAACL,SAASO,MAAMN,QAAQ;IAC3B,IAAIA,OAAOT,cAAcA,WAAWS,SAAS5E,QAC3C;IAEF,MAAMmF,eAAeC,gBAAgBF,MAAM7C,YAAY0C,KAAK;IAE5D,IAAII,iBAAiBnF,QACnBmE,WAAWS,OAAOO;GAEtB,CAAC;GAED,OAAO;IACLjB;IACAhE;IACAyC;IACAwB;IACAI;GACF;EACF;EAEA,MAAMc,WAAW,KAAKC,YAAYjD,UAAU;EAE5C,IAAIgD,UACF;OAAI,aAAaA,UAAU,OAAOA,SAAS3D;EAAO;EAEpD,OAAO;CACT;;;;;;;;;;;;CAaA4D,YAAYjD,YAAqE;EAC/E,OAAO,KAAKhB,YAAYoD,IAAIpC,WAAWM,GAAG,KAAK;CACjD;;;;;;;;CASA6C,OAAOnD,YAAyBH,MAA8BuD,kBAA6C;EACzGzG,0BAA0B,KAAKgC,aAAa;EAC5C,MAAM+D,QAAQ,KAAK/D,cAAcwC;EACjC,IAAI,CAACuB,MAAMW,MAAM;GACf,IAAIC,SAA0B3F;GAE9B+E,MAAMa,WAAW;IACfD,SAASE,YAAY,MAAMxD,YAAYH,MAAMuD,gBAAgB;GAC/D,CAAC;GACD,OAAOE;EACT;EAEA,OAAOE,YAAY,MAAMxD,YAAYH,MAAMuD,gBAAgB;CAC7D;;;;;;;;;;;CAgBAK,OAAuB;EACrB,MAAM,IAAIC,MAAM,iBAAiB;CACnC;;;;;;;;;;;CAYAC,MAAMC,QAA8B;EAClC,MAAM,IAAIF,MAAM,iBAAiB;CACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCAG,OAA0B;EACxB,MAAM,IAAIH,MAAM,iBAAiB;CACnC;;;;;;;;;CAcAI,OAAyC;EACvC,MAAM,IAAIJ,MAAM,iBAAiB;CACnC;;;;;;;;;;;;;;;;CAiBAK,QAAQC,QAAgD;EACtD,MAAM,IAAIN,MAAM,iBAAiB;CACnC;;;;;;;;;;CAeAO,gBAAgBjE,YAAyBa,SAA0D;EAWjG,MAAMqD,SAAS,KAAKC,aAAanE,UAAU;EAC3CkE,OAAO9F,QAAQ;EACf,MAAMgG,gBAAyC,CAAC;EAEhD,IAAIvD,YAAYlD,QAAW;GACzB,MAAM0G,SAASzB,eAAe,MAAM5C,UAAU;GAC9C,MAAMsE,QAAQ,KAAKxF;GACnB,MAAMyF,gBAAgBvC,OAAOK,KAAKxB,OAAO;GAEzC,KAAK,IAAItB,IAAI,GAAGA,IAAIgF,cAAc/E,QAAQD,KAAK;IAC7C,MAAM0B,OAAOsD,cAAchF;IAC3B,MAAMiF,gBAAgB3D,QAAQI;IAE9B,IAAIA,SAAS,MACX;IAGF,MAAMwD,YAAqCJ,OAAOjC,IAAInB,IAAI;IAC1D,MAAMyD,OAAOD,cAAc9G,SAAa,UAAU8G,YAAYA,UAAUC,OAAO,cAAe;IAC9F,IAAItH;IAEJ,QAAQsH,MAAR;KACE,KAAK;MACH,KAAKC,QAAQ3E,YAAYiB,MAAMuD,aAAa;MAC5CJ,cAAcnD,QAAQuD;MACtB;KACF,KAAK;MACH,KAAKjD,OAAO;OACVZ,IAAI;OACJI,OAAOE;OACPD,QAAQhB;OACRtC,OAAO8G;MACT,CAAC;MACDpH,eAAekH,MAAMlC,IAAIpC,YAAYiB,IAAI;MACzC7D,aAAawH,MAAMC,kBAAkB;MACrCzH,aAAawH,MAAME,UAAU;MAC7B;KACF,KAAK;MACH,KAAKvD,OAAO;OACVZ,IAAI;OACJI,OAAOE;OACPD,QAAQhB;OACRtC,OAAO8G;MACT,CAAC;MACDpH,eAAekH,MAAMlC,IAAIpC,YAAYiB,IAAI;MACzC7D,aAAawH,MAAMC,kBAAkB;MACrCzH,aAAawH,MAAME,UAAU;MAC7B;KACF,SAEEV,cAAcnD,QAAQuD;IAC1B;GACF;EACF;EAEA,KAAK7F,cAAc+B,aAAaV,YAAY,SAAS,IAAI;EAEzD,OAAOoE;CACT;;;;;;;;CASAW,WAAW/E,YAAyCgF,UAAuC;EACzF,IAAIrF,MAAMC,QAAQI,UAAU,GAC1B,KAAK,MAAMuC,OAAOvC,YAChB+E,WAAW,MAAMxC,GAAG;OAGtBwC,WAAW,MAAM/E,UAAU;CAE/B;;;;;;;;CAqBAiF,UACEC,qBACA5B,QAC6D;EAC7D,MAAM6B,UAAU7B,SAASA,OAAOjE,UAAU;EAC1C,MAAMgC,YAAYiC,QAAQlD,SAASO,MAAM;EACzC,MAAMd,OAAOsF,WAAWA,QAAQtF;EAahC,MAAMuF,uBAAuBzF,MAAMC,QAAQC,IAAI;EAC/C,MAAMwF,yBAAyB1F,MAAMC,QAAQsF,mBAAmB,KAAKA,oBAAoB1F,SAAS;EAElG,IAAIG,MAAMC,QAAQsF,mBAAmB,GAAG;GAOtC,IAAIE,sBACF,KAAK,IAAI7F,IAAI,GAAGA,IAAI2F,oBAAoB1F,QAAQD,KAAK;IACnD,MAAMS,aAAakF,oBAAoB3F;IACvC0F,UAAU,MAAMjF,YAAYH,KAAKN,MAAM,MAAM8B,SAAS;GACxD;QAIA,KAAK,IAAI9B,IAAI,GAAGA,IAAI2F,oBAAoB1F,QAAQD,KAAK;IACnD,MAAMS,aAAakF,oBAAoB3F;IACvC0F,UAAU,MAAMjF,YAAYT,MAAM,IAAIM,OAAO,MAAMwB,SAAS;GAC9D;EAEJ,OACE4D,UAAU,MAAMC,qBAAqBrF,MAAuCwB,SAAS;EAGvF,MAAM/B,WAAW6F,WAAWA,QAAQ7F;EACpC,MAAM,EAAEG,oBAAoB,KAAKd;EACjC,IAAIW,UACF,KAAK,IAAIC,IAAI,GAAGC,SAASF,SAASE,QAAQD,IAAIC,QAAQD,KACpDG,OAAO,MAAMD,iBAAiBH,SAASC,EAAE;EAI7C,OAAO8F,0BAA0BD,uBAC7B,EACEvF,MAAMqF,oBACR,IACA,EACErF,MAAOF,MAAMC,QAAQsF,mBAAmB,IACpCA,oBAAoB,KACpBA,oBACN;CACN;;;;;;;;CASAI,kBAAkBtF,YAAyC7B,QAA2B;EACpF,IAAIwB,MAAMC,QAAQI,UAAU,GAAG;GAC7B,KAAK,IAAIT,IAAI,GAAGA,IAAIS,WAAWR,QAAQD,KACrCgG,eAAe,MAAMvF,WAAWT,IAAIpB,UAAUoB,MAAM,IAAIpB,SAAS,IAAI;GAEvE;EACF;EAEA,OAAOoH,eAAe,MAAMvF,YAAY7B,UAAU,IAAI;CACxD;;;;;;;;;;CAWAqH,aAAaxF,YAA+B;EAC1C,MAAMyF,eAAe,KAAK9G;EAM1B,IAAI,CAAC,KAAKC,QAAQ4B,IAAIR,UAAU,GAAG;GAEjCtD,UAAU+I,YAAY,CAAC,EAAEC,OAAO1F,UAAU;GAC1C;EACF;EACA,MAAM2F,wBAAwB,CAAC,KAAKrH,oBAAoB0B,UAAU;EAClE,IAAI4F,UAAU;EACd,MAAM1B,SAAS,KAAK2B,OAAO7F,YAAY,KAAK;EAE5C,IAAIkE,OAAO9F,SAAS8F,OAAO5F,qBACzB5B,UAAU+I,YAAY,CAAC,EAAE1F,KAAK;GAC5BY,IAAI;GACJK,QAAQhB;GACR5B,OAAO8F,OAAO9F;EAChB,CAAC;OAED1B,UAAU+I,YAAY,CAAC,EAAEC,OAAO1F,UAAU;EAK5CkE,OAAOnG,aAAa;EACpBmG,OAAOpG,cAAc;EACrBoG,OAAOlG,eAAe;EACtBkG,OAAOjG,gBAAgB;EAEvB,MAAM6H,qBAAqBC,uBAAuBN,cAAczF,UAAU;EAC1E,IAAIgG,qBAAqBP,cAAcK,kBAAkB,GACvD,KAAK,IAAIvG,IAAI,GAAGA,IAAIuG,mBAAmBtG,QAAQ,EAAED,GAAG;GAClD,MAAM0G,oBAAoBH,mBAAmBvG;GAC7CkG,aAAa/E,aAAauF,mBAAmB,WAAW,IAAI;GAC5DL,UAAU;GACVH,aAAaS,iBAAiBD,iBAAiB;EACjD;EAGF,KAAKrH,QAAQuH,OAAOnG,UAAU;EAC9B,KAAKjB,iBAAiB0B,IAAIT,YAAYkE,MAAM;EAe5C,IAAI,KAAKnF,iBAAiBqH,SAAS,GAEjCC,iBAAiB;GACf,KAAKtH,iBAAiBuH,MAAM;EAC9B,GAAG,GAAG;EAGR,IAAI,CAACV,WAAWD,uBACdF,aAAa/E,aAAaV,YAAY,WAAW,IAAI;CAEzD;;;;;;;;CAaAuG,QAAQvG,YAAyB6C,MAA4C;EAC3E,MAAM2D,eAAe,CAAC7G,MAAMC,QAAQiD,IAAI,KAAKA,KAAKrD,WAAW;EAC7D,IAAIG,MAAMC,QAAQiD,IAAI,KAAKA,KAAKrD,WAAW,GACzCqD,OAAOA,KAAK;EAGd,IAAI2D,cAAc;GAChB,MAAMC,YAAY5D;GAClB,MAAMqB,SAAS,KAAK2B,OAAO7F,YAAY,IAAI;GAQ3C,IAAI,CAACkE,QACH;GAGF,IAAIA,OAAOnG,cAAc0I,aAAavC,OAAOnG,YAC3C,OAAOmG,OAAOnG,WAAW0I;QACpB,IAAIvC,OAAOjG,iBAAiBwI,aAAavC,OAAOjG,eACrD,OAAOiG,OAAOjG,cAAcwI;QACvB,IAAIvC,OAAOpG,eAAe2I,aAAavC,OAAOpG,aACnD,OAAOoG,OAAOpG,YAAY2I;QACrB,IAAIvC,OAAOlG,gBAAgByI,aAAavC,OAAOlG,cACpD,OAAOkG,OAAOlG,aAAayI;QACtB;IACL,MAAMC,aAAa9D,eAAe,MAAM5C,UAAU,CAAC,CAACoC,IAAIqE,SAAS;IAEjE9J,0BAA0B,KAAKgC,aAAa;IAC5C,MAAMmE,eAAeC,gBAAgB2D,YAAY1G,YAAY,KAAKrB,cAAcwC,MAAM;IACtF,IAAIwF,8BAA8BD,UAAU,GAAG;KAC7CxC,OAAOlG,eAAekG,OAAOlG,gBAAiBgE,OAAO4E,OAAO,IAAI;KAChE1C,OAAOlG,aAAayI,aAAa3D;IACnC;IACA,OAAOA;GACT;EACF;EAIA,MAAM+D,OAAiBhE;EACvB,MAAMqB,SAAS,KAAK2B,OAAO7F,YAAY,IAAI;EAC3C,MAAM8G,WAAWD,KAAK;EACtB,IAAIE,UAAU7C,OAAOnG,cAAc+I,YAAY5C,OAAOnG,aAAamG,OAAOnG,WAAW+I,YAAYnJ;EACjG,IAAIoJ,YAAYpJ,QACdoJ,UAAU7C,OAAOjG,iBAAiB6I,YAAY5C,OAAOjG,gBAAgBiG,OAAOjG,cAAc6I,YAAYnJ;EAExG,IAAIoJ,YAAYpJ,QACdoJ,UAAU7C,OAAOpG,eAAegJ,YAAY5C,OAAOpG,cAAcoG,OAAOpG,YAAYgJ,YAAYnJ;EAElG,IAAIoJ,YAAYpJ,QACd;EAEF,KAAK,IAAI4B,IAAI,GAAGA,IAAIsH,KAAKrH,QAAQD,KAAK;GACpCwH,UAAWA,QAAwBF,KAAKtH;GACxC,IAAIwH,YAAYpJ,QACd;EAEJ;EACA,OAAOoJ;CACT;;;;;;;CAQAC,cAAchH,YAAyB6C,MAA4C;EACjF,MAAM2D,eAAe,CAAC7G,MAAMC,QAAQiD,IAAI,KAAKA,KAAKrD,WAAW;EAC7D,IAAIG,MAAMC,QAAQiD,IAAI,KAAKA,KAAKrD,WAAW,GACzCqD,OAAOA,KAAK;EAGd,IAAI2D,cAAc;GAChB,MAAMC,YAAY5D;GAClB,MAAMqB,SAAS,KAAK2B,OAAO7F,YAAY,IAAI;GAQ3C,IAAI,CAACkE,QACH;GAGF,IAAIA,OAAOpG,eAAe2I,aAAavC,OAAOpG,aAC5C,OAAOoG,OAAOpG,YAAY2I;QAGrB,IAAIvC,OAAOlG,gBAAgByI,aAAavC,OAAOlG,cACpD,OAAOkG,OAAOlG,aAAayI;QACtB;IACL,MAAMC,aAAa9D,eAAe,MAAM5C,UAAU,CAAC,CAACoC,IAAIqE,SAAS;IAEjE9J,0BAA0B,KAAKgC,aAAa;IAC5C,MAAMmE,eAAeC,gBAAgB2D,YAAY1G,YAAY,KAAKrB,cAAcwC,MAAM;IACtF,IAAIwF,8BAA8BD,UAAU,GAAG;KAC7CxC,OAAOlG,eAAekG,OAAOlG,gBAAiBgE,OAAO4E,OAAO,IAAI;KAChE1C,OAAOlG,aAAayI,aAAa3D;IACnC;IACA,OAAOA;GACT;EACF;EAIA,MAAM+D,OAAiBhE;EACvB,MAAMqB,SAAS,KAAK2B,OAAO7F,YAAY,IAAI;EAC3C,MAAM8G,WAAWD,KAAK;EACtB,IAAIE,UAAU7C,OAAOpG,eAAegJ,YAAY5C,OAAOpG,cAAcoG,OAAOpG,YAAYgJ,YAAYnJ;EAEpG,IAAIoJ,YAAYpJ,QACd;EAGF,KAAK,IAAI4B,IAAI,GAAGA,IAAIsH,KAAKrH,QAAQD,KAAK;GACpCwH,UAAWA,QAAwBF,KAAKtH;GACxC,IAAIwH,YAAYpJ,QACd;EAEJ;EACA,OAAOoJ;CACT;;;;;;;;;CAUApC,QAAQ3E,YAAyB6C,MAAyBnF,OAAoB;EAG5E,MAAM8I,eAAe,CAAC7G,MAAMC,QAAQiD,IAAI,KAAKA,KAAKrD,WAAW;EAE7D,IAAIG,MAAMC,QAAQiD,IAAI,KAAKA,KAAKrD,WAAW,GACzCqD,OAAOA,KAAK;EAGd,IAAI2D,cAAc;GAChB,MAAMtC,SAAS,KAAK2B,OAAO7F,YAAY,KAAK;GAC5C,MAAMiH,cAAcpE;GACpB,MAAMqE,WACJhD,OAAOjG,iBAAiBgJ,eAAe/C,OAAOjG,gBAC1CiG,OAAOjG,cAAcgJ,eACrB/C,OAAOpG,eAAemJ,eAAe/C,OAAOpG,cAC1CoG,OAAOpG,YAAYmJ,eACnBtJ;GAER,IAAIuJ,aAAaxJ,OAAO;IACtBwG,OAAOnG,aAAamG,OAAOnG,cAAeiE,OAAO4E,OAAO,IAAI;IAC5D1C,OAAOnG,WAAWkJ,eAAevJ;IACjCwG,OAAOhG,UAAUgG,OAAOhG,WAAY8D,OAAO4E,OAAO,IAAI;IACtD1C,OAAOhG,QAAQ+I,eAAe,CAACC,UAAUxJ,KAAK;GAChD,OAAO,IAAIwG,OAAOnG,YAAY;IAC5B,OAAOmG,OAAOnG,WAAWkJ;IACzB,OAAO/C,OAAOhG,QAAS+I;GACzB;GAEA,IAAI/C,OAAOlG,gBAAgBiJ,eAAe/C,OAAOlG,cAC/C,OAAOkG,OAAOlG,aAAaiJ;GAG7B,KAAKtI,cAAc+B,aAAaV,YAAY,cAAciH,WAAW;GACrE;EACF;EASA,MAAMJ,OAAiBhE;EAEvB,MAAMqB,SAAS,KAAK2B,OAAO7F,YAAY,KAAK;EAG5C,MAAM8G,WAAWD,KAAK;EACtB,MAAMK,WACJhD,OAAOjG,iBAAiB6I,YAAY5C,OAAOjG,gBACvCiG,OAAOjG,cAAc6I,YACrB5C,OAAOpG,eAAegJ,YAAY5C,OAAOpG,cACvCoG,OAAOpG,YAAYgJ,YACnBnJ;EAER,IAAIwJ;EACJ,IAAID,UAAU;GACZC,eAAgBD,SAAyBL,KAAK;GAE9C,KAAK,IAAItH,IAAI,GAAGA,IAAIsH,KAAKrH,QAAQD,KAE/B4H,eAAgBA,aAA6BN,KAAKtH;EAEtD;EAEA,IAAI4H,iBAAiBzJ,OAAO;GAC1BwG,OAAOnG,aAAamG,OAAOnG,cAAeiE,OAAO4E,OAAO,IAAI;GAC5D1C,OAAOnG,WAAW+I,YAAY5C,OAAOnG,WAAW+I,aAAa/E,gBAAgBmF,QAAQ;GACrFhD,OAAOhG,UAAUgG,OAAOhG,WAAY8D,OAAO4E,OAAO,IAAI;GACtD,IAAIQ,eAAelD,OAAOnG,WAAW+I;GACrC,IAAIO,WAAW;GAEf,OAAOA,WAAWR,KAAKrH,SAAS,GAC9B4H,eAAeA,aAAaP,KAAKQ;GAEnCD,aAAaP,KAAKQ,aAAa3J;GAE/BwG,OAAOhG,QAAQ4I,YAAY,CAACI,UAAUhD,OAAOnG,WAAW+I,SAAS;EAWnE,OAAO,IAAI5C,OAAOnG,YAChB,IAAI;GACF,IAAI,CAACmJ,UACH;GAKF,IAHoBK,KAAKC,UAAUN,QAG/BI,MAFWC,KAAKC,UAAUtD,OAAOnG,WAAW+I,SAE5BW,GAAQ;IAC1B,OAAOvD,OAAOnG,WAAW+I;IACzB,OAAO5C,OAAOhG,QAAS4I;GACzB;EACF,QAAQ,CACN;EAIJ,KAAKnI,cAAc+B,aAAaV,YAAY,cAAc8G,QAAQ;CACpE;;;;;;;;CASAY,aAAa1H,YAAgD;EAC3D,MAAMkE,SAAS,KAAK2B,OAAO7F,YAAY,KAAK;EAQ5C,IAAI,CAACkE,QACH,OAAOlC,OAAO4E,OAAO,IAAI;EAI3B,OAAO1C,OAAOhG,WAAY8D,OAAO4E,OAAO,IAAI;CAC9C;;;;;;;CAQAe,gBAAgB3H,YAAkC;EAChD,MAAMkE,SAAS,KAAK2B,OAAO7F,YAAY,IAAI;EAQ3C,IAAI,CAACkE,QACH,OAAO;EAGT,OACGA,OAAOjG,kBAAkB,QAAQ+D,OAAOK,KAAK6B,OAAOjG,aAAa,CAAC,CAACuB,SAAS,KAC5E0E,OAAOnG,eAAe,QAAQiE,OAAOK,KAAK6B,OAAOnG,UAAU,CAAC,CAACyB,SAAS;CAE3E;;;;;;;;;;CAWAoI,cAAc5H,YAAmC;EAC/C,MAAMkE,SAAS,KAAK2B,OAAO7F,YAAY,KAAK;EAC5C,IAAI6H;EACJ3D,OAAO7F,YAAY;EAEnB,IAAI6F,OAAOnG,eAAe,MAAM;GAC9B8J,YAAY7F,OAAOK,KAAK6B,OAAOnG,UAAU;GACzCmG,OAAOnG,aAAa;GACpBmG,OAAOhG,UAAU;EACnB;EAEA,IAAIgG,OAAO9F,OAAO;GAEhB8F,OAAO5F,sBAAsB;GAC7B4F,OAAO7F,YAAY;GACnB6F,OAAO9F,QAAQ;EACjB;EAEA8F,OAAOjG,gBAAgB;EACvBiG,OAAOlG,eAAe;EAEtB,IAAIkG,OAAO/F,QAAQ;GACjB+F,OAAO/F,SAAS;GAChB,KAAKQ,cAAc+B,aAAaV,YAAY,UAAU,IAAI;EAC5D;EAEA,KAAKrB,cAAc+B,aAAaV,YAAY,SAAS,IAAI;EAEzD,IAAI6H,aAAaA,UAAUrI,QAIzBsI,iBAAiB,KAAKnJ,eAAeqB,YAAY,IAAI+H,IAAIF,SAAS,CAAC;EAGrE,OAAOA,aAAa,CAAA;CACtB;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BAG,qBAAqBhI,YAAwD;EAC3E,OAAO,KAAKlB,QAAQmJ,WAAWjI,UAAU;CAC3C;;;;;;;CAQAkI,wBAAwBlI,YAAkC;EACxD,OAAO,KAAKlB,QAAQqJ,WAAWnI,UAAU;CAC3C;;;;;;;;;;;;CAaAoI,sBAAsBpI,YAAmC;EACvDrD,0BAA0B,KAAKgC,aAAa;EAC5C,IAAI2E;EAEJ,KAAK3E,cAAcwC,OAAOC,YAAY;GACpCkC,SAAS,KAAKxE,QAAQuJ,SAASrI,UAAU;EAC3C,CAAC;EACD,OAAOsD;CACT;;;;;;;;CASAgF,gBAAgBtI,YAAyBe,OAA8D;EACrG,OAAO,KAAKjC,QAAQ2D,QAAQzC,YAAYe,KAAK;CAC/C;;;;;;;;CASAwH,sBAAsBvI,YAAyBe,OAA8D;EAC3G,OAAO,KAAKjC,QAAQ0J,cAAcxI,YAAYe,KAAK;CACrD;;;;;;;;;;CAeA0H,aAAazI,YAAyB3B,WAA0B;EAC9D,MAAM6F,SAAS,KAAK2B,OAAO7F,YAAY,KAAK;EAC5CkE,OAAO7F,YAAYA;EAEnB,KAAKM,cAAc+B,aAAaV,YAAY,SAAS,IAAI;CAC3D;;;;;;;CAQA0I,UAAU1I,YAAqC;EAC7C,OAAO,KAAK6F,OAAO7F,YAAY,IAAI,CAAC,CAAC7B,UAAU,CAAA;CACjD;;;;;;;CAQA2G,QAAQ9E,YAAkC;EACxC,MAAMkE,SAAS,KAAKtC,WAAW5B,YAAY,IAAI;EAC/C,OAAOkE,SAASA,OAAOpG,gBAAgB,QAAQoG,OAAOjG,kBAAkB,QAAQiG,OAAOnG,eAAe,OAAO;CAC/G;;;;;;;;CASAK,MAAM4B,YAAkC;EAEtC,OAAO,KAAK4B,WAAW5B,YAAY,IAAI,CAAC,EAAE5B,SAAS;CACrD;;;;;;;;CASAC,UAAU2B,YAAkC;EAE1C,OAAO,KAAK4B,WAAW5B,YAAY,IAAI,CAAC,EAAE3B,aAAa;CACzD;;;;;;;;CASAC,oBAAoB0B,YAAkC;EAEpD,OAAO,KAAK4B,WAAW5B,YAAY,IAAI,CAAC,EAAE1B,uBAAuB;CACnE;;;;;;CAOA6F,aAAanE,YAAyC;EAEpD,MAAM2I,QAAQ/K,UAAU;EACxB,KAAKgB,QAAQ6B,IAAIT,YAAY2I,KAAK;EAClC,OAAOA;CACT;;;;;;;CAQA/G,WAAW5B,YAAyB4I,gBAAqD;EACvF,IAAIC,WAAW,KAAKjK,QAAQwD,IAAIpC,UAAU;EAC1C,IAAI,CAAC6I,YAAYD,gBACfC,WAAW,KAAK9J,iBAAiBqD,IAAIpC,UAAU;EAEjD,OAAO6I;CACT;;;;;;;CAQAhD,OAAO7F,YAAyB4I,gBAAyC;EAMvE,OALiB,KAAKhH,WAAW5B,YAAY4I,cAKtCC;CACT;AACF;AAEA,SAASC,sBAAsBH,OAAqBhI,IAAkC;CAMpF,MAAM,EAAEtB,YAHIsJ,MAAM3J,YAAYoD,IAAIzB,GAAGK,OAAOV,GAGxBpB;CAEpB,IAAIyB,GAAGI,UAAU,QAAQ;EACvB,IAAIgI,eAAe;EAKnB,IAAI,CAACpJ,MAAMC,QAAQP,QAAQQ,IAAI,GAAG;GAEhCkJ,eAAe1J,QAAQQ,SAASc,GAAGjD;GACnC,IAAIqL,cAAc1J,QAAQQ,OAAOc,GAAGjD;EAKtC,OAGE,IAAIiC,MAAMC,QAAQe,GAAGjD,KAAK,GAAG;GAC3B,IAAIiD,GAAGsI,UAAUtL,QAAW;IAE1BoL,eAAe;IACf1J,QAAQQ,KAAKqJ,OAAOvI,GAAGsI,OAAO,GAAG,GAAGtI,GAAGjD,KAAK;GAC9C,OAAO;IAELqL,eAAe;IACf1J,QAAQQ,KAAKE,KAAK,GAAGY,GAAGjD,KAAK;GAC/B;EACF,OACE,IAAIiD,GAAGsI,UAAUtL,QAAW;GAE1BoL,eAAe;GACf1J,QAAQQ,KAAKqJ,OAAOvI,GAAGsI,OAAO,GAAGtI,GAAGjD,KAAK;EAC3C,OAAO;GAELqL,eAAe;GACf1J,QAAQQ,KAAKE,KAAKY,GAAGjD,KAAK;EAC5B;EAKJ,IAAIqL,cAAcJ,MAAMhK,cAAc+B,aAAaC,GAAGK,QAAQ,WAAW,IAAI;EAC7E;CACF;CAGA3B,QAAQC,WAAWD,QAAQC,YAAY,CAAA;CAGvC,IAAIK,MAAMC,QAAQe,GAAGjD,KAAK,GAMxB2B,QAAQC,WAAWD,QAAQC,SAAS6J,OAAOxI,GAAGjD,KAAK;MAInD2B,QAAQC,SAASS,KAAKY,GAAGjD,KAAK;AAKlC;AAEA,SAAS0L,2BAA2BT,OAAqBhI,IAAuC;CAM9F,MAAM,EAAEtB,YAHIsJ,MAAM3J,YAAYoD,IAAIzB,GAAGK,OAAOV,GAGxBpB;CAEpB,IAAIyB,GAAGI,UAAU,QAAQ;EACvB,IAAIgI,eAAe;EAKnB,IAAI,CAACpJ,MAAMC,QAAQP,QAAQQ,IAAI,GAAG;GAEhCkJ,eAAe1J,QAAQQ,SAASc,GAAGjD;GAEnC,IAAIqL,cAAc1J,QAAQQ,OAAO;EAKnC,OAAO;GAEL,MAAMwJ,WAAW1J,MAAMC,QAAQe,GAAGjD,KAAK,IAAIiD,GAAGjD,QAAQ,CAACiD,GAAGjD,KAAK;GAE/D,KAAK,IAAI6B,IAAI,GAAGA,IAAI8J,SAAS7J,QAAQD,KAAK;IACxC,MAAM7B,QAAQ2L,SAAS9J;IACvB,IAAIoB,GAAGsI,UAAUtL,QAAW;KAG1B,MAAMsL,QACJtI,GAAGsI,QAAQ5J,QAAQQ,KAAKL,UAAUH,QAAQQ,KAAKc,GAAGsI,WAAWvL,QAAQiD,GAAGsI,QAAQ5J,QAAQQ,KAAKyJ,QAAQ5L,KAAK;KAO5G,IAAIuL,UAAU,IAAI;MAEhBF,eAAe;MACf1J,QAAQQ,KAAKqJ,OAAOD,OAAO,CAAC;KAC9B;IACF,OAAO;KAEL,MAAMA,QAAQ5J,QAAQQ,KAAKyJ,QAAQ5L,KAAK;KACxC,IAAIuL,UAAU,IAAI;MAChBF,eAAe;MACf1J,QAAQQ,KAAKqJ,OAAOD,OAAO,CAAC;KAC9B;IACF;GACF;EACF;EAGA,IAAIF,cAAcJ,MAAMhK,cAAc+B,aAAaC,GAAGK,QAAQ,WAAW,IAAI;CAC/E,OAAO;EAEL3B,QAAQC,WAAWD,QAAQC,YAAY,CAAA;EAGvC,MAAM+J,WAAW1J,MAAMC,QAAQe,GAAGjD,KAAK,IAAIiD,GAAGjD,QAAQ,CAACiD,GAAGjD,KAAK;EAC/D,KAAK,MAAMsC,cAAcqJ,UAAU;GAKjC,MAAMJ,QAAQ5J,QAAQC,SAASgK,QAAQtJ,UAAU;GAKjD,IAAIiJ,UAAU,IACZ5J,QAAQC,SAAS4J,OAAOD,OAAO,CAAC;EAEpC;CAIF;AACF;AAEA,SAASjD,qBAAqBuD,SAAmCzJ,aAAqC;CACpG,KAAK,IAAIP,IAAI,GAAGA,IAAIO,YAAYN,QAAQ,EAAED,GAAG;EAC3C,MAAMS,aAAaF,YAAYP;EAC/B,IAAIgK,QAAQC,UAAUxJ,UAAU,GAC9B,OAAO;CAEX;CACA,OAAO;AACT;AAEA,SAASyJ,cAAcjH,KAAmD;CACxE,IAAI/F,YAAY+F,GAAG,GACjB,OAAOA,IAAIkH,aAAa,CAAClH,IAAIkH,UAAU,IAAI,CAAA;CAE7C,OAAOlH,IAAImH,YAAY,CAAC,GAAGnH,IAAImH,SAAS,IAAI,CAAA;AAC9C;AAEA,SAASC,eAAepH,KAAoC;CAC1D,IAAI/F,YAAY+F,GAAG,GACjB,OAAOA,IAAIqH,cAAc,CAACrH,IAAIqH,WAAW,IAAI,CAAA;CAE/C,OAAOrH,IAAIqH;AACb;AAEA,SAASlD,8BAA8BmD,QAA2E;CAChH,IAAI,CAACA,QAAQ,OAAO;CACpB,OAAOC,wBAAwBD,OAAOjJ,OAAO;AAC/C;AAEA,SAASkJ,wBAAwBlJ,SAAuE;CACtG,OAAO,CAAC,CAACA,WAAW,OAAQA,QAA0CiC,iBAAiB;AACzF;AAEA,SAASC,gBACP+G,QACA9J,YACA0C,OACmB;CACnB,MAAM7B,UAAUiJ,QAAQjJ;CAExB,IAAI,CAACiJ,UAAW,CAACjJ,WAAW,CAACiJ,OAAOjI,MAClC;CAGF,IAAIiI,OAAOpF,SAAS,eAAeoF,OAAOpF,SAAS,SACjD;CAIF,IAAIqF,wBAAwBlJ,OAAO,GAIjC,OAAOA,QAAQiC,aAAa;MAEvB,IAAIjC,WAAW,kBAAkBA,SAMtC,OALqBA,QAAQiC;MAQxB,IAAIgH,OAAOpF,SAAS,eAAeoF,OAAOjI,MAAM;EACrD,MAAMmI,YAAYtH,MAAMoH,OAAOG,eAAeH,MAAM;EAEpD,IAAIE,WAAWlH,cACb,OAAOkH,UAAUlH,aAAcjC,WAA2B,MAAMb,UAAU;CAE9E;AACF;AAEA,SAAS8H,iBAAiBrC,cAAwCzF,YAAyBqC,MAAmB;CAC5G,IAAI,CAACA,MAAM;EACToD,aAAa/E,aAAaV,YAAY,cAAc,IAAI;EACxD;CACF;CAcAyF,aAAa/E,aAAaV,YAAY,cAAcqC,IAAI;AAC1D;AAOA,SAAS6H,qBACPhG,QACAiG,SACA9F,QACa;CACb,MAAM+F,8BAAc,IAAIrC,IAAY;CACpC,MAAM1F,OAAOL,OAAOK,KAAK8H,OAAO;CAChC,MAAM3K,SAAS6C,KAAK7C;CACpB,MAAMzB,aAAamG,OAAOnG;CAE1B,MAAMsM,WAAoCrI,OAAOC,OAC/CD,OAAO4E,OAAO,IAAI,GAClB1C,OAAOpG,aACPoG,OAAOjG,aACT;CAEA,KAAK,IAAIsB,IAAI,GAAGA,IAAIC,QAAQD,KAAK;EAC/B,MAAMgD,MAAMF,KAAK9C;EACjB,IAAI,CAAC8E,OAAO7D,IAAI+B,GAAG,GACjB;EAGF,MAAM7E,QAAQyM,QAAQ5H;EAMtB,IAAIxE,cAAcA,WAAWwE,SAAS5E,QACpC;EAGF,IAAI0M,SAAS9H,SAAS7E,OACpB0M,YAAYE,IAAI/H,GAAG;CAEvB;CAEA,OAAO6H;AACT;AAEA,SAASG,aAAarG,QAA6C;CACjE,OAAO,CAACA,UAAWA,OAAOpG,gBAAgB,QAAQoG,OAAOjG,kBAAkB,QAAQiG,OAAOnG,eAAe;AAC3G;AAEA,SAASyM,SAAS7I,QAA6C;CAC7D,IAAI,CAACA,QACH,OAAO;CAET,MAAMvD,QAAQuD,OAAOvD;CACrB,MAAMC,YAAYsD,OAAOtD;CACzB,MAAMyG,UAAUyF,aAAa5I,MAAM;CAEnC,QAAQ,CAACvD,SAASC,cAAcyG;AAClC;AAEA,SAAS2F,eAAevG,QAAoCwG,gBAAgB,OAAgB;CAC1F,IAAI,CAACxG,QACH,OAAO;CAET,MAAM9F,QAAQ8F,OAAO9F;CACrB,MAAM0G,UAAUyF,aAAarG,MAAM;CAGnC,IAAI9F,OACF,OAAO,CAAC8F,OAAO7F;CASjB,OAAOqM,iBAAiBxG,OAAO5F,sBAAsB,QAAQ,CAACwG;AAChE;AAEA,SAAS6F,WACPhJ,QACAlD,cACAuB,YACS;CACTrD,0BAA0B8B,YAAY;CAGtC,MAAMmM,MAAMnM,aAAa0C,OAAO0J,uBAAuB;CAIvD,OACE,CAHeJ,eAAe9I,MAG7BmJ,KAEDF,IAAIG,4BAA4B/K,UAAU,CAAC,CAACgL,MAAMC,MAAMA,EAAEpJ,SAAS,OAAO;AAE9E;AAEA,SAASqJ,mBACP5G,OACAD,QACArE,YACAH,MACA;CACA,KAAK,MAAMoB,QAAQpB,KAAKqC,eAAgB;EACtC,MAAMiJ,mBAAmBtL,KAAKqC,cAAcjB;EAC5C,MAAMF,QAAQsD,OAAOjC,IAAInB,IAAI;EAG7B,IAAI,CAACkK,oBAAoB,CAACpK,SAAS,CAACqK,eAAerK,KAAK,GAAG;EAE3DuD,MAAMvE,KAAK;GACTY,IAAI;GACJK,QAAQhB;GACRe,OAAOE;GACPvD,OAAOyN;EACT,CAAC;CACH;AACF;AAEA,SAASC,eAAerK,OAAwF;CAC9G,MAAM,EAAE2D,SAAS3D;CACjB,OAAO2D,SAAS,aAAaA,SAAS,eAAeA,SAAS,cAAcA,SAAS;AACvF;AAEA,SAAS2G,qBAAqBnH,QAAwBoH,mBAA0C;CAC9F,MAAM,EAAEvN,YAAYD,aAAaG,eAAeD,cAAcE,YAAYgG;CAC1E,IAAI,CAACnG,YAAY;EACfmG,OAAOhG,UAAU;EACjB,OAAO;CACT;CACA,IAAIqN,kBAAkB;CACtB,MAAMC,cAAcxJ,OAAOK,KAAKtE,UAAU;CAE1C,KAAK,IAAIwB,IAAI,GAAGC,SAASgM,YAAYhM,QAAQD,IAAIC,QAAQD,KAAK;EAC5D,MAAMsD,OAAO2I,YAAYjM;EAQzB,KANEtB,iBAAiB4E,QAAQ5E,gBACrBA,cAAc4E,QACd/E,eAAe+E,QAAQ/E,cACrBA,YAAY+E,QACZlF,YAESI,WAAW8E,OAAO;GACjC0I,kBAAkB;GAIlBD,mBAAmBnF,OAAOtD,IAAI;GAE9B,OAAO9E,WAAW8E;GAClB,OAAO3E,QAAS2E;EAClB;EAEA,IAAI7E,gBAAgB6E,QAAQ7E,cAC1B,OAAOA,aAAa6E;CAExB;CACA,OAAO0I;AACT;AAKA,SAAS7L,OACPiJ,OACA7I,aACA+I,UACsB;CAStB,IAAI7I,aAAsCF,YAAY4L,gBAAgB7C,QAAQ;CAE9E,IAAI7I,YACFA,aAAaF,YAAY6L,uBAAuB3L,YAAY6I,QAAQ;MAEpE7I,aAAaF,YAAY8L,4BAA4B/C,QAAQ;CAE/DF,MAAMxF,OAAOnD,YAAY6I,UAAUF,MAAMhK,cAAc6K,UAAUxJ,UAAU,CAAC;CAE5E,OAAOA;AACT;AAMA,SAAS6L,oCAAoCpG,cAAwCqG,aAA0B;CAE7G,MAAMC,2BADQrP,UAAU+I,YACSnB,CAAK,EAAExE,YAAYsC,IAAI0J,WAAW;CAEnE,IAAI,CAACC,0BACH,OAAOzO;CAGT,MAAM0O,8BAAoE,CAAA;CAC1EhK,OAAOK,KAAK0J,wBAAwB,CAAC,CAACzJ,SAASC,QAAQ;EACrD,MAAMC,MAAMuJ,yBAAyBxJ;EACrC,IAAIC,OAAO,CAACrF,WAAWqF,GAAG,GACxBwJ,4BAA4BjM,KAAKyC,GAAG;CAExC,CAAC;CAED,IAAIjD,IAAI;CACR,IAAI0M,IAAI;CACR,IAAIC,IAAI;CAER,MAAMC,iBAA0C;EAC9C,OAAO5M,IAAIyM,4BAA4BxM,QAAQ;GAC7C,OAAOyM,IAAI,GAAG;IACZ,MAAMnG,qBACJmG,MAAM,IAAIxC,cAAcuC,4BAA4BzM,EAAE,IAAIqK,eAAeoC,4BAA4BzM,EAAE;IACzG,OAAO2M,IAAIpG,mBAAmBtG,QAAQ;KACpC,MAAMyG,oBAAoBH,mBAAmBoG;KAC7C,IAAIjG,sBAAsB,MACxB,OAAOA;IAEX;IACAiG,IAAI;IACJD;GACF;GACAA,IAAI;GACJ1M;EACF;CAEF;CAEA,OAAO,EACLhC,WAAW;EACT,OAAO,EACLC,YAA+D;GAC7D,MAAME,QAAQyO,SAAS;GACvB,OAAO;IAAEzO;IAAOD,MAAMC,UAAUC;GAAU;EAC5C,EACF;CACF,EACF;AACF;AAYA,SAASoI,uBAAuBN,cAAwCqG,aAAyC;CAC/G,MAAMM,QAAuB,CAAA;CAC7B,MAAMC,QAAuB,CAAA;CAC7B,MAAMC,uBAAO,IAAIvE,IAAI;CACrBsE,MAAMtM,KAAK+L,WAAW;CACtB,OAAOO,MAAM7M,SAAS,GAAG;EACvB,MAAMQ,aAAaqM,MAAME,MAAM;EAC/BH,MAAMrM,KAAKC,UAAU;EACrBsM,KAAKhC,IAAItK,UAAU;EAEnB,MAAMzC,WAAWsO,oCAAoCpG,cAAcqG,WAAW,CAAC,CAACvO,SAAS;EACzF,KAAK,IAAIiP,MAAMjP,SAASC,KAAK,GAAG,CAACgP,IAAI/O,MAAM+O,MAAMjP,SAASC,KAAK,GAAG;GAChE,MAAMyI,oBAAoBuG,IAAI9O;GAC9B,IAAIuI,qBAAqB,CAACqG,KAAK9L,IAAIyF,iBAAiB,GAAG;IACrDqG,KAAKhC,IAAIrE,iBAAiB;IAC1BoG,MAAMtM,KAAKkG,iBAAiB;GAC9B;EACF;CACF;CAEA,OAAOmG;AACT;AAEA,SAASjM,iBAAiBjB,KAAsE;CAC9F,MAAMe,mBAAmB,CAAC;CAC1B,MAAMb,aAAaF,IAAIG;CACvB,IAAID,YACFqN,iBAAiBxM,kBAAkBb,UAAU;CAE/C,OAAOa;AACT;AAEA,SAASC,oBAAoBhB,KAA4E;CACvG,MAAMwN,WAAkC,CAAC;CAEzC,IAAIxN,IAAIG,SAAS;EACfoN,iBAAiBC,UAAUxN,IAAIG,OAAO;EAEtC,IAAI,YAAYH,IAAIG,SAClBqN,SAASvO,SAASe,IAAIG,QAAQlB;OACzB,IAAI,OAAOe,IAAIyN,UAAU,YAAY,YAAYzN,IAAIyN,OAC1DD,SAASvO,SAASe,IAAIyN,MAAMxO;OAE5BuO,SAASvO,SAAS,CAAC,EAAEyO,OAAO1N,IAAI2N,QAAQ,CAAC;CAE7C;CAEA,OAAOH;AACT;AAEA,SAASD,iBAAiBK,QAA6CC,QAAgB;CACrF,IAAI,WAAWA,QACbD,OAAOE,QAAQD,OAAOC;CAExB,IAAI,UAAUD,QACZD,OAAOG,OAAOF,OAAOE;AAEzB;AAEA,SAASzJ,YACPmF,OACA3I,YACAH,MACAuD,kBACA;CACA,IAAIgH;CACJ,MAAMzI,SAASgH,MAAM/G,WAAW5B,YAAY,KAAK;CACjD,MAAMkN,UAAU,CAAC,CAACvL;CAClB,MAAMuC,SAASvC,UAAUgH,MAAMxE,aAAanE,UAAU;CAEtD,MAAMmN,YAA8BxC,WAAWhJ,QAAQgH,MAAMhK,eAAeqB,UAAU,KAAK,CAACyK,eAAe9I,MAAM;CACjH,MAAMyL,WAA6B,CAAC5C,SAAS7I,MAAM,KAAK,CAACwL;CAsBzD,IAAIjJ,OAAO9F,OAAO;EAChB8F,OAAO9F,QAAQ;EACfuK,MAAMhK,cAAc+B,aAAaV,YAAY,YAAY,IAAI;EAC7D2I,MAAMhK,cAAc+B,aAAaV,YAAY,SAAS,IAAI;CAC5D;CAEA,MAAMqE,SAASzB,eAAe+F,OAAO3I,UAAU;CAI/C,IAAIoD,oBAAoB8J,WAAWrN,KAAKiC,YACtCsI,cAAcF,qBAAqBhG,QAAQrE,KAAKiC,YAAYuC,MAAM;CAGpEH,OAAOpG,cAAckE,OAAOC,OAC1BiC,OAAOpG,eAAgBkE,OAAO4E,OAAO,IAAI,GACzC/G,KAAKiC,UACP;CAEA,IAAIoC,OAAOnG,YACT;MAAIsN,qBAAqBnH,QAAQkG,WAAW,GAC1CzB,MAAMhK,cAAc+B,aAAaV,YAAY,SAAS,IAAI;CAC5D;CAGF,IAAI,CAACoN,UACHzE,MAAMhK,cAAc+B,aAAaV,YAAY,SAAS,IAAI;CAG5D,IAAIH,KAAKhC,IACPqG,OAAOrG,KAAKgC,KAAKhC;CAGnB,IAAIgC,KAAKqC,eACPgJ,mBAAmBvC,MAAM7J,SAASuF,QAAQrE,YAAYH,IAAI;CAG5D,IAAIuK,aAAahE,MACf0B,iBAAiBa,MAAMhK,eAAeqB,YAAYoK,WAAW;CAQ/D,OAAOA,aAAahE,OAAOzG,MAAM0N,KAAKjD,WAAW,IAAIzM;AACvD;AAEA,SAAS2D,WAAWgM,OAAqB3M,IAAqB;CAC5D,MAAM4M,WAAW1Q,cAAc8D,GAAGK,MAAM;CACrB,CAACuM,YAAY3Q,aAAa+D,GAAGK,MAAM;CAuBtD,QAAQL,GAAGA,IAAX;EACE,KAAK,oBAAoB;GACvB,MAAMgI,QAAQ2E,MAAM1O,QAAQwD,IAAIzB,GAAGK,MAAM;GACzC,IAAI2H,OAAO;IACT2E,MAAM1O,QAAQ6B,IAAIE,GAAGjD,OAAOiL,KAAK;IACjC2E,MAAM1O,QAAQuH,OAAOxF,GAAGK,MAAM;GAChC;GACAsM,MAAMxO,QAAQ2C,OAAOd,IAAI,IAAI;GAC7B;EACF;EACA,KAAK;GACH,IAAI4M,UAAU;IACZ,IAAI,WAAW5M,IAAI;KAGjB,IAAIyK,eAFUxI,eAAe0K,OAAO3M,GAAGK,MAAM,CAAC,CAACoB,IAAIzB,GAAGI,KAEnCA,CAAK,GAEtBuM,MAAMxO,QAAQiB,KAAKY,EAAE;UAGrB2M,MAAMnK,OACJxC,GAAGK,QACH;MACEa,MAAMlB,GAAGK,OAAOa;MAChBhE,IAAI8C,GAAGK,OAAOnD;MACdiE,YAAY,GACTnB,GAAGI,QAAQJ,GAAGjD,MACjB;KACF,GACA4P,MAAM3O,cAAc6K,UAAU7I,GAAGK,MAAM,CACzC;IAEJ,OAEEsM,MAAMnK,OAAOxC,GAAGK,QAAQL,GAAGjD,OAAO4P,MAAM3O,cAAc6K,UAAU7I,GAAGK,MAAM,CAAC;GAE9E;GAGA;EAEF,KAAK;GACH,IAAIuM,UAAU;IACZ,IAAI,WAAW5M,IAEb2M,MAAMxO,QAAQiB,KAAKY,EAAE;SAGrB2M,MAAMnK,OAAOxC,GAAGK,QAAQL,GAAGjD,OAAO4P,MAAM3O,cAAc6K,UAAU7I,GAAGK,MAAM,CAAC;GAE9E,OAGE8H,sBAAsBwE,OAAO3M,EAAE;GAEjC;EAEF,KAAK,UACH,IAAI4M,UAAU;GACZ,IAAI,WAAW5M,IAEb2M,MAAMxO,QAAQiB,KAAKY,EAAE;QAChB;IAEL,MAAMuD,SAASoJ,MAAM1L,WAAWjB,GAAGK,QAAQ,KAAK;IAChD,IAAIkD,QAAQ;KACVA,OAAO7F,YAAY;KACnB6F,OAAO5F,sBAAsB;KAC7BgP,MAAM9H,aAAa7E,GAAGK,MAAM;IAC9B,OACEtE,UAAU4Q,MAAM3O,aAAa,CAAC,EAAEoB,KAAK;KACnCY,IAAI;KACJK,QAAQL,GAAGK;KACX5C,OAAO;IACT,CAAC;GAEL;EACF,OACE,IAAI,WAAWuC,IAIbyI,2BAA2BkE,OAAO3M,EAAE;CAe5C;AAMF;AAEA,SAASiC,eACP+F,OACA3I,YAC2D;CAC3D,IAAI2I,MAAMhK,cAAcmL,OAAO2D,aAAa;EAC1C,MAAMnK,SAASqF,MAAMhK,cAAcmL,OAAO2D,YAAYzN,UAAU;EAChE,IAAIsD,QACF,OAAOA;CAEX;CAGA,OAAOqF,MAAMhK,cAAcmL,OAAOzF,OAAOrE,UAAU;AAIrD;AAEA,SAASuF,eAAeoD,OAAqB3I,YAAyB7B,QAAiC;CACrG,MAAM+F,SAASyE,MAAM9C,OAAO7F,YAAY,KAAK;CAC7C,IAAIkE,OAAOjG,eAAe;EACxB,MAAMoE,OAAOL,OAAOK,KAAK6B,OAAOjG,aAAa;EAC7C,IAAIoE,KAAK7C,SAAS,GAAG;GACnB,MAAMmD,QAASuB,OAAOnG,aACpBmG,OAAOnG,cAAeiE,OAAO4E,OAAO,IAAI;GAC1C,KAAK,IAAIrH,IAAI,GAAGA,IAAI8C,KAAK7C,QAAQD,KAC/B,IAAIoD,MAAMN,KAAK9C,QAAQ5B,QACrBgF,MAAMN,KAAK9C,MAAM2E,OAAOjG,cAAcoE,KAAK9C;EAGjD;EACA2E,OAAOjG,gBAAgB;CACzB;CACA,IAAIE,QACF+F,OAAO/F,SAASA;CAElBwK,MAAMhK,cAAc+B,aAAaV,YAAY,UAAU,IAAI;AAC7D;AAEA,SAASiF,UACP0D,OACAzD,qBACArF,MACAc,IACM;CACN,IAAI,CAACd,MAAM,CAKX;CAEA,MAAM,EAAEJ,oBAAoBkJ,MAAMhK;CAClC,MAAM+O,aAAaxI,oBAAoBrH;CACvC,MAAMmC,aACJW,OAAO,kBAAkBd,OACrBJ,gBAAgBkM,uBAAuBzG,qBAAqBrF,IAAI,IAChEqF;CAEN,MAAMhB,SAASyE,MAAM9C,OAAO7F,YAAY,KAAK;CAC7C,IAAIkE,OAAO7F,aAAasC,OAAO,gBAAgB;EAC7CgI,MAAM7J,QAAQiB,KAAK;GACjBY,IAAI;GACJK,QAAQhB;GACR5B,OAAO;EACT,CAAC;EACD8F,OAAO7F,YAAY;EACnB6F,OAAO5F,sBAAsB;EAC7BqK,MAAMhK,cAAc+B,aAAaV,YAAY,WAAW,IAAI;CAE9D;CAaA,MAAMqE,SAASzB,eAAe+F,OAAO3I,UAAU;CAC/CkE,OAAO9F,QAAQ;CACf,IAAIuP;CACJ,IAAI9N,MAAM;EACR,IAAIA,KAAKhC,MAAM,CAACqG,OAAOrG,IACrBqG,OAAOrG,KAAKgC,KAAKhC;EAEnB,IAAImC,eAAekF,uBAAuBlF,WAAWnC,OAAO6P,YAC1D/E,MAAMhK,cAAc+B,aAAaV,YAAY,YAAY,IAAI;EAQ/D,IAAIH,KAAKqC,eA8BPgJ,mBAAmBvC,MAAM7J,SAASuF,QAAQrE,YAAYH,IAAI;EAE5D8N,yBAAyB9N,KAAKiC;CAChC;CACA,MAAMsI,cAAcuD,0BAA0BzD,qBAAqBhG,QAAQyJ,wBAAwBtJ,MAAM;CAEzGH,OAAOpG,cAAckE,OAAOC,OAC1BiC,OAAOpG,eAAgBkE,OAAO4E,OAAO,IAAI,GACzC1C,OAAOjG,eACP0P,sBACF;CACAzJ,OAAOjG,gBAAgB;CACvBoN,qBAAqBnH,QAAQkG,WAAW;CAExC,IAAIlG,OAAO/F,QAAQ;EACjB+F,OAAO/F,SAAS;EAChBwK,MAAMhK,cAAc+B,aAAaV,YAAY,UAAU,IAAI;CAC7D;CAEA,IAAIoK,aAAahE,MAAM0B,iBAAiBa,MAAMhK,eAAeqB,YAAYoK,WAAW;CACpFzB,MAAMhK,cAAc+B,aAAaV,YAAY,SAAS,IAAI;AAC5D;AAEA,SAAS+E,WAAW4D,OAAqB3I,YAA+B;CACtE,MAAMkE,SAASyE,MAAM9C,OAAO7F,YAAY,KAAK;CA0B7C,IAAIkE,OAAOjG,eACT;MAAIiG,OAAOnG,YACTiE,OAAOC,OAAOiC,OAAOjG,eAAeiG,OAAOnG,UAAU;CACvD,OAEAmG,OAAOjG,gBAAgBiG,OAAOnG;CAEhCmG,OAAOnG,aAAa;AAkBtB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warp-drive/json-api",
|
|
3
|
-
"version": "5.9.0-beta.
|
|
3
|
+
"version": "5.9.0-beta.1",
|
|
4
4
|
"description": "A {json:api} Cache Implementation for WarpDrive",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -40,24 +40,24 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@warp-drive/core": "5.9.0-beta.
|
|
43
|
+
"@warp-drive/core": "5.9.0-beta.1"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@embroider/macros": "^1.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
46
|
+
"@embroider/macros": "^1.20.6",
|
|
47
|
+
"fuse.js": "7.1.0",
|
|
48
|
+
"json-to-ast": "2.1.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@babel/core": "^7.28.3",
|
|
52
52
|
"@babel/plugin-transform-typescript": "^7.28.0",
|
|
53
53
|
"@babel/preset-typescript": "^7.27.1",
|
|
54
54
|
"@types/json-to-ast": "^2.1.4",
|
|
55
|
-
"@warp-drive/
|
|
56
|
-
"@warp-drive/
|
|
55
|
+
"@warp-drive/core": "5.9.0-beta.1",
|
|
56
|
+
"@warp-drive/internal-config": "5.9.0-beta.1",
|
|
57
57
|
"decorator-transforms": "^2.3.0",
|
|
58
58
|
"expect-type": "^1.2.2",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
59
|
+
"tsdown": "^0.22.14",
|
|
60
|
+
"typescript": "^5.9.3"
|
|
61
61
|
},
|
|
62
62
|
"volta": {
|
|
63
63
|
"extends": "../../package.json"
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"edition": "octane"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
|
-
"build:pkg": "
|
|
74
|
+
"build:pkg": "tsdown",
|
|
75
75
|
"lint": "eslint . --quiet --cache --cache-strategy=content",
|
|
76
76
|
"sync": "echo \"syncing\"",
|
|
77
|
-
"start": "
|
|
77
|
+
"start": "tsdown --watch"
|
|
78
78
|
}
|
|
79
79
|
}
|