UNPKG

12.7 kBPlain TextView Raw
1import React, {ReactNode} from 'react';
2
3import Types from '../types';
4import { IComponent} from "../types/component";
5import { IInfrastructure } from "../types";
6
7import {
8 setEntry, ddbGetEntry, ddbListEntries, getEntryListQuery, getEntryQuery, setEntryMutation, deleteEntryMutation,
9 deleteEntry, getEntryScanQuery, ddbScan
10} from './datalayer-libs';
11import createMiddleware from '../middleware/middleware-component';
12
13
14import {
15 graphql,
16 GraphQLObjectType,
17 GraphQLString,
18 GraphQLNonNull,
19 GraphQLList,
20 GraphQLInputObjectType
21} from 'graphql';
22
23
24export const ENTRY_INSTANCE_TYPE = "EntryComponent";
25
26
27/**
28 * Specifies all the properties that a Entity-Component must have
29 */
30export interface IEntryArgs {
31
32 /**
33 * the id must be unique across all entities of the data-layer
34 */
35 id: string,
36
37 /**
38 * the primary key, not necessarily unique, but must be unique in combination with the rangeKey
39 */
40 primaryKey: string,
41
42 /**
43 * second part of the overall primary key
44 */
45 rangeKey: string,
46
47 /**
48 * any jsonifyable object that holds data
49 */
50 data: any
51
52};
53
54export interface IEntryProps {
55
56 createEntryFields: () => any,
57
58 createEntryType: (prefix: string) => any,
59
60 createKeyArgs: () => any,
61
62 /**
63 * creates an argument list of all the data of the entry, keys+jsonData
64 * @param entry
65 * @returns {{}}
66 */
67 createEntryArgs: () => any,
68
69 /**
70 * Get a list of entries that satisfy the query
71 *
72 * @param dictKey an object that has one key that specifies the pk or sk to query with its value
73 */
74 getEntryListQuery: (dictKey: any) => any,
75
76 getEntryQuery: (dictKey: any) => any,
77
78 getEntryScanQuery: (dictKey: any) => any,
79
80 /**
81 * set an entry with the specified values
82 *
83 * @param values
84 */
85 setEntryMutation: (values: any) => any,
86
87 setEntry: (args, context, tableName, isOffline) => any,
88 listEntries: (args, context, tableName, key, isOffline) => any,
89 getEntry: (args, context, tableName, isOffline) => any,
90 scan: (args, context, tableName, isOffline) => any,
91
92
93 middleware: any,
94
95
96 /**
97 * delete an entry with the specified values
98 *
99 * @param values
100 */
101 deleteEntryMutation: (values: any) => any,
102
103 deleteEntry: (args, context, tableName, isOffline) => any,
104
105 /**
106 * Provide the name of the list-query with primary entity
107 */
108 getPrimaryListQueryName: () => string,
109 getSecondaryListQueryName: () => string,
110 getGetQueryName: () => string,
111 getSetMutationName: () => string,
112 getPrimaryScanName: () => string,
113 getRangeScanName: () => string,
114 getScanName: () => string,
115
116 /**
117 * Returns whether this entry provides the query/mutation with the specified name
118 * @param name
119 */
120 providesQuery: (name: string) => boolean
121}
122
123
124export const createEntryProps = (props): IEntryProps => {
125
126 const entryProps = {
127 createEntryFields: () => {
128 const fields = Object.keys(props.data).reduce((result, key)=> {
129 result[key] = {type: props.data[key]};
130 return result;
131 }, {});
132
133 if (props.primaryKey) {
134 fields[props.primaryKey] = {type: GraphQLString};
135 }
136
137 if (props.rangeKey) {
138 fields[props.rangeKey] = {type: GraphQLString};
139 }
140
141 return fields;
142 },
143
144 createEntryType: (prefix) => {
145 return new GraphQLObjectType({
146 name: prefix + props.id,
147 fields: () => entryProps.createEntryFields()
148 })
149 },
150
151 createKeyArgs: () => {
152
153 const args = {};
154
155 if (props.primaryKey) {
156 args[props.primaryKey] = {name: props.primaryKey, type: GraphQLString};
157 }
158
159 if (props.rangeKey) {
160 args[props.rangeKey] = {name: props.rangeKey, type: GraphQLString};
161 }
162
163 return args;
164 },
165
166 createEntryArgs: () => {
167
168 const args = Object.keys(props.data).reduce((result, key)=> {
169 result[key] = {name: key, type: GraphQLString};
170 return result;
171 }, {});
172
173 if (props.primaryKey) {
174 args[props.primaryKey] = {name: props.primaryKey, type: GraphQLString};
175 }
176
177 if (props.rangeKey) {
178 args[props.rangeKey] = {name: props.rangeKey, type: GraphQLString};
179 }
180
181 return args;
182 },
183
184 getEntryListQuery: (dictKey) => {
185 const fields = entryProps.createEntryFields();
186 //console.log("fields: ", fields);
187
188 return getEntryListQuery(
189 props.id,
190 dictKey,
191 fields
192 );
193 },
194
195 getEntryQuery: (dictKey) => {
196 const fields = entryProps.createEntryFields();
197 //console.log("fields: ", fields);
198
199 return getEntryQuery(
200 props.id,
201 dictKey,
202 fields
203 );
204
205 },
206
207 getEntryScanQuery: (dictKey) => {
208 const fields = entryProps.createEntryFields();
209 //console.log("fields: ", fields);
210
211 return getEntryScanQuery(
212 props.id,
213 dictKey,
214 fields
215 );
216 },
217
218 setEntryMutation: (values) => {
219 const fields = entryProps.createEntryFields();
220 //console.log("fields: ", fields);
221
222 return setEntryMutation(
223 props.id,
224 values,
225 fields
226 );
227
228 },
229
230 setEntry: (args, context, tableName, isOffline) => {
231
232 //console.log("setEntry: ", args, "offline: ", isOffline);
233
234 return setEntry(
235 tableName, //"code-architect-dev-data-layer",
236 props.primaryKey, // schema.Entry.ENTITY, //pkEntity
237 args[props.primaryKey], // pkId
238 props.rangeKey, //schema.Data.ENTITY, // skEntity
239 args[props.rangeKey], // skId
240 Object.keys(args).reduce((result, key) => {
241 if (Object.keys(props.data).find(datakey => datakey === key) !== undefined) {
242 result[key] = args[key];
243 }
244 return result;
245 }, {}), // jsonData
246 isOffline // do we run offline?
247 );
248 },
249
250 listEntries: (args, context, tableName, key, isOffline) => {
251 const entity = key === "pk" ? props.primaryKey : props.rangeKey;
252 const range = key === "pk" ? props.rangeKey : props.primaryKey;
253
254 //console.log("listEntries: offline? ", isOffline)
255
256 return ddbListEntries(
257 tableName, //tablename
258 key, // key
259 entity, //entity
260 args[entity], //value
261 range, //rangeEntity
262 isOffline
263 ).then(results => {
264
265 //console.log("promised: ", results);
266 return results.map(item => {
267 const data = item.jsonData !== undefined ? JSON.parse(item.jsonData) : {};
268 data[props.primaryKey] = item.pk.substring(item.pk.indexOf("|") + 1);
269 data[props.rangeKey] = item.sk.substring(item.sk.indexOf("|") + 1);
270 return data;
271 });
272
273 });
274
275 },
276
277 getEntry: (args, context, tableName, isOffline) => {
278
279 return ddbGetEntry(
280 tableName, //tablename
281 props.primaryKey, // pkEntity,
282 args[props.primaryKey], // pkValue,
283 props.rangeKey, // skEntity,
284 args[props.rangeKey], // skValue
285 isOffline
286 ).then((result: any)=> {
287
288 //console.log("entry-component getEntry result: ", result);
289
290 const data = result.jsonData !== undefined ? JSON.parse(result.jsonData) : {};
291
292 if (result && result.pk && result.sk) {
293 data[props.primaryKey] = result.pk.substring(result.pk.indexOf("|") + 1);
294 data[props.rangeKey] = result.sk.substring(result.sk.indexOf("|") + 1);
295 }
296 return data;
297
298 });
299
300 },
301
302 scan: (args, context, tableName, key, isOffline) => {
303
304 //console.log("scan entry! ", args, "offline: ", isOffline)
305
306
307
308 return ddbScan(
309 tableName, //tablename
310 key, // key
311 key === "pk" ? props.primaryKey : props.rangeKey, // pkEntity,
312 args.scanall ? undefined : args[`start_${key === "pk" ? props.primaryKey : props.rangeKey}`], // start_value,
313 args.scanall ? undefined : args[`end_${key === "pk" ? props.primaryKey : props.rangeKey}`], // end_Value,
314 key === "pk" ? props.rangeKey : props.primaryKey, // skEntity,
315 isOffline
316 ).then((result: any)=> {
317
318 //console.log("entry-component scan result: ", result);
319 return result.map(entry => {
320 //console.log("scanned entry: ", entry);
321 const data = entry.jsonData !== undefined ? JSON.parse(entry.jsonData) : {};
322
323 if (entry && entry.pk && entry.sk) {
324 data[props.primaryKey] = entry.pk.substring(entry.pk.indexOf("|") + 1);
325 data[props.rangeKey] = entry.sk.substring(entry.sk.indexOf("|") + 1);
326 }
327
328 //console.log("returned data: ", data);
329 return data;
330 });
331
332
333
334
335 });
336
337 },
338
339
340
341 deleteEntryMutation: (values) => {
342 const fields = entryProps.createEntryFields();
343 //const fields = entryProps.createEntryFields();
344 //console.log("fields: ", fields);
345
346 return deleteEntryMutation(
347 props.id,
348 values,
349 fields
350 );
351
352 },
353
354 deleteEntry: (args, context, tableName, isOffline) => {
355
356 return deleteEntry(
357 tableName, //"code-architect-dev-data-layer",
358 props.primaryKey, // schema.Entry.ENTITY, //pkEntity
359 args[props.primaryKey], // pkId
360 props.rangeKey, //schema.Data.ENTITY, // skEntity
361 args[props.rangeKey], // skId
362 isOffline
363 );
364 },
365
366 middleware: createMiddleware({ callback: (req, res, next) => {
367 //console.log("this is the mw of the entry: ", props.id)
368 return next();
369
370 }}),
371
372 getPrimaryListQueryName: () => "list_"+props.id+"_"+props.primaryKey,
373 getRangeListQueryName: () => "list_"+props.id+"_"+props.rangeKey,
374 getGetQueryName: () => "get_"+props.id,
375 getSetMutationName: () => "set_"+props.id,
376 getDeleteMutationName: () => "delete_"+props.id,
377 getPrimaryScanName: () => "scan_"+props.id+"_"+props.primaryKey,
378 getRangeScanName: () => "scan_"+props.id+"_"+props.rangeKey,
379 getScanName: () => "scan_"+props.id,
380
381 /**
382 * Returns whether this entry provides the query/mutation with the specified name
383 * @param name
384 */
385 providesQuery: (name: string) => {
386
387 const result = name === entryProps.getPrimaryListQueryName() ||
388 name === entryProps.getRangeListQueryName() ||
389 name === entryProps.getSetMutationName() ||
390 name === entryProps.getDeleteMutationName() ||
391 name === entryProps.getPrimaryScanName() ||
392 name === entryProps.getRangeScanName() ||
393 name === entryProps.getScanName()
394 ;
395
396 //console.log("does ", props.id , " provide ", name, "? ", result)
397
398 return result;
399 }
400
401 };
402
403
404 return Object.assign({}, props, entryProps);
405
406};
407
408/**
409 * an entry specifies a kind of data that can be stored in a line of the table
410 */
411export default (props: IEntryArgs | any) => {
412
413 // the component must have the properties of IComponent
414 const componentProps: IInfrastructure & IComponent = {
415 infrastructureType: Types.INFRASTRUCTURE_TYPE_COMPONENT,
416 instanceType: ENTRY_INSTANCE_TYPE,
417 instanceId: props.id
418 };
419
420
421 return createEntryProps(Object.assign({}, props, componentProps));
422
423
424};
425
426
427export const isEntry = (component) => {
428
429 return component !== undefined && component.instanceType === ENTRY_INSTANCE_TYPE;
430};