Skip to content

Commit

Permalink
JNG-5921 fix identifier issues
Browse files Browse the repository at this point in the history
  • Loading branch information
noherczeg committed Sep 10, 2024
1 parent c575932 commit 62dc5dc
Show file tree
Hide file tree
Showing 10 changed files with 709 additions and 777 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
/**
* Utility Interface to use in places where we are not interested in a Stored object's data, only
* it's `__signedIdentifier`.
* Utility interface used for
* - mapped elements received from the backend
* - ui unmapped element discrimination which is mandatory in case an element is inside an iterable visual element such as tables.
*/
export interface JudoIdentifiable<T> {
export interface JudoTechnicalIdentifiable {
__identifier?: string;
}

/**
* Utility Interface to use in places where we are not interested in a Stored object's data, only
* it's `__signedIdentifier`. This identifier may change on the backend based on what operations are triggered on it,
* or it's containing parent.
*/
export interface JudoIdentifiable<T> extends JudoTechnicalIdentifiable {
__signedIdentifier: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ export interface SerializerUtil {
}

export interface Serializer<T> {
serialize(instance: T, cleanup?: boolean): any;
serialize(instance: T): any;
deserialize(data: any): T;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type JudoStored } from './JudoStored';

export const draftIdentifierPrefix = 'draft:';

export const applyStoredMembers = (result: JudoStored<any>, instance: JudoStored<any>, cleanup = false): void => {
export const applyStoredMembers = (result: JudoStored<any>, instance: JudoStored<any>): void => {
if (typeof instance.__deleteable === 'boolean') {
result.__deleteable = instance.__deleteable;
}
Expand All @@ -18,7 +18,7 @@ export const applyStoredMembers = (result: JudoStored<any>, instance: JudoStored
if (typeof instance.__entityType === 'string') {
result.__entityType = instance.__entityType;
}
if (typeof instance.__identifier === 'string' && (!cleanup || !instance.__identifier.startsWith(draftIdentifierPrefix))) {
if (typeof instance.__identifier === 'string' && !instance.__identifier.startsWith(draftIdentifierPrefix)) {
result.__identifier = instance.__identifier;
}
if (typeof instance.__signedIdentifier === 'string') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{{> fragment.header.hbs }}

import type { JudoStored } from '../common';
import type { JudoStored, JudoTechnicalIdentifiable } from '../common';
{{# each (getImportTokens application.actor classType) as | token | }}
import { {{ @key }} } from './{{ token }}';
{{/ each }}

export interface {{ classDataName classType '' }} {
export interface {{ classDataName classType '' }} extends JudoTechnicalIdentifiable {
__identifier?: string;
{{# each classType.attributes as | attribute | }}
{{ attribute.name }}{{# if attribute.isRequired }}: {{ else }}?: null | {{/ if}}{{ typescriptType attribute.dataType }};
{{/ each }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function serialize{{ classDataName classType "QueryCustomizer" }}(queryCu
const { lastItem, ...seekRest } = _seek;
result._seek = { ...seekRest };
if (lastItem) {
result._seek.lastItem = serializer.serialize(lastItem as {{ classDataName classType "Stored" }}, true);
result._seek.lastItem = serializer.serialize(lastItem as {{ classDataName classType "Stored" }});
}
}
return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{{> fragment.header.hbs }}

import { v4 as uuidv4 } from 'uuid';
import type { JudoStored, Serializer, SerializerUtil } from '../common';
import { applyStoredMembers } from '../common/utils';
import { applyStoredMembers, draftIdentifierPrefix } from '../common/utils';
import type { {{ classDataName classType '' }}, {{ classDataName classType 'Stored' }} } from '../model/{{ classDataName classType '' }}';
{{# each (getRelatedClasses classType) as |classType| }}
import { {{ classDataName classType 'Serializer' }} } from './{{ classDataName classType 'Serializer' }}';
Expand All @@ -24,8 +25,8 @@ export class {{ classDataName classType 'Stored' }}Serializer implements Seriali
this.normalSerializer = new {{ classDataName classType 'Serializer' }}();
}

serialize(instance: {{ classDataName classType 'Stored' }}, cleanup = false): any {
return this.normalSerializer.serialize(instance, cleanup);
serialize(instance: {{ classDataName classType 'Stored' }}): any {
return this.normalSerializer.serialize(instance);
}

deserialize(data: any = {}): {{ classDataName classType 'Stored' }} {
Expand All @@ -47,7 +48,7 @@ export class {{ classDataName classType 'Serializer' }} implements Serializer<{{
return {{ classDataName classType '' }}Serializer._instance;
}

serialize(instance: {{ classDataName classType '' }}, cleanup = false): any {
serialize(instance: {{ classDataName classType '' }}): any {
const result: any = {};
{{# each classType.attributes as |attribute| }}
if (instance.{{ attribute.name }} !== undefined) {
Expand All @@ -57,15 +58,15 @@ export class {{ classDataName classType 'Serializer' }} implements Serializer<{{
{{# each classType.relations as |relation| }}
{{# if relation.isCollection }}
if (Array.isArray(instance.{{ relation.name }})) {
result.{{ relation.name }} = instance.{{ relation.name }}.map(r => {{ classDataName relation.target 'Serializer' }}.getInstance().serialize(r, cleanup));
result.{{ relation.name }} = instance.{{ relation.name }}.map(r => {{ classDataName relation.target 'Serializer' }}.getInstance().serialize(r));
}
{{ else }}
if (instance.{{ relation.name }} !== undefined) {
result.{{ relation.name }} = {{# if relation.isOptional }}instance.{{ relation.name }} === null ? null : {{/ if }}{{ classDataName relation.target 'Serializer' }}.getInstance().serialize(instance.{{ relation.name }}, cleanup);
result.{{ relation.name }} = {{# if relation.isOptional }}instance.{{ relation.name }} === null ? null : {{/ if }}{{ classDataName relation.target 'Serializer' }}.getInstance().serialize(instance.{{ relation.name }});
}
{{/ if }}
{{/ each }}
applyStoredMembers(result, instance as unknown as JudoStored<any>, true);
applyStoredMembers(result, instance as unknown as JudoStored<any>);
return result;
}

Expand All @@ -88,6 +89,10 @@ export class {{ classDataName classType 'Serializer' }} implements Serializer<{{
{{/ if }}
{{/ each }}
applyStoredMembers(result, instance as unknown as JudoStored<any>);
if (!result.__identifier) {
result.__identifier = `${draftIdentifierPrefix}${uuidv4()}`;
}

return result as {{ classDataName classType '' }};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async update(target: {{ classDataName classType "Stored" }}, queryCustomizer?: CommandQueryCustomizer): Promise<JudoRestResponse<{{ classDataName classType "Stored" }}>> {
const path = '{{ restPath classType '/~update' '' '' }}';
const input = this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(target, true);
const input = this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(target);
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), input, {
headers: {
[X_JUDO_SIGNED_IDENTIFIER]: target.__signedIdentifier!,
Expand All @@ -95,7 +95,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async validateUpdate(target: {{ classDataName classType "Stored" }}): Promise<JudoRestResponse<{{ classDataName classType "Stored" }}>> {
const path = '{{ restPath classType '/~validate' '' '' }}';
const input = this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(target, true);
const input = this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(target);
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), input, {
headers: {
[X_JUDO_SIGNED_IDENTIFIER]: target.__signedIdentifier!,
Expand Down Expand Up @@ -126,7 +126,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async create{{ firstToUpper relation.name }}(owner: {{ classDataName classType "Stored" }}, target: {{ classDataName relation.target "" }}, queryCustomizer?: CommandQueryCustomizer): Promise<JudoRestResponse<{{ classDataName relation.target "Stored" }}>> {
const path = '{{ restPath classType "/~update/" relation.name "/~create" }}';
const input = this.{{ firstToLower (classDataName relation.target "Serializer") }}.serialize(target, true);
const input = this.{{ firstToLower (classDataName relation.target "Serializer") }}.serialize(target);
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), input, {
headers: {
[X_JUDO_SIGNED_IDENTIFIER]: owner.__signedIdentifier!,
Expand All @@ -145,7 +145,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async validateCreate{{ firstToUpper relation.name }}(owner: {{ classDataName classType "Stored" }}, target: {{ classDataName relation.target "" }}): Promise<JudoRestResponse<{{ classDataName relation.target "" }}>> {
const path = '{{ restPath classType "/~update/" relation.name "/~validate" }}';
const input = this.{{ firstToLower (classDataName relation.target "Serializer") }}.serialize(target, true);
const input = this.{{ firstToLower (classDataName relation.target "Serializer") }}.serialize(target);
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), input, {
headers: {
[X_JUDO_SIGNED_IDENTIFIER]: owner.__signedIdentifier!,
Expand Down Expand Up @@ -186,7 +186,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async getRangeFor{{ firstToUpper relation.name }}(owner?: {{ classDataName classType "Stored" }}, queryCustomizer?:{{ classDataName relation.target "QueryCustomizer" }}, headers?: Record<string, string>): Promise<JudoRestResponse<Array<{{ classDataName relation.target "Stored" }}>>> {
const path = '{{ restPath classType "/" relation.name "/~range" }}';
const input = owner ? this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(owner, true) : {};
const input = owner ? this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(owner) : {};
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), { owner: input, queryCustomizer: serialize{{ classDataName relation.target "QueryCustomizer" }}(queryCustomizer) ?? {} }, headers ? { headers } : undefined);
return {
...rest,
Expand All @@ -201,9 +201,9 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
async set{{ firstToUpper relation.name }}(owner: {{ classDataName classType "Stored" }}, selected:{{# if relation.isCollection }}Array<{{/ if }}{{ classDataName relation.target "Stored" }}{{# if relation.isCollection }}>{{/ if }}): Promise<JudoRestResponse<void>> {
const path = '{{ restPath classType "/~update/" relation.name "/~set" }}';
{{# if relation.isCollection }}
const input = selected.map(s => this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(s, true));
const input = selected.map(s => this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(s));
{{ else }}
const input = this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(selected, true);
const input = this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(selected);
{{/ if }}
return this.axios.post(this.getPathForActor(path), input, {
headers: {
Expand Down Expand Up @@ -233,7 +233,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async add{{ firstToUpper relation.name }}(owner: {{ classDataName classType "Stored" }}, selected: Array<{{ classDataName relation.target "Stored" }}>): Promise<JudoRestResponse<void>> {
const path = '{{ restPath classType "/~update/" relation.name "/~add" }}';
const input = selected.map(s => this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(s, true));
const input = selected.map(s => this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(s));
return this.axios.post(this.getPathForActor(path), input, {
headers: {
[X_JUDO_SIGNED_IDENTIFIER]: owner.__signedIdentifier!,
Expand All @@ -248,7 +248,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async remove{{ firstToUpper relation.name }}(owner: {{ classDataName classType "Stored" }}, selected: Array<{{ classDataName relation.target "Stored" }}>): Promise<JudoRestResponse<void>> {
const path = '{{ restPath classType "/~update/" relation.name "/~remove" }}';
const input = selected.map(s => this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(s, true));
const input = selected.map(s => this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(s));
return this.axios.post(this.getPathForActor(path), input, {
headers: {
[X_JUDO_SIGNED_IDENTIFIER]: owner.__signedIdentifier!,
Expand Down Expand Up @@ -279,7 +279,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
async {{ operation.name }}For{{ firstToUpper relation.name }}({{# if operation.isMapped }}owner: {{ classDataName relation.target "Stored" }}{{/ if }}{{# if operation.input }}{{# if operation.isMapped }},{{/ if }}target:{{ classDataName operation.input.target "Stored" }}{{/ if }}): Promise<JudoRestResponse<{{# if operation.output }}{{ classDataName operation.output.target "Stored" }}{{ else }}void{{/ if }}>> {
const path = '{{ operationRestPath relation.target operation '' }}';
{{# if operation.input }}
const input = target ? this.{{ firstToLower (classDataName operation.input.target "StoredSerializer") }}.serialize(target, true) : null;
const input = target ? this.{{ firstToLower (classDataName operation.input.target "StoredSerializer") }}.serialize(target) : null;
{{/ if }}
const { data, ...rest } = await this.axios.post(this.getPathForActor(path){{# if operation.input }}, input{{ else }}, undefined{{/ if }}{{# if operation.isMapped }}, {
headers: {
Expand Down Expand Up @@ -315,7 +315,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async getRangeOn{{ firstToUpper operation.name }}For{{ firstToUpper relation.name }}(owner?: {{ classDataName relation.target "Stored" }}, queryCustomizer?:{{ classDataName operation.input.target "QueryCustomizer" }}, headers?: Record<string, string>): Promise<JudoRestResponse<Array<{{ classDataName operation.input.target "Stored" }}>>> {
const path = '{{ operationRestPath relation.target operation '/~range' }}';
const input = owner ? this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(owner, true) : {};
const input = owner ? this.{{ firstToLower (classDataName relation.target "StoredSerializer") }}.serialize(owner) : {};
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), { owner: input, queryCustomizer: serialize{{ classDataName operation.input.target "QueryCustomizer" }}(queryCustomizer) ?? {} }, headers ? { headers } : undefined);
return {
...rest,
Expand All @@ -334,7 +334,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
async {{ operation.name }}({{# if operation.isMapped }}owner: {{ classDataName classType "Stored" }}{{/ if }}{{# if operation.input }}{{# if operation.isMapped }},{{/ if }}target:{{ classDataName operation.input.target "" }}{{/ if }}): Promise<JudoRestResponse<{{# if operation.output }}{{ classDataName operation.output.target "Stored" }}{{ else }}void{{/ if }}>> {
const path = '{{ operationRestPath classType operation '' }}';
{{# if operation.input }}
const input = target ? this.{{ firstToLower (classDataName operation.input.target "Serializer") }}.serialize(target, true) : null;
const input = target ? this.{{ firstToLower (classDataName operation.input.target "Serializer") }}.serialize(target) : null;
{{/ if }}
const { data, ...rest } = await this.axios.post(this.getPathForActor(path){{# if operation.input }}, input{{ else }}, undefined{{/ if }}{{# if operation.isMapped }}, {
headers: {
Expand Down Expand Up @@ -369,7 +369,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async getRangeOn{{ firstToUpper operation.name }}For{{ firstToUpper relation.name }}(owner?: {{ classDataName operation.input.target "Stored" }}, queryCustomizer?:{{ classDataName relation.target "QueryCustomizer" }}, headers?: Record<string, string>): Promise<JudoRestResponse<Array<{{ classDataName relation.target "Stored" }}>>> {
const path = '{{ restPath operation.input.target "/" relation.name "/~range" }}';
const input = owner ? this.{{ firstToLower (classDataName operation.input.target "StoredSerializer") }}.serialize(owner, true) : {};
const input = owner ? this.{{ firstToLower (classDataName operation.input.target "StoredSerializer") }}.serialize(owner) : {};
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), { owner: input, queryCustomizer: serialize{{ classDataName relation.target "QueryCustomizer" }}(queryCustomizer) ?? {} }, headers ? { headers } : undefined);
return {
...rest,
Expand All @@ -385,7 +385,7 @@ private readonly {{ firstToLower imp }}StoredSerializer = {{ imp }}StoredSeriali
*/
async getRangeOn{{ firstToUpper operation.name }}(owner?: {{ classDataName classType "Stored" }}, queryCustomizer?:{{ classDataName operation.input.target "QueryCustomizer" }}, headers?: Record<string, string>): Promise<JudoRestResponse<Array<{{ classDataName operation.input.target "Stored" }}>>> {
const path = '{{ operationRestPath classType operation '/~range' }}';
const input = owner ? this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(owner, true) : {};
const input = owner ? this.{{ firstToLower (classDataName classType "StoredSerializer") }}.serialize(owner) : {};
const { data, ...rest } = await this.axios.post(this.getPathForActor(path), { owner: input, queryCustomizer: serialize{{ classDataName operation.input.target "QueryCustomizer" }}(queryCustomizer) ?? {} }, headers ? { headers } : undefined);
return {
...rest,
Expand Down
Loading

0 comments on commit 62dc5dc

Please sign in to comment.