@warp-drive/core 5.6.0-alpha.14 → 5.6.0-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/declarations/configure.d.ts +1 -1
  2. package/declarations/configure.d.ts.map +1 -1
  3. package/declarations/reactive/-private/fields/compute.d.ts.map +1 -1
  4. package/declarations/reactive/-private/fields/extension.d.ts +9 -0
  5. package/declarations/reactive/-private/fields/extension.d.ts.map +1 -0
  6. package/declarations/reactive/-private/fields/managed-array.d.ts.map +1 -1
  7. package/declarations/reactive/-private/fields/managed-object.d.ts.map +1 -1
  8. package/declarations/reactive/-private/record.d.ts +4 -3
  9. package/declarations/reactive/-private/record.d.ts.map +1 -1
  10. package/declarations/reactive/-private/schema.d.ts +73 -0
  11. package/declarations/reactive/-private/schema.d.ts.map +1 -1
  12. package/declarations/reactive/-private/symbols.d.ts +1 -1
  13. package/declarations/reactive/-private/symbols.d.ts.map +1 -1
  14. package/declarations/reactive.d.ts +1 -1
  15. package/declarations/reactive.d.ts.map +1 -1
  16. package/declarations/store/-private/new-core-tmp/promise-state.d.ts.map +1 -1
  17. package/declarations/store/-private/new-core-tmp/reactivity/configure.d.ts +86 -2
  18. package/declarations/store/-private/new-core-tmp/reactivity/configure.d.ts.map +1 -1
  19. package/declarations/store/-private/new-core-tmp/request-subscription.d.ts +231 -0
  20. package/declarations/store/-private/new-core-tmp/request-subscription.d.ts.map +1 -0
  21. package/declarations/store/-private/record-arrays/identifier-array.d.ts +2 -0
  22. package/declarations/store/-private/record-arrays/identifier-array.d.ts.map +1 -1
  23. package/declarations/store/-private/record-arrays/many-array.d.ts +2 -0
  24. package/declarations/store/-private/record-arrays/many-array.d.ts.map +1 -1
  25. package/declarations/store/-private.d.ts +1 -0
  26. package/declarations/store/-private.d.ts.map +1 -1
  27. package/declarations/store/-types/q/schema-service.d.ts +20 -0
  28. package/declarations/store/-types/q/schema-service.d.ts.map +1 -1
  29. package/declarations/types/-private.d.ts +1 -1
  30. package/declarations/types/-private.d.ts.map +1 -1
  31. package/declarations/types/schema/fields.d.ts +133 -7
  32. package/declarations/types/schema/fields.d.ts.map +1 -1
  33. package/dist/{configure-BgaZESRo.js → configure-B48bFHOl.js} +38 -2
  34. package/dist/configure-B48bFHOl.js.map +1 -0
  35. package/dist/configure.js +1 -1
  36. package/dist/graph/-private.js +2 -2
  37. package/dist/{handler-cHghx9Y9.js → handler-D1C3Innj.js} +1 -1
  38. package/dist/{handler-cHghx9Y9.js.map → handler-D1C3Innj.js.map} +1 -1
  39. package/dist/index.js +3 -3
  40. package/dist/reactive/-private.js +1 -1
  41. package/dist/reactive.js +248 -31
  42. package/dist/reactive.js.map +1 -1
  43. package/dist/{request-state-DgwTEXLU.js → request-state-CCOJIj5i.js} +778 -11
  44. package/dist/request-state-CCOJIj5i.js.map +1 -0
  45. package/dist/store/-private.js +3 -3
  46. package/dist/{symbols-BmDcn6hS.js → symbols-epHW0Vm9.js} +2 -2
  47. package/dist/{symbols-BmDcn6hS.js.map → symbols-epHW0Vm9.js.map} +1 -1
  48. package/dist/types/-private.js +1 -1
  49. package/dist/types/-private.js.map +1 -1
  50. package/dist/types/schema/fields.js +4 -4
  51. package/dist/types/schema/fields.js.map +1 -1
  52. package/package.json +3 -3
  53. package/dist/configure-BgaZESRo.js.map +0 -1
  54. package/dist/request-state-DgwTEXLU.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"handler-cHghx9Y9.js","sources":["../src/store/-private/cache-handler/utils.ts","../src/store/-private/cache-handler/handler.ts"],"sourcesContent":["import type { StableDocumentIdentifier } from '../../../types/identifier.ts';\nimport type {\n ImmutableCreateRequestOptions,\n ImmutableDeleteRequestOptions,\n ImmutableRequestInfo,\n ImmutableUpdateRequestOptions,\n StructuredDataDocument,\n} from '../../../types/request.ts';\nimport type { ResourceDataDocument, ResourceErrorDocument } from '../../../types/spec/document.ts';\nimport type { ApiError } from '../../../types/spec/error.ts';\nimport type { Store } from '../store-service.ts';\n\nexport const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);\n\nexport function calcShouldFetch(\n store: Store,\n request: ImmutableRequestInfo,\n hasCachedValue: boolean,\n identifier: StableDocumentIdentifier | null\n): boolean {\n const { cacheOptions } = request;\n return (\n (request.op && MUTATION_OPS.has(request.op)) ||\n cacheOptions?.reload ||\n !hasCachedValue ||\n (store.lifetimes && identifier ? store.lifetimes.isHardExpired(identifier, store) : false)\n );\n}\n\nexport function calcShouldBackgroundFetch(\n store: Store,\n request: ImmutableRequestInfo,\n willFetch: boolean,\n identifier: StableDocumentIdentifier | null\n): boolean {\n const { cacheOptions } = request;\n return (\n !willFetch &&\n (cacheOptions?.backgroundReload ||\n (store.lifetimes && identifier ? store.lifetimes.isSoftExpired(identifier, store) : false))\n );\n}\n\nexport function isMutation(\n request: Partial<ImmutableRequestInfo>\n): request is ImmutableUpdateRequestOptions | ImmutableCreateRequestOptions | ImmutableDeleteRequestOptions {\n return Boolean(request.op && MUTATION_OPS.has(request.op));\n}\n\nexport function isCacheAffecting<T>(document: StructuredDataDocument<T>): boolean {\n if (!isMutation(document.request)) {\n return true;\n }\n // a mutation combined with a 204 has no cache impact when no known records were involved\n // a createRecord with a 201 with an empty response and no known records should similarly\n // have no cache impact\n\n if (document.request.op === 'createRecord' && document.response?.status === 201) {\n return document.content ? Object.keys(document.content).length > 0 : false;\n }\n\n return document.response?.status !== 204;\n}\n\nexport function isAggregateError(\n error: Error & { errors?: ApiError[] }\n): error is AggregateError & { errors: ApiError[] } {\n return error instanceof AggregateError || (error.name === 'AggregateError' && Array.isArray(error.errors));\n}\n\nexport type RobustError = Error & { error: string | object; errors?: ApiError[]; content?: unknown };\n\n// TODO @runspired, consider if we should deep freeze errors (potentially only in debug) vs cloning them\nexport function cloneError(error: RobustError) {\n const isAggregate = isAggregateError(error);\n\n const cloned = (\n isAggregate ? new AggregateError(structuredClone(error.errors), error.message) : new Error(error.message)\n ) as RobustError;\n cloned.stack = error.stack!;\n cloned.error = error.error;\n\n // copy over enumerable properties\n Object.assign(cloned, error);\n\n return cloned;\n}\n\nexport function isErrorDocument(\n document: ResourceDataDocument | ResourceErrorDocument\n): document is ResourceErrorDocument {\n return 'errors' in document;\n}\n\nexport function getPriority(\n identifier: StableDocumentIdentifier | null,\n deduped: Map<StableDocumentIdentifier, { priority: { blocking: boolean } }>,\n priority: { blocking: boolean }\n) {\n if (identifier) {\n const existing = deduped.get(identifier);\n if (existing) {\n return existing.priority;\n }\n }\n return priority;\n}\n","import { assert } from '@warp-drive/core/build-config/macros';\n\nimport { ReactiveDocument } from '../../../reactive/-private/document.ts';\nimport type { CacheHandler as CacheHandlerType, Future, ManagedRequestPriority, NextFn } from '../../../request.ts';\nimport type { StableDocumentIdentifier } from '../../../types/identifier.ts';\nimport type {\n ImmutableRequestInfo,\n RequestContext,\n StructuredDataDocument,\n StructuredErrorDocument,\n} from '../../../types/request.ts';\nimport { EnableHydration, SkipCache } from '../../../types/request.ts';\nimport type { ResourceDataDocument, ResourceDocument, ResourceErrorDocument } from '../../../types/spec/document.ts';\nimport type { ApiError } from '../../../types/spec/error.ts';\nimport type { ResourceIdentifierObject } from '../../../types/spec/json-api-raw.ts';\nimport type { RequestSignature } from '../../../types/symbols.ts';\nimport type { Store } from '../store-service.ts';\nimport {\n calcShouldBackgroundFetch,\n calcShouldFetch,\n cloneError,\n getPriority,\n isCacheAffecting,\n isMutation,\n} from './utils.ts';\n\nexport type LooseStoreRequestInfo<RT = unknown, T = unknown> = Omit<\n ImmutableRequestInfo<RT, T>,\n 'records' | 'headers' | typeof RequestSignature\n> & {\n records?: ResourceIdentifierObject[];\n headers?: Headers;\n};\n\nexport type StoreRequestInput<RT = unknown, T = unknown> = ImmutableRequestInfo<RT, T> | LooseStoreRequestInfo<RT, T>;\n\nexport interface StoreRequestContext extends RequestContext {\n request: ImmutableRequestInfo & { store: Store };\n}\n\n/**\n * A CacheHandler that adds support for using an WarpDrive Cache with a RequestManager.\n *\n * This handler will only run when a request has supplied a `store` instance. Requests\n * issued by the store via `store.request()` will automatically have the `store` instance\n * attached to the request.\n *\n * ```ts\n * requestManager.request({\n * store: store,\n * url: '/api/posts',\n * method: 'GET'\n * });\n * ```\n *\n * When this handler elects to handle a request, it will return the raw `StructuredDocument`\n * unless the request has `[EnableHydration]` set to `true`. In this case, the handler will\n * return a `Document` instance that will automatically update the UI when the cache is updated\n * in the future and will hydrate any identifiers in the StructuredDocument into Record instances.\n *\n * When issuing a request via the store, [EnableHydration] is automatically set to `true`. This\n * means that if desired you can issue requests that utilize the cache without needing to also\n * utilize Record instances if desired.\n *\n * Said differently, you could elect to issue all requests via a RequestManager, without ever using\n * the store directly, by setting [EnableHydration] to `true` and providing a store instance. Not\n * necessarily the most useful thing, but the decoupled nature of the RequestManager and incremental-feature\n * approach of WarpDrive allows for this flexibility.\n *\n * ```ts\n * import { EnableHydration } from '@warp-drive/core/types/request';\n *\n * requestManager.request({\n * store: store,\n * url: '/api/posts',\n * method: 'GET',\n * [EnableHydration]: true\n * });\n *\n */\nexport const CacheHandler: CacheHandlerType = {\n request<T>(\n context: StoreRequestContext & { setIdentifier(identifier: StableDocumentIdentifier): void },\n next: NextFn<T>\n ): Promise<T | StructuredDataDocument<T>> | Future<T> | T {\n // if we have no cache or no cache-key skip cache handling\n if (!context.request.store || context.request.cacheOptions?.[SkipCache]) {\n return next(context.request);\n }\n\n const { store } = context.request;\n const identifier = store.identifierCache.getOrCreateDocumentIdentifier(context.request);\n\n if (identifier) {\n context.setIdentifier(identifier);\n }\n\n // used to dedupe existing requests that match\n const DEDUPE = store.requestManager._deduped;\n const activeRequest = identifier && DEDUPE.get(identifier);\n const peeked = identifier ? store.cache.peekRequest(identifier) : null;\n\n // determine if we should skip cache\n if (calcShouldFetch(store, context.request, !!peeked, identifier)) {\n if (activeRequest) {\n activeRequest.priority = { blocking: true };\n return activeRequest.promise as Promise<T>;\n }\n let promise = fetchContentAndHydrate(next, context, identifier, { blocking: true });\n if (identifier) {\n promise = promise.finally(() => {\n DEDUPE.delete(identifier);\n store.notifications.notify(identifier, 'state');\n });\n DEDUPE.set(identifier, { priority: { blocking: true }, promise });\n store.notifications.notify(identifier, 'state');\n }\n return promise;\n }\n\n // if we have not skipped cache, determine if we should update behind the scenes\n if (calcShouldBackgroundFetch(store, context.request, false, identifier)) {\n let promise = activeRequest?.promise || fetchContentAndHydrate(next, context, identifier, { blocking: false });\n if (identifier && !activeRequest) {\n promise = promise.finally(() => {\n DEDUPE.delete(identifier);\n store.notifications.notify(identifier, 'state');\n });\n DEDUPE.set(identifier, { priority: { blocking: false }, promise });\n store.notifications.notify(identifier, 'state');\n }\n store.requestManager._pending.set(context.id, promise);\n }\n\n assert(`Expected a peeked request to be present`, peeked);\n\n const shouldHydrate: boolean = context.request[EnableHydration] || false;\n context.setResponse(peeked.response);\n\n if ('error' in peeked) {\n const content = shouldHydrate\n ? maybeUpdateUiObjects<T>(store, context.request, { shouldHydrate, identifier }, peeked.content)\n : peeked.content;\n const newError = cloneError(peeked);\n newError.content = content as object;\n throw newError;\n }\n\n const result = shouldHydrate\n ? (maybeUpdateUiObjects<T>(store, context.request, { shouldHydrate, identifier }, peeked.content) as T)\n : (peeked.content as T);\n\n return result;\n },\n};\n\ntype HydrationOptions = {\n shouldHydrate?: boolean;\n identifier: StableDocumentIdentifier | null;\n};\n\ntype UpdateOptions = HydrationOptions & {\n priority: ManagedRequestPriority;\n};\n\nfunction maybeUpdateUiObjects<T>(\n store: Store,\n request: ImmutableRequestInfo,\n options: HydrationOptions,\n document: ResourceDocument | null | undefined\n): ReactiveDocument<T> | ResourceDocument | null {\n const { identifier } = options;\n\n if (!document || !options.shouldHydrate) {\n assert(`The CacheHandler expected response content but none was found`, !options.shouldHydrate);\n return document ?? null;\n }\n\n if (identifier) {\n return store._instanceCache.getDocument<T>(identifier);\n }\n\n // if we don't have an identifier, we give the document\n // its own local cache\n return new ReactiveDocument<T>(store, null, {\n request,\n document,\n });\n}\n\nfunction updateCacheForSuccess<T>(\n store: Store,\n request: StoreRequestContext['request'],\n options: HydrationOptions,\n document: StructuredDataDocument<T>\n) {\n let response: ResourceDataDocument | null = null;\n if (isMutation(request)) {\n const record = request.data?.record || request.records?.[0];\n if (record) {\n response = store.cache.didCommit(record, document) as ResourceDataDocument;\n\n // a mutation combined with a 204 has no cache impact when no known records were involved\n // a createRecord with a 201 with an empty response and no known records should similarly\n // have no cache impact\n } else if (isCacheAffecting(document)) {\n response = store.cache.put(document) as ResourceDataDocument;\n }\n } else {\n response = store.cache.put(document) as ResourceDataDocument;\n }\n return maybeUpdateUiObjects(store, request, options, response);\n}\n\nfunction handleFetchSuccess<T>(\n store: Store,\n context: StoreRequestContext,\n options: UpdateOptions,\n document: StructuredDataDocument<T>\n): ResourceDataDocument | void {\n const { request } = context;\n store.requestManager._pending.delete(context.id);\n store._enableAsyncFlush = true;\n let response: ResourceDataDocument;\n store._join(() => {\n response = updateCacheForSuccess<T>(store, request, options, document) as ResourceDataDocument;\n });\n store._enableAsyncFlush = null;\n\n if (store.lifetimes?.didRequest) {\n store.lifetimes.didRequest(context.request, document.response, options.identifier, store);\n }\n\n const finalPriority = getPriority(options.identifier, store.requestManager._deduped, options.priority);\n if (finalPriority.blocking) {\n return response!;\n } else {\n store.notifications._flush();\n }\n}\n\nfunction updateCacheForError<T>(\n store: Store,\n context: StoreRequestContext,\n options: HydrationOptions,\n error: StructuredErrorDocument<T>\n) {\n let response: ResourceErrorDocument | undefined;\n if (isMutation(context.request)) {\n // TODO similar to didCommit we should spec this to be similar to cache.put for handling full response\n // currently we let the response remain undefiend.\n const errors =\n error &&\n error.content &&\n typeof error.content === 'object' &&\n 'errors' in error.content &&\n Array.isArray(error.content.errors)\n ? (error.content.errors as ApiError[])\n : undefined;\n\n const record = context.request.data?.record || context.request.records?.[0];\n\n store.cache.commitWasRejected(record, errors);\n } else {\n response = store.cache.put(error) as ResourceErrorDocument;\n return maybeUpdateUiObjects(store, context.request, options, response);\n }\n}\n\nfunction handleFetchError<T>(\n store: Store,\n context: StoreRequestContext,\n options: UpdateOptions,\n error: StructuredErrorDocument<T>\n): ResourceErrorDocument | void {\n store.requestManager._pending.delete(context.id);\n if (context.request.signal?.aborted) {\n throw error;\n }\n store._enableAsyncFlush = true;\n let response: ResourceErrorDocument | undefined;\n store._join(() => {\n response = updateCacheForError(store, context, options, error) as ResourceErrorDocument;\n });\n store._enableAsyncFlush = null;\n\n if (options.identifier && store.lifetimes?.didRequest) {\n store.lifetimes.didRequest(context.request, error.response, options.identifier, store);\n }\n\n if (isMutation(context.request)) {\n throw error;\n }\n\n const finalPriority = getPriority(options.identifier, store.requestManager._deduped, options.priority);\n if (finalPriority.blocking) {\n const newError = cloneError(error);\n newError.content = response!;\n throw newError;\n } else {\n store.notifications._flush();\n }\n}\n\nfunction fetchContentAndHydrate<T>(\n next: NextFn<T>,\n context: StoreRequestContext,\n identifier: StableDocumentIdentifier | null,\n priority: { blocking: boolean }\n): Promise<T> {\n const { store } = context.request;\n const shouldHydrate: boolean = context.request[EnableHydration] || false;\n const options = { shouldHydrate, identifier, priority };\n\n let isMut = false;\n if (isMutation(context.request)) {\n isMut = true;\n // TODO should we handle multiple records in request.records by iteratively calling willCommit for each\n const record = context.request.data?.record || context.request.records?.[0];\n assert(\n `Expected to receive a list of records included in the ${context.request.op} request`,\n record || !shouldHydrate\n );\n if (record) {\n store.cache.willCommit(record, context);\n }\n }\n\n if (store.lifetimes?.willRequest) {\n store.lifetimes.willRequest(context.request, identifier, store);\n }\n\n const promise = next(context.request).then(\n (document) => {\n return handleFetchSuccess(store, context, options, document);\n },\n (error: StructuredErrorDocument<T>) => {\n return handleFetchError(store, context, options, error);\n }\n ) as Promise<T>;\n\n if (!isMut) {\n return promise;\n }\n assert(`Expected a mutation`, isMutation(context.request));\n\n // for mutations we need to enqueue the promise with the requestStateService\n // TODO should we enque a request per record in records?\n const record = context.request.data?.record || context.request.records?.[0];\n\n return store._requestCache._enqueue(promise, {\n data: [{ op: 'saveRecord', recordIdentifier: record, options: undefined }],\n });\n}\n"],"names":["MUTATION_OPS","Set","calcShouldFetch","store","request","hasCachedValue","identifier","cacheOptions","op","has","reload","lifetimes","isHardExpired","calcShouldBackgroundFetch","willFetch","backgroundReload","isSoftExpired","isMutation","Boolean","isCacheAffecting","document","response","status","content","Object","keys","length","isAggregateError","error","AggregateError","name","Array","isArray","errors","cloneError","isAggregate","cloned","structuredClone","message","Error","stack","assign","getPriority","deduped","priority","existing","get","CacheHandler","context","next","SkipCache","identifierCache","getOrCreateDocumentIdentifier","setIdentifier","DEDUPE","requestManager","_deduped","activeRequest","peeked","cache","peekRequest","blocking","promise","fetchContentAndHydrate","finally","delete","notifications","notify","set","_pending","id","macroCondition","getGlobalConfig","WarpDrive","env","DEBUG","test","shouldHydrate","EnableHydration","setResponse","maybeUpdateUiObjects","newError","result","options","_instanceCache","getDocument","ReactiveDocument","updateCacheForSuccess","record","data","records","didCommit","put","handleFetchSuccess","_enableAsyncFlush","_join","didRequest","finalPriority","_flush","updateCacheForError","undefined","commitWasRejected","handleFetchError","signal","aborted","isMut","willCommit","willRequest","then","_requestCache","_enqueue","recordIdentifier"],"mappings":"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"}
