-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeep.json
259 lines (259 loc) · 45.6 KB
/
deep.json
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
{
"package": {
"name": "@deep-foundation/object-to-links-converter",
"version": "0.0.1-dev.3"
},
"data": [
{
"package": {
"dependencyId": 0,
"containValue": "TSX"
},
"id": 1
},
{
"package": {
"dependencyId": 1,
"containValue": "Tree"
},
"id": 2
},
{
"package": {
"dependencyId": 1,
"containValue": "TreeIncludeFromCurrent"
},
"id": 3
},
{
"package": {
"dependencyId": 2,
"containValue": "Boolean"
},
"id": 4
},
{
"package": {
"dependencyId": 1,
"containValue": "Type"
},
"id": 5
},
{
"package": {
"dependencyId": 1,
"containValue": "Any"
},
"id": 6
},
{
"package": {
"dependencyId": 1,
"containValue": "TreeIncludeDown"
},
"id": 7
},
{
"package": {
"dependencyId": 1,
"containValue": "Value"
},
"id": 8
},
{
"package": {
"dependencyId": 1,
"containValue": "Object"
},
"id": 9
},
{
"package": {
"dependencyId": 1,
"containValue": "SyncTextFile"
},
"id": 10
},
{
"package": {
"dependencyId": 1,
"containValue": "Handler"
},
"id": 11
},
{
"package": {
"dependencyId": 1,
"containValue": "dockerSupportsJs"
},
"id": 12
},
{
"package": {
"dependencyId": 1,
"containValue": "HandleInsert"
},
"id": 13
},
{
"package": {
"dependencyId": 1,
"containValue": "GeneratedFrom"
},
"id": 14
},
{
"package": {
"dependencyId": 1,
"containValue": "clientSupportsJs"
},
"id": 15
},
{
"id": "parseItInsertHandlerCode",
"type": 1,
"value": {
"value": "import { DeepClient } from \"@deep-foundation/deeplinks/imports/client.js\";\r\nimport { Link } from \"@deep-foundation/deeplinks/imports/minilinks.js\";\r\nimport { DeepClientInstance } from \"@deep-foundation/deeplinks/imports/client\";\r\n\r\nasync (options: {\r\n deep: DeepClient;\r\n data: {\r\n newLink: Link<number>;\r\n };\r\n}) => {\r\n const {\r\n deep,\r\n data: { newLink: parseItLink },\r\n } = options;\r\n const { default: ts } = await import(\"typescript\");\r\n const { default: util } = await import(\"util\");\r\n try {\r\n const result = await main();\r\n return {\r\n result: util.inspect(result),\r\n };\r\n } catch (error) {\r\n throw {\r\n error: util.inspect(error),\r\n };\r\n }\r\n\r\n async function main() {\r\n const {\r\n data: [rootLink],\r\n } = await deep.select({\r\n id: parseItLink.from_id,\r\n });\r\n if (!rootLink) {\r\n throw new Error(`parseIt.to does not exist: ##${parseItLink.from_id}`);\r\n }\r\n \r\n let obj;\r\n if(typeof rootLink.value?.value === 'object') {\r\n obj = rootLink.value?.value;\r\n } else if (typeof rootLink.value?.value === 'string') {\r\n try {\r\n obj = JSON.parse(rootLink.value?.value);\r\n } catch (error) {\r\n throw new Error(`##${rootLink.id} must be valid JSON if it is a string`);\r\n }\r\n } else {\r\n throw new Error(`##${rootLink.id} must have value`);\r\n }\r\n if (!obj) {\r\n throw new Error(`##${rootLink.id} must have value`);\r\n }\r\n\r\n const clientHandlerResult = await callClientHandler({\r\n deep,\r\n linkId: await deep.id(deep.linkId!, \"clientHandler\"),\r\n args: [\r\n {\r\n deep: deep,\r\n obj: obj,\r\n rootLinkId: rootLink.id,\r\n resultLinkId: parseItLink.to_id,\r\n // TODO?\r\n // customMethods: options.customMethods,\r\n },\r\n ],\r\n });\r\n\r\n return clientHandlerResult;\r\n }\r\n\r\n async function callClientHandler(\r\n options: CallClientHandlerOptions,\r\n ): Promise<any> {\r\n const { linkId, deep, args } = options;\r\n const code = await deep\r\n .select({\r\n in: {\r\n id: linkId,\r\n },\r\n })\r\n .then((result) => {\r\n const link = result.data[0];\r\n if (!link)\r\n throw new Error(`Unable to find SyncTextFile for ##${linkId}`);\r\n const code = link.value?.value;\r\n if (!code) throw new Error(`##${link.id} must have value`);\r\n return code;\r\n });\r\n\r\n const functionExpressionString = ts\r\n .transpileModule(code, {\r\n compilerOptions: {\r\n module: ts.ModuleKind.ESNext,\r\n sourceMap: true,\r\n target: ts.ScriptTarget.ESNext,\r\n },\r\n })\r\n .outputText.replace(\"export {}\", \"\");\r\n const fn: Function = eval(functionExpressionString);\r\n\r\n const result = await fn(...args);\r\n return result;\r\n }\r\n\r\n interface CallClientHandlerOptions {\r\n deep: DeepClientInstance;\r\n linkId: number;\r\n args: Array<any>;\r\n }\r\n};\r\n"
}
},
{
"id": "propertiesTree",
"type": 2
},
{
"id": "treeIncludeFromCurrentBoolean",
"type": 3,
"from": "propertiesTree",
"to": 4
},
{
"id": "HasResult",
"type": 5,
"from": 6,
"to": 6
},
{
"id": "treeIncludeDownHasResult",
"type": 7,
"from": "propertiesTree",
"to": "HasResult"
},
{
"id": "Root",
"type": 5
},
{
"id": "rootValue",
"type": 8,
"from": "Root",
"to": 9
},
{
"id": "dependency@deep-foundation/boolean",
"type": 5,
"from": 4,
"to": 4
},
{
"id": "Boolean",
"type": 5,
"from": 6,
"to": 4
},
{
"id": "Object",
"type": 5,
"from": 6,
"to": 6
},
{
"id": "treeIncludeFromCurrentObject",
"type": 3,
"from": "propertiesTree",
"to": "Object"
},
{
"id": "Number",
"type": 5,
"from": 6,
"to": 6
},
{
"id": "treeIncludeFromCurrentNumber",
"type": 3,
"from": "propertiesTree",
"to": "Number"
},
{
"id": "String",
"type": 5,
"from": 6,
"to": 6
},
{
"id": "treeIncludeFromCurrentString",
"type": 3,
"from": "propertiesTree",
"to": "String"
},
{
"id": "ParseIt",
"type": 5,
"from": 6,
"to": 6
},
{
"id": "parseItInsertHandlerTranspiledCode",
"type": 10,
"value": {
"value": "async (options) => {\n const { deep, data: { newLink: parseItLink }, } = options;\n const { default: ts } = await import(\"typescript\");\n const { default: util } = await import(\"util\");\n try {\n const result = await main();\n return {\n result: util.inspect(result),\n };\n }\n catch (error) {\n throw {\n error: util.inspect(error),\n };\n }\n async function main() {\n const { data: [rootLink], } = await deep.select({\n id: parseItLink.from_id,\n });\n if (!rootLink) {\n throw new Error(`parseIt.to does not exist: ##${parseItLink.from_id}`);\n }\n let obj;\n if (typeof rootLink.value?.value === 'object') {\n obj = rootLink.value?.value;\n }\n else if (typeof rootLink.value?.value === 'string') {\n try {\n obj = JSON.parse(rootLink.value?.value);\n }\n catch (error) {\n throw new Error(`##${rootLink.id} must be valid JSON if it is a string`);\n }\n }\n else {\n throw new Error(`##${rootLink.id} must have value`);\n }\n if (!obj) {\n throw new Error(`##${rootLink.id} must have value`);\n }\n const clientHandlerResult = await callClientHandler({\n deep,\n linkId: await deep.id(deep.linkId, \"clientHandler\"),\n args: [\n {\n deep: deep,\n obj: obj,\n rootLinkId: rootLink.id,\n resultLinkId: parseItLink.to_id,\n },\n ],\n });\n return clientHandlerResult;\n }\n async function callClientHandler(options) {\n const { linkId, deep, args } = options;\n const code = await deep\n .select({\n in: {\n id: linkId,\n },\n })\n .then((result) => {\n const link = result.data[0];\n if (!link)\n throw new Error(`Unable to find SyncTextFile for ##${linkId}`);\n const code = link.value?.value;\n if (!code)\n throw new Error(`##${link.id} must have value`);\n return code;\n });\n const functionExpressionString = ts\n .transpileModule(code, {\n compilerOptions: {\n module: ts.ModuleKind.ESNext,\n sourceMap: true,\n target: ts.ScriptTarget.ESNext,\n },\n })\n .outputText.replace(\"export {}\", \"\");\n const fn = eval(functionExpressionString);\n const result = await fn(...args);\n return result;\n }\n};\n//# sourceMappingURL=module.js.map"
}
},
{
"id": "parseItInsertHandler",
"type": 11,
"from": 12,
"to": "parseItInsertHandlerTranspiledCode"
},
{
"id": "handleParseItInsert",
"type": 13,
"from": "ParseIt",
"to": "parseItInsertHandler"
},
{
"id": "parseItInsertHandlerTranspiledCodeGeneratedFrom",
"type": 14,
"from": "parseItInsertHandlerTranspiledCode",
"to": "parseItInsertHandlerCode"
},
{
"id": "clientHandlerCode",
"type": 1,
"value": {
"value": "import {\r\n DeepClient,\r\n DeepClientResult,\r\n SerialOperation,\r\n Table,\r\n} from \"@deep-foundation/deeplinks/imports/client.js\";\r\nimport { BoolExpLink } from \"@deep-foundation/deeplinks/imports/client_types.js\";\r\nimport {\r\n Link,\r\n MinilinksResult,\r\n} from \"@deep-foundation/deeplinks/imports/minilinks.js\";\r\n\r\nasync (options: {\r\n deep: DeepClient;\r\n rootLinkId?: number;\r\n obj: Obj;\r\n customMethods?: Record<string, Function>;\r\n resultLinkId?: number;\r\n}) => {\r\n const { deep, rootLinkId, obj, customMethods, resultLinkId } = options;\r\n const { createSerialOperation } = await import(\r\n \"@deep-foundation/deeplinks/imports/gql/index.js\"\r\n );\r\n const { pascalCase } = await import(\"case-anything\");\r\n const { default: debug } = await import(\"debug\");\r\n const { default: util } = await import(\"util\");\r\n const logs: Array<any> = [];\r\n const packageLog = debug(\"@deep-foundation/object-to-links-converter\");\r\n packageLog({ options });\r\n\r\n class ObjectToLinksConverter {\r\n reservedLinkIds: Array<number>;\r\n rootLink: Link<number>;\r\n obj: Obj;\r\n resultLink: Link<number>;\r\n deep = deep;\r\n static requiredPackageNames = {\r\n core: \"@deep-foundation/core\",\r\n boolean: \"@deep-foundation/boolean\",\r\n };\r\n static requiredPackagesInMinilinks = {\r\n ...this.requiredPackageNames,\r\n objectToLinksConverter:\r\n \"@deep-foundation/object-to-links-converter\",\r\n };\r\n\r\n constructor(options: ObjectToLinksConverterOptions) {\r\n this.rootLink = options.rootLink;\r\n this.reservedLinkIds = options.reservedLinkIds;\r\n this.obj = options.obj;\r\n this.resultLink = options.resultLink;\r\n }\r\n\r\n static getLogger(namespace: string) {\r\n const getLoggerLogger = debug(this.getLogger.name);\r\n getLoggerLogger({ options });\r\n const resultLogger = packageLog.extend(\r\n `${ObjectToLinksConverter.name}${namespace ? `:${namespace}` : \"\"}`,\r\n );\r\n resultLogger.enabled = true;\r\n resultLogger.log = (...content: Array<any>) => {\r\n logs.push(...content);\r\n };\r\n return resultLogger;\r\n }\r\n\r\n static async applyContainTreeLinksDownToParentToMinilinks(\r\n options: ApplyContainTreeLinksDownToParentToMinilinksOptions,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n ObjectToLinksConverter.applyContainTreeLinksDownToParentToMinilinks\r\n .name,\r\n );\r\n const links = (await this.getContainTreeLinksDownToParent({\r\n linkExp: options.linkExp,\r\n })) as DeepClientResult<Link<number>[]>;\r\n log({ links });\r\n const minilinksApplyResult = options.minilinks.apply(links.data);\r\n log({ minilinksApplyResult });\r\n return minilinksApplyResult;\r\n }\r\n\r\n static async getContainTreeLinksDownToParent(\r\n options: GetContainTreeLinksDownToLinkOptions,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n ObjectToLinksConverter.getContainTreeLinksDownToParent.name,\r\n );\r\n const { linkExp } = options;\r\n const query: BoolExpLink = {\r\n up: {\r\n tree_id: await deep.id(\"@deep-foundation/core\", \"containTree\"),\r\n parent: linkExp,\r\n },\r\n };\r\n log({ query });\r\n const result = await deep.select(query);\r\n log({ result });\r\n return result;\r\n }\r\n\r\n /**\r\n * Undefined is returned of root object is empty\r\n */\r\n static async init(\r\n options: ObjectToLinksConverterInitOptions,\r\n ): Promise<ObjectToLinksConverter> {\r\n const log = ObjectToLinksConverter.getLogger(\r\n ObjectToLinksConverter.init.name,\r\n );\r\n const { obj } = options;\r\n const containTreeLinksDownToCoreAndThisPackageLinkApplyMinilinksResult =\r\n await this.applyContainTreeLinksDownToParentToMinilinks({\r\n linkExp: {\r\n _or: Object.values(\r\n ObjectToLinksConverter.requiredPackagesInMinilinks,\r\n ).map((packageName) => ({\r\n id: {\r\n _id: [packageName],\r\n },\r\n })),\r\n },\r\n minilinks: deep.minilinks,\r\n });\r\n log({ containTreeLinksDownToCoreAndThisPackageLinkApplyMinilinksResult });\r\n const rootLink: Link<number> = options.rootLinkId\r\n ? await deep.select(options.rootLinkId).then((result) => result.data[0])\r\n : await deep\r\n .insert(\r\n {\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(deep.linkId!, \"Root\"),\r\n },\r\n {\r\n returning: deep.linksSelectReturning,\r\n },\r\n )\r\n .then((result) => result.data[0] as Link<number>);\r\n log({ rootLink });\r\n const containTreeLinksDownToRootLinkApplyMinilinksResult =\r\n await this.applyContainTreeLinksDownToParentToMinilinks({\r\n linkExp: {\r\n id: rootLink.id,\r\n },\r\n minilinks: deep.minilinks,\r\n });\r\n log({ containTreeLinksDownToRootLinkApplyMinilinksResult });\r\n const linkIdsToReserveCount = this.getLinksToReserveCount({ value: obj });\r\n log({ linkIdsToReserveCount });\r\n const reservedLinkIds = await deep.reserve(linkIdsToReserveCount);\r\n log({ reservedLinkIds });\r\n const resultLink = options.resultLinkId\r\n ? await deep\r\n .select(options.resultLinkId)\r\n .then((result) => result.data[0])\r\n : rootLink;\r\n if (options.resultLinkId && !resultLink) {\r\n throw new Error(\r\n `Result link with id ${options.resultLinkId} not found`,\r\n );\r\n }\r\n const converter = new this({\r\n reservedLinkIds,\r\n rootLink,\r\n obj,\r\n resultLink,\r\n });\r\n log({ converter });\r\n return converter;\r\n }\r\n\r\n async convert() {\r\n const log = ObjectToLinksConverter.getLogger(\"convert\");\r\n\r\n const operations = await this.makeUpdateOperationsForObjectValue({\r\n link: this.resultLink,\r\n value: this.obj,\r\n });\r\n log({ operations });\r\n\r\n const hasResultTypeLinkId = await deep.id(\r\n deep.linkId!,\r\n \"HasResult\",\r\n );\r\n const {\r\n data: [hasResultLink],\r\n } = await deep.select({\r\n type_id: hasResultTypeLinkId,\r\n from_id: this.rootLink.id,\r\n });\r\n if (hasResultLink) {\r\n operations.push(\r\n createSerialOperation({\r\n type: \"update\",\r\n table: \"links\",\r\n exp: {\r\n type_id: hasResultTypeLinkId,\r\n from_id: this.rootLink.id,\r\n },\r\n value: {\r\n to_id: this.resultLink.id,\r\n },\r\n }),\r\n );\r\n } else {\r\n operations.push(\r\n createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n type_id: hasResultTypeLinkId,\r\n from_id: this.rootLink.id,\r\n to_id: this.resultLink.id,\r\n },\r\n }),\r\n );\r\n }\r\n\r\n const serialResult = await deep.serial({\r\n operations,\r\n });\r\n log({ serialResult });\r\n\r\n return {\r\n serialResult,\r\n rootLinkId: this.rootLink.id,\r\n resultLinkId: this.resultLink.id,\r\n };\r\n }\r\n\r\n static getLinksToReserveCount(options: {\r\n value: string | number | boolean | object;\r\n }): number {\r\n const { value } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n ObjectToLinksConverter.getLinksToReserveCount.name,\r\n );\r\n let count = 0;\r\n const typeOfValue = typeof value;\r\n log({ typeOfValue });\r\n const reservedLinksCountForOneLink =\r\n 1 + // Type\r\n 1; // Contain for type\r\n if (typeOfValue === \"string\") {\r\n count = reservedLinksCountForOneLink;\r\n } else if (typeOfValue === \"number\") {\r\n count = reservedLinksCountForOneLink;\r\n } else if (typeOfValue === \"boolean\") {\r\n count = reservedLinksCountForOneLink;\r\n } else if (Array.isArray(value)) {\r\n const array = value as Array<any>;\r\n for (const arrayValue of array) {\r\n if (!arrayValue) return count;\r\n count += this.getLinksToReserveCount({ value: arrayValue });\r\n }\r\n } else if (typeOfValue === \"object\") {\r\n count += reservedLinksCountForOneLink;\r\n for (const [propertyKey, propertyValue] of Object.entries(value)) {\r\n if (!value) return count;\r\n count += this.getLinksToReserveCount({ value: propertyValue });\r\n }\r\n }\r\n log({ count });\r\n return count;\r\n }\r\n\r\n async makeUpdateOperationsForBooleanValue(\r\n options: MakeUpdateOperationsForAnyValueOptions<boolean>,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeUpdateOperationsForBooleanValue.name,\r\n );\r\n log({ options });\r\n const { link, value } = options;\r\n const operations: Array<SerialOperation> = [];\r\n operations.push(\r\n createSerialOperation({\r\n type: \"update\",\r\n table: \"links\",\r\n exp: {\r\n id: link.id,\r\n },\r\n value: {\r\n to_id: await deep.id(\r\n ObjectToLinksConverter.requiredPackageNames.boolean,\r\n pascalCase(value.toString()),\r\n ),\r\n },\r\n }),\r\n );\r\n log({ operations });\r\n return operations;\r\n }\r\n\r\n async makeUpdateOperationsForStringValue(\r\n options: MakeUpdateOperationsForStringValueOptions,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeUpdateOperationsForStringValue.name,\r\n );\r\n log({ options });\r\n const { link, value } = options;\r\n const operations: Array<SerialOperation> = [];\r\n operations.push(\r\n createSerialOperation({\r\n type: \"update\",\r\n table: `${typeof value\r\n .toString()\r\n .toLocaleLowerCase()}s` as Table<\"update\">,\r\n exp: {\r\n link_id: link.id,\r\n },\r\n value: {\r\n value: value,\r\n },\r\n }),\r\n );\r\n log({ operations });\r\n return operations;\r\n }\r\n\r\n async makeUpdateOperationsForNumberValue(\r\n options: MakeUpdateOperationsForNumberValueOptions,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeUpdateOperationsForNumberValue.name,\r\n );\r\n log({ options });\r\n const { link, value } = options;\r\n const operations: Array<SerialOperation> = [];\r\n operations.push(\r\n createSerialOperation({\r\n type: \"update\",\r\n table: `${typeof value\r\n .toString()\r\n .toLocaleLowerCase()}s` as Table<\"update\">,\r\n exp: {\r\n link_id: link.id,\r\n },\r\n value: {\r\n value: value,\r\n },\r\n }),\r\n );\r\n log({ operations });\r\n return operations;\r\n }\r\n\r\n async makeUpdateOperationsForArrayValue<TValue extends AllowedArray>(\r\n options: MakeUpdateOperationsForAnyValueOptions<TValue>,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeUpdateOperationsForAnyValue.name,\r\n );\r\n const { link, value } = options;\r\n const operations: Array<SerialOperation> = [];\r\n\r\n await deep.delete({\r\n up: {\r\n tree_id: await deep.id(\r\n ObjectToLinksConverter.requiredPackagesInMinilinks.core,\r\n \"ContainTree\",\r\n ),\r\n parent_id: link.id,\r\n },\r\n });\r\n\r\n for (let i = 0; i < value.length; i++) {\r\n const element = value[i];\r\n operations.push(\r\n ...(await this.makeInsertOperationsForAnyValue({\r\n value: element,\r\n linkId: this.reservedLinkIds.pop()!,\r\n name: i.toString(0),\r\n parentLinkId: link.id,\r\n })),\r\n );\r\n }\r\n\r\n return operations;\r\n }\r\n\r\n async makeUpdateOperationsForAnyValue<TValue extends AllowedValue>(\r\n options: MakeUpdateOperationsForAnyValueOptions<TValue>,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeUpdateOperationsForAnyValue.name,\r\n );\r\n const { link, value } = options;\r\n const operations: Array<SerialOperation> = [];\r\n if (typeof value === \"boolean\") {\r\n operations.push(\r\n ...(await this.makeUpdateOperationsForBooleanValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (typeof value === \"string\") {\r\n operations.push(\r\n ...(await this.makeUpdateOperationsForStringValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (typeof value === \"number\") {\r\n operations.push(\r\n ...(await this.makeUpdateOperationsForNumberValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (Array.isArray(value)) {\r\n operations.push(\r\n ...(await this.makeUpdateOperationsForArrayValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (typeof value === \"object\") {\r\n operations.push(\r\n ...(await this.makeUpdateOperationsForObjectValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else {\r\n throw new Error(`Type of value ${typeof value} is not supported`);\r\n }\r\n\r\n return operations;\r\n }\r\n\r\n async makeUpdateOperationsForObjectValue(\r\n options: MakeUpdateOperationsForObjectValueOptions,\r\n ) {\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeUpdateOperationsForObjectValue.name,\r\n );\r\n const { link, value } = options;\r\n log({ options });\r\n const operations: Array<SerialOperation> = [];\r\n\r\n for (const [propertyKey, propertyValue] of Object.entries(value)) {\r\n log({ propertyKey, propertyValue });\r\n const [propertyLink] = deep.minilinks.query({\r\n id: {\r\n _id: [link.id, propertyKey],\r\n },\r\n });\r\n log({ propertyLink });\r\n if (propertyLink) {\r\n let propertyUpdateOperations: Array<SerialOperation> = [];\r\n propertyUpdateOperations = await this.makeUpdateOperationsForAnyValue(\r\n {\r\n link: propertyLink,\r\n value: propertyValue,\r\n },\r\n );\r\n log({ propertyUpdateOperations });\r\n operations.push(...propertyUpdateOperations);\r\n } else {\r\n if (\r\n typeof propertyValue !== \"string\" &&\r\n typeof propertyValue !== \"number\" &&\r\n typeof propertyValue !== \"boolean\" &&\r\n !Array.isArray(propertyValue) &&\r\n typeof propertyValue !== \"object\"\r\n ) {\r\n log(\r\n `Skipping property ${propertyKey} because its type ${typeof value} is not supported`,\r\n );\r\n continue;\r\n }\r\n\r\n log(\"TEMPORARY! REMOVE THIS!\");\r\n log(`minilinks.links`, deep.minilinks.links);\r\n log(\r\n `package link`,\r\n deep.minilinks.query({\r\n id: deep.linkId!,\r\n }),\r\n );\r\n log(\r\n `contain to string`,\r\n deep.minilinks.query({\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(\"@deep-foundation/core\", \"Contain\"),\r\n string: {\r\n value: \"String\",\r\n },\r\n from_id: deep.linkId!,\r\n }),\r\n );\r\n log(\r\n `contain to string`,\r\n deep.minilinks.query({\r\n id: {\r\n _id: [deep.linkId!, \"String\"],\r\n },\r\n }),\r\n );\r\n\r\n const propertyLinkId = this.reservedLinkIds.pop();\r\n log({ propertyLinkId });\r\n if (!propertyLinkId) {\r\n throw new Error(`Not enough reserved link ids`);\r\n }\r\n const propertyInsertOperations =\r\n await this.makeInsertOperationsForAnyValue({\r\n linkId: propertyLinkId,\r\n parentLinkId: link.id,\r\n value: propertyValue,\r\n name: propertyKey,\r\n });\r\n log({ propertyInsertOperations });\r\n operations.push(...propertyInsertOperations);\r\n }\r\n\r\n log({ operations });\r\n }\r\n\r\n return operations;\r\n }\r\n\r\n async makeInsertOperationsForBooleanValue(\r\n options: MakeInsertOperationsForBooleanOptions,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value, parentLinkId, linkId, name } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeInsertOperationsForBooleanValue.name,\r\n );\r\n\r\n const linkInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n id: linkId,\r\n type_id: await deep.id(deep.linkId!, pascalCase(typeof value)),\r\n from_id: parentLinkId,\r\n to_id: await deep.id(\r\n ObjectToLinksConverter.requiredPackageNames.boolean,\r\n pascalCase(value.toString()),\r\n ),\r\n },\r\n });\r\n log({ linkInsertSerialOperation });\r\n operations.push(linkInsertSerialOperation);\r\n\r\n const containInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(\"@deep-foundation/core\", \"Contain\"),\r\n from_id: parentLinkId,\r\n to_id: linkId,\r\n string: {\r\n data: {\r\n value: name,\r\n },\r\n },\r\n },\r\n });\r\n log({ containInsertSerialOperation });\r\n operations.push(containInsertSerialOperation);\r\n\r\n log({ operations });\r\n return operations;\r\n }\r\n async makeInsertOperationsForStringValue(\r\n options: MakeInsertOperationsForStringOptions,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value, parentLinkId, linkId, name } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n \"makeInsertOperationsForStringValue\",\r\n );\r\n const linkInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n id: linkId,\r\n from_id: parentLinkId,\r\n to_id: parentLinkId,\r\n type_id: await deep.id(deep.linkId!, pascalCase(typeof value)),\r\n },\r\n });\r\n log({ linkInsertSerialOperation });\r\n operations.push(linkInsertSerialOperation);\r\n\r\n const stringValueInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: `${typeof value}s` as Table<\"insert\">,\r\n objects: {\r\n link_id: linkId,\r\n value: value,\r\n },\r\n });\r\n log({ stringValueInsertSerialOperation });\r\n operations.push(stringValueInsertSerialOperation);\r\n\r\n const containInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(\"@deep-foundation/core\", \"Contain\"),\r\n from_id: parentLinkId,\r\n to_id: linkId,\r\n string: {\r\n data: {\r\n value: name,\r\n },\r\n },\r\n },\r\n });\r\n log({ containInsertSerialOperation });\r\n operations.push(containInsertSerialOperation);\r\n\r\n log({ operations });\r\n return operations;\r\n }\r\n\r\n async makeInsertOperationsForNumberValue(\r\n options: MakeInsertOperationsForNumberOptions,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value, parentLinkId, linkId, name } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n \"makeInsertOperationsForStringValue\",\r\n );\r\n const linkInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n id: linkId,\r\n from_id: parentLinkId,\r\n to_id: parentLinkId,\r\n type_id: await deep.id(deep.linkId!, pascalCase(typeof value)),\r\n },\r\n });\r\n log({ linkInsertSerialOperation });\r\n operations.push(linkInsertSerialOperation);\r\n\r\n const stringValueInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: `${typeof value}s` as Table<\"insert\">,\r\n objects: {\r\n link_id: linkId,\r\n value: value,\r\n },\r\n });\r\n log({ stringValueInsertSerialOperation });\r\n operations.push(stringValueInsertSerialOperation);\r\n\r\n const containInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(\"@deep-foundation/core\", \"Contain\"),\r\n from_id: parentLinkId,\r\n to_id: linkId,\r\n string: {\r\n data: {\r\n value: name,\r\n },\r\n },\r\n },\r\n });\r\n log({ containInsertSerialOperation });\r\n operations.push(containInsertSerialOperation);\r\n\r\n log({ operations });\r\n return operations;\r\n }\r\n\r\n async makeInsertOperationsForArrayValue(\r\n options: MakeInsertOperationsForArrayValueOptions,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value, linkId, name, parentLinkId } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n \"makeInsertOperationsForStringValue\",\r\n );\r\n\r\n const linkInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n id: linkId,\r\n type_id: await deep.id(deep.linkId!, pascalCase(typeof value)),\r\n from_id: parentLinkId,\r\n to_id: parentLinkId,\r\n },\r\n });\r\n log({ linkInsertSerialOperation });\r\n operations.push(linkInsertSerialOperation);\r\n\r\n const containInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(\"@deep-foundation/core\", \"Contain\"),\r\n from_id: parentLinkId,\r\n to_id: linkId,\r\n string: {\r\n data: {\r\n value: name,\r\n },\r\n },\r\n },\r\n });\r\n log({ containInsertSerialOperation });\r\n operations.push(containInsertSerialOperation);\r\n\r\n for (let i = 0; i < value.length; i++) {\r\n const element = value[i];\r\n operations.push(\r\n ...(await this.makeInsertOperationsForAnyValue({\r\n value: element,\r\n parentLinkId: linkId,\r\n linkId: this.reservedLinkIds.pop()!,\r\n name: i.toString(),\r\n })),\r\n );\r\n }\r\n\r\n return operations;\r\n }\r\n\r\n async makeInsertOperationsForPrimitiveValue(\r\n options: MakeInsertOperationsForPrimitiveValueOptions,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value } = options;\r\n if (typeof value === \"string\") {\r\n operations.push(\r\n ...(await this.makeInsertOperationsForStringValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (typeof value === \"number\") {\r\n operations.push(\r\n ...(await this.makeInsertOperationsForNumberValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (typeof value === \"boolean\") {\r\n operations.push(\r\n ...(await this.makeInsertOperationsForBooleanValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n }\r\n return operations;\r\n }\r\n\r\n async makeInsertOperationsForObjectValue(\r\n options: MakeInsertOperationsForObjectValue,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value, linkId, name, parentLinkId } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeInsertOperationsForObjectValue.name,\r\n );\r\n\r\n const linkInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n id: linkId,\r\n type_id: await deep.id(deep.linkId!, pascalCase(typeof value)),\r\n from_id: parentLinkId,\r\n to_id: parentLinkId,\r\n },\r\n });\r\n log({ linkInsertSerialOperation });\r\n operations.push(linkInsertSerialOperation);\r\n\r\n const containInsertSerialOperation = createSerialOperation({\r\n type: \"insert\",\r\n table: \"links\",\r\n objects: {\r\n // TODO: Replace id with idLocal when it work properly\r\n type_id: await deep.id(\"@deep-foundation/core\", \"Contain\"),\r\n from_id: parentLinkId,\r\n to_id: linkId,\r\n string: {\r\n data: {\r\n value: name,\r\n },\r\n },\r\n },\r\n });\r\n log({ containInsertSerialOperation });\r\n operations.push(containInsertSerialOperation);\r\n\r\n for (const [propertyKey, propertyValue] of Object.entries(value)) {\r\n if (\r\n typeof propertyValue !== \"string\" &&\r\n typeof propertyValue !== \"number\" &&\r\n typeof propertyValue !== \"boolean\" &&\r\n !Array.isArray(propertyValue) &&\r\n typeof propertyValue !== \"object\"\r\n ) {\r\n log(\r\n `Skipping property ${propertyKey} because its type ${typeof value} is not supported`,\r\n );\r\n continue;\r\n }\r\n const propertyLinkId = this.reservedLinkIds.pop();\r\n log({ propertyLinkId });\r\n if (!propertyLinkId) {\r\n throw new Error(`Not enough reserved link ids`);\r\n }\r\n const propertyInsertOperations =\r\n await this.makeInsertOperationsForAnyValue({\r\n linkId: propertyLinkId,\r\n parentLinkId: linkId,\r\n value: propertyValue,\r\n name: propertyKey,\r\n });\r\n operations.push(...propertyInsertOperations);\r\n }\r\n\r\n return operations;\r\n }\r\n\r\n async makeInsertOperationsForAnyValue(\r\n options: MakeInsertOperationsForAnyValueOptions,\r\n ) {\r\n const operations: Array<SerialOperation> = [];\r\n const { value } = options;\r\n const log = ObjectToLinksConverter.getLogger(\r\n this.makeInsertOperationsForAnyValue.name,\r\n );\r\n\r\n if (\r\n typeof value === \"string\" ||\r\n typeof value === \"number\" ||\r\n typeof value === \"boolean\"\r\n ) {\r\n operations.push(\r\n ...(await this.makeInsertOperationsForPrimitiveValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (Array.isArray(value)) {\r\n operations.push(\r\n ...(await this.makeInsertOperationsForArrayValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else if (typeof value === \"object\") {\r\n operations.push(\r\n ...(await this.makeInsertOperationsForObjectValue({\r\n ...options,\r\n value,\r\n })),\r\n );\r\n } else {\r\n throw new Error(`Type of value ${typeof value} is not supported`);\r\n }\r\n\r\n log({ operations });\r\n return operations;\r\n }\r\n }\r\n\r\n function getObjectToLinksConverterProxy(options: {\r\n target: ObjectToLinksConverter;\r\n customMethods?: Record<string, Function>;\r\n }): ObjectToLinksConverter {\r\n const { target, customMethods } = options;\r\n\r\n return new Proxy(target, {\r\n get: function (obj: ObjectToLinksConverter, prop: string | symbol) {\r\n if (customMethods && prop in customMethods) {\r\n // If the property is in the customMethods object, return that.\r\n return customMethods[prop as string];\r\n }\r\n\r\n // Otherwise, return the property from the original object.\r\n return obj[prop as keyof ObjectToLinksConverter];\r\n },\r\n }) as ObjectToLinksConverter;\r\n }\r\n\r\n try {\r\n const result = await main();\r\n return {\r\n result,\r\n logs: logs,\r\n };\r\n } catch (error) {\r\n throw {\r\n error: util.inspect(error),\r\n logs: logs,\r\n };\r\n }\r\n\r\n async function main() {\r\n const log = ObjectToLinksConverter.getLogger(main.name);\r\n\r\n if (Object.keys(obj).length === 0) {\r\n return;\r\n }\r\n\r\n const objectToLinksConverter = await ObjectToLinksConverter.init({\r\n obj,\r\n rootLinkId,\r\n resultLinkId,\r\n });\r\n log({ objectToLinksConverter });\r\n\r\n const proxiedObjectToLinksConverter = getObjectToLinksConverterProxy({\r\n target: objectToLinksConverter,\r\n customMethods,\r\n });\r\n log({ proxiedObjectToLinksConverter });\r\n\r\n const convertResult = await proxiedObjectToLinksConverter.convert();\r\n log({ convertResult });\r\n\r\n return convertResult;\r\n }\r\n\r\n type ApplyContainTreeLinksDownToParentToMinilinksOptions = Omit<\r\n GetContainTreeLinksDownToLinkOptions,\r\n \"useMinilinks\"\r\n > & {\r\n minilinks: MinilinksResult<Link<number>>;\r\n };\r\n\r\n interface GetContainTreeLinksDownToLinkOptions {\r\n linkExp: BoolExpLink;\r\n }\r\n\r\n type CustomMethods = {\r\n convert: typeof ObjectToLinksConverter.prototype.convert;\r\n makeInsertOperationsForAnyValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForAnyValue;\r\n makeUpdateOperationsForAnyValue: typeof ObjectToLinksConverter.prototype.makeUpdateOperationsForAnyValue;\r\n makeInsertOperationsForPrimitiveValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForPrimitiveValue;\r\n makeInsertOperationsForArrayValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForArrayValue;\r\n makeInsertOperationsForObjectValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForObjectValue;\r\n makeInsertOperationsForStringValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForStringValue;\r\n makeInsertOperationsForNumberValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForNumberValue;\r\n makeInsertOperationsForBooleanValue: typeof ObjectToLinksConverter.prototype.makeInsertOperationsForBooleanValue;\r\n makeUpdateOperationsForBooleanValue: typeof ObjectToLinksConverter.prototype.makeUpdateOperationsForBooleanValue;\r\n makeUpdateOperationsForStringOrNumberValue: typeof ObjectToLinksConverter.prototype.makeUpdateOperationsForStringValue;\r\n makeUpdateOperationsForArrayValue: typeof ObjectToLinksConverter.prototype.makeUpdateOperationsForArrayValue;\r\n makeUpdateOperationsForObjectValue: typeof ObjectToLinksConverter.prototype.makeUpdateOperationsForObjectValue;\r\n applyContainTreeLinksDownToParentToMinilinks: typeof ObjectToLinksConverter.applyContainTreeLinksDownToParentToMinilinks;\r\n getContainTreeLinksDownToParent: typeof ObjectToLinksConverter.getContainTreeLinksDownToParent;\r\n getLinksToReserveCount: typeof ObjectToLinksConverter.getLinksToReserveCount;\r\n init: typeof ObjectToLinksConverter.init;\r\n };\r\n\r\n interface ObjectToLinksConverterOptions {\r\n rootLink: Link<number>;\r\n reservedLinkIds: Array<number>;\r\n obj: Obj;\r\n customMethods?: CustomMethods;\r\n resultLink: Link<number>;\r\n }\r\n\r\n interface ObjectToLinksConverterInitOptions {\r\n obj: Obj;\r\n rootLinkId?: number;\r\n customMethods?: CustomMethods;\r\n resultLinkId?: number;\r\n }\r\n\r\n type AllowedPrimitive = string | number | boolean;\r\n\r\n interface AllowedObject {\r\n [key: string]: AllowedValue;\r\n }\r\n\r\n type AllowedArray = Array<AllowedValue>;\r\n\r\n type AllowedValue = AllowedPrimitive | AllowedObject | AllowedArray;\r\n\r\n type MakeInsertOperationsForStringOptions =\r\n MakeInsertOperationsForValueOptions<string>;\r\n\r\n type MakeInsertOperationsForNumberOptions =\r\n MakeInsertOperationsForValueOptions<number>;\r\n\r\n type MakeInsertOperationsForBooleanOptions =\r\n MakeInsertOperationsForValueOptions<boolean>;\r\n\r\n type MakeInsertOperationsForObjectValue =\r\n MakeInsertOperationsForValueOptions<AllowedObject>;\r\n\r\n type MakeInsertOperationsForArrayValueOptions =\r\n MakeInsertOperationsForValueOptions<AllowedArray>;\r\n\r\n type MakeInsertOperationsForPrimitiveValueOptions =\r\n MakeInsertOperationsForValueOptions<AllowedPrimitive>;\r\n\r\n type MakeInsertOperationsForAnyValueOptions = Omit<\r\n MakeInsertOperationsForValueOptions<AllowedValue>,\r\n \"typeLinkId\"\r\n >;\r\n\r\n type MakeInsertOperationsForValueOptions<TValue extends AllowedValue> = {\r\n parentLinkId: number;\r\n linkId: number;\r\n value: TValue;\r\n name: string;\r\n };\r\n\r\n interface MakeUpdateOperationsForValueOptions<TValue extends AllowedValue> {\r\n link: Link<number>;\r\n value: TValue;\r\n }\r\n\r\n type MakeUpdateOperationsForAnyValueOptions<TValue extends AllowedValue> =\r\n MakeUpdateOperationsForValueOptions<TValue>;\r\n\r\n type MakeUpdateOperationsForObjectValueOptions =\r\n MakeUpdateOperationsForValueOptions<AllowedObject>;\r\n\r\n type MakeUpdateOperationsForStringValueOptions =\r\n MakeUpdateOperationsForValueOptions<string>;\r\n\r\n type MakeUpdateOperationsForArrayValueOptions =\r\n MakeUpdateOperationsForValueOptions<AllowedArray>;\r\n\r\n type MakeUpdateOperationsForBooleanValueOptions =\r\n MakeUpdateOperationsForValueOptions<boolean>;\r\n\r\n type MakeUpdateOperationsForNumberValueOptions =\r\n MakeUpdateOperationsForValueOptions<number>;\r\n};\r\n\r\ninterface Obj {\r\n [key: string]: string | number | Obj | boolean;\r\n}\r\n"
}
},
{
"id": "clientHandler",
"type": 11,
"from": 15,
"to": "clientHandlerCode"
}
],
"errors": [],
"dependencies": [
{
"name": "@deep-foundation/tsx",
"version": "0.0.4"
},
{
"name": "@deep-foundation/core",
"version": "0.0.2"
},
{
"name": "@deep-foundation/boolean",
"version": "1.0.0"
}
]
}