@raketa-cloud/admin 1.2.0 → 1.4.0

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.
Files changed (41) hide show
  1. package/package.json +1 -1
  2. package/src/HonoAdapter.js +304 -169
  3. package/src/filters.js +17 -0
  4. package/src/handlers/article_revisions/ArticleRevisionsHandler.js +8 -0
  5. package/src/handlers/articles/ArticlesHandler.js +12 -1
  6. package/src/handlers/event_revisions/EventRevisionsHandler.js +8 -0
  7. package/src/handlers/events/EventsHandler.js +13 -2
  8. package/src/handlers/page_revisions/PageRevisionsHandler.js +8 -0
  9. package/src/handlers/pages/PagesHandler.js +12 -1
  10. package/src/index.js +1 -0
  11. package/src/routeCollection.js +14 -83
  12. package/src/routeMember.js +10 -33
  13. package/src/routeNestedCollection.js +19 -47
  14. package/src/routeNestedMember.js +14 -40
  15. package/src/tests/Adapter.test.js +4 -4
  16. package/src/tests/HonoAdapter.filter.test.js +40 -0
  17. package/src/tests/HonoAdapter.test.js +110 -9
  18. package/src/tests/RaketaContext.test.js +65 -0
  19. package/src/tests/cipher.test.js +73 -0
  20. package/src/tests/filters.test.js +97 -0
  21. package/src/tests/handlers/article_revisions/ArticleRevisionsHandler.test/create.test.js +43 -35
  22. package/src/tests/handlers/articles/ArticlesHandler.test/show.test.js +12 -1
  23. package/src/tests/handlers/event_revisions/EventRevisionsHandler.test/create.test.js +41 -33
  24. package/src/tests/handlers/events/EventsHandler.test/show.test.js +12 -1
  25. package/src/tests/handlers/page_revisions/PageRevisionsHandler.test/create.test.js +41 -27
  26. package/src/tests/handlers/pages/PagesHandler.test/show.test.js +12 -1
  27. package/src/tests/routeCollection.test.js +0 -92
  28. package/src/tests/routeMember.test.js +0 -6
  29. package/src/tests/routeNestedCollection.test.js +0 -14
  30. package/src/tests/routeNestedMember.test.js +0 -6
  31. package/src/tests/utils.test.js +70 -0
  32. package/src/views/articles/_shared/_history_toolbar.ejs +2 -2
  33. package/src/views/articles/_shared/_toolbar.ejs +38 -26
  34. package/src/views/articles/_shared/history_table.ejs +6 -0
  35. package/src/views/events/_shared/_history_toolbar.ejs +2 -2
  36. package/src/views/events/_shared/_toolbar.ejs +38 -26
  37. package/src/views/events/_shared/history_table.ejs +6 -0
  38. package/src/views/pages/_shared/_history_toolbar.ejs +2 -2
  39. package/src/views/pages/_shared/_toolbar.ejs +38 -26
  40. package/src/views/pages/_shared/history_table.ejs +6 -0
  41. package/src/Adapter.js +0 -265
