@canmingir/link 1.2.63 → 1.2.65

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.
@@ -1,632 +0,0 @@
1
- import ActionTemplate from "../templates/ActionTemplate.js";
2
- import Context from "./Context.js";
3
- import { jwtDecode } from "jwt-decode";
4
- import { publish } from "@nucleoidai/react-event";
5
- import { storage } from "@nucleoidjs/webstorage";
6
- import { v4 as uuid } from "uuid";
7
-
8
- let login = true;
9
- const itemId = storage.get("itemId");
10
- try {
11
- const token = storage.get("link", "accessToken");
12
- const decodedToken = jwtDecode(token);
13
-
14
- if (decodedToken.exp * 1000 < Date.now()) {
15
- login = false;
16
- }
17
- } catch (err) {
18
- login = false;
19
- }
20
-
21
- export const initialState = new Context({
22
- login,
23
- itemId,
24
- specification: {
25
- api: [],
26
- functions: [],
27
- types: [],
28
- declarations: [],
29
- },
30
- pages: {
31
- api: {
32
- selected: { path: "/", method: "get" },
33
- dialog: {
34
- type: null,
35
- action: null,
36
- open: false,
37
- view: null,
38
- map: {},
39
- params: {},
40
- },
41
- resourceMenu: {
42
- open: false,
43
- anchor: null,
44
- path: null,
45
- },
46
- },
47
- functions: {
48
- selected: null,
49
- dialog: {
50
- type: null,
51
- open: false,
52
- },
53
- AIDialog: {
54
- open: false,
55
- },
56
- },
57
- logic: {
58
- selected: null,
59
- AIDialog: {
60
- open: false,
61
- },
62
- },
63
- query: {
64
- results: null,
65
- },
66
- },
67
- });
68
-
69
- export const reducer = (context, action) => {
70
- context = Context.copy(context);
71
-
72
- const { specification, pages } = context;
73
-
74
- switch (action.type) {
75
- case "LOGIN": {
76
- context.login = true;
77
- break;
78
- }
79
- case "LOGOUT": {
80
- storage.clear();
81
- context.login = false;
82
- break;
83
- }
84
-
85
- case "ITEM_SELECT": {
86
- context.itemId = action.payload;
87
- storage.set("itemId", context.itemId);
88
- break;
89
- }
90
-
91
- case "ITEM_DELETE": {
92
- storage.remove("itemId");
93
- context.itemId = null;
94
- break;
95
- }
96
-
97
- case "SET_PROJECT": {
98
- specification.api = action.payload.project.specification.api;
99
- specification.functions = action.payload.project.specification.functions;
100
- specification.types = action.payload.project.specification.types;
101
- pages.api.selected.path = "/";
102
- break;
103
- }
104
-
105
- case "OPEN_API_DIALOG": {
106
- const { type, action: dialogAction } = action.payload;
107
- pages.api.dialog.type = type;
108
- pages.api.dialog.action = dialogAction;
109
- pages.api.dialog.open = true;
110
- break;
111
- }
112
-
113
- case "SAVE_API_DIALOG": {
114
- const {
115
- path,
116
- method,
117
- request,
118
- response,
119
- params,
120
- types,
121
- summary,
122
- description,
123
- } = action.payload;
124
-
125
- const newApi = {
126
- path,
127
- method,
128
- request,
129
- response,
130
- params,
131
- summary,
132
- description,
133
- action: ActionTemplate[method.toUpperCase()],
134
- };
135
- pages.api.dialog.open = false;
136
- specification.api.push(newApi);
137
- pages.api.selected = { path, method };
138
- publish("SELECTED_API_CHANGED", {
139
- path: path,
140
- method: method,
141
- });
142
-
143
- specification.types = types;
144
- break;
145
- }
146
-
147
- case "CLOSE_API_DIALOG": {
148
- pages.api.dialog.open = false;
149
- break;
150
- }
151
-
152
- case "SET_API_DIALOG_VIEW":
153
- pages.api.dialog.view = action.payload.view;
154
- break;
155
-
156
- case "SET_SELECTED_API": {
157
- if (action.payload.method === null) {
158
- const endpoint = specification.api.find(
159
- (endpoint) => endpoint.path === action.payload.path
160
- );
161
-
162
- if (endpoint && endpoint.method) {
163
- action.payload.method = endpoint.method;
164
- }
165
- }
166
- pages.api.selected = {
167
- path: action.payload.path,
168
- method: action.payload.method,
169
- };
170
-
171
- publish("SELECTED_API_CHANGED", {
172
- path: action.payload.path,
173
- method: action.payload.method,
174
- });
175
-
176
- break;
177
- }
178
-
179
- case "SET_SELECTED_FUNCTION": {
180
- pages.functions.selected = action.payload.function;
181
- break;
182
- }
183
-
184
- case "SET_SELECTED_LOGIC": {
185
- pages.logic.selected = action.payload.logic;
186
- break;
187
- }
188
-
189
- // ===== Resource Menu Actions =====
190
- case "OPEN_RESOURCE_MENU":
191
- pages.api.resourceMenu.open = true;
192
- pages.api.resourceMenu.anchor = action.payload.anchor;
193
- pages.api.resourceMenu.path = action.payload.path;
194
- break;
195
-
196
- case "DELETE_RESOURCE": {
197
- const { path } = action.payload;
198
-
199
- specification.api = specification.api.filter(
200
- (api) => !api.path.startsWith(path)
201
- );
202
-
203
- if (pages.api.selected.path.startsWith(path)) {
204
- if (specification.api.length > 0) {
205
- pages.api.selected.path = specification.api[0].path;
206
- pages.api.selected.method = specification.api[0].method;
207
- } else {
208
- pages.api.selected.path = "/";
209
- pages.api.selected.method = "get";
210
- }
211
-
212
- publish("SELECTED_API_CHANGED", {
213
- path: pages.api.selected.path,
214
- method: pages.api.selected.method,
215
- });
216
- }
217
-
218
- break;
219
- }
220
-
221
- case "DELETE_METHOD": {
222
- const { path, method } = pages.api.selected;
223
-
224
- const routeIndex = specification.api.findIndex(
225
- (route) =>
226
- route.path === path &&
227
- route.method.toLowerCase() === method.toLowerCase()
228
- );
229
-
230
- if (routeIndex !== -1) {
231
- specification.api.splice(routeIndex, 1);
232
- }
233
-
234
- const samePathRoutes = specification.api.filter(
235
- (route) => route.path === path
236
- );
237
- if (samePathRoutes.length > 0) {
238
- context.pages.api.selected.method = samePathRoutes[0].method;
239
- } else {
240
- context.pages.api.selected.method = null;
241
- }
242
-
243
- break;
244
- }
245
-
246
- case "CLOSE_RESOURCE_MENU":
247
- pages.api.resourceMenu.open = false;
248
- pages.api.resourceMenu = {};
249
- break;
250
-
251
- // ===== Function Dialog Actions =====
252
- case "OPEN_FUNCTION_DIALOG": {
253
- pages.functions.dialog.type = action.payload.type;
254
- pages.functions.dialog.open = true;
255
- break;
256
- }
257
-
258
- case "OPEN_AI_DIALOG": {
259
- const page = action.payload.page;
260
- pages[page].AIDialog.open = true;
261
- break;
262
- }
263
-
264
- case "CLOSE_AI_DIALOG": {
265
- const page = action.payload.page;
266
- pages[page].AIDialog.open = false;
267
- break;
268
- }
269
-
270
- case "SAVE_LOGIC_DIALOG": {
271
- const { description, summary, definition } = action.payload;
272
- const declarations = specification.declarations;
273
-
274
- declarations.push({
275
- description,
276
- summary,
277
- definition,
278
- });
279
-
280
- publish("LOGIC_ADDED", {
281
- declaration: declarations[declarations.length - 1],
282
- });
283
-
284
- break;
285
- }
286
-
287
- case "SAVE_FUNCTION_DIALOG": {
288
- const { path, type, definition, params, ext } = action.payload;
289
- const functions = specification.functions;
290
-
291
- functions.push({
292
- path,
293
- type,
294
- ext,
295
- definition,
296
- params,
297
- });
298
-
299
- publish("CONTEXT_CHANGED", {
300
- files: [{ key: `${path}.${ext}`, value: definition }],
301
- });
302
-
303
- break;
304
- }
305
-
306
- case "DELETE_FUNCTION": {
307
- const { path } = action.payload;
308
-
309
- if (specification.functions.length > 1) {
310
- const index = specification.functions.findIndex(
311
- (data) => data.path === path
312
- );
313
-
314
- const deletedFunction = specification.functions[index];
315
- specification.functions.splice(index, 1);
316
-
317
- const remainingFunctions = specification.functions.filter(
318
- (data) => data.path !== path
319
- );
320
-
321
- const files = remainingFunctions.map((func) => ({
322
- key: `${func.path}.ts`,
323
- value: func,
324
- }));
325
-
326
- publish("CONTEXT_CHANGED", {
327
- files: [{ key: `${deletedFunction.path}.ts` }, ...files],
328
- });
329
- context.pages.functions.selected = specification.functions[0].path;
330
- }
331
-
332
- break;
333
- }
334
-
335
- case "CLOSE_FUNCTION_DIALOG": {
336
- pages.functions.dialog.open = false;
337
- break;
338
- }
339
-
340
- // ===== Type Management Actions =====
341
- case "UPDATE_TYPE": {
342
- const { id, name, type } = action.payload;
343
- const map = pages.api.dialog.map;
344
-
345
- if (name !== undefined) map[id].name = name;
346
- if (type !== undefined) {
347
- if (map[id].type === "array") map[id].items.type = type;
348
- else {
349
- map[id].type = type;
350
-
351
- if (type === "array") map[id].items = { type: "integer" };
352
- else if (type === "object") map[id].properties = {};
353
- }
354
- }
355
-
356
- break;
357
- }
358
-
359
- case "ADD_SCHEMA_PROPERTY": {
360
- const { id } = action.payload;
361
- const map = pages.api.dialog.map;
362
- const key = uuid();
363
- map[key] = map[id].properties[key] = {
364
- id: key,
365
- type: "integer",
366
- };
367
- break;
368
- }
369
-
370
- case "REMOVE_SCHEMA_PROPERTY": {
371
- const { id } = action.payload;
372
- const map = pages.api.dialog.map;
373
- delete map[id];
374
- break;
375
- }
376
-
377
- case "ADD_PARAM": {
378
- const map = pages.api.dialog.map;
379
- const id = uuid();
380
- pages.api.dialog.params[id] = map[id] = {
381
- id,
382
- type: "string",
383
- required: true,
384
- };
385
- break;
386
- }
387
-
388
- case "REMOVE_PARAM": {
389
- const { id } = action.payload;
390
- const map = pages.api.dialog.map;
391
- delete pages.api.dialog.params[id];
392
- delete map[id];
393
- break;
394
- }
395
-
396
- case "QUERY_RESULTS": {
397
- const query = context.get("pages.query");
398
- query.results = action.payload.results;
399
- break;
400
- }
401
-
402
- // ===== CRUD Actions =====
403
- case "CREATE_SAMPLE_CRUD": {
404
- const { api, functions } = specification;
405
- const className = action.payload.resource;
406
- const resource = action.payload.resource.toLowerCase() + "s";
407
-
408
- const template = {
409
- request: { type: "object", properties: {} },
410
- response: { type: "object", properties: {} },
411
- };
412
-
413
- api[`/${resource}`] = {
414
- get: {
415
- ...template,
416
- summary: `Get ${className} list`,
417
- description: `Get ${className} list`,
418
- action: `function action(req) {\n return ${className};\n}\n`,
419
- },
420
- post: {
421
- ...template,
422
- summary: `Create ${className}`,
423
- description: `Create ${className}`,
424
- action: `function action(req) {\n return new ${className}();\n}\n`,
425
- },
426
- };
427
- api[`/${resource}/{${resource}}`] = {
428
- get: {
429
- ...template,
430
- summary: `Get ${className}`,
431
- description: `Get ${className}`,
432
- action: `function action(req) {\n const ${resource} = req.params.${resource};\n return ${className}[${resource}];\n}\n`,
433
- },
434
- put: {
435
- ...template,
436
- summary: `Update ${className}`,
437
- description: `Update ${className}`,
438
- action: `function action(req) {\n const ${resource} = req.params.${resource};\n return ${className}[${resource}];\n}\n`,
439
- },
440
- del: {
441
- ...template,
442
- summary: `Delete ${className}`,
443
- description: `Delete ${className}`,
444
- action: `function action(req) {\n const ${resource} = req.params.${resource};\n delete ${className}[${resource}];\n}\n`,
445
- },
446
- };
447
-
448
- const sample = {
449
- definition: `class ${className} {\n constructor() {\n }\n}\n`,
450
- ext: "ts",
451
- params: [],
452
- path: `/${className}`,
453
- type: "CLASS",
454
- };
455
-
456
- functions.push(sample);
457
-
458
- publish("CONTEXT_CHANGED", {
459
- files: [
460
- { key: `${sample.path}.${sample.ext}`, value: sample.definition },
461
- ],
462
- });
463
-
464
- break;
465
- }
466
-
467
- case "UPDATE_API_SCHEMAS": {
468
- const { path, method, requestSchema, responseSchema } = action.payload;
469
- const apiIndex = specification.api.findIndex(
470
- (api) => api.path === path && api.method === method
471
- );
472
-
473
- if (apiIndex !== -1) {
474
- specification.api[apiIndex].request = {
475
- ...specification.api[apiIndex].request,
476
- schema: requestSchema,
477
- };
478
- specification.api[apiIndex].response = {
479
- ...specification.api[apiIndex].response,
480
- schema: responseSchema,
481
- };
482
- }
483
- break;
484
- }
485
-
486
- case "UPDATE_API_SUMMARY": {
487
- const { path, method, newSummary } = action.payload;
488
- const apiEndpoint = specification.api.find(
489
- (api) => api.path === path && api.method === method
490
- );
491
- if (apiEndpoint) {
492
- apiEndpoint.summary = newSummary;
493
- }
494
- break;
495
- }
496
-
497
- case "UPDATE_API_DESCRIPTION": {
498
- const { path, method, newDescription } = action.payload;
499
- const apiEndpoint = specification.api.find(
500
- (api) => api.path === path && api.method === method
501
- );
502
- if (apiEndpoint) {
503
- apiEndpoint.description = newDescription;
504
- }
505
- break;
506
- }
507
-
508
- case "DELETE_API": {
509
- const selectedIndex = specification.api.findIndex(
510
- (api) =>
511
- api.path === pages.api.selected.path &&
512
- api.method === pages.api.selected.method
513
- );
514
-
515
- if (selectedIndex > -1) {
516
- specification.api.splice(selectedIndex, 1);
517
- if (specification.api.length > 0) {
518
- pages.api.selected.path = specification.api[0].path;
519
- pages.api.selected.method = specification.api[0].method;
520
- } else {
521
- pages.api.selected.path = "/";
522
- pages.api.selected.method = "get";
523
- }
524
- }
525
- pages.api.dialog.open = false;
526
-
527
- break;
528
- }
529
-
530
- case "UPDATE_API_TYPES": {
531
- const { updatedTypes } = action.payload;
532
- const typeIndex = specification.types.findIndex(
533
- (type) => type.name === updatedTypes.name
534
- );
535
- const updatedType = {
536
- ...specification.types[typeIndex],
537
- schema: {
538
- ...updatedTypes,
539
- },
540
- };
541
- if (typeIndex !== -1) {
542
- specification.types[typeIndex] = updatedType;
543
- } else {
544
- specification.types.push(updatedTypes);
545
- }
546
- break;
547
- }
548
-
549
- case "ADD_TYPE": {
550
- const { typeName } = action.payload;
551
- const newType = {
552
- name: typeName,
553
- schema: {
554
- name: typeName,
555
- type: "object",
556
- properties: [
557
- { type: "string", name: "id" },
558
- { type: "string", name: "name" },
559
- ],
560
- },
561
- };
562
- specification.types.push(newType);
563
- break;
564
- }
565
-
566
- case "DELETE_TYPE": {
567
- const { typeName } = action.payload;
568
- const typeIndex = specification.types.findIndex(
569
- (type) => type.name === typeName
570
- );
571
-
572
- if (typeIndex !== -1) {
573
- specification.types.splice(typeIndex, 1);
574
- }
575
- break;
576
- }
577
-
578
- case "UPDATE_TYPE_NAME": {
579
- const { oldTypeName, newTypeName } = action.payload;
580
- const typeIndex = specification.types.findIndex(
581
- (type) => type.name === oldTypeName
582
- );
583
-
584
- if (typeIndex !== -1) {
585
- specification.types[typeIndex].name = newTypeName;
586
- specification.types[typeIndex].schema.name = newTypeName;
587
- }
588
- break;
589
- }
590
-
591
- case "SAVE_API_PARAMS": {
592
- console.log("SAVE_API_PARAMS", action.payload);
593
- const { path, method, params } = action.payload;
594
- const apiIndex = specification.api.findIndex(
595
- (api) => api.path === path && api.method === method
596
- );
597
-
598
- if (apiIndex !== -1) {
599
- specification.api[apiIndex].params = params;
600
- }
601
- break;
602
- }
603
-
604
- case "UPDATE_API_PATH_METHOD": {
605
- const { path, method } = action.payload;
606
-
607
- const apiIndex = specification.api.findIndex(
608
- (api) =>
609
- api.path === pages.api.selected.path &&
610
- api.method === pages.api.selected.method
611
- );
612
-
613
- if (apiIndex !== -1) {
614
- specification.api[apiIndex].path = path;
615
- specification.api[apiIndex].method = method;
616
- }
617
-
618
- pages.api.selected = {
619
- ...pages.api.selected,
620
- path: path,
621
- method: method,
622
- };
623
-
624
- break;
625
- }
626
-
627
- default:
628
- }
629
-
630
- console.debug("reducer", action.type, context);
631
- return context;
632
- };