1
+ {"version":3,"file":"handler-D1C3Innj.js","sources":["../src/store/-private/cache-handler/utils.ts","../src/store/-private/cache-handler/handler.ts"],"sourcesContent":["import type { StableDocumentIdentifier } from '../../../types/identifier.ts';\nimport type {\n ImmutableCreateRequestOptions,\n ImmutableDeleteRequestOptions,\n ImmutableRequestInfo,\n ImmutableUpdateRequestOptions,\n StructuredDataDocument,\n} from '../../../types/request.ts';\nimport type { ResourceDataDocument, ResourceErrorDocument } from '../../../types/spec/document.ts';\nimport type { ApiError } from '../../../types/spec/error.ts';\nimport type { Store } from '../store-service.ts';\n\nexport const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);\n\nexport function calcShouldFetch(\n store: Store,\n request: ImmutableRequestInfo,\n hasCachedValue: boolean,\n identifier: StableDocumentIdentifier | null\n): boolean {\n const { cacheOptions } = request;\n return (\n (request.op && MUTATION_OPS.has(request.op)) ||\n cacheOptions?.reload ||\n !hasCachedValue ||\n (store.lifetimes && identifier ? store.lifetimes.isHardExpired(identifier, store) : false)\n );\n}\n\nexport function calcShouldBackgroundFetch(\n store: Store,\n request: ImmutableRequestInfo,\n willFetch: boolean,\n identifier: StableDocumentIdentifier | null\n): boolean {\n const { cacheOptions } = request;\n return (\n !willFetch &&\n (cacheOptions?.backgroundReload ||\n (store.lifetimes && identifier ? store.lifetimes.isSoftExpired(identifier, store) : false))\n );\n}\n\nexport function isMutation(\n request: Partial<ImmutableRequestInfo>\n): request is ImmutableUpdateRequestOptions | ImmutableCreateRequestOptions | ImmutableDeleteRequestOptions {\n return Boolean(request.op && MUTATION_OPS.has(request.op));\n}\n\nexport function isCacheAffecting<T>(document: StructuredDataDocument<T>): boolean {\n if (!isMutation(document.request)) {\n return true;\n }\n // a mutation combined with a 204 has no cache impact when no known records were involved\n // a createRecord with a 201 with an empty response and no known records should similarly\n // have no cache impact\n\n if (document.request.op === 'createRecord' && document.response?.status === 201) {\n return document.content ? Object.keys(document.content).length > 0 : false;\n }\n\n return document.response?.status !== 204;\n}\n\nexport function isAggregateError(\n error: Error & { errors?: ApiError[] }\n): error is AggregateError & { errors: ApiError[] } {\n return error instanceof AggregateError || (error.name === 'AggregateError' && Array.isArray(error.errors));\n}\n\nexport type RobustError = Error & { error: string | object; errors?: ApiError[]; content?: unknown };\n\n// TODO @runspired, consider if we should deep freeze errors (potentially only in debug) vs cloning them\nexport function cloneError(error: RobustError) {\n const isAggregate = isAggregateError(error);\n\n const cloned = (\n isAggregate ? new AggregateError(structuredClone(error.errors), error.message) : new Error(error.message)\n ) as RobustError;\n cloned.stack = error.stack!;\n cloned.error = error.error;\n\n // copy over enumerable properties\n Object.assign(cloned, error);\n\n return cloned;\n}\n\nexport function isErrorDocument(\n document: ResourceDataDocument | ResourceErrorDocument\n): document is ResourceErrorDocument {\n return 'errors' in document;\n}\n\nexport function getPriority(\n identifier: StableDocumentIdentifier | null,\n deduped: Map<StableDocumentIdentifier, { priority: { blocking: boolean } }>,\n priority: { blocking: boolean }\n) {\n if (identifier) {\n const existing = deduped.get(identifier);\n if (existing) {\n return existing.priority;\n }\n }\n return priority;\n}\n","import { assert } from '@warp-drive/core/build-config/macros';\n\nimport { ReactiveDocument } from '../../../reactive/-private/document.ts';\nimport type { CacheHandler as CacheHandlerType, Future, ManagedRequestPriority, NextFn } from '../../../request.ts';\nimport type { StableDocumentIdentifier } from '../../../types/identifier.ts';\nimport type {\n ImmutableRequestInfo,\n RequestContext,\n StructuredDataDocument,\n StructuredErrorDocument,\n} from '../../../types/request.ts';\nimport { EnableHydration, SkipCache } from '../../../types/request.ts';\nimport type { ResourceDataDocument, ResourceDocument, ResourceErrorDocument } from '../../../types/spec/document.ts';\nimport type { ApiError } from '../../../types/spec/error.ts';\nimport type { ResourceIdentifierObject } from '../../../types/spec/json-api-raw.ts';\nimport type { RequestSignature } from '../../../types/symbols.ts';\nimport type { Store } from '../store-service.ts';\nimport {\n calcShouldBackgroundFetch,\n calcShouldFetch,\n cloneError,\n getPriority,\n isCacheAffecting,\n isMutation,\n} from './utils.ts';\n\nexport type LooseStoreRequestInfo<RT = unknown, T = unknown> = Omit<\n ImmutableRequestInfo<RT, T>,\n 'records' | 'headers' | typeof RequestSignature\n> & {\n records?: ResourceIdentifierObject[];\n headers?: Headers;\n};\n\nexport type StoreRequestInput<RT = unknown, T = unknown> = ImmutableRequestInfo<RT, T> | LooseStoreRequestInfo<RT, T>;\n\nexport interface StoreRequestContext extends RequestContext {\n request: ImmutableRequestInfo & { store: Store };\n}\n\n/**\n * A CacheHandler that adds support for using an WarpDrive Cache with a RequestManager.\n *\n * This handler will only run when a request has supplied a `store` instance. Requests\n * issued by the store via `store.request()` will automatically have the `store` instance\n * attached to the request.\n *\n * ```ts\n * requestManager.request({\n * store: store,\n * url: '/api/posts',\n * method: 'GET'\n * });\n * ```\n *\n * When this handler elects to handle a request, it will return the raw `StructuredDocument`\n * unless the request has `[EnableHydration]` set to `true`. In this case, the handler will\n * return a `Document` instance that will automatically update the UI when the cache is updated\n * in the future and will hydrate any identifiers in the StructuredDocument into Record instances.\n *\n * When issuing a request via the store, [EnableHydration] is automatically set to `true`. This\n * means that if desired you can issue requests that utilize the cache without needing to also\n * utilize Record instances if desired.\n *\n * Said differently, you could elect to issue all requests via a RequestManager, without ever using\n * the store directly, by setting [EnableHydration] to `true` and providing a store instance. Not\n * necessarily the most useful thing, but the decoupled nature of the RequestManager and incremental-feature\n * approach of WarpDrive allows for this flexibility.\n *\n * ```ts\n * import { EnableHydration } from '@warp-drive/core/types/request';\n *\n * requestManager.request({\n * store: store,\n * url: '/api/posts',\n * method: 'GET',\n * [EnableHydration]: true\n * });\n *\n */\nexport const CacheHandler: CacheHandlerType = {\n request<T>(\n context: StoreRequestContext & { setIdentifier(identifier: StableDocumentIdentifier): void },\n next: NextFn<T>\n ): Promise<T | StructuredDataDocument<T>> | Future<T> | T {\n // if we have no cache or no cache-key skip cache handling\n if (!context.request.store || context.request.cacheOptions?.[SkipCache]) {\n return next(context.request);\n }\n\n const { store } = context.request;\n const identifier = store.identifierCache.getOrCreateDocumentIdentifier(context.request);\n\n if (identifier) {\n context.setIdentifier(identifier);\n }\n\n // used to dedupe existing requests that match\n const DEDUPE = store.requestManager._deduped;\n const activeRequest = identifier && DEDUPE.get(identifier);\n const peeked = identifier ? store.cache.peekRequest(identifier) : null;\n\n // determine if we should skip cache\n if (calcShouldFetch(store, context.request, !!peeked, identifier)) {\n if (activeRequest) {\n activeRequest.priority = { blocking: true };\n return activeRequest.promise as Promise<T>;\n }\n let promise = fetchContentAndHydrate(next, context, identifier, { blocking: true });\n if (identifier) {\n promise = promise.finally(() => {\n DEDUPE.delete(identifier);\n store.notifications.notify(identifier, 'state');\n });\n DEDUPE.set(identifier, { priority: { blocking: true }, promise });\n store.notifications.notify(identifier, 'state');\n }\n return promise;\n }\n\n // if we have not skipped cache, determine if we should update behind the scenes\n if (calcShouldBackgroundFetch(store, context.request, false, identifier)) {\n let promise = activeRequest?.promise || fetchContentAndHydrate(next, context, identifier, { blocking: false });\n if (identifier && !activeRequest) {\n promise = promise.finally(() => {\n DEDUPE.delete(identifier);\n store.notifications.notify(identifier, 'state');\n });\n DEDUPE.set(identifier, { priority: { blocking: false }, promise });\n store.notifications.notify(identifier, 'state');\n }\n store.requestManager._pending.set(context.id, promise);\n }\n\n assert(`Expected a peeked request to be present`, peeked);\n\n const shouldHydrate: boolean = context.request[EnableHydration] || false;\n context.setResponse(peeked.response);\n\n if ('error' in peeked) {\n const content = shouldHydrate\n ? maybeUpdateUiObjects<T>(store, context.request, { shouldHydrate, identifier }, peeked.content)\n : peeked.content;\n const newError = cloneError(peeked);\n newError.content = content as object;\n throw newError;\n }\n\n const result = shouldHydrate\n ? (maybeUpdateUiObjects<T>(store, context.request, { shouldHydrate, identifier }, peeked.content) as T)\n : (peeked.content as T);\n\n return result;\n },\n};\n\ntype HydrationOptions = {\n shouldHydrate?: boolean;\n identifier: StableDocumentIdentifier | null;\n};\n\ntype UpdateOptions = HydrationOptions & {\n priority: ManagedRequestPriority;\n};\n\nfunction maybeUpdateUiObjects<T>(\n store: Store,\n request: ImmutableRequestInfo,\n options: HydrationOptions,\n document: ResourceDocument | null | undefined\n): ReactiveDocument<T> | ResourceDocument | null {\n const { identifier } = options;\n\n if (!document || !options.shouldHydrate) {\n assert(`The CacheHandler expected response content but none was found`, !options.shouldHydrate);\n return document ?? null;\n }\n\n if (identifier) {\n return store._instanceCache.getDocument<T>(identifier);\n }\n\n // if we don't have an identifier, we give the document\n // its own local cache\n return new ReactiveDocument<T>(store, null, {\n request,\n document,\n });\n}\n\nfunction updateCacheForSuccess<T>(\n store: Store,\n request: StoreRequestContext['request'],\n options: HydrationOptions,\n document: StructuredDataDocument<T>\n) {\n let response: ResourceDataDocument | null = null;\n if (isMutation(request)) {\n const record = request.data?.record || request.records?.[0];\n if (record) {\n response = store.cache.didCommit(record, document) as ResourceDataDocument;\n\n // a mutation combined with a 204 has no cache impact when no known records were involved\n // a createRecord with a 201 with an empty response and no known records should similarly\n // have no cache impact\n } else if (isCacheAffecting(document)) {\n response = store.cache.put(document) as ResourceDataDocument;\n }\n } else {\n response = store.cache.put(document) as ResourceDataDocument;\n }\n return maybeUpdateUiObjects(store, request, options, response);\n}\n\nfunction handleFetchSuccess<T>(\n store: Store,\n context: StoreRequestContext,\n options: UpdateOptions,\n document: StructuredDataDocument<T>\n): ResourceDataDocument | void {\n const { request } = context;\n store.requestManager._pending.delete(context.id);\n store._enableAsyncFlush = true;\n let response: ResourceDataDocument;\n store._join(() => {\n response = updateCacheForSuccess<T>(store, request, options, document) as ResourceDataDocument;\n });\n store._enableAsyncFlush = null;\n\n if (store.lifetimes?.didRequest) {\n store.lifetimes.didRequest(context.request, document.response, options.identifier, store);\n }\n\n const finalPriority = getPriority(options.identifier, store.requestManager._deduped, options.priority);\n if (finalPriority.blocking) {\n return response!;\n } else {\n store.notifications._flush();\n }\n}\n\nfunction updateCacheForError<T>(\n store: Store,\n context: StoreRequestContext,\n options: HydrationOptions,\n error: StructuredErrorDocument<T>\n) {\n let response: ResourceErrorDocument | undefined;\n if (isMutation(context.request)) {\n // TODO similar to didCommit we should spec this to be similar to cache.put for handling full response\n // currently we let the response remain undefiend.\n const errors =\n error &&\n error.content &&\n typeof error.content === 'object' &&\n 'errors' in error.content &&\n Array.isArray(error.content.errors)\n ? (error.content.errors as ApiError[])\n : undefined;\n\n const record = context.request.data?.record || context.request.records?.[0];\n\n store.cache.commitWasRejected(record, errors);\n } else {\n response = store.cache.put(error) as ResourceErrorDocument;\n return maybeUpdateUiObjects(store, context.request, options, response);\n }\n}\n\nfunction handleFetchError<T>(\n store: Store,\n context: StoreRequestContext,\n options: UpdateOptions,\n error: StructuredErrorDocument<T>\n): ResourceErrorDocument | void {\n store.requestManager._pending.delete(context.id);\n if (context.request.signal?.aborted) {\n throw error;\n }\n store._enableAsyncFlush = true;\n let response: ResourceErrorDocument | undefined;\n store._join(() => {\n response = updateCacheForError(store, context, options, error) as ResourceErrorDocument;\n });\n store._enableAsyncFlush = null;\n\n if (options.identifier && store.lifetimes?.didRequest) {\n store.lifetimes.didRequest(context.request, error.response, options.identifier, store);\n }\n\n if (isMutation(context.request)) {\n throw error;\n }\n\n const finalPriority = getPriority(options.identifier, store.requestManager._deduped, options.priority);\n if (finalPriority.blocking) {\n const newError = cloneError(error);\n newError.content = response!;\n throw newError;\n } else {\n store.notifications._flush();\n }\n}\n\nfunction fetchContentAndHydrate<T>(\n next: NextFn<T>,\n context: StoreRequestContext,\n identifier: StableDocumentIdentifier | null,\n priority: { blocking: boolean }\n): Promise<T> {\n const { store } = context.request;\n const shouldHydrate: boolean = context.request[EnableHydration] || false;\n const options = { shouldHydrate, identifier, priority };\n\n let isMut = false;\n if (isMutation(context.request)) {\n isMut = true;\n // TODO should we handle multiple records in request.records by iteratively calling willCommit for each\n const record = context.request.data?.record || context.request.records?.[0];\n assert(\n `Expected to receive a list of records included in the ${context.request.op} request`,\n record || !shouldHydrate\n );\n if (record) {\n store.cache.willCommit(record, context);\n }\n }\n\n if (store.lifetimes?.willRequest) {\n store.lifetimes.willRequest(context.request, identifier, store);\n }\n\n const promise = next(context.request).then(\n (document) => {\n return handleFetchSuccess(store, context, options, document);\n },\n (error: StructuredErrorDocument<T>) => {\n return handleFetchError(store, context, options, error);\n }\n ) as Promise<T>;\n\n if (!isMut) {\n return promise;\n }\n assert(`Expected a mutation`, isMutation(context.request));\n\n // for mutations we need to enqueue the promise with the requestStateService\n // TODO should we enque a request per record in records?\n const record = context.request.data?.record || context.request.records?.[0];\n\n return store._requestCache._enqueue(promise, {\n data: [{ op: 'saveRecord', recordIdentifier: record, options: undefined }],\n });\n}\n"],"names":["MUTATION_OPS","Set","calcShouldFetch","store","request","hasCachedValue","identifier","cacheOptions","op","has","reload","lifetimes","isHardExpired","calcShouldBackgroundFetch","willFetch","backgroundReload","isSoftExpired","isMutation","Boolean","isCacheAffecting","document","response","status","content","Object","keys","length","isAggregateError","error","AggregateError","name","Array","isArray","errors","cloneError","isAggregate","cloned","structuredClone","message","Error","stack","assign","getPriority","deduped","priority","existing","get","CacheHandler","context","next","SkipCache","identifierCache","getOrCreateDocumentIdentifier","setIdentifier","DEDUPE","requestManager","_deduped","activeRequest","peeked","cache","peekRequest","blocking","promise","fetchContentAndHydrate","finally","delete","notifications","notify","set","_pending","id","macroCondition","getGlobalConfig","WarpDrive","env","DEBUG","test","shouldHydrate","EnableHydration","setResponse","maybeUpdateUiObjects","newError","result","options","_instanceCache","getDocument","ReactiveDocument","updateCacheForSuccess","record","data","records","didCommit","put","handleFetchSuccess","_enableAsyncFlush","_join","didRequest","finalPriority","_flush","updateCacheForError","undefined","commitWasRejected","handleFetchError","signal","aborted","isMut","willCommit","willRequest","then","_requestCache","_enqueue","recordIdentifier"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { setLogging, getRuntimeConfig } from './types/runtime.js';
2
2
  import { a as cloneResponseProperties, I as IS_CACHE_HANDLER, b as assertValidRequest, e as executeNextHandler, d as getRequestResult, u as upgradePromise, s as setPromiseResult, f as clearRequestResult } from "./context-COmAnXUQ.js";
3
3
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
4
- import { w as waitFor } from "./configure-BgaZESRo.js";
4
+ import { w as waitFor } from "./configure-B48bFHOl.js";
5
5
  import { peekUniversalTransient, setUniversalTransient } from './types/-private.js';
6
- export { S as Store, r as recordIdentifierFor, K as setIdentifierForgetMethod, H as setIdentifierGenerationMethod, L as setIdentifierResetMethod, J as setIdentifierUpdateMethod, N as setKeyInfoForResource, s as storeFor } from "./request-state-DgwTEXLU.js";
7
- export { C as CacheHandler } from "./handler-cHghx9Y9.js";
6
+ export { S as Store, r as recordIdentifierFor, N as setIdentifierForgetMethod, K as setIdentifierGenerationMethod, O as setIdentifierResetMethod, L as setIdentifierUpdateMethod, P as setKeyInfoForResource, s as storeFor } from "./request-state-CCOJIj5i.js";
7
+ export { C as CacheHandler } from "./handler-D1C3Innj.js";
8
8
  import '@ember/debug';
9
9
  import './utils/string.js';
10
10
 
@@ -1 +1 @@
1
- export { E as Editable, L as Legacy } from "../symbols-BmDcn6hS.js";
1
+ export { E as Editable, L as Legacy } from "../symbols-epHW0Vm9.js";
package/dist/reactive.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { isResourceSchema } from './types/schema/fields.js';
2
- import { B as withSignalStore, w as entangleSignal, E as consumeInternalSignal, d as SOURCE$1, f as fastPush, x as defineSignal, l as RelatedCollection, F as getOrCreateInternalSignal, D as notifyInternalSignal, z as Signals, h as setRecordIdentifier, r as recordIdentifierFor } from "./request-state-DgwTEXLU.js";
2
+ import { E as withSignalStore, Q as isExtensionProp, T as performExtensionSet, G as consumeInternalSignal, U as performArrayExtensionGet, x as entangleSignal, V as performObjectExtensionGet, d as SOURCE$1, f as fastPush, y as defineSignal, l as RelatedCollection, H as getOrCreateInternalSignal, F as notifyInternalSignal, A as Signals, h as setRecordIdentifier, r as recordIdentifierFor } from "./request-state-CCOJIj5i.js";
3
3
  import { EnableHydration, STRUCTURED } from './types/request.js';
4
4
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
5
5
  import { deprecate } from '@ember/debug';
6
6
  import './utils/string.js';
7
- import { A as ARRAY_SIGNAL, O as OBJECT_SIGNAL, c as createMemo } from "./configure-BgaZESRo.js";
7
+ import { A as ARRAY_SIGNAL, O as OBJECT_SIGNAL, c as createMemo } from "./configure-B48bFHOl.js";
8
8
  import { RecordStore, Type } from './types/symbols.js';
9
9
  import { getOrSetGlobal } from './types/-private.js';
10
- import { S as SOURCE, E as Editable, L as Legacy, I as Identifier, P as Parent, a as EmbeddedPath, D as Destroy, C as Checkout, b as EmbeddedType } from "./symbols-BmDcn6hS.js";
10
+ import { S as SOURCE, E as Editable, L as Legacy, I as Identifier, P as Parent, a as EmbeddedPath, D as Destroy, C as Checkout, b as EmbeddedField } from "./symbols-epHW0Vm9.js";
11
11
  import './index.js';
12
12
  const ARRAY_GETTER_METHODS = new Set([Symbol.iterator, 'concat', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'flat', 'flatMap', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'map', 'reduce', 'reduceRight', 'slice', 'some', 'values']);
13
13
  // const ARRAY_SETTER_METHODS = new Set<KeyType>(['push', 'pop', 'unshift', 'shift', 'splice', 'sort']);
@@ -61,11 +61,8 @@ class ManagedArray {
61
61
  this[SOURCE] = data?.slice();
62
62
  const IS_EDITABLE = this[Editable] = editable ?? false;
63
63
  this[Legacy] = legacy;
64
-
65
- // FIXME probably can get rid of the manual ARRAY_SIGNAL storage
66
- // FIXME probably the storage should be on the proxy/receiver not this class
67
64
  const signals = withSignalStore(this);
68
- const _SIGNAL = this[ARRAY_SIGNAL] = entangleSignal(signals, this, ARRAY_SIGNAL, undefined);
65
+ let _SIGNAL = null;
69
66
  const boundFns = new Map();
70
67
  this.identifier = identifier;
71
68
  this.path = path;
@@ -81,6 +78,7 @@ class ManagedArray {
81
78
  // into two separate methods.
82
79
  Map;
83
80
  const ManagedRecordRefs = isSchemaArray ? new RefStorage() : null;
81
+ const extensions = legacy ? schema.CAUTION_MEGA_DANGER_ZONE_arrayExtensions(field) : null;
84
82
  const proxy = new Proxy(this[SOURCE], {
85
83
  get(target, prop, receiver) {
86
84
  if (prop === ARRAY_SIGNAL) {
@@ -101,6 +99,10 @@ class ManagedArray {
101
99
  self[SOURCE].push(...newData);
102
100
  }
103
101
  }
102
+ if (prop === 'length') {
103
+ return consumeInternalSignal(_SIGNAL), target.length;
104
+ }
105
+ if (prop === '[]') return consumeInternalSignal(_SIGNAL), receiver;
104
106
  if (index !== null) {
105
107
  let val;
106
108
  if (mode === '@hash') {
@@ -159,7 +161,7 @@ class ManagedArray {
159
161
  record = new ReactiveResource(store, recordIdentifier, {
160
162
  [Editable]: self.owner[Editable],
161
163
  [Legacy]: self.owner[Legacy]
162
- }, true, field.type, recordPath);
164
+ }, true, field, recordPath);
163
165
  // if mode is not @identity or @index, then access the key path now
164
166
  // to determine the key value.
165
167
  // chris says we can implement this as a special kind `@hash` which
@@ -224,6 +226,9 @@ class ManagedArray {
224
226
  }
225
227
  return fn;
226
228
  }
229
+ if (isExtensionProp(extensions, prop)) {
230
+ return performArrayExtensionGet(receiver, extensions, signals, prop, _SIGNAL, boundFns, v => void (transaction = v));
231
+ }
227
232
  return Reflect.get(target, prop, receiver);
228
233
  },
229
234
  set(target, prop, value, receiver) {
@@ -235,15 +240,16 @@ class ManagedArray {
235
240
  throw new Error(`Cannot set ${String(prop)} on ${errorPath} because the record is not editable`);
236
241
  }
237
242
  if (prop === 'identifier') {
238
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
239
243
  self.identifier = value;
240
244
  return true;
241
245
  }
242
246
  if (prop === 'owner') {
243
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
244
247
  self.owner = value;
245
248
  return true;
246
249
  }
250
+ if (isExtensionProp(extensions, prop)) {
251
+ return performExtensionSet(receiver, extensions, signals, prop, value);
252
+ }
247
253
  const reflect = Reflect.set(target, prop, value, receiver);
248
254
  if (reflect) {
249
255
  if (!field.type) {
@@ -271,9 +277,31 @@ class ManagedArray {
271
277
  return Reflect.has(target, prop);
272
278
  }
273
279
  });
280
+
281
+ // we entangle the signal on the returned proxy since that is
282
+ // the object that other code will be interfacing with.
283
+ _SIGNAL = entangleSignal(signals, proxy, ARRAY_SIGNAL, undefined);
274
284
  return proxy;
275
285
  }
276
286
  }
287
+
288
+ // this will error if someone tries to call
289
+ // A(identifierArray) since it is not configurable
290
+ // which is preferable to the `meta` override we used
291
+ // before which required importing all of Ember
292
+ const desc = {
293
+ enumerable: true,
294
+ configurable: false,
295
+ get: function () {
296
+ // here to support computed chains
297
+ // and {{#each}}
298
+ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_COMPUTED_CHAINS)) {
299
+ return this;
300
+ }
301
+ }
302
+ };
303
+ // compat(desc);
304
+ Object.defineProperty(ManagedArray.prototype, '[]', desc);
277
305
  const ObjectSymbols = new Set([OBJECT_SIGNAL, Parent, SOURCE, Editable, EmbeddedPath]);
278
306
 
279
307
  // const ignoredGlobalFields = new Set<string>(['setInterval', 'nodeType', 'nodeName', 'length', 'document', STRUCTURED]);
@@ -291,6 +319,9 @@ class ManagedObject {
291
319
  this[Legacy] = legacy;
292
320
  this[Parent] = identifier;
293
321
  this[EmbeddedPath] = path;
322
+
323
+ // prettier-ignore
324
+ const extensions = !legacy ? null : schema.CAUTION_MEGA_DANGER_ZONE_objectExtensions(field);
294
325
  const proxy = new Proxy(this[SOURCE], {
295
326
  ownKeys() {
296
327
  return Object.keys(self[SOURCE]);
@@ -328,11 +359,6 @@ class ManagedObject {
328
359
  return '<span>ManagedObject</span>';
329
360
  };
330
361
  }
331
- if (prop === 'toJSON') {
332
- return function () {
333
- return structuredClone(self[SOURCE]);
334
- };
335
- }
336
362
  if (_SIGNAL.isStale) {
337
363
  _SIGNAL.isStale = false;
338
364
  let newData = cache.getAttr(identifier, path);
@@ -346,10 +372,22 @@ class ManagedObject {
346
372
  }; // Add type assertion for newData
347
373
  }
348
374
  }
375
+
376
+ // toJSON and extensions need to come after we update data if stale
377
+ if (prop === 'toJSON') {
378
+ return function () {
379
+ return structuredClone(self[SOURCE]);
380
+ };
381
+ }
382
+
383
+ // we always defer to data before extensions
349
384
  if (prop in self[SOURCE]) {
350
385
  consumeInternalSignal(_SIGNAL);
351
386
  return self[SOURCE][prop];
352
387
  }
388
+ if (isExtensionProp(extensions, prop)) {
389
+ return performObjectExtensionGet(receiver, extensions, signals, prop);
390
+ }
353
391
  return Reflect.get(target, prop, receiver);
354
392
  },
355
393
  set(target, prop, value, receiver) {
@@ -358,6 +396,12 @@ class ManagedObject {
358
396
  throw new Error(`Cannot set read-only property '${String(prop)}' on ManagedObject`);
359
397
  }
360
398
  })(editable) : {};
399
+
400
+ // since objects function as dictionaries, we can't defer to schema/data before extensions
401
+ // unless the prop is in the existing data.
402
+ if (!(prop in self[SOURCE]) && isExtensionProp(extensions, prop)) {
403
+ return performExtensionSet(receiver, extensions, signals, prop, value);
404
+ }
361
405
  const reflect = Reflect.set(target, prop, value, receiver);
362
406
  if (!reflect) {
363
407
  return false;
@@ -553,7 +597,7 @@ function computeSchemaObject(store, cache, record, identifier, field, path, lega
553
597
  schemaObject = new ReactiveResource(store, identifier, {
554
598
  [Editable]: editable,
555
599
  [Legacy]: legacy
556
- }, true, field.type, embeddedPath);
600
+ }, true, field, embeddedPath);
557
601
  }
558
602
  if (!schemaObjectMapForRecord) {
559
603
  ManagedObjectMap.set(record, new Map([[field.name, schemaObject]]));
@@ -645,6 +689,7 @@ function computeHasMany(store, schema, cache, record, identifier, field, path, e
645
689
  type: field.type,
646
690
  identifier,
647
691
  cache,
692
+ field: legacy ? field : undefined,
648
693
  // we divorce the reference here because ManyArray mutates the target directly
649
694
  // before sending the mutation op to the cache. We may be able to avoid this in the future
650
695
  identifiers: rawValue.data?.slice(),
@@ -669,7 +714,7 @@ function computeHasMany(store, schema, cache, record, identifier, field, path, e
669
714
  return managedArray;
670
715
  }
671
716
  const IgnoredGlobalFields = new Set(['length', 'nodeType', 'then', 'setInterval', 'document', STRUCTURED]);
672
- const symbolList = [Destroy, RecordStore, Identifier, Editable, Parent, Checkout, Legacy, EmbeddedPath, EmbeddedType];
717
+ const symbolList = [Destroy, RecordStore, Identifier, Editable, Parent, Checkout, Legacy, EmbeddedPath, EmbeddedField];
673
718
  const RecordSymbols = new Set(symbolList);
674
719
  function isPathMatch(a, b) {
675
720
  return a.length === b.length && a.every((v, i) => v === b[i]);
@@ -707,7 +752,7 @@ class ReactiveResource {
707
752
 
708
753
  /** @internal */
709
754
 
710
- constructor(store, identifier, Mode, isEmbedded = false, embeddedType = null, embeddedPath = null) {
755
+ constructor(store, identifier, Mode, isEmbedded = false, embeddedField = null, embeddedPath = null) {
711
756
  // eslint-disable-next-line @typescript-eslint/no-this-alias
712
757
  const self = this;
713
758
  this[RecordStore] = store;
@@ -720,15 +765,14 @@ class ReactiveResource {
720
765
  this[Legacy] = Mode[Legacy] ?? false;
721
766
  const schema = store.schema;
722
767
  const cache = store.cache;
723
- const identityField = schema.resource(isEmbedded ? {
724
- type: embeddedType
725
- } : identifier).identity;
768
+ const identityField = schema.resource(isEmbedded ? embeddedField : identifier).identity;
726
769
  const BoundFns = new Map();
727
- this[EmbeddedType] = embeddedType;
770
+
771
+ // prettier-ignore
772
+ const extensions = !Mode[Legacy] ? null : isEmbedded ? schema.CAUTION_MEGA_DANGER_ZONE_objectExtensions(embeddedField) : schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(identifier);
773
+ this[EmbeddedField] = embeddedField;
728
774
  this[EmbeddedPath] = embeddedPath;
729
- const fields = isEmbedded ? schema.fields({
730
- type: embeddedType
731
- }) : schema.fields(identifier);
775
+ const fields = isEmbedded ? schema.fields(embeddedField) : schema.fields(identifier);
732
776
  const signals = withSignalStore(this);
733
777
  const proxy = new Proxy(this, {
734
778
  ownKeys() {
@@ -880,11 +924,15 @@ class ReactiveResource {
880
924
  if (prop === 'constructor') {
881
925
  return ReactiveResource;
882
926
  }
927
+ if (isExtensionProp(extensions, prop)) {
928
+ return performObjectExtensionGet(receiver, extensions, signals, prop);
929
+ }
930
+
883
931
  // too many things check for random symbols
884
932
  if (typeof prop === 'symbol') return undefined;
885
933
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
886
934
  {
887
- throw new Error(`No field named ${String(prop)} on ${isEmbedded ? embeddedType : identifier.type}`);
935
+ throw new Error(`No field named ${String(prop)} on ${isEmbedded ? embeddedField.type : identifier.type}`);
888
936
  }
889
937
  })() : {};
890
938
  return undefined;
@@ -967,13 +1015,21 @@ class ReactiveResource {
967
1015
  },
968
1016
  set(target, prop, value, receiver) {
969
1017
  if (!IS_EDITABLE) {
970
- const type = isEmbedded ? embeddedType : identifier.type;
1018
+ const type = isEmbedded ? embeddedField.type : identifier.type;
971
1019
  throw new Error(`Cannot set ${String(prop)} on ${type} because the record is not editable`);
972
1020
  }
973
1021
  const maybeField = prop === identityField?.name ? identityField : fields.get(prop);
974
1022
  if (!maybeField) {
975
- const type = isEmbedded ? embeddedType : identifier.type;
976
- throw new Error(`There is no field named ${String(prop)} on ${type}`);
1023
+ const type = isEmbedded ? embeddedField.type : identifier.type;
1024
+ if (isExtensionProp(extensions, prop)) {
1025
+ return performExtensionSet(receiver, extensions, signals, prop, value);
1026
+ }
1027
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1028
+ {
1029
+ throw new Error(`There is no settable field named ${String(prop)} on ${type}`);
1030
+ }
1031
+ })() : {};
1032
+ return false;
977
1033
  }
978
1034
  const field = maybeField.kind === 'alias' ? maybeField.options : maybeField;
979
1035
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
@@ -1356,7 +1412,7 @@ class ReactiveResource {
1356
1412
  if (editable) {
1357
1413
  return Promise.resolve(editable);
1358
1414
  }
1359
- const embeddedType = this[EmbeddedType];
1415
+ const embeddedType = this[EmbeddedField];
1360
1416
  const embeddedPath = this[EmbeddedPath];
1361
1417
  const isEmbedded = embeddedType !== null && embeddedPath !== null;
1362
1418
  if (isEmbedded) {
@@ -1438,6 +1494,139 @@ function _constructor(record) {
1438
1494
  }
1439
1495
  _constructor[Type] = '@constructor';
1440
1496
 
1497
+ /**
1498
+ * Extensions allow providing non-schema driven behaviors to
1499
+ * reactive resources and arrays.
1500
+ */
1501
+
1502
+ const BannedKeys = ['constructor', '__proto__'];
1503
+ function processExtension(extension) {
1504
+ const {
1505
+ kind,
1506
+ name
1507
+ } = extension;
1508
+ const features = new Map();
1509
+ const baseFeatures = typeof extension.features === 'function' ? extension.features.prototype : extension.features;
1510
+ for (const key of Object.getOwnPropertyNames(baseFeatures)) {
1511
+ if (BannedKeys.includes(key)) continue;
1512
+ const decl = Object.getOwnPropertyDescriptor(baseFeatures, key);
1513
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1514
+ if (!test) {
1515
+ throw new Error(`Expected to find a declaration for ${key} on extension ${name}`);
1516
+ }
1517
+ })(decl) : {};
1518
+ if (decl.value) {
1519
+ const {
1520
+ value
1521
+ } = decl;
1522
+ features.set(key, typeof value === 'function' ? {
1523
+ kind: 'method',
1524
+ fn: value
1525
+ } : decl.writable ? {
1526
+ kind: 'mutable-value',
1527
+ value
1528
+ } : {
1529
+ kind: 'readonly-value',
1530
+ value
1531
+ });
1532
+ continue;
1533
+ }
1534
+ if (decl.get || decl.set) {
1535
+ const {
1536
+ get,
1537
+ set
1538
+ } = decl;
1539
+ features.set(key,
1540
+ // prettier-ignore
1541
+ get && set ? {
1542
+ kind: 'mutable-field',
1543
+ get,
1544
+ set
1545
+ } : get ? {
1546
+ kind: 'readonly-field',
1547
+ get
1548
+ } : {
1549
+ kind: 'writeonly-field',
1550
+ set: set
1551
+ });
1552
+ continue;
1553
+ }
1554
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1555
+ {
1556
+ throw new Error(`The feature ${key} on extension ${name} is of an unknown variety.`);
1557
+ }
1558
+ })() : {};
1559
+ }
1560
+ return {
1561
+ kind,
1562
+ name,
1563
+ features
1564
+ };
1565
+ }
1566
+ function getExt(extCache, type, extName) {
1567
+ const ext = extCache[type].get(extName);
1568
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1569
+ if (!test) {
1570
+ throw new Error(`expected to have an extension named ${String(extName)} available for ${type}s`);
1571
+ }
1572
+ })(ext) : {};
1573
+ return ext?.features ?? null;
1574
+ }
1575
+ function hasObjectSchema(field) {
1576
+ return 'kind' in field && (field.kind === 'schema-array' || field.kind === 'schema-object');
1577
+ }
1578
+ function processExtensions(schema, field, scenario) {
1579
+ // if we're looking up extensions for a resource, there is no
1580
+ // merging required so if we have no objectExtensions
1581
+ // we are done.
1582
+ if (scenario === 'resource') {
1583
+ if (!('objectExtensions' in field || !field.objectExtensions?.length)) {
1584
+ return null;
1585
+ }
1586
+ }
1587
+ const type = scenario === 'resource' ? 'object' : scenario;
1588
+ const extCache = schema._extensions;
1589
+ const fieldCache = schema._cachedFieldExtensionsByField;
1590
+ if (fieldCache[type].has(field)) {
1591
+ return fieldCache[type].get(field);
1592
+ }
1593
+
1594
+ // prettier-ignore
1595
+ const extensions = (scenario === 'resource' ? field.objectExtensions : scenario === 'object' ? field.options?.objectExtensions : field.options?.arrayExtensions) || null;
1596
+
1597
+ // if we are a resource scenario, we know from the first check we do have extensions
1598
+ // if we are an object scenario, we can now return the resource scenario.
1599
+ // if we are an array scenario, there is nothing more to process.
1600
+ if (!extensions) {
1601
+ if (scenario === 'array') return null;
1602
+ if (!hasObjectSchema(field)) {
1603
+ return null;
1604
+ }
1605
+ return schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(field);
1606
+ }
1607
+
1608
+ // if we have made it here, we have extensions, lets check if there's
1609
+ // a cached version we can use
1610
+ const baseExtensions = scenario === 'resource' && hasObjectSchema(field) ? schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(field) : scenario === 'object' && hasObjectSchema(field) ? schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(field) : null;
1611
+ if (!baseExtensions && extensions.length === 1) {
1612
+ const value = getExt(extCache, type, extensions[0]);
1613
+ fieldCache[type].set(field, value);
1614
+ return value;
1615
+ }
1616
+ const features = new Map(baseExtensions);
1617
+ for (const extName of extensions) {
1618
+ const value = getExt(extCache, type, extName);
1619
+ if (value) {
1620
+ for (const [feature, desc] of value) {
1621
+ features.set(feature, desc);
1622
+ }
1623
+ }
1624
+ }
1625
+ const value = features.size ? features : null;
1626
+ fieldCache[type].set(field, value);
1627
+ return value;
1628
+ }
1629
+
1441
1630
  /**
1442
1631
  * Utility for constructing a ResourceSchema with the recommended
1443
1632
  * fields for the PolarisMode experience.
@@ -1559,6 +1748,8 @@ class SchemaService {
1559
1748
 
1560
1749
  /** @internal */
1561
1750
 
1751
+ /** @internal */
1752
+
1562
1753
  constructor() {
1563
1754
  this._schemas = new Map();
1564
1755
  this._transforms = new Map();
@@ -1566,6 +1757,14 @@ class SchemaService {
1566
1757
  this._derivations = new Map();
1567
1758
  this._traits = new Set();
1568
1759
  this._modes = new Map();
1760
+ this._extensions = {
1761
+ object: new Map(),
1762
+ array: new Map()
1763
+ };
1764
+ this._cachedFieldExtensionsByField = {
1765
+ object: new Map(),
1766
+ array: new Map()
1767
+ };
1569
1768
  }
1570
1769
  resourceTypes() {
1571
1770
  return Array.from(this._schemas.keys());
@@ -1687,6 +1886,24 @@ class SchemaService {
1687
1886
  registerDerivation(derivation) {
1688
1887
  this._derivations.set(derivation[Type], makeCachedDerivation(derivation));
1689
1888
  }
1889
+ CAUTION_MEGA_DANGER_ZONE_registerExtension(extension) {
1890
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1891
+ if (!test) {
1892
+ throw new Error(`an extension named ${extension.name} for ${extension.kind} already exists!`);
1893
+ }
1894
+ })(!this._extensions[extension.kind].has(extension.name)) : {};
1895
+ this._extensions[extension.kind].set(extension.name, processExtension(extension));
1896
+ }
1897
+ CAUTION_MEGA_DANGER_ZONE_resourceExtensions(resource) {
1898
+ const schema = this.resource(resource);
1899
+ return processExtensions(this, schema, 'resource');
1900
+ }
1901
+ CAUTION_MEGA_DANGER_ZONE_objectExtensions(field) {
1902
+ return processExtensions(this, field, 'object');
1903
+ }
1904
+ CAUTION_MEGA_DANGER_ZONE_arrayExtensions(field) {
1905
+ return processExtensions(this, field, 'array');
1906
+ }
1690
1907
 
1691
1908
  /**
1692
1909
  * This is an internal method used to register behaviors for legacy mode.
@@ -1704,7 +1921,7 @@ class SchemaService {
1704
1921
  if (!test) {
1705
1922
  throw new Error(`Mode '${mode}' is already registered`);
1706
1923
  }
1707
- })(!this._traits.has(mode)) : {};
1924
+ })(!this._modes.has(mode)) : {};
1708
1925
  this._modes.set(mode, kinds);
1709
1926
  }
1710
1927