@isardsat/editorial-server 6.0.3 → 6.0.5
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/dist/app.js +0 -2
- package/dist/lib/hooks.d.ts +2 -2
- package/dist/lib/hooks.js +10 -18
- package/dist/lib/storage.d.ts +2 -5
- package/dist/lib/storage.js +14 -18
- package/dist/routes/actions.d.ts +3 -3
- package/dist/routes/actions.js +15 -47
- package/dist/routes/data.js +8 -36
- package/dist/routes/files.d.ts +1 -1
- package/dist/routes/files.js +32 -44
- package/package.json +3 -3
package/dist/app.js
CHANGED
|
@@ -7,7 +7,6 @@ import { createHooks } from "./lib/hooks.js";
|
|
|
7
7
|
import { createStorage } from "./lib/storage.js";
|
|
8
8
|
import { createActionRoutes } from "./routes/actions.js";
|
|
9
9
|
import { createAdminRoutes } from "./routes/admin.js";
|
|
10
|
-
import { createConfigRoutes } from "./routes/config.js";
|
|
11
10
|
import { createDataRoutes } from "./routes/data.js";
|
|
12
11
|
import { createFilesRoutes } from "./routes/files.js";
|
|
13
12
|
export const BASE_EDITORIAL_PATH = "./editorial";
|
|
@@ -17,7 +16,6 @@ export async function createEditorialServer({ configDirectory = BASE_EDITORIAL_P
|
|
|
17
16
|
const storage = createStorage(editorialDirectory);
|
|
18
17
|
const hooks = await createHooks(configDirectory);
|
|
19
18
|
app.use(logger());
|
|
20
|
-
app.route("/api/v1", createConfigRoutes(config));
|
|
21
19
|
app.route("/api/v1", createDataRoutes(storage));
|
|
22
20
|
app.route("/api/v1", createFilesRoutes());
|
|
23
21
|
app.route("/api/v1", createActionRoutes(storage, hooks));
|
package/dist/lib/hooks.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare function createHooks(configDirectory: string): Promise<{
|
|
|
2
2
|
onPublish: (content: any, schema: any) => Promise<any>;
|
|
3
3
|
onLocalize: (content: any, schema: any) => Promise<any>;
|
|
4
4
|
onLocalizeEnd: (content: any, schema: any) => Promise<any>;
|
|
5
|
-
onPull: (
|
|
6
|
-
onPush: (
|
|
5
|
+
onPull: () => Promise<any>;
|
|
6
|
+
onPush: () => Promise<any>;
|
|
7
7
|
}>;
|
|
8
8
|
export type Hooks = Awaited<ReturnType<typeof createHooks>>;
|
package/dist/lib/hooks.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { join } from
|
|
1
|
+
import { join } from 'node:path';
|
|
2
2
|
export async function createHooks(configDirectory) {
|
|
3
|
-
const hooksDirPath = join(configDirectory,
|
|
3
|
+
const hooksDirPath = join(configDirectory, 'hooks');
|
|
4
4
|
async function loadHook(name) {
|
|
5
5
|
const hookScript = join(process.cwd(), hooksDirPath, name);
|
|
6
6
|
const module = await import(`${hookScript}.mjs`);
|
|
7
|
-
const hookFunction = typeof module.default ===
|
|
7
|
+
const hookFunction = typeof module.default === 'function' ? module.default : null;
|
|
8
8
|
return hookFunction;
|
|
9
9
|
}
|
|
10
10
|
async function executeHook(hookName, ...args) {
|
|
@@ -14,27 +14,19 @@ export async function createHooks(configDirectory) {
|
|
|
14
14
|
return hook(...args);
|
|
15
15
|
}
|
|
16
16
|
async function onPublish(content, schema) {
|
|
17
|
-
return executeHook(
|
|
17
|
+
return executeHook('onPublish', content, schema);
|
|
18
18
|
}
|
|
19
19
|
async function onLocalize(content, schema) {
|
|
20
|
-
return executeHook(
|
|
20
|
+
return executeHook('onLocalize', content, schema);
|
|
21
21
|
}
|
|
22
22
|
async function onLocalizeEnd(content, schema) {
|
|
23
|
-
return executeHook(
|
|
23
|
+
return executeHook('onLocalizeEnd', content, schema);
|
|
24
24
|
}
|
|
25
|
-
async function onPull(
|
|
26
|
-
|
|
27
|
-
console.info("Dropping onPull hook event in development environment");
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
return executeHook("onPull", author);
|
|
25
|
+
async function onPull() {
|
|
26
|
+
return executeHook('onPull');
|
|
31
27
|
}
|
|
32
|
-
async function onPush(
|
|
33
|
-
|
|
34
|
-
console.info("Dropping onPush hook event in development environment");
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
return executeHook("onPush", author);
|
|
28
|
+
async function onPush() {
|
|
29
|
+
return executeHook('onPush');
|
|
38
30
|
}
|
|
39
31
|
return { onPublish, onLocalize, onLocalizeEnd, onPull, onPush };
|
|
40
32
|
}
|
package/dist/lib/storage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EditorialData, EditorialDataObjectWithType } from
|
|
1
|
+
import type { EditorialData, EditorialDataObjectWithType } from '@isardsat/editorial-common';
|
|
2
2
|
export declare function createStorage(dataDirectory: string): {
|
|
3
3
|
getSchema: () => Promise<Record<string, {
|
|
4
4
|
displayName: string;
|
|
@@ -13,7 +13,6 @@ export declare function createStorage(dataDirectory: string): {
|
|
|
13
13
|
singleton?: boolean | undefined;
|
|
14
14
|
}>>;
|
|
15
15
|
getContent: () => Promise<EditorialData>;
|
|
16
|
-
getLocalisationMessages: (langCode: string) => Promise<any>;
|
|
17
16
|
saveLocalisationMessages: (messages: any) => Promise<boolean>;
|
|
18
17
|
createItem: (item: EditorialDataObjectWithType) => Promise<import("zod").objectOutputType<{
|
|
19
18
|
id: import("zod").ZodString;
|
|
@@ -29,8 +28,6 @@ export declare function createStorage(dataDirectory: string): {
|
|
|
29
28
|
createdAt: import("zod").ZodDefault<import("zod").ZodString>;
|
|
30
29
|
updatedAt: import("zod").ZodDefault<import("zod").ZodString>;
|
|
31
30
|
}, import("zod").ZodTypeAny, "passthrough">>>>;
|
|
32
|
-
|
|
33
|
-
production?: boolean;
|
|
34
|
-
}) => Promise<boolean>;
|
|
31
|
+
saveProdContent: () => Promise<boolean>;
|
|
35
32
|
};
|
|
36
33
|
export type Storage = ReturnType<typeof createStorage>;
|
package/dist/lib/storage.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { EditorialDataItemSchema, EditorialDataSchema, EditorialSchemaSchema, } from
|
|
2
|
-
import { readFile } from
|
|
3
|
-
import { join } from
|
|
4
|
-
import { parse } from
|
|
5
|
-
import { writeFileSafe } from
|
|
1
|
+
import { EditorialDataItemSchema, EditorialDataSchema, EditorialSchemaSchema, } from '@isardsat/editorial-common';
|
|
2
|
+
import { readFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { parse } from 'yaml';
|
|
5
|
+
import { writeFileSafe } from './utils/fs.js';
|
|
6
6
|
export function createStorage(dataDirectory) {
|
|
7
|
-
const schemaPath = join(dataDirectory,
|
|
8
|
-
const dataPath = join(dataDirectory,
|
|
9
|
-
const dataProdPath = join(dataDirectory,
|
|
10
|
-
const dataExtractedPath = join(dataDirectory,
|
|
7
|
+
const schemaPath = join(dataDirectory, 'schema.yaml');
|
|
8
|
+
const dataPath = join(dataDirectory, 'data.json');
|
|
9
|
+
const dataProdPath = join(dataDirectory, 'data.prod.json');
|
|
10
|
+
const dataExtractedPath = join(dataDirectory, 'data.messages.json');
|
|
11
11
|
async function getSchema() {
|
|
12
|
-
const schemaFile = await readFile(schemaPath,
|
|
12
|
+
const schemaFile = await readFile(schemaPath, 'utf-8').then((value) => parse(value));
|
|
13
13
|
const schema = EditorialSchemaSchema.parse(schemaFile);
|
|
14
14
|
return schema;
|
|
15
15
|
}
|
|
@@ -17,14 +17,11 @@ export function createStorage(dataDirectory) {
|
|
|
17
17
|
* TODO: This should ideally cache the result of reading the file until an update occurs.
|
|
18
18
|
*/
|
|
19
19
|
async function getContent() {
|
|
20
|
-
return await readFile(dataPath,
|
|
20
|
+
return await readFile(dataPath, 'utf-8').then((value) => JSON.parse(value));
|
|
21
21
|
}
|
|
22
|
-
async function
|
|
23
|
-
return await readFile(join(dataDirectory, "locales", "messages", `${langCode}.json`), "utf-8").then((value) => JSON.parse(value));
|
|
24
|
-
}
|
|
25
|
-
async function saveContent({ production }) {
|
|
22
|
+
async function saveProdContent() {
|
|
26
23
|
const content = await getContent();
|
|
27
|
-
await writeFileSafe(
|
|
24
|
+
await writeFileSafe(dataProdPath, JSON.stringify(EditorialDataSchema.parse(content), null, 2));
|
|
28
25
|
return true;
|
|
29
26
|
}
|
|
30
27
|
async function saveLocalisationMessages(messages) {
|
|
@@ -61,11 +58,10 @@ export function createStorage(dataDirectory) {
|
|
|
61
58
|
return {
|
|
62
59
|
getSchema,
|
|
63
60
|
getContent,
|
|
64
|
-
getLocalisationMessages,
|
|
65
61
|
saveLocalisationMessages,
|
|
66
62
|
createItem,
|
|
67
63
|
updateItem,
|
|
68
64
|
deleteItem,
|
|
69
|
-
|
|
65
|
+
saveProdContent,
|
|
70
66
|
};
|
|
71
67
|
}
|
package/dist/routes/actions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OpenAPIHono } from
|
|
2
|
-
import type { Hooks } from
|
|
3
|
-
import type { Storage } from
|
|
1
|
+
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
2
|
+
import type { Hooks } from '../lib/hooks.js';
|
|
3
|
+
import type { Storage } from '../lib/storage.js';
|
|
4
4
|
export declare function createActionRoutes(storage: Storage, hooks: Hooks): OpenAPIHono<import("hono").Env, {}, "/">;
|
package/dist/routes/actions.js
CHANGED
|
@@ -1,35 +1,23 @@
|
|
|
1
|
-
import { createRoute, OpenAPIHono, z } from
|
|
2
|
-
const ActionRequestSchema = z.object({
|
|
3
|
-
author: z.string(),
|
|
4
|
-
});
|
|
1
|
+
import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi';
|
|
5
2
|
export function createActionRoutes(storage, hooks) {
|
|
6
3
|
const app = new OpenAPIHono();
|
|
7
4
|
app.openapi(createRoute({
|
|
8
|
-
method:
|
|
9
|
-
path:
|
|
10
|
-
request: {
|
|
11
|
-
body: {
|
|
12
|
-
content: {
|
|
13
|
-
"application/json": {
|
|
14
|
-
schema: ActionRequestSchema,
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
5
|
+
method: 'post',
|
|
6
|
+
path: '/publish',
|
|
19
7
|
responses: {
|
|
20
8
|
202: {
|
|
21
9
|
content: {
|
|
22
|
-
|
|
10
|
+
'application/json': {
|
|
23
11
|
schema: z.boolean(),
|
|
24
12
|
},
|
|
25
13
|
},
|
|
26
|
-
description:
|
|
14
|
+
description: 'Trigger the publishing process',
|
|
27
15
|
},
|
|
28
16
|
},
|
|
29
17
|
}),
|
|
30
18
|
// TODO: Don't async, let the promises run in the background.
|
|
31
19
|
async (c) => {
|
|
32
|
-
await storage.
|
|
20
|
+
await storage.saveProdContent();
|
|
33
21
|
const content = await storage.getContent();
|
|
34
22
|
const schema = await storage.getSchema();
|
|
35
23
|
try {
|
|
@@ -37,53 +25,33 @@ export function createActionRoutes(storage, hooks) {
|
|
|
37
25
|
await storage.saveLocalisationMessages(scriptResult);
|
|
38
26
|
}
|
|
39
27
|
catch (error) {
|
|
40
|
-
console.error(
|
|
28
|
+
console.error('Error executing script:', error);
|
|
41
29
|
return c.json(false);
|
|
42
30
|
}
|
|
43
31
|
return c.json(true);
|
|
44
32
|
});
|
|
45
33
|
app.openapi(createRoute({
|
|
46
|
-
method:
|
|
47
|
-
path:
|
|
48
|
-
request: {
|
|
49
|
-
body: {
|
|
50
|
-
content: {
|
|
51
|
-
"application/json": {
|
|
52
|
-
schema: ActionRequestSchema,
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
},
|
|
34
|
+
method: 'post',
|
|
35
|
+
path: '/pull',
|
|
57
36
|
responses: {
|
|
58
37
|
200: {
|
|
59
|
-
description:
|
|
38
|
+
description: 'Trigger the pull process',
|
|
60
39
|
},
|
|
61
40
|
},
|
|
62
41
|
}), async (c) => {
|
|
63
|
-
|
|
64
|
-
await hooks.onPull(author);
|
|
42
|
+
await hooks.onPull();
|
|
65
43
|
return c.json(true);
|
|
66
44
|
});
|
|
67
45
|
app.openapi(createRoute({
|
|
68
|
-
method:
|
|
69
|
-
path:
|
|
70
|
-
request: {
|
|
71
|
-
body: {
|
|
72
|
-
content: {
|
|
73
|
-
"application/json": {
|
|
74
|
-
schema: ActionRequestSchema,
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
46
|
+
method: 'post',
|
|
47
|
+
path: '/push',
|
|
79
48
|
responses: {
|
|
80
49
|
200: {
|
|
81
|
-
description:
|
|
50
|
+
description: 'Trigger the push process',
|
|
82
51
|
},
|
|
83
52
|
},
|
|
84
53
|
}), async (c) => {
|
|
85
|
-
|
|
86
|
-
await hooks.onPush(author);
|
|
54
|
+
await hooks.onPush();
|
|
87
55
|
return c.json(true);
|
|
88
56
|
});
|
|
89
57
|
return app;
|
package/dist/routes/data.js
CHANGED
|
@@ -45,14 +45,12 @@ export function createDataRoutes(storage) {
|
|
|
45
45
|
param: { name: "itemType", in: "path" },
|
|
46
46
|
example: "newsItem",
|
|
47
47
|
}),
|
|
48
|
-
|
|
49
|
-
query: z.object({
|
|
50
|
-
lang: z
|
|
48
|
+
locale: z
|
|
51
49
|
.string()
|
|
52
50
|
.optional()
|
|
53
51
|
.openapi({
|
|
54
|
-
param: { name: "
|
|
55
|
-
example: "
|
|
52
|
+
param: { name: "locale", in: "query" },
|
|
53
|
+
example: "es_ES",
|
|
56
54
|
}),
|
|
57
55
|
}),
|
|
58
56
|
},
|
|
@@ -68,20 +66,8 @@ export function createDataRoutes(storage) {
|
|
|
68
66
|
},
|
|
69
67
|
}), async (c) => {
|
|
70
68
|
const { itemType } = c.req.valid("param");
|
|
71
|
-
const { lang } = c.req.valid("query");
|
|
72
69
|
const content = await storage.getContent();
|
|
73
|
-
|
|
74
|
-
// TODO: Formalize this process.
|
|
75
|
-
if (lang) {
|
|
76
|
-
const messages = await storage.getLocalisationMessages(lang);
|
|
77
|
-
for (const [key, message] of Object.entries(messages)) {
|
|
78
|
-
const [contentKey, typeKey, fieldKey, hash] = key.split(".");
|
|
79
|
-
if (contentKey === itemType) {
|
|
80
|
-
collection[typeKey][fieldKey] = message.defaultMessage;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return c.json(collection);
|
|
70
|
+
return c.json(content[itemType]);
|
|
85
71
|
});
|
|
86
72
|
app.openapi(createRoute({
|
|
87
73
|
method: "get",
|
|
@@ -122,14 +108,12 @@ export function createDataRoutes(storage) {
|
|
|
122
108
|
param: { name: "id", in: "path" },
|
|
123
109
|
example: "about-us",
|
|
124
110
|
}),
|
|
125
|
-
|
|
126
|
-
query: z.object({
|
|
127
|
-
lang: z
|
|
111
|
+
locale: z
|
|
128
112
|
.string()
|
|
129
113
|
.optional()
|
|
130
114
|
.openapi({
|
|
131
|
-
param: { name: "
|
|
132
|
-
example: "
|
|
115
|
+
param: { name: "locale", in: "query" },
|
|
116
|
+
example: "es_ES",
|
|
133
117
|
}),
|
|
134
118
|
}),
|
|
135
119
|
},
|
|
@@ -145,20 +129,8 @@ export function createDataRoutes(storage) {
|
|
|
145
129
|
},
|
|
146
130
|
}), async (c) => {
|
|
147
131
|
const { itemType, id } = c.req.valid("param");
|
|
148
|
-
const { lang } = c.req.valid("query");
|
|
149
132
|
const content = await storage.getContent();
|
|
150
|
-
|
|
151
|
-
// TODO: Formalize this process.
|
|
152
|
-
if (lang) {
|
|
153
|
-
const messages = await storage.getLocalisationMessages(lang);
|
|
154
|
-
for (const [key, message] of Object.entries(messages)) {
|
|
155
|
-
const [contentKey, typeKey, fieldKey, hash] = key.split(".");
|
|
156
|
-
if (typeKey === id) {
|
|
157
|
-
item[fieldKey] = message.defaultMessage;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return c.json(item);
|
|
133
|
+
return c.json(content[itemType][id]);
|
|
162
134
|
});
|
|
163
135
|
app.openapi(createRoute({
|
|
164
136
|
method: "put",
|
package/dist/routes/files.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { OpenAPIHono } from
|
|
1
|
+
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
2
2
|
export declare function createFilesRoutes(): OpenAPIHono<import("hono").Env, {}, "/">;
|
package/dist/routes/files.js
CHANGED
|
@@ -1,41 +1,30 @@
|
|
|
1
|
-
import { createRoute, OpenAPIHono, z } from
|
|
2
|
-
import {
|
|
3
|
-
import { readdirSync, statSync } from
|
|
4
|
-
import { access, constants, mkdir, rename } from
|
|
5
|
-
import { basename, join, normalize } from
|
|
1
|
+
import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi';
|
|
2
|
+
import { EditorialFilesSchema, } from '@isardsat/editorial-common';
|
|
3
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
4
|
+
import { access, constants, mkdir, rename } from 'node:fs/promises';
|
|
5
|
+
import { basename, join, normalize } from 'node:path';
|
|
6
6
|
export function createFilesRoutes() {
|
|
7
7
|
const app = new OpenAPIHono();
|
|
8
|
-
const publicDirPath =
|
|
9
|
-
const deletedDirPath =
|
|
8
|
+
const publicDirPath = 'public';
|
|
9
|
+
const deletedDirPath = 'public/.deleted';
|
|
10
10
|
app.openapi(createRoute({
|
|
11
|
-
method:
|
|
12
|
-
path:
|
|
11
|
+
method: 'get',
|
|
12
|
+
path: '/files',
|
|
13
13
|
responses: {
|
|
14
14
|
200: {
|
|
15
15
|
content: {
|
|
16
|
-
|
|
17
|
-
schema:
|
|
16
|
+
'application/json': {
|
|
17
|
+
schema: EditorialFilesSchema,
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
|
-
description:
|
|
20
|
+
description: 'Get tree of public files',
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
}), async (c) => {
|
|
24
|
-
function calculateTotalSize(files) {
|
|
25
|
-
return files.reduce((total, file) => {
|
|
26
|
-
if (file.type === "file") {
|
|
27
|
-
return total + file.size;
|
|
28
|
-
}
|
|
29
|
-
else if (file.children) {
|
|
30
|
-
return total + calculateTotalSize(file.children);
|
|
31
|
-
}
|
|
32
|
-
return total;
|
|
33
|
-
}, 0);
|
|
34
|
-
}
|
|
35
24
|
function readDirectoryChildren(path) {
|
|
36
25
|
const directory = readdirSync(path);
|
|
37
26
|
return directory
|
|
38
|
-
.filter((fileName) => !fileName.startsWith(
|
|
27
|
+
.filter((fileName) => !fileName.startsWith('.'))
|
|
39
28
|
.map((fileName) => {
|
|
40
29
|
const file = statSync(join(path, fileName));
|
|
41
30
|
const isDirectory = file.isDirectory();
|
|
@@ -43,25 +32,24 @@ export function createFilesRoutes() {
|
|
|
43
32
|
name: basename(fileName),
|
|
44
33
|
path: join(path, fileName),
|
|
45
34
|
size: file.size,
|
|
46
|
-
type: isDirectory ?
|
|
35
|
+
type: isDirectory ? 'directory' : 'file',
|
|
47
36
|
children: isDirectory
|
|
48
37
|
? readDirectoryChildren(join(path, fileName))
|
|
49
38
|
: undefined,
|
|
50
39
|
};
|
|
51
40
|
})
|
|
52
|
-
.sort((a, b) => (a.type ===
|
|
41
|
+
.sort((a, b) => (a.type === 'directory' ? -1 : 0));
|
|
53
42
|
}
|
|
54
43
|
const files = readDirectoryChildren(publicDirPath);
|
|
55
|
-
|
|
56
|
-
return c.json({ files, totalSize });
|
|
44
|
+
return c.json(files);
|
|
57
45
|
});
|
|
58
46
|
app.openapi(createRoute({
|
|
59
|
-
method:
|
|
60
|
-
path:
|
|
47
|
+
method: 'delete',
|
|
48
|
+
path: '/files',
|
|
61
49
|
request: {
|
|
62
50
|
body: {
|
|
63
51
|
content: {
|
|
64
|
-
|
|
52
|
+
'application/json': {
|
|
65
53
|
schema: z.object({
|
|
66
54
|
path: z.string(),
|
|
67
55
|
}),
|
|
@@ -73,55 +61,55 @@ export function createFilesRoutes() {
|
|
|
73
61
|
responses: {
|
|
74
62
|
200: {
|
|
75
63
|
content: {
|
|
76
|
-
|
|
64
|
+
'application/json': {
|
|
77
65
|
schema: z.boolean(),
|
|
78
66
|
},
|
|
79
67
|
},
|
|
80
|
-
description:
|
|
68
|
+
description: '',
|
|
81
69
|
},
|
|
82
70
|
400: {
|
|
83
71
|
content: {
|
|
84
|
-
|
|
72
|
+
'application/json': {
|
|
85
73
|
schema: z.object({
|
|
86
74
|
error: z.string(),
|
|
87
75
|
}),
|
|
88
76
|
},
|
|
89
77
|
},
|
|
90
|
-
description:
|
|
78
|
+
description: 'Invalid file path',
|
|
91
79
|
},
|
|
92
80
|
404: {
|
|
93
81
|
content: {
|
|
94
|
-
|
|
82
|
+
'application/json': {
|
|
95
83
|
schema: z.object({
|
|
96
84
|
error: z.string(),
|
|
97
85
|
}),
|
|
98
86
|
},
|
|
99
87
|
},
|
|
100
|
-
description:
|
|
88
|
+
description: 'File not found',
|
|
101
89
|
},
|
|
102
90
|
500: {
|
|
103
91
|
content: {
|
|
104
|
-
|
|
92
|
+
'application/json': {
|
|
105
93
|
schema: z.object({
|
|
106
94
|
error: z.string(),
|
|
107
95
|
}),
|
|
108
96
|
},
|
|
109
97
|
},
|
|
110
|
-
description:
|
|
98
|
+
description: 'Server error',
|
|
111
99
|
},
|
|
112
100
|
},
|
|
113
101
|
}), async (c) => {
|
|
114
|
-
const { path: filePath } = c.req.valid(
|
|
102
|
+
const { path: filePath } = c.req.valid('json');
|
|
115
103
|
try {
|
|
116
104
|
const normalizedPath = normalize(filePath);
|
|
117
105
|
if (!normalizedPath.startsWith(publicDirPath)) {
|
|
118
|
-
return c.json({ error:
|
|
106
|
+
return c.json({ error: 'Invalid file path' }, 400);
|
|
119
107
|
}
|
|
120
108
|
const exists = await access(filePath, constants.W_OK)
|
|
121
109
|
.then(() => true)
|
|
122
110
|
.catch(() => false);
|
|
123
111
|
if (!exists) {
|
|
124
|
-
return c.json({ error:
|
|
112
|
+
return c.json({ error: 'File not found' }, 404);
|
|
125
113
|
}
|
|
126
114
|
// Move to deleted directory
|
|
127
115
|
await mkdir(deletedDirPath, { recursive: true });
|
|
@@ -129,8 +117,8 @@ export function createFilesRoutes() {
|
|
|
129
117
|
return c.json(true, 200);
|
|
130
118
|
}
|
|
131
119
|
catch (err) {
|
|
132
|
-
console.error(
|
|
133
|
-
return c.json({ error:
|
|
120
|
+
console.error('Delete failed:', err);
|
|
121
|
+
return c.json({ error: 'Server error' }, 500);
|
|
134
122
|
}
|
|
135
123
|
});
|
|
136
124
|
return app;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isardsat/editorial-server",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"hono": "^4.6.20",
|
|
15
15
|
"yaml": "^2.7.0",
|
|
16
16
|
"zod": "^3.24.1",
|
|
17
|
-
"@isardsat/editorial-
|
|
18
|
-
"@isardsat/editorial-
|
|
17
|
+
"@isardsat/editorial-common": "^6.0.5",
|
|
18
|
+
"@isardsat/editorial-admin": "^6.0.5"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@tsconfig/node22": "^22.0.0",
|