@ruiapp/rapid-core 0.1.2 → 0.1.3

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,3 +1,290 @@
1
- import { RpdApplicationConfig } from "./types";
2
- declare const _default: RpdApplicationConfig;
1
+ declare const _default: {
2
+ code: string;
3
+ name: string;
4
+ models: ({
5
+ maintainedBy: string;
6
+ namespace: string;
7
+ name: string;
8
+ singularCode: string;
9
+ pluralCode: string;
10
+ schema: string;
11
+ tableName: string;
12
+ properties: ({
13
+ name: string;
14
+ code: string;
15
+ columnName: string;
16
+ type: "integer";
17
+ required: true;
18
+ autoIncrement: true;
19
+ relation?: undefined;
20
+ targetSingularCode?: undefined;
21
+ targetIdColumnName?: undefined;
22
+ defaultValue?: undefined;
23
+ } | {
24
+ name: string;
25
+ code: string;
26
+ type: "relation";
27
+ required: true;
28
+ relation: "one";
29
+ targetSingularCode: string;
30
+ targetIdColumnName: string;
31
+ columnName?: undefined;
32
+ autoIncrement?: undefined;
33
+ defaultValue?: undefined;
34
+ } | {
35
+ name: string;
36
+ code: string;
37
+ columnName: string;
38
+ type: "text";
39
+ required: true;
40
+ autoIncrement?: undefined;
41
+ relation?: undefined;
42
+ targetSingularCode?: undefined;
43
+ targetIdColumnName?: undefined;
44
+ defaultValue?: undefined;
45
+ } | {
46
+ name: string;
47
+ code: string;
48
+ columnName: string;
49
+ type: "text";
50
+ required: false;
51
+ autoIncrement?: undefined;
52
+ relation?: undefined;
53
+ targetSingularCode?: undefined;
54
+ targetIdColumnName?: undefined;
55
+ defaultValue?: undefined;
56
+ } | {
57
+ name: string;
58
+ code: string;
59
+ columnName: string;
60
+ type: "boolean";
61
+ required: true;
62
+ defaultValue: string;
63
+ autoIncrement?: undefined;
64
+ relation?: undefined;
65
+ targetSingularCode?: undefined;
66
+ targetIdColumnName?: undefined;
67
+ } | {
68
+ name: string;
69
+ code: string;
70
+ columnName: string;
71
+ type: "json";
72
+ required: false;
73
+ autoIncrement?: undefined;
74
+ relation?: undefined;
75
+ targetSingularCode?: undefined;
76
+ targetIdColumnName?: undefined;
77
+ defaultValue?: undefined;
78
+ } | {
79
+ name: string;
80
+ code: string;
81
+ columnName: string;
82
+ type: "integer";
83
+ required: false;
84
+ autoIncrement?: undefined;
85
+ relation?: undefined;
86
+ targetSingularCode?: undefined;
87
+ targetIdColumnName?: undefined;
88
+ defaultValue?: undefined;
89
+ })[];
90
+ } | {
91
+ maintainedBy: string;
92
+ namespace: string;
93
+ name: string;
94
+ singularCode: string;
95
+ pluralCode: string;
96
+ schema: string;
97
+ tableName: string;
98
+ properties: ({
99
+ name: string;
100
+ code: string;
101
+ columnName: string;
102
+ type: "integer";
103
+ required: true;
104
+ autoIncrement: true;
105
+ defaultValue?: undefined;
106
+ relation?: undefined;
107
+ targetSingularCode?: undefined;
108
+ selfIdColumnName?: undefined;
109
+ } | {
110
+ name: string;
111
+ code: string;
112
+ columnName: string;
113
+ type: "text";
114
+ required: true;
115
+ autoIncrement?: undefined;
116
+ defaultValue?: undefined;
117
+ relation?: undefined;
118
+ targetSingularCode?: undefined;
119
+ selfIdColumnName?: undefined;
120
+ } | {
121
+ name: string;
122
+ code: string;
123
+ columnName: string;
124
+ type: "text";
125
+ required: false;
126
+ defaultValue: string;
127
+ autoIncrement?: undefined;
128
+ relation?: undefined;
129
+ targetSingularCode?: undefined;
130
+ selfIdColumnName?: undefined;
131
+ } | {
132
+ name: string;
133
+ code: string;
134
+ columnName: string;
135
+ type: "text";
136
+ required: false;
137
+ autoIncrement?: undefined;
138
+ defaultValue?: undefined;
139
+ relation?: undefined;
140
+ targetSingularCode?: undefined;
141
+ selfIdColumnName?: undefined;
142
+ } | {
143
+ name: string;
144
+ code: string;
145
+ columnName: string;
146
+ type: "json";
147
+ required: false;
148
+ autoIncrement?: undefined;
149
+ defaultValue?: undefined;
150
+ relation?: undefined;
151
+ targetSingularCode?: undefined;
152
+ selfIdColumnName?: undefined;
153
+ } | {
154
+ name: string;
155
+ code: string;
156
+ type: "relation[]";
157
+ relation: "many";
158
+ targetSingularCode: string;
159
+ selfIdColumnName: string;
160
+ columnName?: undefined;
161
+ required?: undefined;
162
+ autoIncrement?: undefined;
163
+ defaultValue?: undefined;
164
+ })[];
165
+ } | {
166
+ maintainedBy: string;
167
+ namespace: string;
168
+ name: string;
169
+ singularCode: string;
170
+ pluralCode: string;
171
+ schema: string;
172
+ tableName: string;
173
+ properties: ({
174
+ name: string;
175
+ code: string;
176
+ columnName: string;
177
+ type: "integer";
178
+ required: true;
179
+ autoIncrement: true;
180
+ relation?: undefined;
181
+ targetSingularCode?: undefined;
182
+ targetIdColumnName?: undefined;
183
+ defaultValue?: undefined;
184
+ } | {
185
+ name: string;
186
+ code: string;
187
+ type: "relation";
188
+ relation: "one";
189
+ targetSingularCode: string;
190
+ targetIdColumnName: string;
191
+ columnName?: undefined;
192
+ required?: undefined;
193
+ autoIncrement?: undefined;
194
+ defaultValue?: undefined;
195
+ } | {
196
+ name: string;
197
+ code: string;
198
+ columnName: string;
199
+ type: "integer";
200
+ required: true;
201
+ defaultValue: string;
202
+ autoIncrement?: undefined;
203
+ relation?: undefined;
204
+ targetSingularCode?: undefined;
205
+ targetIdColumnName?: undefined;
206
+ } | {
207
+ name: string;
208
+ code: string;
209
+ columnName: string;
210
+ type: "text";
211
+ required: true;
212
+ autoIncrement?: undefined;
213
+ relation?: undefined;
214
+ targetSingularCode?: undefined;
215
+ targetIdColumnName?: undefined;
216
+ defaultValue?: undefined;
217
+ } | {
218
+ name: string;
219
+ code: string;
220
+ columnName: string;
221
+ type: "text";
222
+ required: false;
223
+ autoIncrement?: undefined;
224
+ relation?: undefined;
225
+ targetSingularCode?: undefined;
226
+ targetIdColumnName?: undefined;
227
+ defaultValue?: undefined;
228
+ } | {
229
+ name: string;
230
+ code: string;
231
+ columnName: string;
232
+ type: "boolean";
233
+ required: false;
234
+ autoIncrement?: undefined;
235
+ relation?: undefined;
236
+ targetSingularCode?: undefined;
237
+ targetIdColumnName?: undefined;
238
+ defaultValue?: undefined;
239
+ })[];
240
+ } | {
241
+ maintainedBy: string;
242
+ namespace: string;
243
+ name: string;
244
+ singularCode: string;
245
+ pluralCode: string;
246
+ schema: string;
247
+ tableName: string;
248
+ properties: ({
249
+ name: string;
250
+ code: string;
251
+ columnName: string;
252
+ type: "integer";
253
+ required: true;
254
+ autoIncrement: true;
255
+ } | {
256
+ name: string;
257
+ code: string;
258
+ columnName: string;
259
+ type: "text";
260
+ required: true;
261
+ autoIncrement?: undefined;
262
+ } | {
263
+ name: string;
264
+ code: string;
265
+ columnName: string;
266
+ type: "text";
267
+ required: false;
268
+ autoIncrement?: undefined;
269
+ } | {
270
+ name: string;
271
+ code: string;
272
+ columnName: string;
273
+ type: "json";
274
+ required: true;
275
+ autoIncrement?: undefined;
276
+ })[];
277
+ })[];
278
+ routes: {
279
+ namespace: string;
280
+ name: string;
281
+ code: string;
282
+ type: "RESTful";
283
+ method: "GET";
284
+ endpoint: string;
285
+ handlers: {
286
+ code: string;
287
+ }[];
288
+ }[];
289
+ };
3
290
  export default _default;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CREDIT: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727
