springnext 0.0.1 → 0.0.2

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.
@@ -0,0 +1,37 @@
1
+ export type ErrorBaseCreatingPayload = {
2
+ error: unknown;
3
+ code?: string;
4
+ details?: any;
5
+ };
6
+ export type ErrorBaseModel = {
7
+ name: string;
8
+ message: string;
9
+ code: string;
10
+ timestamp: number;
11
+ details: any | null;
12
+ };
13
+ export type ModuleErrorModel = ErrorBaseModel & {
14
+ module: string;
15
+ method: string;
16
+ cause: ErrorBaseModel | null;
17
+ };
18
+ export type ControllerErrorModel = ErrorBaseModel & {
19
+ module: string;
20
+ method: string;
21
+ cause: ModuleErrorModel | ErrorBaseModel | null;
22
+ statusCode: number;
23
+ };
24
+ export declare const isControllerError: (error: unknown) => error is ControllerErrorModel;
25
+ export declare const isModuleError: (arg: any) => arg is ModuleErrorModel;
26
+ export declare const spawnModuleError: (moduleName: string) => {
27
+ inMethod: (methodName: string) => {
28
+ newError: (payload: ErrorBaseCreatingPayload, cause?: unknown) => ModuleErrorModel;
29
+ };
30
+ };
31
+ export declare const spawnControllerError: (controllerName: string) => {
32
+ inMethod: (methodName: string) => {
33
+ newError: (payload: ErrorBaseCreatingPayload & {
34
+ statusCode: number;
35
+ }, cause?: unknown) => ControllerErrorModel;
36
+ };
37
+ };
package/dist/index.cjs CHANGED
@@ -1,5 +1,14 @@
1
1
  "use strict";
2
2
  var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
