This repository was archived by the owner on Sep 23, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathAtomicExtractEntity.ts
More file actions
123 lines (119 loc) · 3.73 KB
/
Copy pathAtomicExtractEntity.ts
File metadata and controls
123 lines (119 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import {
AtomicConnector,
AtomicProjection,
AtomicIdentityMap,
AtomicLens,
AtomicSchema,
AtomicStore,
Datatype,
IS_A,
} from '../src/main.js';
// Example application vocabulary. Production deployments must publish their definitions.
export const orderVocabulary = {
order: 'https://example.com/classes/Order',
customer: 'https://example.com/classes/Customer',
item: 'https://example.com/properties/item',
quantity: 'https://example.com/properties/quantity',
customerLink: 'https://example.com/properties/customer',
name: 'https://example.com/properties/name',
address: 'https://example.com/properties/address',
note: 'https://example.com/properties/note',
};
export interface FlatOrder {
id: string;
item: string;
quantity: number;
customerId: string;
customerName: string;
customerAddress?: string;
platformNote?: string;
}
export function orderSchema(): AtomicSchema {
const v = orderVocabulary;
return new AtomicSchema()
.property(v.item, Datatype.STRING)
.property(v.quantity, Datatype.INTEGER)
.property(v.customerLink, Datatype.ATOMIC_URL)
.property(v.name, Datatype.STRING)
.property(v.address, Datatype.STRING)
.property(v.note, Datatype.STRING);
}
/** Flattened platform orders <-> native linked Order and Customer resources. */
export function atomicOrderLens(
store: AtomicStore,
identities: AtomicIdentityMap,
connector: AtomicConnector<FlatOrder>,
): AtomicLens<FlatOrder> {
const v = orderVocabulary;
const scope = 'https://example.com/accounts/acme';
const customerScope = { scope, entity: 'customer' };
return new AtomicLens({
store,
identities,
connector,
scope,
entity: 'order',
read: (input): AtomicProjection => {
const customer = identities.subjectFor(customerScope, input.customerId);
return {
set: {
[IS_A]: [v.order],
[v.item]: input.item,
[v.quantity]: input.quantity,
[v.customerLink]: customer,
},
identities: [
{ scope: customerScope, id: input.customerId, subject: customer },
],
related: [
{
subject: customer,
patch: {
set: {
[IS_A]: [v.customer],
[v.name]: input.customerName,
...(input.customerAddress === undefined
? {}
: { [v.address]: input.customerAddress }),
},
unset: input.customerAddress === undefined ? [v.address] : [],
},
},
],
};
},
write: (resource, previous): FlatOrder => {
const customerSubject = resource[v.customerLink];
if (typeof customerSubject !== 'string')
throw new Error('Order requires a customer link');
const customer = store.get(customerSubject);
if (!customer) throw new Error(`Missing customer: ${customerSubject}`);
const customerId = identities.externalId(customerScope, customerSubject);
const item = resource[v.item];
const quantity = resource[v.quantity];
const customerName = customer[v.name];
const address = customer[v.address];
if (
customerId === undefined ||
typeof item !== 'string' ||
typeof quantity !== 'number' ||
typeof customerName !== 'string'
) {
throw new Error(
'Missing required order fields or external customer identity',
);
}
const output: FlatOrder = {
...previous,
id: previous?.id ?? '',
item,
quantity,
customerId: String(customerId),
customerName,
};
if (typeof address === 'string') output.customerAddress = address;
else delete output.customerAddress;
return output;
},
});
}