@xleddyl/nuxt-cms 0.1.29 → 0.1.30
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/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -11,6 +11,30 @@ import { minifyIntrospection, outputIntrospectionFile } from 'gql.tada/internal'
|
|
|
11
11
|
import { createJiti } from 'jiti';
|
|
12
12
|
import { typeName, blockTypeName, blockUnionName, renderGraphqlSdl } from '../dist/runtime/shared/graphql-sdl.js';
|
|
13
13
|
import { isMultiSelect, isTranslatableField, isTranslatableMediaField, DEFAULT_MEDIA_MAX_FILE_SIZE } from '../dist/runtime/shared/index.js';
|
|
14
|
+
import { scanMediaDirectory, readMediaFileMeta } from '../dist/runtime/server/utils/media-sync.js';
|
|
15
|
+
|
|
16
|
+
async function collectMediaManifest(root) {
|
|
17
|
+
const files = await scanMediaDirectory(root);
|
|
18
|
+
return Promise.all(files.map((file) => readMediaFileMeta(root, file)));
|
|
19
|
+
}
|
|
20
|
+
function renderMediaManifestFile(files) {
|
|
21
|
+
return [
|
|
22
|
+
`export const generated = ${files !== null}`,
|
|
23
|
+
``,
|
|
24
|
+
`export const files = ${JSON.stringify(files ?? [], null, 3)}`,
|
|
25
|
+
``
|
|
26
|
+
].join("\n");
|
|
27
|
+
}
|
|
28
|
+
function renderMediaManifestTypes(typesPath) {
|
|
29
|
+
return [
|
|
30
|
+
`import type { MediaFileMeta } from '${typesPath}'`,
|
|
31
|
+
``,
|
|
32
|
+
`export declare const generated: boolean`,
|
|
33
|
+
``,
|
|
34
|
+
`export declare const files: MediaFileMeta[]`,
|
|
35
|
+
``
|
|
36
|
+
].join("\n");
|
|
37
|
+
}
|
|
14
38
|
|
|
15
39
|
const IDENTIFIER = /^[a-z_]\w*$/i;
|
|
16
40
|
const RESERVED_ENTRY_KEYS = ["admin", "auth", "login", "media", "graphql", "cms_media"];
|
|
@@ -697,6 +721,30 @@ const module$1 = defineNuxtModule({
|
|
|
697
721
|
``
|
|
698
722
|
].join("\n")
|
|
699
723
|
});
|
|
724
|
+
const publicDir = resolve(nuxt.options.rootDir, nuxt.options.dir?.public ?? "public");
|
|
725
|
+
const mediaLocalRoot = resolved.media.storage === "local" && resolved.media.publicBaseUrl.startsWith("/") ? join(publicDir, ...resolved.media.publicBaseUrl.split("/").filter(Boolean)) : "";
|
|
726
|
+
addTemplate({
|
|
727
|
+
filename: "cms/media-manifest.d.ts",
|
|
728
|
+
write: true,
|
|
729
|
+
getContents: () => renderMediaManifestTypes(
|
|
730
|
+
toPosix(resolver.resolve("./runtime/server/utils/media-sync"))
|
|
731
|
+
)
|
|
732
|
+
});
|
|
733
|
+
const mediaManifestTemplate = addTemplate({
|
|
734
|
+
filename: "cms/media-manifest.js",
|
|
735
|
+
write: true,
|
|
736
|
+
getContents: async () => {
|
|
737
|
+
if (!mediaLocalRoot || nuxt.options.dev) return renderMediaManifestFile(null);
|
|
738
|
+
if (!existsSync(mediaLocalRoot)) {
|
|
739
|
+
logger.warn(
|
|
740
|
+
`[nuxt-cms] Local media folder not found at build time: ${mediaLocalRoot}. The media library will not be synced at runtime.`
|
|
741
|
+
);
|
|
742
|
+
return renderMediaManifestFile(null);
|
|
743
|
+
}
|
|
744
|
+
return renderMediaManifestFile(await collectMediaManifest(mediaLocalRoot));
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
nuxt.options.alias["#cms-media-manifest"] = mediaManifestTemplate.dst;
|
|
700
748
|
addServerPlugin(
|
|
701
749
|
resolver.resolve(
|
|
702
750
|
driver === "postgres" ? "./runtime/server/plugins/migrate-postgres" : driver === "libsql" ? "./runtime/server/plugins/migrate-libsql" : "./runtime/server/plugins/migrate-sqlite"
|
|
@@ -726,8 +774,6 @@ const module$1 = defineNuxtModule({
|
|
|
726
774
|
logger.error(`[nuxt-cms] drizzle-kit generate failed (exit code ${code})`);
|
|
727
775
|
});
|
|
728
776
|
}
|
|
729
|
-
const publicDir = resolve(nuxt.options.rootDir, nuxt.options.dir?.public ?? "public");
|
|
730
|
-
const mediaLocalRoot = resolved.media.storage === "local" && resolved.media.publicBaseUrl.startsWith("/") ? join(publicDir, ...resolved.media.publicBaseUrl.split("/").filter(Boolean)) : "";
|
|
731
777
|
const existingConfig = nuxt.options.runtimeConfig.cms ?? {};
|
|
732
778
|
nuxt.options.runtimeConfig.cms = {
|
|
733
779
|
adminEmail: resolved.admin.email,
|
|
@@ -1,39 +1,56 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { eq, inArray } from "drizzle-orm";
|
|
3
3
|
import { useDb } from "#cms-db";
|
|
4
|
+
import { files as manifestFiles, generated as manifestGenerated } from "#cms-media-manifest";
|
|
4
5
|
import { cms_media } from "#cms-tables";
|
|
5
6
|
import { useRuntimeConfig } from "#imports";
|
|
6
7
|
import { chunked, planMediaSync, readMediaFileMeta, scanMediaDirectory } from "../utils/media-sync.js";
|
|
7
8
|
const CHUNK_SIZE = 100;
|
|
9
|
+
async function resolveMediaSource(root) {
|
|
10
|
+
if (existsSync(root)) {
|
|
11
|
+
return {
|
|
12
|
+
origin: root,
|
|
13
|
+
files: await scanMediaDirectory(root),
|
|
14
|
+
meta: (file) => readMediaFileMeta(root, file)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
if (!manifestGenerated) return null;
|
|
18
|
+
const byKey = new Map(manifestFiles.map((file) => [file.key, file]));
|
|
19
|
+
return {
|
|
20
|
+
origin: `build manifest of ${root}`,
|
|
21
|
+
files: manifestFiles.map(({ key, size }) => ({ key, size })),
|
|
22
|
+
meta: async (file) => byKey.get(file.key)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
8
25
|
export default async () => {
|
|
9
26
|
try {
|
|
10
27
|
const { media } = useRuntimeConfig().cms;
|
|
11
28
|
if (media?.storage !== "local") return;
|
|
12
29
|
const root = media.localRoot;
|
|
13
30
|
if (!root) return;
|
|
14
|
-
|
|
31
|
+
const source = await resolveMediaSource(root);
|
|
32
|
+
if (!source) {
|
|
15
33
|
console.info(
|
|
16
|
-
`[nuxt-cms] Local media folder not found: ${root}. Skipping media library sync.`
|
|
34
|
+
`[nuxt-cms] Local media folder not found: ${root}, and no build manifest was generated. Skipping media library sync.`
|
|
17
35
|
);
|
|
18
36
|
return;
|
|
19
37
|
}
|
|
20
|
-
const files = await scanMediaDirectory(root);
|
|
21
38
|
const db = useDb();
|
|
22
39
|
const rows = await db.select({ key: cms_media.key, size: cms_media.size }).from(cms_media);
|
|
23
|
-
const { insert, update, remove } = planMediaSync(files, rows);
|
|
40
|
+
const { insert, update, remove } = planMediaSync(source.files, rows);
|
|
24
41
|
for (const chunk of chunked(insert, CHUNK_SIZE)) {
|
|
25
|
-
const values = await Promise.all(chunk.map((file) =>
|
|
42
|
+
const values = await Promise.all(chunk.map((file) => source.meta(file)));
|
|
26
43
|
await db.insert(cms_media).values(values.map((value) => ({ ...value, alt: null }))).onConflictDoNothing();
|
|
27
44
|
}
|
|
28
45
|
for (const file of update) {
|
|
29
|
-
const { mime, size, width, height } = await
|
|
46
|
+
const { mime, size, width, height } = await source.meta(file);
|
|
30
47
|
await db.update(cms_media).set({ mime, size, width, height }).where(eq(cms_media.key, file.key));
|
|
31
48
|
}
|
|
32
49
|
for (const chunk of chunked(remove, CHUNK_SIZE)) {
|
|
33
50
|
await db.delete(cms_media).where(inArray(cms_media.key, chunk));
|
|
34
51
|
}
|
|
35
52
|
console.info(
|
|
36
|
-
`[nuxt-cms] Local media sync: ${insert.length} added, ${remove.length} removed, ${update.length} updated (${files.length} file${files.length === 1 ? "" : "s"} in ${
|
|
53
|
+
`[nuxt-cms] Local media sync: ${insert.length} added, ${remove.length} removed, ${update.length} updated (${source.files.length} file${source.files.length === 1 ? "" : "s"} in ${source.origin})`
|
|
37
54
|
);
|
|
38
55
|
} catch (error) {
|
|
39
56
|
console.warn("[nuxt-cms] Local media sync failed:", error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xleddyl/nuxt-cms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "Lightweight CMS that ships with your Nuxt app: runs on the Nitro server, content types defined in code, /cms admin panel, GraphQL API, SQLite or Postgres. No external CMS needed!",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Edoardo Alberti (https://github.com/xleddyl)",
|
|
@@ -105,6 +105,6 @@
|
|
|
105
105
|
"test": "vitest run",
|
|
106
106
|
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
107
107
|
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,md,html,json,sql,vue}\" --log-level error",
|
|
108
|
-
"release": "changelogen --release && git push origin main && git push origin v$(node -p \"require('./package.json').version\")"
|
|
108
|
+
"release": "changelogen --release --no-github && git push origin main && git push origin v$(node -p \"require('./package.json').version\")"
|
|
109
109
|
}
|
|
110
110
|
}
|