package/src/Adapter.js DELETED
@@ -1,265 +0,0 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import path from "node:path";
3
- import ejs from "ejs";
4
- import Logger from "./Logger";
5
- import currentPath from "./currentPath.cjs";
6
- import FormBuilder from "./helpers/FormBuilder";
7
- import HTMLBuilder from "./helpers/HTMLBuilder";
8
- import Inflector from "./helpers/Inflector";
9
- import form_for from "./helpers/form_for";
10
- import history from "./helpers/historyUtils";
11
- import pagination from "./helpers/pagination_helper";
12
- import sort_button from "./helpers/sort_button";
13
- import utils from "./helpers/utils";
14
-
15
- function escapeHtml(string) {
16
- var matchHtmlRegExp = /["'&<>]/;
17
-
18
- var str = "" + string;
19
- var match = matchHtmlRegExp.exec(str);
20
-
21
- if (!match) {
22
- return str;
23
- }
24
-
25
- var escape;
26
- var html = "";
27
- var index = 0;
28
- var lastIndex = 0;
29
-
30
- for (index = match.index; index < str.length; index++) {
31
- switch (str.charCodeAt(index)) {
32
- case 34: // "
33
- escape = "&quot;";
34
- break;
35
- case 38: // &
36
- escape = "&amp;";
37
- break;
38
- case 39: // '
39
- escape = "&#39;";
40
- break;
41
- case 60: // <
42
- escape = "&lt;";
43
- break;
44
- case 62: // >
45
- escape = "&gt;";
46
- break;
47
- default:
48
- continue;
49
- }
50
-
51
- if (lastIndex !== index) {
52
- html += str.substring(lastIndex, index);
53
- }
54
-
55
- lastIndex = index + 1;
56
- html += escape;
57
- }
58
-
59
- return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
60
- }
61
-
62
- const renderError = (message, stack) => {
63
- const errorCSS = `
64
- * { box-sizing: border-box; margin: 0; padding: 0; }
65
- html { font-family: sans-serif; font-size: 16px; padding: 2rem; background-color: pink; }
66
- h1 { margin-bottom: 1rem; color: FireBrick; }
67
- .fail-squid { font-size: 7rem; }
68
- pre { padding: 1.5rem 2rem; border-radius: 0.5rem; background-color: black; color: white; line-height: 1.5; font-size: 1.25rem; }
69
- `;
70
- return `<style>${errorCSS}</style><div class="fail-squid">🦑</div><h1>${message}</h1><pre>${escapeHtml(stack)}</pre>`;
71
- };
72
-
73
- function toArray(value) {
74
- if (Array.isArray(value)) {
75
- return value;
76
- }
77
-
78
- return [value].filter(Boolean);
79
- }
80
-
81
- function putIn(result, key, value) {
82
- const segments = key.split(/[\[\]]+/).filter(Boolean);
83
- let current = result;
84
-
85
- segments.forEach((segment, idx) => {
86
- if (idx === segments.length - 1) {
87
- if (key.endsWith("[]") || Array.isArray(value)) {
88
- current[segment] = toArray(value);
89
- } else {
90
- current[segment] = value;
91
- }
92
- } else {
93
- if (!current[segment]) {
94
- current[segment] = {};
95
- }
96
-
97
- current = current[segment];
98
- }
99
- });
100
- }
101
-
102
- function sanitizePath(filePath) {
103
- return path.normalize(path.join(...["/", ...filePath.split("/")]));
104
- }
105
-
106
- function getPartialPath(partialPath, views, viewsFallback) {
107
- const packagePath = sanitizePath(
108
- `${currentPath}/views/${views}/${partialPath}`
109
- );
110
-
111
- const fallbackPackagePath = sanitizePath(
112
- `${currentPath}/views/${viewsFallback}/${partialPath}`
113
- );
114
-
115
- const appPath = sanitizePath(
116
- `${process.cwd()}/src/views/${views}/${partialPath}`
117
- );
118
-
119
- if (existsSync(appPath)) {
120
- return appPath;
121
- }
122
-
123
- if (existsSync(packagePath)) {
124
- return packagePath;
125
- }
126
-
127
- if (existsSync(fallbackPackagePath)) {
128
- return fallbackPackagePath;
129
- }
130
-
131
- throw new Error(
132
- `Looked for "${partialPath}" in the following places: \n${appPath}\n${packagePath}\n${fallbackPackagePath}\n`
133
- );
134
- }
135
-
136
- export default class Adapter {
137
- constructor(router) {
138
- this.router = router;
139
- }
140
-
141
- routeCollection(_resource, _mapping, _resourceConfig) {
142
- throw new Error("Implement in an adapter");
143
- }
144
-
145
- routeNestedCollection(_resource, _mapping, _resourceConfig) {
146
- throw new Error("Implement in an adapter");
147
- }
148
-
149
- routeMember(_resource, _mapping, _resourceConfig) {
150
- throw new Error("Implement in an adapter");
151
- }
152
-
153
- routeNestedMember(_resource, _mapping, _resourceConfig) {
154
- throw new Error("Implement in an adapter");
155
- }
156
-
157
- getActionPath(views, viewsFallback, action) {
158
- const packagePath = viewsFallback
159
- ? `${currentPath}/views/${viewsFallback}/${action}.ejs`
160
- : `${currentPath}/views/${views}/${action}.ejs`;
161
-
162
- const appPath = `${process.cwd()}/src/views/${views}/${action}.ejs`;
163
-
164
- return existsSync(appPath) ? appPath : packagePath;
165
- }
166
-
167
- getHelpers(viewHelpersConfig) {
168
- const t = new HTMLBuilder();
169
- const f = new FormBuilder();
170
-
171
- return {
172
- t,
173
- f,
174
- form_for: form_for(viewHelpersConfig),
175
- history,
176
- utils,
177
- sort_button,
178
- pagination,
179
- Inflector,
180
- };
181
- }
182
-
183
- async renderLayout(assigns, body) {
184
- const layoutTemplate = `${currentPath}/views/layouts/application.ejs`;
185
-
186
- return await ejs.renderFile(layoutTemplate, {
187
- ...assigns,
188
- body,
189
- });
190
- }
191
-
192
- renderPartial(assigns, views, viewsFallback) {
193
- return function render(relativePath, localAssigns) {
194
- const partialPath = getPartialPath(relativePath, views, viewsFallback);
195
-
196
- try {
197
- // Synchronously read the partial file as ejs does not support async/await
198
- const partialTemplate = readFileSync(partialPath, "utf8");
199
- const rendered = ejs.render(
200
- partialTemplate,
201
- {
202
- ...assigns,
203
- ...localAssigns,
204
- },
205
- { filename: partialPath }
206
- );
207
-
208
- return rendered;
209
- } catch (e) {
210
- const error = `Error rendering:\n ${partialPath}`;
211
- Logger.error(`${error}\n\n${e.stack}`);
212
-
213
- return renderError(error, e.stack);
214
- }
215
- };
216
- }
217
-
218
- async renderAction(
219
- { views, viewsFallback, action, assigns },
220
- viewHelpersConfig = {}
221
- ) {
222
- // Pick the parent here in the views so we can reuse stuff...
223
- const fullTemplatePath = this.getActionPath(views, viewsFallback, action);
224
- const renderAssigns = { ...this.getHelpers(viewHelpersConfig), ...assigns };
225
- const renderPartialHelper = this.renderPartial(
226
- renderAssigns,
227
- views,
228
- viewsFallback
229
- );
230
-
231
- try {
232
- // Synchronously read the full template file
233
- const template = readFileSync(fullTemplatePath, "utf8");
234
-
235
- // Render the full template with synchronous partial rendering
236
- const rendered = ejs.render(
237
- template,
238
- {
239
- ...renderAssigns,
240
- render_partial: renderPartialHelper,
241
- },
242
- { filename: fullTemplatePath }
243
- );
244
-
245
- const fullPage = this.renderLayout(renderAssigns, rendered);
246
-
247
- return fullPage;
248
- } catch (e) {
249
- const error = `Error rendering:\n ${fullTemplatePath}`;
250
- Logger.error(`${error}\n\n${e.stack}`);
251
-
252
- return renderError(error, e.stack);
253
- }
254
- }
255
-
256
- parseFormBody(body) {
257
- const result = {};
258
-
259
- for (const [key, value] of Object.entries(body)) {
260
- putIn(result, key, value);
261
- }
262
-
263
- return { ...result };
264
- }
265
- }