@raketa-cloud/admin 0.0.2 → 0.0.4
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/babel.config.js +6 -0
- package/bin/tailwind +2 -0
- package/package.json +22 -29
- package/src/Adapter.js +105 -0
- package/src/HonoAdapter.js +120 -0
- package/src/RaketaContext.js +33 -0
- package/src/createNestedResource.js +83 -0
- package/src/createResource.js +83 -0
- package/src/index.js +3 -0
- package/src/styles/application.css +17 -0
- package/src/tests/HonoAdapter.test.js +33 -0
- package/src/tests/createNestedResource.test.js +150 -0
- package/src/tests/createResource.test.js +115 -0
- package/src/views/layouts/application.ejs +22 -0
- package/src/views/redirects/index.ejs +1 -0
- package/tailwind.config.js +8 -0
- package/tsconfig.json +14 -14
- package/tsconfig.lint.json +8 -0
- package/biome.json +0 -6
- package/jest.config.js +0 -15
- package/src/app.tsx +0 -19
- package/src/crud/login.tsx +0 -99
- package/src/crud/logout.tsx +0 -14
- package/src/crud/tags.tsx +0 -235
- package/src/index.ts +0 -1
- package/src/lib/dxp/private/tags.ts +0 -106
- package/src/lib/dxp/protocol.ts +0 -32
- package/src/lib/gateway/login.ts +0 -44
- package/src/lib/gateway/protocol.ts +0 -8
- package/src/lib/gqlEngine.ts +0 -17
- package/src/lib/logger.tsx +0 -149
- package/src/middleware/authentication.ts +0 -62
- package/src/middleware/http_logger.ts +0 -41
- package/src/middleware/logger.ts +0 -9
- package/src/shared/Layout.tsx +0 -50
- package/tests/integration/authentication/middleware.test.ts +0 -100
- package/tests/integration/login/create.test.ts +0 -117
- package/tests/integration/login/index.test.ts +0 -16
- package/tests/integration/logout/delete.test.ts +0 -17
- package/tests/integration/tags/create.test.ts +0 -66
- package/tests/integration/tags/delete.test.ts +0 -74
- package/tests/integration/tags/edit.test.ts +0 -43
- package/tests/integration/tags/index.test.ts +0 -66
- package/tests/integration/tags/new.test.ts +0 -16
- package/tests/integration/tags/update.test.ts +0 -87
- package/tests/support/helpers.ts +0 -53
- package/tests/support/setup.js +0 -9
- package/turbo/generators/config.ts +0 -30
- package/turbo/generators/templates/component.hbs +0 -14
- package/turbo.json +0 -9
package/babel.config.js
ADDED
package/bin/tailwind
ADDED
package/package.json
CHANGED
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@biomejs/biome": "1.5.3",
|
|
27
|
-
"graphql-request": "^6.1.0",
|
|
28
|
-
"hono": "^3.12.3",
|
|
29
|
-
"prettier": "^3.2.4"
|
|
30
|
-
}
|
|
2
|
+
"name": "@raketa-cloud/admin",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"main": "src/index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "bin/tailwind",
|
|
7
|
+
"test": "jest"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"@babel/core": "^7.24.7",
|
|
11
|
+
"@babel/preset-env": "^7.24.7",
|
|
12
|
+
"@babel/preset-typescript": "^7.24.7",
|
|
13
|
+
"@repo/typescript-config": "*",
|
|
14
|
+
"@tailwindcss/forms": "^0.5.7",
|
|
15
|
+
"@tailwindcss/typography": "^0.5.13",
|
|
16
|
+
"@types/node": "^20.11.24",
|
|
17
|
+
"jest": "^29.7.0",
|
|
18
|
+
"tailwindcss": "^3.4.4",
|
|
19
|
+
"typescript": "^5.3.3"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"ejs": "^3.1.10"
|
|
23
|
+
}
|
|
31
24
|
}
|
package/src/Adapter.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const nodePath = require("node:path");
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import ejs from "ejs";
|
|
4
|
+
|
|
5
|
+
function escapeHtml(string) {
|
|
6
|
+
var matchHtmlRegExp = /["'&<>]/;
|
|
7
|
+
|
|
8
|
+
var str = "" + string;
|
|
9
|
+
var match = matchHtmlRegExp.exec(str);
|
|
10
|
+
|
|
11
|
+
if (!match) {
|
|
12
|
+
return str;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
var escape;
|
|
16
|
+
var html = "";
|
|
17
|
+
var index = 0;
|
|
18
|
+
var lastIndex = 0;
|
|
19
|
+
|
|
20
|
+
for (index = match.index; index < str.length; index++) {
|
|
21
|
+
switch (str.charCodeAt(index)) {
|
|
22
|
+
case 34: // "
|
|
23
|
+
escape = """;
|
|
24
|
+
break;
|
|
25
|
+
case 38: // &
|
|
26
|
+
escape = "&";
|
|
27
|
+
break;
|
|
28
|
+
case 39: // '
|
|
29
|
+
escape = "'";
|
|
30
|
+
break;
|
|
31
|
+
case 60: // <
|
|
32
|
+
escape = "<";
|
|
33
|
+
break;
|
|
34
|
+
case 62: // >
|
|
35
|
+
escape = ">";
|
|
36
|
+
break;
|
|
37
|
+
default:
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (lastIndex !== index) {
|
|
42
|
+
html += str.substring(lastIndex, index);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
lastIndex = index + 1;
|
|
46
|
+
html += escape;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const renderError = (message, stack) => {
|
|
53
|
+
const errorCSS = `
|
|
54
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
55
|
+
html { font-family: sans-serif; font-size: 16px; padding: 2rem; background-color: pink; }
|
|
56
|
+
h1 { margin-bottom: 1rem; color: FireBrick; }
|
|
57
|
+
.fail-squid { font-size: 7rem; }
|
|
58
|
+
pre { padding: 1.5rem 2rem; border-radius: 0.5rem; background-color: black; color: white; line-height: 1.5; font-size: 1.25rem; }
|
|
59
|
+
`;
|
|
60
|
+
return `<style>${errorCSS}</style><div class="fail-squid">🦑</div><h1>${message}</h1><pre>${escapeHtml(stack)}</pre>`;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const Logger = {
|
|
64
|
+
error: (msg) => {
|
|
65
|
+
console.error(`\x1b[31m🦑 ${msg}\x1b[0m`);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default class Adapter {
|
|
70
|
+
constructor(router) {
|
|
71
|
+
this.router = router;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
createResource(_resource, _mapping) {
|
|
75
|
+
throw new Error("Implement in an adapter");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getActionPath(resource, action) {
|
|
79
|
+
const packagePath = `${nodePath.dirname(__filename)}/views/${resource}/${action}.ejs`;
|
|
80
|
+
const appPath = `${process.cwd()}/src/views/${resource}/${action}.ejs`;
|
|
81
|
+
|
|
82
|
+
return existsSync(appPath) ? appPath : packagePath;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async renderLayout(assigns, body) {
|
|
86
|
+
const layoutTemplate = `${nodePath.dirname(__filename)}/views/layouts/application.ejs`;
|
|
87
|
+
return await ejs.renderFile(layoutTemplate, { ...assigns, body });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async renderAction({ resource, action, assigns }) {
|
|
91
|
+
const fullTemplatePath = this.getActionPath(resource, action);
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const rendered = await ejs.renderFile(fullTemplatePath, assigns);
|
|
95
|
+
const fullPage = await this.renderLayout(assigns, rendered);
|
|
96
|
+
|
|
97
|
+
return fullPage;
|
|
98
|
+
} catch (e) {
|
|
99
|
+
const error = `Error rendering:\n ${fullTemplatePath}`;
|
|
100
|
+
Logger.error(`${error}\n\n${e.stack}`);
|
|
101
|
+
|
|
102
|
+
return renderError(error, e.stack);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import Adapter from "./Adapter";
|
|
2
|
+
import RaketaContext from "./RaketaContext";
|
|
3
|
+
|
|
4
|
+
export default class HonoAdapter extends Adapter {
|
|
5
|
+
constructor(router) {
|
|
6
|
+
super(router);
|
|
7
|
+
this.router = router;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async createContext(router, next, verb, resource, action) {
|
|
11
|
+
return new RaketaContext({
|
|
12
|
+
router,
|
|
13
|
+
res: next,
|
|
14
|
+
req: router.req,
|
|
15
|
+
method: verb,
|
|
16
|
+
headers: router.req.header(),
|
|
17
|
+
rawPath: router.req.routePath,
|
|
18
|
+
path: router.req.path,
|
|
19
|
+
url: router.req.url,
|
|
20
|
+
action,
|
|
21
|
+
params: router.req.param(),
|
|
22
|
+
body: await router.req.parseBody(),
|
|
23
|
+
query: router.req.query(),
|
|
24
|
+
resource,
|
|
25
|
+
assigns: {},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
createAction([
|
|
30
|
+
verb,
|
|
31
|
+
path,
|
|
32
|
+
resource,
|
|
33
|
+
action,
|
|
34
|
+
handler,
|
|
35
|
+
before_filter,
|
|
36
|
+
after_filter,
|
|
37
|
+
]) {
|
|
38
|
+
const method = this.getMethod(verb);
|
|
39
|
+
|
|
40
|
+
method(path, async (router, next) => {
|
|
41
|
+
const ctx = await this.createContext(
|
|
42
|
+
router,
|
|
43
|
+
next,
|
|
44
|
+
verb,
|
|
45
|
+
resource,
|
|
46
|
+
action
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
console.info(
|
|
50
|
+
`\x1b[35m[${ctx.method}] ${ctx.rawPath}\x1b[0m -> ${resource}/${action} | ${JSON.stringify(ctx.params)}`
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const assigns = {
|
|
54
|
+
beforeFilterAssigns: {},
|
|
55
|
+
actionAssigns: {},
|
|
56
|
+
afterFilterAssigns: {},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Process before filters
|
|
60
|
+
if (before_filter) {
|
|
61
|
+
const { redirect, assigns: beforeFilterAssigns = {} } =
|
|
62
|
+
before_filter(ctx) || {};
|
|
63
|
+
|
|
64
|
+
if (redirect) return router.redirect(redirect);
|
|
65
|
+
|
|
66
|
+
assigns.beforeFilterAssigns = beforeFilterAssigns;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Process action
|
|
70
|
+
const { redirect, assigns: actionAssigns = {} } = handler(ctx) || {};
|
|
71
|
+
assigns.actionAssigns = actionAssigns;
|
|
72
|
+
|
|
73
|
+
if (redirect) return router.redirect(redirect);
|
|
74
|
+
|
|
75
|
+
// Process after filters
|
|
76
|
+
if (after_filter) {
|
|
77
|
+
const { redirect, assigns: afterFilterAssigns = {} } =
|
|
78
|
+
after_filter(ctx) || {};
|
|
79
|
+
|
|
80
|
+
if (redirect) return router.redirect(redirect);
|
|
81
|
+
|
|
82
|
+
assigns.afterFilterAssigns = afterFilterAssigns;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const fullAssigns = {
|
|
86
|
+
...ctx.assigns,
|
|
87
|
+
...assigns.beforeFilterAssigns,
|
|
88
|
+
...assigns.actionAssigns,
|
|
89
|
+
...assigns.afterFilterAssigns,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const rendered = this.renderAction({
|
|
93
|
+
resource,
|
|
94
|
+
action,
|
|
95
|
+
assigns: fullAssigns,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return router.html(rendered);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
createResource(mapping) {
|
|
103
|
+
mapping.forEach((handlerMap) => this.createAction(handlerMap));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
createNestedResource(mapping) {
|
|
107
|
+
mapping.forEach((handlerMap) => this.createAction(handlerMap));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getMethod(verb) {
|
|
111
|
+
return (
|
|
112
|
+
{
|
|
113
|
+
GET: this.router.get,
|
|
114
|
+
POST: this.router.post,
|
|
115
|
+
PUT: this.router.put,
|
|
116
|
+
DELETE: this.router.delete,
|
|
117
|
+
}[verb] || this.router.get
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default class RaketaContext {
|
|
2
|
+
constructor({
|
|
3
|
+
router,
|
|
4
|
+
res,
|
|
5
|
+
req,
|
|
6
|
+
method,
|
|
7
|
+
headers,
|
|
8
|
+
rawPath,
|
|
9
|
+
path,
|
|
10
|
+
url,
|
|
11
|
+
action,
|
|
12
|
+
params,
|
|
13
|
+
query,
|
|
14
|
+
body,
|
|
15
|
+
resource,
|
|
16
|
+
assigns,
|
|
17
|
+
}) {
|
|
18
|
+
this.router = router;
|
|
19
|
+
this.res = res;
|
|
20
|
+
this.req = req;
|
|
21
|
+
this.method = method;
|
|
22
|
+
this.headers = headers;
|
|
23
|
+
this.rawPath = rawPath;
|
|
24
|
+
this.path = path;
|
|
25
|
+
this.url = url;
|
|
26
|
+
this.action = action;
|
|
27
|
+
this.params = params;
|
|
28
|
+
this.query = query;
|
|
29
|
+
this.body = body;
|
|
30
|
+
this.resource = resource;
|
|
31
|
+
this.assigns = assigns;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const createNestedResource = (adapter, parent, resource, handler) => {
|
|
2
|
+
const {
|
|
3
|
+
before_filter,
|
|
4
|
+
after_filter,
|
|
5
|
+
index,
|
|
6
|
+
show,
|
|
7
|
+
create_form,
|
|
8
|
+
edit_form,
|
|
9
|
+
create,
|
|
10
|
+
update,
|
|
11
|
+
destroy,
|
|
12
|
+
} = handler;
|
|
13
|
+
|
|
14
|
+
const mapping = [
|
|
15
|
+
[
|
|
16
|
+
"GET",
|
|
17
|
+
`/${parent}/:parent_id/${resource}`,
|
|
18
|
+
resource,
|
|
19
|
+
"index",
|
|
20
|
+
index,
|
|
21
|
+
before_filter,
|
|
22
|
+
after_filter,
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
"GET",
|
|
26
|
+
`/${parent}/:parent_id/${resource}/new`,
|
|
27
|
+
resource,
|
|
28
|
+
"create_form",
|
|
29
|
+
create_form,
|
|
30
|
+
before_filter,
|
|
31
|
+
after_filter,
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"GET",
|
|
35
|
+
`/${resource}/:id`,
|
|
36
|
+
resource,
|
|
37
|
+
"show",
|
|
38
|
+
show,
|
|
39
|
+
before_filter,
|
|
40
|
+
after_filter,
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"GET",
|
|
44
|
+
`/${resource}/:id/edit`,
|
|
45
|
+
resource,
|
|
46
|
+
"edit_form",
|
|
47
|
+
edit_form,
|
|
48
|
+
before_filter,
|
|
49
|
+
after_filter,
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
"POST",
|
|
53
|
+
`/orders/:parent_id/${resource}`,
|
|
54
|
+
resource,
|
|
55
|
+
"create",
|
|
56
|
+
create,
|
|
57
|
+
before_filter,
|
|
58
|
+
after_filter,
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"PUT",
|
|
62
|
+
`/${resource}/:id`,
|
|
63
|
+
resource,
|
|
64
|
+
"update",
|
|
65
|
+
update,
|
|
66
|
+
before_filter,
|
|
67
|
+
after_filter,
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
"DELETE",
|
|
71
|
+
`/${resource}/:id`,
|
|
72
|
+
resource,
|
|
73
|
+
"destroy",
|
|
74
|
+
destroy,
|
|
75
|
+
before_filter,
|
|
76
|
+
after_filter,
|
|
77
|
+
],
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
adapter.createNestedResource(mapping);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default createNestedResource;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const createResource = (adapter, resource, handler) => {
|
|
2
|
+
const {
|
|
3
|
+
before_filter,
|
|
4
|
+
after_filter,
|
|
5
|
+
index,
|
|
6
|
+
show,
|
|
7
|
+
create_form,
|
|
8
|
+
edit_form,
|
|
9
|
+
create,
|
|
10
|
+
update,
|
|
11
|
+
destroy,
|
|
12
|
+
} = handler;
|
|
13
|
+
|
|
14
|
+
const mapping = [
|
|
15
|
+
[
|
|
16
|
+
"GET",
|
|
17
|
+
`/${resource}`,
|
|
18
|
+
resource,
|
|
19
|
+
"index",
|
|
20
|
+
index,
|
|
21
|
+
before_filter,
|
|
22
|
+
after_filter,
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
"GET",
|
|
26
|
+
`/${resource}/new`,
|
|
27
|
+
resource,
|
|
28
|
+
"create_form",
|
|
29
|
+
create_form,
|
|
30
|
+
before_filter,
|
|
31
|
+
after_filter,
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"GET",
|
|
35
|
+
`/${resource}/:id`,
|
|
36
|
+
resource,
|
|
37
|
+
"show",
|
|
38
|
+
show,
|
|
39
|
+
before_filter,
|
|
40
|
+
after_filter,
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"GET",
|
|
44
|
+
`/${resource}/:id/edit`,
|
|
45
|
+
resource,
|
|
46
|
+
"edit_form",
|
|
47
|
+
edit_form,
|
|
48
|
+
before_filter,
|
|
49
|
+
after_filter,
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
"POST",
|
|
53
|
+
`/${resource}`,
|
|
54
|
+
resource,
|
|
55
|
+
"create",
|
|
56
|
+
create,
|
|
57
|
+
before_filter,
|
|
58
|
+
after_filter,
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"PUT",
|
|
62
|
+
`/${resource}/:id`,
|
|
63
|
+
resource,
|
|
64
|
+
"update",
|
|
65
|
+
update,
|
|
66
|
+
before_filter,
|
|
67
|
+
after_filter,
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
"DELETE",
|
|
71
|
+
`/${resource}/:id`,
|
|
72
|
+
resource,
|
|
73
|
+
"destroy",
|
|
74
|
+
destroy,
|
|
75
|
+
before_filter,
|
|
76
|
+
after_filter,
|
|
77
|
+
],
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
adapter.createResource(mapping);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default createResource;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer components {
|
|
6
|
+
.btn-primary {
|
|
7
|
+
@apply bg-purple-500 text-white inline-block py-1 px-3 rounded;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.btn-secondary {
|
|
11
|
+
@apply bg-neutral-300 text-black inline-block py-1 px-3 rounded;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.btn-text {
|
|
15
|
+
@apply underline underline-offset-2;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import HonoAdapter from "../HonoAdapter";
|
|
2
|
+
|
|
3
|
+
class HonoMock {
|
|
4
|
+
get() {}
|
|
5
|
+
post() {}
|
|
6
|
+
put() {}
|
|
7
|
+
delete() {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const app = new HonoMock();
|
|
11
|
+
const adapter = new HonoAdapter(app);
|
|
12
|
+
|
|
13
|
+
describe("HonoAdapter", () => {
|
|
14
|
+
test("getMethod returns Hono's get for invalid verbs", () => {
|
|
15
|
+
expect(adapter.getMethod("not existing")).toBe(app.get);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("getMethod for GET", () => {
|
|
19
|
+
expect(adapter.getMethod("GET")).toBe(app.get);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("getMethod for POST", () => {
|
|
23
|
+
expect(adapter.getMethod("POST")).toBe(app.post);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("getMethod for PUT", () => {
|
|
27
|
+
expect(adapter.getMethod("PUT")).toBe(app.put);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("getMethod for DELETE", () => {
|
|
31
|
+
expect(adapter.getMethod("DELETE")).toBe(app.delete);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import createNestedResource from "../createNestedResource";
|
|
2
|
+
|
|
3
|
+
const OrdersHandler = {
|
|
4
|
+
index: () => {},
|
|
5
|
+
show: () => {},
|
|
6
|
+
create_form: () => {},
|
|
7
|
+
edit_form: () => {},
|
|
8
|
+
create: () => {},
|
|
9
|
+
update: () => {},
|
|
10
|
+
destroy: () => {},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const OrdersHandlerWithFilters = {
|
|
14
|
+
before_filter: () => {},
|
|
15
|
+
after_filter: () => {},
|
|
16
|
+
index: () => {},
|
|
17
|
+
show: () => {},
|
|
18
|
+
create_form: () => {},
|
|
19
|
+
edit_form: () => {},
|
|
20
|
+
create: () => {},
|
|
21
|
+
update: () => {},
|
|
22
|
+
destroy: () => {},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const honoAdapter = {
|
|
26
|
+
createNestedResource: (_mapping) => {},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const adapterSpy = jest.spyOn(honoAdapter, "createNestedResource");
|
|
30
|
+
|
|
31
|
+
describe("createNestedResource", () => {
|
|
32
|
+
test("Valid handler mapping is passed to router", () => {
|
|
33
|
+
createNestedResource(honoAdapter, "orders", "line_items", OrdersHandler);
|
|
34
|
+
|
|
35
|
+
expect(adapterSpy).toHaveBeenCalledWith([
|
|
36
|
+
[
|
|
37
|
+
"GET",
|
|
38
|
+
"/orders/:parent_id/line_items",
|
|
39
|
+
"line_items",
|
|
40
|
+
"index",
|
|
41
|
+
OrdersHandler.index,
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
"GET",
|
|
45
|
+
"/orders/:parent_id/line_items/new",
|
|
46
|
+
"line_items",
|
|
47
|
+
"create_form",
|
|
48
|
+
OrdersHandler.create_form,
|
|
49
|
+
],
|
|
50
|
+
["GET", "/line_items/:id", "line_items", "show", OrdersHandler.show],
|
|
51
|
+
[
|
|
52
|
+
"GET",
|
|
53
|
+
"/line_items/:id/edit",
|
|
54
|
+
"line_items",
|
|
55
|
+
"edit_form",
|
|
56
|
+
OrdersHandler.edit_form,
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"POST",
|
|
60
|
+
"/orders/:parent_id/line_items",
|
|
61
|
+
"line_items",
|
|
62
|
+
"create",
|
|
63
|
+
OrdersHandler.create,
|
|
64
|
+
],
|
|
65
|
+
["PUT", "/line_items/:id", "line_items", "update", OrdersHandler.update],
|
|
66
|
+
[
|
|
67
|
+
"DELETE",
|
|
68
|
+
"/line_items/:id",
|
|
69
|
+
"line_items",
|
|
70
|
+
"destroy",
|
|
71
|
+
OrdersHandler.destroy,
|
|
72
|
+
],
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("Valid handler mapping is passed to router with filters", () => {
|
|
77
|
+
createNestedResource(
|
|
78
|
+
honoAdapter,
|
|
79
|
+
"orders",
|
|
80
|
+
"line_items",
|
|
81
|
+
OrdersHandlerWithFilters
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(adapterSpy).toHaveBeenCalledWith([
|
|
85
|
+
[
|
|
86
|
+
"GET",
|
|
87
|
+
"/orders/:parent_id/line_items",
|
|
88
|
+
"line_items",
|
|
89
|
+
"index",
|
|
90
|
+
OrdersHandlerWithFilters.index,
|
|
91
|
+
OrdersHandlerWithFilters.before_filter,
|
|
92
|
+
OrdersHandlerWithFilters.after_filter,
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
"GET",
|
|
96
|
+
"/orders/:parent_id/line_items/new",
|
|
97
|
+
"line_items",
|
|
98
|
+
"create_form",
|
|
99
|
+
OrdersHandlerWithFilters.create_form,
|
|
100
|
+
OrdersHandlerWithFilters.before_filter,
|
|
101
|
+
OrdersHandlerWithFilters.after_filter,
|
|
102
|
+
],
|
|
103
|
+
[
|
|
104
|
+
"GET",
|
|
105
|
+
"/line_items/:id",
|
|
106
|
+
"line_items",
|
|
107
|
+
"show",
|
|
108
|
+
OrdersHandlerWithFilters.show,
|
|
109
|
+
OrdersHandlerWithFilters.before_filter,
|
|
110
|
+
OrdersHandlerWithFilters.after_filter,
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
"GET",
|
|
114
|
+
"/line_items/:id/edit",
|
|
115
|
+
"line_items",
|
|
116
|
+
"edit_form",
|
|
117
|
+
OrdersHandlerWithFilters.edit_form,
|
|
118
|
+
OrdersHandlerWithFilters.before_filter,
|
|
119
|
+
OrdersHandlerWithFilters.after_filter,
|
|
120
|
+
],
|
|
121
|
+
[
|
|
122
|
+
"POST",
|
|
123
|
+
"/orders/:parent_id/line_items",
|
|
124
|
+
"line_items",
|
|
125
|
+
"create",
|
|
126
|
+
OrdersHandlerWithFilters.create,
|
|
127
|
+
OrdersHandlerWithFilters.before_filter,
|
|
128
|
+
OrdersHandlerWithFilters.after_filter,
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
"PUT",
|
|
132
|
+
"/line_items/:id",
|
|
133
|
+
"line_items",
|
|
134
|
+
"update",
|
|
135
|
+
OrdersHandlerWithFilters.update,
|
|
136
|
+
OrdersHandlerWithFilters.before_filter,
|
|
137
|
+
OrdersHandlerWithFilters.after_filter,
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
"DELETE",
|
|
141
|
+
"/line_items/:id",
|
|
142
|
+
"line_items",
|
|
143
|
+
"destroy",
|
|
144
|
+
OrdersHandlerWithFilters.destroy,
|
|
145
|
+
OrdersHandlerWithFilters.before_filter,
|
|
146
|
+
OrdersHandlerWithFilters.after_filter,
|
|
147
|
+
],
|
|
148
|
+
]);
|
|
149
|
+
});
|
|
150
|
+
});
|