Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,22 @@ describe('JsonApiUtilsService', () => {
expect(meta?.asleepSince).toBeNull();
});

it('stores under a globally registered symbol', () => {
// The symbol has to come from the global registry, not from this module.
// Two copies of resource-meta in one bundle -- the cjs and mjs entry
// points resolving apart, or one inlined while the other stays external
// -- would otherwise write under one symbol and read under another, and
// getResourceMeta would quietly answer undefined.
const [entity] = service['convertResponseData'](listBody(), []) as any[];

const key = Symbol.for('@klerick/json-api-nestjs-sdk/resource-meta');

expect(Reflect.get(entity, key)).toEqual({
resetsAt: '2026-10-11T09:00:00Z',
asleepSince: null,
});
});

it('reports nothing for an entity that never came from a response', () => {
expect(getResourceMeta({ id: 1 })).toBeUndefined();
expect(getDocumentMeta({ id: 1 })).toBeUndefined();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export class JsonApiUtilsService {
// Beside the entity, never among its attributes: the entity may own an
// attribute called `meta`, and anything merged in here would be sent
// back on the next write.
setResourceMeta(itemEntity, (dataItem as { meta?: unknown }).meta);
setResourceMeta(itemEntity, dataItem.meta);

result.push(itemEntity);
}
Expand All @@ -315,7 +315,7 @@ export class JsonApiUtilsService {
if (firstItem) {
// A single-resource document has no container to carry its own meta,
// so it rides on the entity. Lists get it on the EntityArray instead.
setDocumentMeta(firstItem, (body as { meta?: unknown }).meta);
setDocumentMeta(firstItem, body.meta);
return firstItem;
}
}
Expand Down
14 changes: 12 additions & 2 deletions libs/json-api/json-api-nestjs-sdk/src/lib/utils/resource-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@
* `EntityArray` of a list -- and to the entity itself where there is not, which
* is every single-resource response.
*/
const RESOURCE_META = Symbol('json-api-resource-meta');
const DOCUMENT_META = Symbol('json-api-document-meta');
// From the global registry rather than module-local: the package ships two
// entry points, and nothing guarantees a bundler gives them the same copy of
// this module -- cjs and mjs can resolve apart, or one can be inlined while
// the other stays external. Two copies would write under one symbol and read
// under another, and the readers below would answer undefined with nothing to
// show for it. The keys are package-scoped so they cannot collide.
const RESOURCE_META = Symbol.for(
'@klerick/json-api-nestjs-sdk/resource-meta'
);
const DOCUMENT_META = Symbol.for(
'@klerick/json-api-nestjs-sdk/document-meta'
);

/** The shape assumed when the caller names none. */
export type ResourceMeta = Record<string, unknown>;
Expand Down
4 changes: 4 additions & 0 deletions libs/json-api/json-api-nestjs-sdk/src/ngModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ export {
createHttpInnerClient,
} from './lib/json-api-angular.js';
export { JsonApiUtilsService, JsonApiSdkService } from './lib/service/index.js';
// Angular consumers take their services from this entry point; the readers
// belong beside them rather than behind a second import path.
export { getResourceMeta, getDocumentMeta } from './lib/utils/index.js';
export type { ResourceMeta } from './lib/utils/index.js';
export { AtomicOperations, JsonSdkConfig } from './lib/types/index.js';
Loading