3
12
  (()=>{
4
13
  __webpack_require__.d = (exports1, definition)=>{
5
14
  for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
@@ -24,12 +33,509 @@ var __webpack_require__ = {};
24
33
  var __webpack_exports__ = {};
25
34
  __webpack_require__.r(__webpack_exports__);
26
35
  __webpack_require__.d(__webpack_exports__, {
27
- squared: ()=>squared
36
+ Controller: ()=>zod_controller_utils_namespaceObject,
37
+ Store: ()=>store_namespaceObject,
38
+ Module: ()=>zod_module_utils_namespaceObject,
39
+ ValueObjects: ()=>value_objects_namespaceObject
40
+ });
41
+ var zod_module_utils_namespaceObject = {};
42
+ __webpack_require__.r(zod_module_utils_namespaceObject);
43
+ __webpack_require__.d(zod_module_utils_namespaceObject, {
44
+ methods: ()=>methods
28
45
  });
29
- const squared = (n)=>n * n;
30
- exports.squared = __webpack_exports__.squared;
46
+ var zod_controller_utils_namespaceObject = {};
47
+ __webpack_require__.r(zod_controller_utils_namespaceObject);
48
+ __webpack_require__.d(zod_controller_utils_namespaceObject, {
49
+ DefaultErrorCodes: ()=>zod_controller_utils_DefaultErrorCodes,
50
+ endpoints: ()=>endpoints
51
+ });
52
+ var store_namespaceObject = {};
53
+ __webpack_require__.r(store_namespaceObject);
54
+ __webpack_require__.d(store_namespaceObject, {
55
+ InRAM: ()=>InRAM,
56
+ methods: ()=>store_zod_utils_methods,
57
+ toModuleMetadata: ()=>toModuleMetadata
58
+ });
59
+ var value_objects_namespaceObject = {};
60
+ __webpack_require__.r(value_objects_namespaceObject);
61
+ __webpack_require__.d(value_objects_namespaceObject, {
62
+ Pagination: ()=>Pagination
63
+ });
64
+ const isControllerError = (error)=>{
65
+ if (!error || 'object' != typeof error) return false;
66
+ const argKeys = Object.keys(error);
67
+ const requiredKeys = [
68
+ 'name',
69
+ 'message',
70
+ 'code',
71
+ 'module',
72
+ 'method',
73
+ 'timestamp',
74
+ 'statusCode'
75
+ ];
76
+ return requiredKeys.every((x)=>argKeys.includes(x));
77
+ };
78
+ const isModuleError = (arg)=>{
79
+ if ('object' != typeof arg || !arg) return false;
80
+ const argKeys = Object.keys(arg);
81
+ const requiredKeys = [
82
+ 'name',
83
+ 'message',
84
+ 'code',
85
+ 'module',
86
+ 'method',
87
+ 'timestamp'
88
+ ];
89
+ if (!requiredKeys.every((x)=>argKeys.includes(x))) return false;
90
+ return !argKeys.includes('statusCode');
91
+ };
92
+ const spawnBaseError = ({ error, code, details })=>{
93
+ let err = error instanceof Error ? error : new Error('unknown error');
94
+ if ('string' == typeof error || 'number' == typeof error) err = new Error(error?.toString());
95
+ if ('object' == typeof error && null !== error) if (error instanceof Error) err = error;
96
+ else {
97
+ const jsonRepresentation = JSON.stringify(error);
98
+ err = new Error(jsonRepresentation);
99
+ }
100
+ return {
101
+ message: err.message,
102
+ name: err.name,
103
+ timestamp: Date.now(),
104
+ code: code || err.name,
105
+ details: details || null
106
+ };
107
+ };
108
+ const spawnFromUnknownError = (error)=>{
109
+ const isErrorBase = (arg)=>{
110
+ if ('object' != typeof arg || !arg) return false;
111
+ const argKeys = Object.keys(arg);
112
+ const requiredKeys = [
113
+ 'name',
114
+ 'message',
115
+ 'code',
116
+ 'timestamp'
117
+ ];
118
+ return requiredKeys.every((x)=>argKeys.includes(x));
119
+ };
120
+ if (isModuleError(error)) return error;
121
+ if (isErrorBase(error)) return error;
122
+ return spawnBaseError({
123
+ error
124
+ });
125
+ };
126
+ const spawnModuleError = (moduleName)=>({
127
+ inMethod: (methodName)=>({
128
+ newError: (payload, cause)=>{
129
+ const errorBase = spawnBaseError(payload);
130
+ return {
131
+ ...errorBase,
132
+ cause: cause ? spawnFromUnknownError(cause) : null,
133
+ module: moduleName,
134
+ method: methodName
135
+ };
136
+ }
137
+ })
138
+ });
139
+ const spawnControllerError = (controllerName)=>({
140
+ inMethod: (methodName)=>({
141
+ newError: (payload, cause)=>{
142
+ const errorBase = spawnBaseError(payload);
143
+ const formattedCause = cause ? spawnFromUnknownError(cause) : null;
144
+ if (!payload.code && formattedCause?.code) errorBase.code = formattedCause.code;
145
+ return {
146
+ ...errorBase,
147
+ cause: formattedCause,
148
+ module: controllerName,
149
+ method: methodName,
150
+ statusCode: payload.statusCode
151
+ };
152
+ }
153
+ })
154
+ });
155
+ const methods = (metadata, sharedConfig = {})=>(methodName, handler, config = {})=>{
156
+ const { name, schemas } = metadata;
157
+ return async (payload)=>{
158
+ try {
159
+ const parsedPayload = schemas[methodName].payload.parse(payload);
160
+ const response = await handler(parsedPayload, {
161
+ methodError: (payload, cause)=>spawnModuleError(name).inMethod(methodName).newError('string' == typeof payload ? {
162
+ error: payload,
163
+ code: payload,
164
+ details: parsedPayload
165
+ } : payload, cause)
166
+ });
167
+ const parsedResponse = schemas[methodName].response.parse(response);
168
+ return parsedResponse;
169
+ } catch (error) {
170
+ if (isModuleError(error)) {
171
+ if (sharedConfig.onError) await sharedConfig.onError(error);
172
+ if (config.onError) await config.onError(error);
173
+ throw error;
174
+ }
175
+ const serviceErrorGenerator = spawnModuleError(name).inMethod(methodName);
176
+ const serviceError = serviceErrorGenerator.newError({
177
+ error
178
+ });
179
+ if (config.onError) await config.onError(serviceError);
180
+ throw serviceError;
181
+ }
182
+ };
183
+ };
184
+ const external_zod_namespaceObject = require("zod");
185
+ var external_zod_default = /*#__PURE__*/ __webpack_require__.n(external_zod_namespaceObject);
186
+ function jsonResponse(data, init) {
187
+ return new Response(JSON.stringify(data), {
188
+ ...init,
189
+ headers: {
190
+ 'Content-Type': 'application/json',
191
+ ...init?.headers || {}
192
+ }
193
+ });
194
+ }
195
+ var zod_controller_utils_DefaultErrorCodes = /*#__PURE__*/ function(DefaultErrorCodes) {
196
+ DefaultErrorCodes["REQUEST_PARSING"] = "NZMT-CONTROLLER___REQUEST-PARSING";
197
+ DefaultErrorCodes["RESPONSE_PARSING"] = "NZMT-CONTROLLER___RESPONSE-PARSING";
198
+ return DefaultErrorCodes;
199
+ }({});
200
+ const endpoints = (metadata, sharedConfig = {})=>{
201
+ const endpointLogic = (method, handler, configuration = {})=>async (request)=>{
202
+ let requestPayload = {};
203
+ const errorFactory = spawnControllerError(metadata.name).inMethod(method);
204
+ try {
205
+ const endpointError = (payload, errorStatus, cause)=>{
206
+ if ('string' == typeof payload) return errorFactory.newError({
207
+ statusCode: errorStatus ?? 500,
208
+ code: payload,
209
+ error: payload,
210
+ details: requestPayload
211
+ }, cause);
212
+ return errorFactory.newError({
213
+ ...payload,
214
+ statusCode: errorStatus ?? 500
215
+ }, cause);
216
+ };
217
+ if (sharedConfig.guards) for (const sharedGuard of sharedConfig.guards){
218
+ const error = await sharedGuard({
219
+ request,
220
+ endpointError
221
+ });
222
+ if (error) throw error;
223
+ }
224
+ if (configuration.guards) for (const endpointGuard of configuration.guards){
225
+ const error = await endpointGuard({
226
+ request,
227
+ endpointError
228
+ });
229
+ if (error) throw error;
230
+ }
231
+ const endpointSchemas = metadata.schemas[method];
232
+ if (!endpointSchemas) throw errorFactory.newError({
233
+ error: 'No schemas were found for the endpoint',
234
+ statusCode: 500
235
+ });
236
+ if (endpointSchemas.query) {
237
+ const queryParamsAsObject = Object.fromEntries(request.nextUrl.searchParams.entries());
238
+ const queryParamsParsed = endpointSchemas.query.safeParse(queryParamsAsObject);
239
+ if (!queryParamsParsed.success) throw errorFactory.newError({
240
+ error: queryParamsParsed.error.message,
241
+ statusCode: 400,
242
+ code: "NZMT-CONTROLLER___REQUEST-PARSING",
243
+ details: external_zod_default().treeifyError(queryParamsParsed.error)
244
+ });
245
+ requestPayload = {
246
+ ...requestPayload,
247
+ ...queryParamsParsed.data
248
+ };
249
+ }
250
+ if (endpointSchemas.body) {
251
+ const body = await request.json();
252
+ const bodyParsed = endpointSchemas.body.safeParse(body);
253
+ if (!bodyParsed.success) throw errorFactory.newError({
254
+ error: bodyParsed.error.message,
255
+ statusCode: 400,
256
+ code: "NZMT-CONTROLLER___REQUEST-PARSING",
257
+ details: external_zod_default().treeifyError(bodyParsed.error)
258
+ });
259
+ requestPayload = {
260
+ ...requestPayload,
261
+ ...bodyParsed.data
262
+ };
263
+ }
264
+ const flags = {};
265
+ const result = await handler(requestPayload, {
266
+ request,
267
+ flags,
268
+ endpointError: (payload, errorStatus, cause)=>{
269
+ if ('string' == typeof payload) return errorFactory.newError({
270
+ statusCode: errorStatus ?? 500,
271
+ code: payload,
272
+ error: payload,
273
+ details: requestPayload
274
+ }, cause);
275
+ return errorFactory.newError({
276
+ ...payload,
277
+ statusCode: errorStatus ?? 500
278
+ }, cause);
279
+ }
280
+ });
281
+ if (endpointSchemas.response) {
282
+ const resultParsed = endpointSchemas.response.safeParse(result);
283
+ if (!resultParsed.success) throw errorFactory.newError({
284
+ error: resultParsed.error.message,
285
+ statusCode: 500,
286
+ code: "NZMT-CONTROLLER___RESPONSE-PARSING",
287
+ details: external_zod_default().treeifyError(resultParsed.error)
288
+ });
289
+ if (configuration.eventHandlers?.onSuccess) for (const onSuccessHandler of configuration.eventHandlers.onSuccess)onSuccessHandler({
290
+ request,
291
+ result: resultParsed.data,
292
+ requestPayload: requestPayload,
293
+ flags
294
+ });
295
+ if (configuration.customResponseLogic?.onSuccess) return await configuration.customResponseLogic.onSuccess({
296
+ req: request,
297
+ response: resultParsed.data
298
+ });
299
+ return jsonResponse(resultParsed.data, {
300
+ status: 200
301
+ });
302
+ }
303
+ if (configuration.eventHandlers?.onSuccess) for (const onSuccessHanlder of configuration.eventHandlers.onSuccess)await onSuccessHanlder({
304
+ request,
305
+ result: void 0,
306
+ requestPayload: requestPayload,
307
+ flags
308
+ });
309
+ if (configuration.customResponseLogic?.onSuccess) return await configuration.customResponseLogic.onSuccess({
310
+ req: request,
311
+ response: {}
312
+ });
313
+ return jsonResponse({}, {
314
+ status: 200
315
+ });
316
+ } catch (e) {
317
+ let controllerError = e;
318
+ if (isControllerError(e)) controllerError = errorFactory.newError({
319
+ error: 'Internal error',
320
+ statusCode: 500
321
+ }, e);
322
+ if (!controllerError.details || 'object' != typeof controllerError.details) controllerError.details = {};
323
+ if (sharedConfig.onErrorHandlers) try {
324
+ for (const sharedOnError of sharedConfig.onErrorHandlers)await sharedOnError({
325
+ error: controllerError,
326
+ req: request
327
+ });
328
+ } catch (errorFromOnErrorHandler) {
329
+ controllerError = errorFactory.newError({
330
+ error: 'onError handler error',
331
+ statusCode: 500
332
+ }, errorFromOnErrorHandler);
333
+ }
334
+ if (configuration.eventHandlers?.onError) try {
335
+ for (const onErrorHandler of configuration.eventHandlers.onError)await onErrorHandler({
336
+ error: controllerError,
337
+ req: request
338
+ });
339
+ } catch (errorFromOnErrorHandler) {
340
+ controllerError = errorFactory.newError({
341
+ error: 'onError handler error',
342
+ statusCode: 500
343
+ }, errorFromOnErrorHandler);
344
+ }
345
+ if (configuration.customResponseLogic?.onError) return await configuration.customResponseLogic.onError({
346
+ req: request,
347
+ error: controllerError
348
+ });
349
+ return jsonResponse({
350
+ message: controllerError.message,
351
+ details: controllerError.statusCode.toString().startsWith('4') ? controllerError.details : null,
352
+ code: controllerError.code
353
+ }, {
354
+ status: controllerError.statusCode
355
+ });
356
+ }
357
+ };
358
+ return endpointLogic;
359
+ };
360
+ class Pagination {
361
+ data;
362
+ static schema = external_zod_default().object({
363
+ zeroBasedIndex: external_zod_default().coerce.number().int().nonnegative(),
364
+ pageSize: external_zod_default().coerce.number().int().positive()
365
+ });
366
+ constructor(data){
367
+ this.data = data;
368
+ }
369
+ static create = (data)=>{
370
+ const parsedModel = Pagination.schema.parse(data);
371
+ return new Pagination(parsedModel);
372
+ };
373
+ get model() {
374
+ return this.data;
375
+ }
376
+ same = (pagination)=>pagination.model.pageSize === this.model.pageSize && pagination.model.zeroBasedIndex === this.model.zeroBasedIndex;
377
+ get nextPage() {
378
+ return Pagination.create({
379
+ pageSize: this.data.pageSize,
380
+ zeroBasedIndex: this.data.zeroBasedIndex + 1
381
+ });
382
+ }
383
+ get previousPage() {
384
+ if (0 === this.model.zeroBasedIndex) return Pagination.create(this.model);
385
+ return Pagination.create({
386
+ pageSize: this.model.pageSize,
387
+ zeroBasedIndex: this.model.zeroBasedIndex - 1
388
+ });
389
+ }
390
+ get previousPage_UNSAFE() {
391
+ return Pagination.create({
392
+ pageSize: this.model.pageSize,
393
+ zeroBasedIndex: this.model.zeroBasedIndex - 1
394
+ });
395
+ }
396
+ }
397
+ const toModuleMetadata = (schemas)=>({
398
+ name: schemas.name,
399
+ schemas: {
400
+ ...schemas.customOperations ?? {},
401
+ list: {
402
+ payload: external_zod_default().object({
403
+ filter: schemas.searchPayload.list,
404
+ pagination: Pagination.schema.optional()
405
+ }),
406
+ response: external_zod_default().array(schemas.models.list)
407
+ },
408
+ details: {
409
+ payload: external_zod_default().object({
410
+ filter: schemas.searchPayload.specific
411
+ }),
412
+ response: schemas.models.details.nullable()
413
+ },
414
+ create: {
415
+ payload: external_zod_default().object({
416
+ payload: schemas.actionsPayload.create
417
+ }),
418
+ response: external_zod_default().object({
419
+ id: external_zod_default().string()
420
+ })
421
+ },
422
+ updateOne: {
423
+ payload: external_zod_default().object({
424
+ filter: schemas.searchPayload.specific,
425
+ payload: schemas.actionsPayload.update
426
+ }),
427
+ response: external_zod_default().object({
428
+ success: external_zod_default().boolean()
429
+ })
430
+ },
431
+ deleteOne: {
432
+ payload: external_zod_default().object({
433
+ filter: schemas.searchPayload.specific
434
+ }),
435
+ response: external_zod_default().object({
436
+ success: external_zod_default().boolean()
437
+ })
438
+ }
439
+ }
440
+ });
441
+ const store_zod_utils_methods = (schemas)=>{
442
+ const data = toModuleMetadata(schemas);
443
+ return methods(data);
444
+ };
445
+ const InRAM = (schemas, options)=>{
446
+ class RAMStore {
447
+ ___data = [];
448
+ method = store_zod_utils_methods(schemas);
449
+ ___listSearchLogic = (entity, pattern)=>{
450
+ const patternKeys = Object.entries(pattern).filter(([_, value])=>!!value).map((x)=>x[0]);
451
+ const entityAsObject = entity;
452
+ return Object.entries(entityAsObject).filter(([key])=>patternKeys.includes(key)).every(([key, value])=>value === pattern[key] || value?.toString()?.includes(pattern[key]?.toString()));
453
+ };
454
+ ___specificSearchLogic = (entity, pattern)=>{
455
+ const patternKeys = Object.entries(pattern).filter(([_, value])=>!!value).map((x)=>x[0]);
456
+ const entityAsObject = entity;
457
+ return Object.entries(entityAsObject).filter(([key])=>patternKeys.includes(key)).every(([key, value])=>value === pattern[key] || value?.toString()?.includes(pattern[key]?.toString()));
458
+ };
459
+ ___mapDetailToList = (entity)=>entity;
460
+ ___mapCreatePayloadToDetail = (payload)=>({
461
+ ...payload,
462
+ id: Math.random().toString()
463
+ });
464
+ ___mapUpdatePayloadToDetail = (prevValue, rawUpdate)=>{
465
+ const update = Object.fromEntries(Object.entries(rawUpdate).filter(([, value])=>void 0 !== value));
466
+ return {
467
+ ...prevValue,
468
+ ...update
469
+ };
470
+ };
471
+ constructor(){
472
+ if (!options) return;
473
+ if (options.searchLogic) {
474
+ if (options.searchLogic.list) this.___listSearchLogic = options.searchLogic.list;
475
+ if (options.searchLogic.specific) this.___specificSearchLogic = options.searchLogic.specific;
476
+ }
477
+ if (options.mappers) {
478
+ if (options.mappers.detailToList) this.___mapDetailToList = options.mappers.detailToList;
479
+ if (options.mappers.createPayloadToDetail) this.___mapCreatePayloadToDetail = options.mappers.createPayloadToDetail;
480
+ if (options.mappers.updatePayloadToDetail) this.___mapUpdatePayloadToDetail = options.mappers.updatePayloadToDetail;
481
+ }
482
+ if (options.initialData) this.___data = [
483
+ ...options.initialData
484
+ ];
485
+ }
486
+ list = this.method('list', async ({ filter, pagination = {
487
+ pageSize: 1000,
488
+ zeroBasedIndex: 0
489
+ } })=>{
490
+ schemas.searchPayload.list.parse(filter);
491
+ Pagination.schema.parse(pagination);
492
+ const afterFiltration = this.___data.filter((x)=>this.___listSearchLogic(x, filter));
493
+ const afterPagination = afterFiltration.filter((_, i)=>i >= pagination.pageSize * pagination.zeroBasedIndex && i < (pagination.zeroBasedIndex + 1) * pagination.pageSize);
494
+ const result = afterPagination.map((x)=>this.___mapDetailToList(x));
495
+ external_zod_default().array(schemas.models.list).parse(result);
496
+ return result;
497
+ });
498
+ details = this.method('details', async ({ filter })=>{
499
+ const details = this.___data.find((x)=>this.___specificSearchLogic(x, filter));
500
+ if (!details) return null;
501
+ return details;
502
+ });
503
+ create = this.method('create', async ({ payload })=>{
504
+ const newItem = this.___mapCreatePayloadToDetail(payload);
505
+ this.___data = this.___data.concat(newItem);
506
+ return {
507
+ id: newItem.id
508
+ };
509
+ });
510
+ updateOne = this.method('updateOne', async ({ filter, payload })=>{
511
+ const index = this.___data.findIndex((x)=>this.___specificSearchLogic(x, filter));
512
+ this.___data = this.___data.map((x, i)=>{
513
+ if (i !== index) return x;
514
+ return this.___mapUpdatePayloadToDetail(x, payload);
515
+ });
516
+ return {
517
+ success: index > -1
518
+ };
519
+ });
520
+ deleteOne = this.method('deleteOne', async ({ filter })=>{
521
+ const index = this.___data.findIndex((x)=>this.___specificSearchLogic(x, filter));
522
+ this.___data = this.___data.filter((_x, i)=>i !== index);
523
+ return {
524
+ success: index > -1
525
+ };
526
+ });
527
+ }
528
+ return RAMStore;
529
+ };
530
+ exports.Controller = __webpack_exports__.Controller;
531
+ exports.Module = __webpack_exports__.Module;
532
+ exports.Store = __webpack_exports__.Store;
533
+ exports.ValueObjects = __webpack_exports__.ValueObjects;
31
534
  for(var __rspack_i in __webpack_exports__)if (-1 === [
32
- "squared"
535
+ "Controller",
536
+ "Module",
537
+ "Store",
538
+ "ValueObjects"
33
539
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
34
540
  Object.defineProperty(exports, '__esModule', {
35
541
  value: true
package/dist/index.d.ts CHANGED
@@ -1 +1,4 @@
1
- export declare const squared: (n: number) => number;
1
+ export * as Module from './zod-module.utils';
2
+ export * as Controller from './zod-controller.utils';
3
+ export * as Store from './store';
4
+ export * as ValueObjects from './value-objects';