@webtypen/webframez-core 0.3.39 → 0.3.41

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.
package/README.md CHANGED
@@ -297,6 +297,57 @@ Example: `GET /api/backoffice/current-user`.
297
297
 
298
298
  The scope middleware runs before the function. Its return value is passed to the function as `apiRequest.context`. Calling `abort(message, status)` stops execution and returns an error response with that status.
299
299
 
300
+ ### Group ApiScopes
301
+
302
+ Use `ApiScopesGroup` to share middleware across multiple scopes:
303
+
304
+ ```ts
305
+ import { ApiScope, ApiScopesGroup, Request, Response } from "@webtypen/webframez-core";
306
+
307
+ class BackofficeApiScope extends ApiScope {
308
+ key = "backoffice";
309
+ apiBasePath = "/api/backoffice";
310
+ functions = [CurrentUserFunction];
311
+
312
+ async middleware(_req: Request, _res: Response, _abort: (message?: any, status?: number) => never) {
313
+ return {
314
+ scope: "backoffice"
315
+ };
316
+ }
317
+
318
+ async groupMiddleware(_req: Request, _res: Response, _abort: (message?: any, status?: number) => never) {
319
+ return {
320
+ reachedThroughGroup: true
321
+ };
322
+ }
323
+ }
324
+
325
+ class BackofficeApiScopesGroup extends ApiScopesGroup {
326
+ key = "backoffice-group";
327
+ apiScopes = [BackofficeApiScope];
328
+
329
+ async middleware(req: Request, _res: Response, abort: (message?: any, status?: number) => never) {
330
+ if (!req.headers.authorization) {
331
+ return abort("Unauthorized", 401);
332
+ }
333
+
334
+ return {
335
+ user: { id: "..." }
336
+ };
337
+ }
338
+ }
339
+ ```
340
+
341
+ When a scope is reached through a group, middleware runs in this order:
342
+
343
+ ```text
344
+ ApiScopesGroup.middleware()
345
+ ApiScope.middleware()
346
+ ApiScope.groupMiddleware()
347
+ ```
348
+
349
+ The context objects are merged in that order, so later scope-specific values can override group values. `groupMiddleware()` only runs when the scope was registered through an `ApiScopesGroup`.
350
+
300
351
  ### Register ApiScopes
301
352
 
302
353
  Register scopes on the web kernel:
@@ -305,7 +356,7 @@ Register scopes on the web kernel:
305
356
  import { BaseKernelWeb } from "@webtypen/webframez-core";
306
357
 
307
358
  class Kernel extends BaseKernelWeb {
308
- static apiScopes = [BackofficeApiScope];
359
+ static apiScopes = [BackofficeApiScope, BackofficeApiScopesGroup];
309
360
  }
310
361
  ```
311
362
 
@@ -315,7 +366,7 @@ Modules can register scopes as instance properties:
315
366
  import { ModuleProvider } from "@webtypen/webframez-core";
316
367
 
317
368
  class BackofficeModuleProvider extends ModuleProvider {
318
- apiScopes = [BackofficeApiScope];
369
+ apiScopes = [BackofficeApiScope, BackofficeApiScopesGroup];
319
370
  }
320
371
  ```
321
372
 
@@ -4,7 +4,12 @@ import { Request } from "../Router/Request";
4
4
  import { Response } from "../Router/Response";
5
5
  import { ApiFunction } from "./ApiFunction";
6
6
  import { ApiScope } from "./ApiScope";