3
+ * Encodes a given Uint8Array, ArrayBuffer or string into RFC4648 base64 representation
4
+ * @param data
5
+ */
6
+ export declare function encode(data: ArrayBuffer | string): string;
7
+ /**
8
+ * Decodes a given RFC4648 base64 encoded string
9
+ * @param b64
10
+ */
11
+ export declare function decode(b64: string): Uint8Array;
package/dist/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from "./server";
3
3
  export * from "./core/request";
4
4
  export * from "./core/routeContext";
5
5
  export * from "./core/server";
6
+ export * from "./utilities/jwtUtility";
6
7
  export * as bootstrapApplicationConfig from "./bootstrapApplicationConfig";
package/dist/index.js CHANGED
@@ -5,6 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var _ = require('lodash');
6
6
  var Router = require('koa-tree-router');
7
7
  var qs = require('qs');
8
+ var jsonwebtoken = require('jsonwebtoken');
9
+ var crypto = require('crypto');
8
10
  var events = require('events');
9
11
 
10
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -30,6 +32,7 @@ function _interopNamespace(e) {
30
32
  var ___namespace = /*#__PURE__*/_interopNamespace(_);
31
33
  var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
32
34
  var qs__default = /*#__PURE__*/_interopDefaultLegacy(qs);
35
+ var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
33
36
 
34
37
  function fixBigIntJSONSerialize() {
35
38
  BigInt.prototype.toJSON = function () {
@@ -1650,7 +1653,6 @@ async function handler$7(plugin, ctx, options) {
1650
1653
  if (!row) {
1651
1654
  throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
1652
1655
  }
1653
- console.log(mergedInput);
1654
1656
  const relationProperty = model.properties.find(e => e.code === property);
1655
1657
  if (!relationProperty) {
1656
1658
  throw new Error(`Property '${property}' was not found in ${options.namespace}.${options.singularCode}`);
@@ -1772,55 +1774,55 @@ const configurations$3 = [];
1772
1774
  const routeConfigs = [
1773
1775
  {
1774
1776
  code: "createBatch",
1775
- method: "post",
1777
+ method: "POST",
1776
1778
  endpoint: "/operations/create_batch",
1777
1779
  handlerCode: "createCollectionEntitiesBatch",
1778
1780
  },
1779
1781
  {
1780
1782
  code: "find",
1781
- method: "post",
1783
+ method: "POST",
1782
1784
  endpoint: "/operations/find",
1783
1785
  handlerCode: "findCollectionEntities",
1784
1786
  },
1785
1787
  {
1786
1788
  code: "count",
1787
- method: "post",
1789
+ method: "POST",
1788
1790
  endpoint: "/operations/count",
1789
1791
  handlerCode: "countCollectionEntities",
1790
1792
  },
1791
1793
  {
1792
1794
  code: "addRelations",
1793
- method: "post",
1795
+ method: "POST",
1794
1796
  endpoint: "/operations/add_relations",
1795
1797
  handlerCode: "addEntityRelations",
1796
1798
  },
1797
1799
  {
1798
1800
  code: "removeRelations",
1799
- method: "post",
1801
+ method: "POST",
1800
1802
  endpoint: "/operations/remove_relations",
1801
1803
  handlerCode: "removeEntityRelations",
1802
1804
  },
1803
1805
  {
1804
1806
  code: "getById",
1805
- method: "get",
1807
+ method: "GET",
1806
1808
  endpoint: "/:id",
1807
1809
  handlerCode: "findCollectionEntityById",
1808
1810
  },
1809
1811
  {
1810
1812
  code: "create",
1811
- method: "post",
1813
+ method: "POST",
1812
1814
  endpoint: "",
1813
1815
  handlerCode: "createCollectionEntity",
1814
1816
  },
1815
1817
  {
1816
1818
  code: "updateById",
1817
- method: "patch",
1819
+ method: "PATCH",
1818
1820
  endpoint: "/:id",
1819
1821
  handlerCode: "updateCollectionEntityById",
1820
1822
  },
1821
1823
  {
1822
1824
  code: "deleteById",
1823
- method: "delete",
1825
+ method: "DELETE",
1824
1826
  endpoint: "/:id",
1825
1827
  handlerCode: "deleteCollectionEntityById",
1826
1828
  },
@@ -1975,7 +1977,7 @@ async function buildRoutes(server, applicationConfig) {
1975
1977
  return;
1976
1978
  }
1977
1979
  const routePath = baseUrl + routeConfig.endpoint;
1978
- router[routeConfig.method](routePath, async (routerContext, next) => {
1980
+ router[routeConfig.method.toLowerCase()](routePath, async (routerContext, next) => {
1979
1981
  const { request, params } = routerContext;
1980
1982
  let search = request.url.search;
1981
1983
  if (search && search.startsWith("?")) {
@@ -2478,8 +2480,151 @@ function setCookie(headers, cookie) {
2478
2480
  }
2479
2481
  }
2480
2482
 
2481
- async function createJWT(payload) {
2482
- return "";
2483
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2484
+ // This module is browser compatible.
2485
+ /**
2486
+ * {@linkcode encode} and {@linkcode decode} for
2487
+ * [base64](https://en.wikipedia.org/wiki/Base64) encoding.
2488
+ *
2489
+ * This module is browser compatible.
2490
+ *
2491
+ * @example
2492
+ * ```ts
2493
+ * import {
2494
+ * decode,
2495
+ * encode,
2496
+ * } from "https://deno.land/std@$STD_VERSION/encoding/base64.ts";
2497
+ *
2498
+ * const b64Repr = "Zm9vYg==";
2499
+ *
2500
+ * const binaryData = decode(b64Repr);
2501
+ * console.log(binaryData);
2502
+ * // => Uint8Array [ 102, 111, 111, 98 ]
2503
+ *
2504
+ * console.log(encode(binaryData));
2505
+ * // => Zm9vYg==
2506
+ * ```
2507
+ *
2508
+ * @module
2509
+ */
2510
+ const base64abc = [
2511
+ "A",
2512
+ "B",
2513
+ "C",
2514
+ "D",
2515
+ "E",
2516
+ "F",
2517
+ "G",
2518
+ "H",
2519
+ "I",
2520
+ "J",
2521
+ "K",
2522
+ "L",
2523
+ "M",
2524
+ "N",
2525
+ "O",
2526
+ "P",
2527
+ "Q",
2528
+ "R",
2529
+ "S",
2530
+ "T",
2531
+ "U",
2532
+ "V",
2533
+ "W",
2534
+ "X",
2535
+ "Y",
2536
+ "Z",
2537
+ "a",
2538
+ "b",
2539
+ "c",
2540
+ "d",
2541
+ "e",
2542
+ "f",
2543
+ "g",
2544
+ "h",
2545
+ "i",
2546
+ "j",
2547
+ "k",
2548
+ "l",
2549
+ "m",
2550
+ "n",
2551
+ "o",
2552
+ "p",
2553
+ "q",
2554
+ "r",
2555
+ "s",
2556
+ "t",
2557
+ "u",
2558
+ "v",
2559
+ "w",
2560
+ "x",
2561
+ "y",
2562
+ "z",
2563
+ "0",
2564
+ "1",
2565
+ "2",
2566
+ "3",
2567
+ "4",
2568
+ "5",
2569
+ "6",
2570
+ "7",
2571
+ "8",
2572
+ "9",
2573
+ "+",
2574
+ "/",
2575
+ ];
2576
+ /**
2577
+ * CREDIT: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727
2578
+ * Encodes a given Uint8Array, ArrayBuffer or string into RFC4648 base64 representation
2579
+ * @param data
2580
+ */
2581
+ function encode(data) {
2582
+ const uint8 = typeof data === "string"
2583
+ ? new TextEncoder().encode(data)
2584
+ : data instanceof Uint8Array
2585
+ ? data
2586
+ : new Uint8Array(data);
2587
+ let result = "", i;
2588
+ const l = uint8.length;
2589
+ for (i = 2; i < l; i += 3) {
2590
+ result += base64abc[uint8[i - 2] >> 2];
2591
+ result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];
2592
+ result += base64abc[((uint8[i - 1] & 0x0f) << 2) | (uint8[i] >> 6)];
2593
+ result += base64abc[uint8[i] & 0x3f];
2594
+ }
2595
+ if (i === l + 1) {
2596
+ // 1 octet yet to write
2597
+ result += base64abc[uint8[i - 2] >> 2];
2598
+ result += base64abc[(uint8[i - 2] & 0x03) << 4];
2599
+ result += "==";
2600
+ }
2601
+ if (i === l) {
2602
+ // 2 octets yet to write
2603
+ result += base64abc[uint8[i - 2] >> 2];
2604
+ result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];
2605
+ result += base64abc[(uint8[i - 1] & 0x0f) << 2];
2606
+ result += "=";
2607
+ }
2608
+ return result;
2609
+ }
2610
+
2611
+ function createJwt(payload, secret) {
2612
+ return jsonwebtoken.sign(payload, secret, {
2613
+ algorithm: 'HS512',
2614
+ });
2615
+ }
2616
+ function verifyJwt(token, secret) {
2617
+ return jsonwebtoken.verify(token, secret, {
2618
+ algorithms: ['HS512'],
2619
+ });
2620
+ }
2621
+ function decodeJwt(token) {
2622
+ return jsonwebtoken.decode(token, { complete: true });
2623
+ }
2624
+ async function generateJwtSecretKey() {
2625
+ const key = await crypto__default["default"].subtle.generateKey({ name: "HMAC", hash: "SHA-512" }, true, ["sign", "verify"]);
2626
+ const exportedKey = await crypto__default["default"].subtle.exportKey("raw", key);
2627
+ return encode(exportedKey);
2483
2628
  }
2484
2629
 
2485
2630
  const code$3 = "createSession";
@@ -2502,13 +2647,14 @@ async function handler$2(plugin, ctx, options) {
2502
2647
  if (!user) {
2503
2648
  throw new Error("Wrong account or password.");
2504
2649
  }
2505
- const token = await createJWT({
2650
+ const secretKey = Buffer.from(server.config.jwtKey, "base64");
2651
+ const token = createJwt({
2506
2652
  iss: "authManager",
2507
2653
  sub: "userAccessToken",
2508
2654
  aud: "" + user.id,
2509
2655
  iat: new Date,
2510
2656
  act: user.login,
2511
- });
2657
+ }, secretKey);
2512
2658
  setCookie(response.headers, {
2513
2659
  name: ctx.server.config.sessionCookieName,
2514
2660
  value: token,
@@ -2650,7 +2796,7 @@ var getMyProfile = {
2650
2796
  name: "auth.getMyProfile",
2651
2797
  code: "",
2652
2798
  type: "RESTful",
2653
- method: "get",
2799
+ method: "GET",
2654
2800
  endpoint: "/me",
2655
2801
  handlers: [
2656
2802
  {
@@ -2664,7 +2810,7 @@ var signin = {
2664
2810
  name: "auth.signin",
2665
2811
  code: "",
2666
2812
  type: "RESTful",
2667
- method: "post",
2813
+ method: "POST",
2668
2814
  endpoint: "/signin",
2669
2815
  handlers: [
2670
2816
  {
@@ -2678,7 +2824,7 @@ var signout = {
2678
2824
  name: "auth.signout",
2679
2825
  code: "",
2680
2826
  type: "RESTful",
2681
- method: "get",
2827
+ method: "GET",
2682
2828
  endpoint: "/signout",
2683
2829
  handlers: [
2684
2830
  {
@@ -3357,7 +3503,7 @@ var bootstrapApplicationConfig = {
3357
3503
  columnName: "order_num",
3358
3504
  type: "integer",
3359
3505
  required: true,
3360
- defaultValue: 0,
3506
+ defaultValue: '0',
3361
3507
  },
3362
3508
  {
3363
3509
  name: "name",
@@ -3485,7 +3631,7 @@ var bootstrapApplicationConfig = {
3485
3631
  name: "meta.model.list",
3486
3632
  code: "meta.model.list",
3487
3633
  type: "RESTful",
3488
- method: "get",
3634
+ method: "GET",
3489
3635
  endpoint: "/_meta/models",
3490
3636
  handlers: [
3491
3637
  {
@@ -3498,7 +3644,7 @@ var bootstrapApplicationConfig = {
3498
3644
  name: "meta.model.getDetail",
3499
3645
  code: "meta.model.getDetail",
3500
3646
  type: "RESTful",
3501
- method: "get",
3647
+ method: "GET",
3502
3648
  endpoint: "/_meta/models/:namespace/:singularCode",
3503
3649
  handlers: [
3504
3650
  {
@@ -3511,7 +3657,7 @@ var bootstrapApplicationConfig = {
3511
3657
  name: "meta.route.list",
3512
3658
  code: "meta.route.list",
3513
3659
  type: "RESTful",
3514
- method: "get",
3660
+ method: "GET",
3515
3661
  endpoint: "/_meta/routes",
3516
3662
  handlers: [
3517
3663
  {
@@ -3677,7 +3823,6 @@ class RapidServer {
3677
3823
  const rapidRequest = new RapidRequest(request);
3678
3824
  await rapidRequest.parseBody();
3679
3825
  const routeContext = new RouteContext(rapidRequest);
3680
- console.log('routeContext', routeContext);
3681
3826
  await this.#buildedRoutes(routeContext, next);
3682
3827
  return routeContext.response.getResponse();
3683
3828
  }
@@ -3690,3 +3835,7 @@ exports.RapidRequest = RapidRequest;
3690
3835
  exports.RapidServer = RapidServer;
3691
3836
  exports.RouteContext = RouteContext;
3692
3837
  exports.bootstrapApplicationConfig = bootstrapApplicationConfig$1;
3838
+ exports.createJwt = createJwt;
3839
+ exports.decodeJwt = decodeJwt;
3840
+ exports.generateJwtSecretKey = generateJwtSecretKey;
3841
+ exports.verifyJwt = verifyJwt;
@@ -1,3 +1,12 @@
1
- import { RpdRoute } from "~/types";
2
- declare const _default: RpdRoute;
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "GET";
7
+ endpoint: string;
8
+ handlers: {
9
+ code: string;
10
+ }[];
11
+ };
3
12
  export default _default;
@@ -1,2 +1,22 @@
1
- declare const _default: import("../../..").RpdRoute[];
1
+ declare const _default: ({
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "GET";
7
+ endpoint: string;
8
+ handlers: {
9
+ code: string;
10
+ }[];
11
+ } | {
12
+ namespace: string;
13
+ name: string;
14
+ code: string;
15
+ type: "RESTful";
16
+ method: "POST";
17
+ endpoint: string;
18
+ handlers: {
19
+ code: string;
20
+ }[];
21
+ })[];
2
22
  export default _default;
@@ -1,3 +1,12 @@
1
- import { RpdRoute } from "~/types";
2
- declare const _default: RpdRoute;
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "POST";
7
+ endpoint: string;
8
+ handlers: {
9
+ code: string;
10
+ }[];
11
+ };
3
12
  export default _default;
@@ -1,3 +1,12 @@
1
- import { RpdRoute } from "~/types";
2
- declare const _default: RpdRoute;
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "GET";
7
+ endpoint: string;
8
+ handlers: {
9
+ code: string;
10
+ }[];
11
+ };
3
12
  export default _default;
package/dist/types.d.ts CHANGED
@@ -247,10 +247,10 @@ export interface RpdRoute {
247
247
  endpoint: string;
248
248
  handlers: RpdHttpHandler[];
249
249
  }
250
- export type RpdHttpMethod = "get" | "post" | "put" | "delete" | "patch";
250
+ export type RpdHttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
251
251
  export interface RpdHttpHandler {
252
252
  code: string;
253
- config: any;
253
+ config?: any;
254
254
  }
255
255
  export interface IRpdDataAccessor<T = any> {
256
256
  getModel(): RpdDataModel;
@@ -1,8 +1,5 @@
1
- export declare function getJWTKey(): string;
2
- export declare function createJWT(payload: Record<string, any>): Promise<string>;
3
- export declare function verifyJWT(jwt: string): Promise<{}>;
4
- export declare function decodeJWT(jwt: string): Promise<{
5
- header: {};
6
- payload: {};
7
- signature: {};
8
- }>;
1
+ import { Secret } from "jsonwebtoken";
2
+ export declare function createJwt(payload: Record<string, any>, secret: Secret): string;
3
+ export declare function verifyJwt(token: string, secret: Secret): string | import("jsonwebtoken").JwtPayload;
4
+ export declare function decodeJwt(token: string): import("jsonwebtoken").Jwt;
5
+ export declare function generateJwtSecretKey(): Promise<string>;
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "keywords": [],
7
7
  "author": "Fossil",
8
8
  "license": "MIT",
9
9
  "devDependencies": {
10
+ "@types/jsonwebtoken": "^9.0.5",
10
11
  "@types/lodash": "^4.14.186",
11
12
  "@types/node": "^20.11.16",
12
13
  "rimraf": "^3.0.2",
@@ -15,8 +16,8 @@
15
16
  "rollup-plugin-typescript2": "^0.34.1",
16
17
  "typescript": "^4.8.4"
17
18
  },
18
- "peerDependencies": {},
19
19
  "dependencies": {
20
+ "jsonwebtoken": "^9.0.2",
20
21
  "koa-tree-router": "^0.12.1",
21
22
  "lodash": "^4.17.21",
22
23
  "qs": "^6.11.0"
@@ -358,7 +358,7 @@ export default {
358
358
  columnName: "order_num",
359
359
  type: "integer",
360
360
  required: true,
361
- defaultValue: 0,
361
+ defaultValue: '0',
362
362
  },
363
363
  {
364
364
  name: "name",
@@ -486,7 +486,7 @@ export default {
486
486
  name: "meta.model.list",
487
487
  code: "meta.model.list",
488
488
  type: "RESTful",
489
- method: "get",
489
+ method: "GET",
490
490
  endpoint: "/_meta/models",
491
491
  handlers: [
492
492
  {
@@ -499,7 +499,7 @@ export default {
499
499
  name: "meta.model.getDetail",
500
500
  code: "meta.model.getDetail",
501
501
  type: "RESTful",
502
- method: "get",
502
+ method: "GET",
503
503
  endpoint: "/_meta/models/:namespace/:singularCode",
504
504
  handlers: [
505
505
  {
@@ -512,7 +512,7 @@ export default {
512
512
  name: "meta.route.list",
513
513
  code: "meta.route.list",
514
514
  type: "RESTful",
515
- method: "get",
515
+ method: "GET",
516
516
  endpoint: "/_meta/routes",
517
517
  handlers: [
518
518
  {
@@ -521,4 +521,4 @@ export default {
521
521
  ],
522
522
  },
523
523
  ],
524
- } as RpdApplicationConfig;
524
+ } satisfies RpdApplicationConfig;
@@ -28,7 +28,7 @@ export async function buildRoutes(
28
28
 
29
29
  const routePath = baseUrl + routeConfig.endpoint;
30
30
 
31
- (router as any)[routeConfig.method](
31
+ (router as any)[routeConfig.method.toLowerCase()](
32
32
  routePath,
33
33
  async (routerContext: RouteContext, next: Next) => {
34
34
  const { request, params } = routerContext;
@@ -0,0 +1,145 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ // This module is browser compatible.
3
+
4
+ /**
5
+ * {@linkcode encode} and {@linkcode decode} for
6
+ * [base64](https://en.wikipedia.org/wiki/Base64) encoding.
7
+ *
8
+ * This module is browser compatible.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import {
13
+ * decode,
14
+ * encode,
15
+ * } from "https://deno.land/std@$STD_VERSION/encoding/base64.ts";
16
+ *
17
+ * const b64Repr = "Zm9vYg==";
18
+ *
19
+ * const binaryData = decode(b64Repr);
20
+ * console.log(binaryData);
21
+ * // => Uint8Array [ 102, 111, 111, 98 ]
22
+ *
23
+ * console.log(encode(binaryData));
24
+ * // => Zm9vYg==
25
+ * ```
26
+ *
27
+ * @module
28
+ */
29
+
30
+ const base64abc = [
31
+ "A",
32
+ "B",
33
+ "C",
34
+ "D",
35
+ "E",
36
+ "F",
37
+ "G",
38
+ "H",
39
+ "I",
40
+ "J",
41
+ "K",
42
+ "L",
43
+ "M",
44
+ "N",
45
+ "O",
46
+ "P",
47
+ "Q",
48
+ "R",
49
+ "S",
50
+ "T",
51
+ "U",
52
+ "V",
53
+ "W",
54
+ "X",
55
+ "Y",
56
+ "Z",
57
+ "a",
58
+ "b",
59
+ "c",
60
+ "d",
61
+ "e",
62
+ "f",
63
+ "g",
64
+ "h",
65
+ "i",
66
+ "j",
67
+ "k",
68
+ "l",
69
+ "m",
70
+ "n",
71
+ "o",
72
+ "p",
73
+ "q",
74
+ "r",
75
+ "s",
76
+ "t",
77
+ "u",
78
+ "v",
79
+ "w",
80
+ "x",
81
+ "y",
82
+ "z",
83
+ "0",
84
+ "1",
85
+ "2",
86
+ "3",
87
+ "4",
88
+ "5",
89
+ "6",
90
+ "7",
91
+ "8",
92
+ "9",
93
+ "+",
94
+ "/",
95
+ ];
96
+
97
+ /**
98
+ * CREDIT: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727
99
+ * Encodes a given Uint8Array, ArrayBuffer or string into RFC4648 base64 representation
100
+ * @param data
101
+ */
102
+ export function encode(data: ArrayBuffer | string): string {
103
+ const uint8 = typeof data === "string"
104
+ ? new TextEncoder().encode(data)
105
+ : data instanceof Uint8Array
106
+ ? data
107
+ : new Uint8Array(data);
108
+ let result = "",
109
+ i;
110
+ const l = uint8.length;
111
+ for (i = 2; i < l; i += 3) {
112
+ result += base64abc[uint8[i - 2] >> 2];
113
+ result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];
114
+ result += base64abc[((uint8[i - 1] & 0x0f) << 2) | (uint8[i] >> 6)];
115
+ result += base64abc[uint8[i] & 0x3f];
116
+ }
117
+ if (i === l + 1) {
118
+ // 1 octet yet to write
119
+ result += base64abc[uint8[i - 2] >> 2];
120
+ result += base64abc[(uint8[i - 2] & 0x03) << 4];
121
+ result += "==";
122
+ }
123
+ if (i === l) {
124
+ // 2 octets yet to write
125
+ result += base64abc[uint8[i - 2] >> 2];
126
+ result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];
127
+ result += base64abc[(uint8[i - 1] & 0x0f) << 2];
128
+ result += "=";
129
+ }
130
+ return result;
131
+ }
132
+
133
+ /**
134
+ * Decodes a given RFC4648 base64 encoded string
135
+ * @param b64
136
+ */
137
+ export function decode(b64: string): Uint8Array {
138
+ const binString = atob(b64);
139
+ const size = binString.length;
140
+ const bytes = new Uint8Array(size);
141
+ for (let i = 0; i < size; i++) {
142
+ bytes[i] = binString.charCodeAt(i);
143
+ }
144
+ return bytes;
145
+ }
package/src/index.ts CHANGED
@@ -8,4 +8,6 @@ export * from "./core/request";
8
8
  export * from "./core/routeContext";
9
9
  export * from "./core/server";
10
10
 
11
+ export * from "./utilities/jwtUtility";
12
+
11
13
  export * as bootstrapApplicationConfig from "./bootstrapApplicationConfig";
@@ -1,6 +1,6 @@
1
1
  import { IPluginInstance } from "~/types";
2
2
  import { setCookie } from "~/deno-std/http/cookie";
3
- import { createJWT } from "~/utilities/jwtUtility";
3
+ import { createJwt } from "~/utilities/jwtUtility";
4
4
  import { HttpHandlerContext } from "~/core/httpHandler";
5
5
 
6
6
  export interface UserAccessToken {
@@ -37,13 +37,14 @@ export async function handler(
37
37
  throw new Error("Wrong account or password.");
38
38
  }
39
39
 
40
- const token = await createJWT({
40
+ const secretKey = Buffer.from(server.config.jwtKey, "base64");
41
+ const token = createJwt({
41
42
  iss: "authManager",
42
43
  sub: "userAccessToken",
43
44
  aud: "" + user.id,
44
45
  iat: new Date,
45
46
  act: user.login,
46
- } as UserAccessToken);
47
+ } as UserAccessToken, secretKey);
47
48
 
48
49
  setCookie(response.headers, {
49
50
  name: ctx.server.config.sessionCookieName,
@@ -5,11 +5,11 @@ export default {
5
5
  name: "auth.getMyProfile",
6
6
  code: "",
7
7
  type: "RESTful",
8
- method: "get",
8
+ method: "GET",
9
9
  endpoint: "/me",
10
10
  handlers: [
11
11
  {
12
12
  code: "getMyProfile",
13
13
  },
14
14
  ],
15
- } as RpdRoute;
15
+ } satisfies RpdRoute;
@@ -5,11 +5,11 @@ export default {
5
5
  name: "auth.signin",
6
6
  code: "",
7
7
  type: "RESTful",
8
- method: "post",
8
+ method: "POST",
9
9
  endpoint: "/signin",
10
10
  handlers: [
11
11
  {
12
12
  code: "createSession",
13
13
  },
14
14
  ],
15
- } as RpdRoute;
15
+ } satisfies RpdRoute;
@@ -5,11 +5,11 @@ export default {
5
5
  name: "auth.signout",
6
6
  code: "",
7
7
  type: "RESTful",
8
- method: "get",
8
+ method: "GET",
9
9
  endpoint: "/signout",
10
10
  handlers: [
11
11
  {
12
12
  code: "deleteSession",
13
13
  },
14
14
  ],
15
- } as RpdRoute;
15
+ } satisfies RpdRoute;
@@ -36,8 +36,6 @@ export async function handler(
36
36
  throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
37
37
  }
38
38
 
39
- console.log(mergedInput);
40
-
41
39
  const relationProperty = model.properties.find(e => e.code === property);
42
40
  if (!relationProperty) {
43
41
  throw new Error(`Property '${property}' was not found in ${options.namespace}.${options.singularCode}`);
@@ -39,55 +39,55 @@ const routeConfigs: {
39
39
  }[] = [
40
40
  {
41
41
  code: "createBatch",
42
- method: "post",
42
+ method: "POST",
43
43
  endpoint: "/operations/create_batch",
44
44
  handlerCode: "createCollectionEntitiesBatch",
45
45
  },
46
46
  {
47
47
  code: "find",
48
- method: "post",
48
+ method: "POST",
49
49
  endpoint: "/operations/find",
50
50
  handlerCode: "findCollectionEntities",
51
51
  },
52
52
  {
53
53
  code: "count",
54
- method: "post",
54
+ method: "POST",
55
55
  endpoint: "/operations/count",
56
56
  handlerCode: "countCollectionEntities",
57
57
  },
58
58
  {
59
59
  code: "addRelations",
60
- method: "post",
60
+ method: "POST",
61
61
  endpoint: "/operations/add_relations",
62
62
  handlerCode: "addEntityRelations",
63
63
  },
64
64
  {
65
65
  code: "removeRelations",
66
- method: "post",
66
+ method: "POST",
67
67
  endpoint: "/operations/remove_relations",
68
68
  handlerCode: "removeEntityRelations",
69
69
  },
70
70
  {
71
71
  code: "getById",
72
- method: "get",
72
+ method: "GET",
73
73
  endpoint: "/:id",
74
74
  handlerCode: "findCollectionEntityById",
75
75
  },
76
76
  {
77
77
  code: "create",
78
- method: "post",
78
+ method: "POST",
79
79
  endpoint: "",
80
80
  handlerCode: "createCollectionEntity",
81
81
  },
82
82
  {
83
83
  code: "updateById",
84
- method: "patch",
84
+ method: "PATCH",
85
85
  endpoint: "/:id",
86
86
  handlerCode: "updateCollectionEntityById",
87
87
  },
88
88
  {
89
89
  code: "deleteById",
90
- method: "delete",
90
+ method: "DELETE",
91
91
  endpoint: "/:id",
92
92
  handlerCode: "deleteCollectionEntityById",
93
93
  },
package/src/server.ts CHANGED
@@ -223,7 +223,6 @@ export class RapidServer implements IRpdServer {
223
223
  const rapidRequest = new RapidRequest(request);
224
224
  await rapidRequest.parseBody();
225
225
  const routeContext = new RouteContext(rapidRequest);
226
- console.log('routeContext', routeContext)
227
226
  await this.#buildedRoutes(routeContext, next);
228
227
  return routeContext.response.getResponse();
229
228
  }
package/src/types.ts CHANGED
@@ -304,11 +304,11 @@ export interface RpdRoute {
304
304
  handlers: RpdHttpHandler[];
305
305
  }
306
306
 
307
- export type RpdHttpMethod = "get" | "post" | "put" | "delete" | "patch";
307
+ export type RpdHttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
308
308
 
309
309
  export interface RpdHttpHandler {
310
310
  code: string;
311
- config: any;
311
+ config?: any;
312
312
  }
313
313
 
314
314
  export interface IRpdDataAccessor<T = any> {
@@ -1,16 +1,30 @@
1
+ import { sign, verify, decode, Secret } from "jsonwebtoken";
2
+ import { encode as base64Encode } from "~/deno-std/encoding/base64";
3
+ import crypto from "crypto";
1
4
 
2
- export function getJWTKey() {
3
- return "";
5
+ export function createJwt(payload: Record<string, any>, secret: Secret) {
6
+ return sign(payload, secret, {
7
+ algorithm: 'HS512',
8
+ });
4
9
  }
5
10
 
6
- export async function createJWT(payload: Record<string, any>) {
7
- return "";
11
+ export function verifyJwt(token: string, secret: Secret) {
12
+ return verify(token, secret, {
13
+ algorithms: ['HS512'],
14
+ });
8
15
  }
9
16
 
10
- export async function verifyJWT(jwt: string) {
11
- return {};
17
+ export function decodeJwt(token: string) {
18
+ return decode(token, { complete: true});
12
19
  }
13
20
 
14
- export async function decodeJWT(jwt: string) {
15
- return { header: {}, payload: {}, signature: {} };
21
+ export async function generateJwtSecretKey() {
22
+ const key = await crypto.subtle.generateKey(
23
+ { name: "HMAC", hash: "SHA-512" },
24
+ true,
25
+ ["sign", "verify"],
26
+ );
27
+
28
+ const exportedKey = await crypto.subtle.exportKey("raw", key);
29
+ return base64Encode(exportedKey);
16
30
  }