7
- import { ApiFunctionClass, ApiFunctionParamDefinition, ApiFunctionParamsDefinition, ApiScopeClass } from "./ApiTypes";
7
+ import { ApiScopesGroup } from "./ApiScopesGroup";
8
+ import { ApiFunctionClass, ApiFunctionParamDefinition, ApiFunctionParamsDefinition, ApiScopeClass, ApiScopeRegistrationClass, ApiScopesGroupClass } from "./ApiTypes";
9
+ export type ApiScopeRegistrationEntry = {
10
+ scopeClass: ApiScopeClass;
11
+ groupClass?: ApiScopesGroupClass;
12
+ };
8
13
  export declare class ApiFunctionRuntimeError extends Error {
9
14
  statusCode: number;
10
15
  constructor(message: string, statusCode?: number);
@@ -15,9 +20,22 @@ export declare function getApiErrorMessage(error: any): any;
15
20
  export declare function isPlainApiObject(value: any): boolean;
16
21
  export declare function normalizeApiFunctionProvider(provider: any): ApiFunctionClass[];
17
22
  export declare function getApiFunctionClasses(scope: ApiScope): ApiFunctionClass[];
23
+ export declare function normalizeApiScopesGroupProvider(provider: any): ApiScopeClass[];
24
+ export declare function isApiScopesGroupInstance(value: any): value is ApiScopesGroup;
25
+ export declare function instantiateApiScopesGroup(GroupClass: ApiScopesGroupClass): ApiScopesGroup;
26
+ export declare function collectApiScopeRegistrations(registrations: ApiScopeRegistrationClass[]): ApiScopeRegistrationEntry[];
18
27
  export declare function runApiScopeMiddleware(scope: ApiScope, req: Request, res: Response): Promise<{
19
28
  [key: string]: any;
20
29
  }>;
30
+ export declare function runApiScopesGroupMiddleware(group: ApiScopesGroup, req: Request, res: Response): Promise<{
31
+ [key: string]: any;
32
+ }>;
33
+ export declare function runApiScopeGroupMiddleware(scope: ApiScope, req: Request, res: Response): Promise<{
34
+ [key: string]: any;
35
+ }>;
36
+ export declare function runApiScopeRegistrationMiddleware(registration: ApiScopeRegistrationEntry, req: Request, res: Response): Promise<{
37
+ [x: string]: any;
38
+ }>;
21
39
  export declare function validateApiFunctionParams(definitions: ApiFunctionParamsDefinition, source: {
22
40
  [key: string]: any;
23
41
  }): {
@@ -9,9 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.instantiateApiFunction = exports.instantiateApiScope = exports.assertUniqueApiFunctionKeys = exports.createApiFrameworkRequest = exports.toApiFunctionPayload = exports.toApiFunctionHttpResult = exports.apiFunctionParamToJsonSchema = exports.apiFunctionParamsToJsonSchema = exports.coerceApiFunctionParam = exports.validateApiFunctionParams = exports.runApiScopeMiddleware = exports.getApiFunctionClasses = exports.normalizeApiFunctionProvider = exports.isPlainApiObject = exports.getApiErrorMessage = exports.joinApiPath = exports.normalizeApiPath = exports.ApiFunctionRuntimeError = void 0;
12
+ exports.instantiateApiFunction = exports.instantiateApiScope = exports.assertUniqueApiFunctionKeys = exports.createApiFrameworkRequest = exports.toApiFunctionPayload = exports.toApiFunctionHttpResult = exports.apiFunctionParamToJsonSchema = exports.apiFunctionParamsToJsonSchema = exports.coerceApiFunctionParam = exports.validateApiFunctionParams = exports.runApiScopeRegistrationMiddleware = exports.runApiScopeGroupMiddleware = exports.runApiScopesGroupMiddleware = exports.runApiScopeMiddleware = exports.collectApiScopeRegistrations = exports.instantiateApiScopesGroup = exports.isApiScopesGroupInstance = exports.normalizeApiScopesGroupProvider = exports.getApiFunctionClasses = exports.normalizeApiFunctionProvider = exports.isPlainApiObject = exports.getApiErrorMessage = exports.joinApiPath = exports.normalizeApiPath = exports.ApiFunctionRuntimeError = void 0;
13
13
  const Request_1 = require("../Router/Request");
14
14
  const ApiFunction_1 = require("./ApiFunction");
15
+ const ApiScopesGroup_1 = require("./ApiScopesGroup");
15
16
  class ApiFunctionRuntimeError extends Error {
16
17
  constructor(message, statusCode = 500) {
17
18
  super(message);
@@ -68,16 +69,92 @@ function getApiFunctionClasses(scope) {
68
69
  return functions;
69
70
  }
70
71
  exports.getApiFunctionClasses = getApiFunctionClasses;
72
+ function createApiScopeMiddlewareAbort() {
73
+ const abort = (message, status = 403) => {
74
+ throw new ApiFunctionRuntimeError(getApiErrorMessage(message || "Request aborted"), status);
75
+ };
76
+ return abort;
77
+ }
78
+ function normalizeApiScopesGroupProvider(provider) {
79
+ if (typeof provider === "function") {
80
+ const resolved = provider();
81
+ if (resolved && typeof resolved.then === "function") {
82
+ throw new Error("Async ApiScopesGroup.apiScopes providers are not supported during web boot");
83
+ }
84
+ return Array.isArray(resolved) ? resolved : [];
85
+ }
86
+ return Array.isArray(provider) ? provider : [];
87
+ }
88
+ exports.normalizeApiScopesGroupProvider = normalizeApiScopesGroupProvider;
89
+ function isApiScopesGroupInstance(value) {
90
+ return value instanceof ApiScopesGroup_1.ApiScopesGroup;
91
+ }
92
+ exports.isApiScopesGroupInstance = isApiScopesGroupInstance;
93
+ function instantiateApiScopesGroup(GroupClass) {
94
+ return new GroupClass();
95
+ }
96
+ exports.instantiateApiScopesGroup = instantiateApiScopesGroup;
97
+ function collectApiScopeRegistrations(registrations) {
98
+ const entries = [];
99
+ for (const RegistrationClass of registrations || []) {
100
+ if (typeof RegistrationClass !== "function") {
101
+ continue;
102
+ }
103
+ const registration = new RegistrationClass();
104
+ if (isApiScopesGroupInstance(registration)) {
105
+ for (const ScopeClass of normalizeApiScopesGroupProvider(registration.apiScopes)) {
106
+ if (typeof ScopeClass === "function") {
107
+ entries.push({
108
+ scopeClass: ScopeClass,
109
+ groupClass: RegistrationClass,
110
+ });
111
+ }
112
+ }
113
+ continue;
114
+ }
115
+ entries.push({
116
+ scopeClass: RegistrationClass,
117
+ });
118
+ }
119
+ return entries;
120
+ }
121
+ exports.collectApiScopeRegistrations = collectApiScopeRegistrations;
71
122
  function runApiScopeMiddleware(scope, req, res) {
72
123
  return __awaiter(this, void 0, void 0, function* () {
73
- const abort = (message, status = 403) => {
74
- throw new ApiFunctionRuntimeError(getApiErrorMessage(message || "Request aborted"), status);
75
- };
124
+ const abort = createApiScopeMiddlewareAbort();
76
125
  const result = yield scope.middleware(req, res, abort);
77
126
  return isPlainApiObject(result) ? result : {};
78
127
  });
79
128
  }
80
129
  exports.runApiScopeMiddleware = runApiScopeMiddleware;
130
+ function runApiScopesGroupMiddleware(group, req, res) {
131
+ return __awaiter(this, void 0, void 0, function* () {
132
+ const abort = createApiScopeMiddlewareAbort();
133
+ const result = yield group.middleware(req, res, abort);
134
+ return isPlainApiObject(result) ? result : {};
135
+ });
136
+ }
137
+ exports.runApiScopesGroupMiddleware = runApiScopesGroupMiddleware;
138
+ function runApiScopeGroupMiddleware(scope, req, res) {
139
+ return __awaiter(this, void 0, void 0, function* () {
140
+ const abort = createApiScopeMiddlewareAbort();
141
+ const result = yield scope.groupMiddleware(req, res, abort);
142
+ return isPlainApiObject(result) ? result : {};
143
+ });
144
+ }
145
+ exports.runApiScopeGroupMiddleware = runApiScopeGroupMiddleware;
146
+ function runApiScopeRegistrationMiddleware(registration, req, res) {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ const groupContext = registration.groupClass
149
+ ? yield runApiScopesGroupMiddleware(instantiateApiScopesGroup(registration.groupClass), req, res)
150
+ : {};
151
+ const scope = instantiateApiScope(registration.scopeClass);
152
+ const scopeContext = yield runApiScopeMiddleware(scope, req, res);
153
+ const groupScopeContext = registration.groupClass ? yield runApiScopeGroupMiddleware(scope, req, res) : {};
154
+ return Object.assign(Object.assign(Object.assign({}, groupContext), scopeContext), groupScopeContext);
155
+ });
156
+ }
157
+ exports.runApiScopeRegistrationMiddleware = runApiScopeRegistrationMiddleware;
81
158
  function validateApiFunctionParams(definitions, source) {
82
159
  const params = {};
83
160
  const input = isPlainApiObject(source) ? source : {};
@@ -9,4 +9,7 @@ export declare class ApiScope {
9
9
  middleware(_req: Request, _res: Response, _abort: ApiScopeMiddlewareAbort): Promise<{
10
10
  [key: string]: any;
11
11
  }>;
12
+ groupMiddleware(_req: Request, _res: Response, _abort: ApiScopeMiddlewareAbort): Promise<{
13
+ [key: string]: any;
14
+ }>;
12
15
  }
@@ -22,5 +22,10 @@ class ApiScope {
22
22
  return {};
23
23
  });
24
24
  }
25
+ groupMiddleware(_req, _res, _abort) {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ return {};
28
+ });
29
+ }
25
30
  }
26
31
  exports.ApiScope = ApiScope;
@@ -1,4 +1,4 @@
1
- import { ApiScopeClass } from "./ApiTypes";
1
+ import { ApiScopeRegistrationEntry } from "./ApiFunctionUtils";
2
2
  type ApiScopeRuntimeContext = {
3
3
  kernel?: any;
4
4
  modulesLoader?: any;
@@ -6,7 +6,7 @@ type ApiScopeRuntimeContext = {
6
6
  declare class ApiScopeRegistryFacade {
7
7
  private context;
8
8
  configure(context?: ApiScopeRuntimeContext): this;
9
- collect(context?: ApiScopeRuntimeContext): ApiScopeClass[];
9
+ collect(context?: ApiScopeRuntimeContext): ApiScopeRegistrationEntry[];
10
10
  register(context?: ApiScopeRuntimeContext): this;
11
11
  private registerHttpRoutes;
12
12
  private registerRouteMethod;
@@ -46,19 +46,19 @@ class ApiScopeRegistryFacade {
46
46
  : [];
47
47
  scopes.push(...moduleScopes);
48
48
  }
49
- return scopes.filter((scopeClass) => typeof scopeClass === "function");
49
+ return (0, ApiFunctionUtils_1.collectApiScopeRegistrations)(scopes);
50
50
  }
51
51
  register(context) {
52
52
  this.configure(context);
53
53
  const scopes = this.collect(context);
54
54
  this.assertUniqueApiPaths(scopes);
55
- for (const ScopeClass of scopes) {
56
- this.registerHttpRoutes(ScopeClass);
55
+ for (const registration of scopes) {
56
+ this.registerHttpRoutes(registration);
57
57
  }
58
58
  return this;
59
59
  }
60
- registerHttpRoutes(ScopeClass) {
61
- const scope = (0, ApiFunctionUtils_1.instantiateApiScope)(ScopeClass);
60
+ registerHttpRoutes(registration) {
61
+ const scope = (0, ApiFunctionUtils_1.instantiateApiScope)(registration.scopeClass);
62
62
  if (!scope.apiBasePath) {
63
63
  return;
64
64
  }
@@ -69,7 +69,7 @@ class ApiScopeRegistryFacade {
69
69
  }
70
70
  const path = (0, ApiFunctionUtils_1.joinApiPath)(scope.apiBasePath, func.key);
71
71
  const handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
72
- return yield this.handleHttpFunction(ScopeClass, FunctionClass, req, res);
72
+ return yield this.handleHttpFunction(registration, FunctionClass, req, res);
73
73
  });
74
74
  this.registerRouteMethod(func.requestMethod, path, handler);
75
75
  }
@@ -85,12 +85,11 @@ class ApiScopeRegistryFacade {
85
85
  }
86
86
  routeMethod.bind(Route_1.Route)(path, handler);
87
87
  }
88
- handleHttpFunction(ScopeClass, FunctionClass, req, res) {
88
+ handleHttpFunction(registration, FunctionClass, req, res) {
89
89
  return __awaiter(this, void 0, void 0, function* () {
90
- const scope = (0, ApiFunctionUtils_1.instantiateApiScope)(ScopeClass);
91
90
  const func = (0, ApiFunctionUtils_1.instantiateApiFunction)(FunctionClass);
92
91
  try {
93
- const context = yield (0, ApiFunctionUtils_1.runApiScopeMiddleware)(scope, req, res);
92
+ const context = yield (0, ApiFunctionUtils_1.runApiScopeRegistrationMiddleware)(registration, req, res);
94
93
  const paramsSource = (func.requestMethod || req.method).toUpperCase() === "GET" ? req.query : req.body;
95
94
  const params = (0, ApiFunctionUtils_1.validateApiFunctionParams)(func.params || {}, paramsSource || {});
96
95
  const result = yield func.handle({ context, params, request: req, response: res });
@@ -107,8 +106,8 @@ class ApiScopeRegistryFacade {
107
106
  }
108
107
  assertUniqueApiPaths(scopes) {
109
108
  const seen = {};
110
- for (const ScopeClass of scopes) {
111
- const scope = (0, ApiFunctionUtils_1.instantiateApiScope)(ScopeClass);
109
+ for (const registration of scopes) {
110
+ const scope = (0, ApiFunctionUtils_1.instantiateApiScope)(registration.scopeClass);
112
111
  if (!scope.apiBasePath) {
113
112
  continue;
114
113
  }
@@ -0,0 +1,10 @@
1
+ import { Request } from "../Router/Request";
2
+ import { Response } from "../Router/Response";
3
+ import { ApiScopeClass, ApiScopeMiddlewareAbort } from "./ApiTypes";
4
+ export declare class ApiScopesGroup {
5
+ key: string;
6
+ apiScopes: Array<ApiScopeClass> | (() => Array<ApiScopeClass>);
7
+ middleware(_req: Request, _res: Response, _abort: ApiScopeMiddlewareAbort): Promise<{
8
+ [key: string]: any;
9
+ }>;
10
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ApiScopesGroup = void 0;
13
+ class ApiScopesGroup {
14
+ constructor() {
15
+ this.key = "unique_api_scopes_group_key";
16
+ this.apiScopes = [];
17
+ }
18
+ middleware(_req, _res, _abort) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ return {};
21
+ });
22
+ }
23
+ }
24
+ exports.ApiScopesGroup = ApiScopesGroup;
@@ -22,6 +22,8 @@ export type ApiFunctionParamsDefinition = {
22
22
  };
23
23
  export type ApiFunctionClass = new (...args: any[]) => any;
24
24
  export type ApiScopeClass = new (...args: any[]) => any;
25
+ export type ApiScopesGroupClass = new (...args: any[]) => any;
26
+ export type ApiScopeRegistrationClass = ApiScopeClass | ApiScopesGroupClass;
25
27
  export type ApiScopeMiddlewareAbort = (message?: any, status?: number) => never;
26
28
  export type ApiFunctionRequest = {
27
29
  context: ApiScopeFunctionContext;
@@ -1,7 +1,7 @@
1
1
  import { Controller } from "./Controller/Controller";
2
2
  import { KernelAiRegistrations } from "./Ai/AiTypes";
3
3
  import { KernelMcpRegistrations } from "./Mcp/McpTypes";
4
- import { ApiScopeClass } from "./Api/ApiTypes";
4
+ import { ApiScopeRegistrationClass } from "./Api/ApiTypes";
5
5
  export declare class BaseKernelWeb {
6
6
  static controller: {
7
7
  [key: string]: Controller;
@@ -9,7 +9,7 @@ export declare class BaseKernelWeb {
9
9
  static middleware: {
10
10
  [key: string]: any;
11
11
  };
12
- static apiScopes: ApiScopeClass[];
12
+ static apiScopes: ApiScopeRegistrationClass[];
13
13
  static mcp?: KernelMcpRegistrations;
14
14
  static ai?: KernelAiRegistrations;
15
15
  }
@@ -57,6 +57,11 @@ export declare class Datatable {
57
57
  entries: any;
58
58
  sums: any;
59
59
  }>;
60
+ stats(req: Request): Promise<Array<{
61
+ label: string;
62
+ type: string;
63
+ value: any;
64
+ }>>;
60
65
  getTotalData(req: Request): Promise<any>;
61
66
  getFilter(req: Request): Promise<any>;
62
67
  getColumns(req: Request): Promise<any>;
@@ -312,6 +312,11 @@ class Datatable {
312
312
  return data;
313
313
  });
314
314
  }
315
+ stats(req) {
316
+ return __awaiter(this, void 0, void 0, function* () {
317
+ return [];
318
+ });
319
+ }
315
320
  getTotalData(req) {
316
321
  return __awaiter(this, void 0, void 0, function* () {
317
322
  const aggregation = [];
@@ -43,6 +43,12 @@ class DatatableController extends Controller_1.Controller {
43
43
  });
44
44
  }
45
45
  const table = new tableClass();
46
+ if (req.body.type === "stats" || req.body.mode === "stats") {
47
+ return res.send({
48
+ status: "success",
49
+ data: yield table.stats(req),
50
+ });
51
+ }
46
52
  if (req.body.apiFunction && typeof req.body.apiFunction === "string" && req.body.apiFunction.trim() !== "") {
47
53
  const func = (_a = table.selectableFunctions) === null || _a === void 0 ? void 0 : _a[req.body.apiFunction];
48
54
  if (!func || !func.handle) {
@@ -1,5 +1,5 @@
1
1
  import { KernelAiRegistrations } from "../Ai/AiTypes";
2
- import { ApiScopeClass } from "../Api/ApiTypes";
2
+ import { ApiScopeRegistrationClass } from "../Api/ApiTypes";
3
3
  import { KernelMcpRegistrations } from "../Mcp/McpTypes";
4
4
  export declare class ModuleProvider {
5
5
  static key: string;
@@ -9,7 +9,7 @@ export declare class ModuleProvider {
9
9
  middleware: {
10
10
  [key: string]: any;
11
11
  };
12
- apiScopes: ApiScopeClass[];
12
+ apiScopes: ApiScopeRegistrationClass[];
13
13
  commands: any[];
14
14
  mcp?: KernelMcpRegistrations;
15
15
  ai?: KernelAiRegistrations;
package/dist/index.d.ts CHANGED
@@ -43,6 +43,7 @@ export * from "./Hooks/WebframezHooks";
43
43
  export * from "./Api/ApiTypes";
44
44
  export * from "./Api/ApiFunction";
45
45
  export * from "./Api/ApiScope";
46
+ export * from "./Api/ApiScopesGroup";
46
47
  export * from "./Api/ApiFunctionUtils";
47
48
  export * from "./Api/ApiScopeRegistry";
48
49
  export * from "./Ai/AiTypes";
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ __exportStar(require("./Hooks/WebframezHooks"), exports);
59
59
  __exportStar(require("./Api/ApiTypes"), exports);
60
60
  __exportStar(require("./Api/ApiFunction"), exports);
61
61
  __exportStar(require("./Api/ApiScope"), exports);
62
+ __exportStar(require("./Api/ApiScopesGroup"), exports);
62
63
  __exportStar(require("./Api/ApiFunctionUtils"), exports);
63
64
  __exportStar(require("./Api/ApiScopeRegistry"), exports);
64
65
  __exportStar(require("./Ai/AiTypes"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-core",
3
- "version": "0.3.39",
3
+ "version": "0.3.41",
4
4
  "description": "The core package of the typescript based webframez (web-framework) by webtypen.de",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "license": "MIT",