forgepress 0.0.1 → 0.0.2
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/THIRD-PARTY-LICENSES.md +28 -83
- package/dist/_chunks/client.d.mts +1 -1
- package/dist/_chunks/config.mjs +61 -19
- package/dist/_chunks/{validate.mjs → content.mjs} +350 -217
- package/dist/_chunks/fetch.mjs +2 -2
- package/dist/_chunks/files.mjs +32 -0
- package/dist/_chunks/libs/diff.mjs +485 -0
- package/dist/_chunks/media.mjs +282 -0
- package/dist/_chunks/once.mjs +16 -0
- package/dist/_chunks/output.mjs +98 -252
- package/dist/_chunks/plugin.mjs +87 -0
- package/dist/_chunks/preview.mjs +248 -0
- package/dist/_chunks/project.d.mts +7 -0
- package/dist/_chunks/reader.mjs +5 -9
- package/dist/_chunks/reader2.mjs +150 -202
- package/dist/_chunks/references.mjs +8 -5
- package/dist/_chunks/resolve.d.mts +2 -0
- package/dist/_chunks/response.mjs +5 -0
- package/dist/_chunks/routes.mjs +9 -0
- package/dist/_chunks/serialize.mjs +82 -0
- package/dist/_chunks/settings.mjs +328 -0
- package/dist/_chunks/settings2.mjs +2 -0
- package/dist/_chunks/types.d.mts +229 -24
- package/dist/_chunks/types2.d.mts +25 -0
- package/dist/_chunks/value.mjs +123 -1
- package/dist/cli/bin.mjs +50 -37
- package/dist/editor/index.mjs +9961 -8653
- package/dist/index.d.mts +2 -3
- package/dist/index.mjs +14 -24
- package/dist/next/preview.d.mts +1 -0
- package/dist/next/preview.mjs +3 -0
- package/dist/next/reload.d.mts +1 -0
- package/dist/next/reload.mjs +20 -0
- package/dist/next/settings.d.mts +12 -0
- package/dist/next/settings.mjs +2 -0
- package/dist/plugin/next.d.mts +11 -0
- package/dist/plugin/next.mjs +213 -0
- package/dist/plugin/nuxt.d.mts +7 -0
- package/dist/plugin/nuxt.mjs +52 -0
- package/dist/plugin/watcher.d.mts +1 -0
- package/dist/plugin/watcher.mjs +23 -0
- package/dist/preview/index.d.mts +1 -2
- package/dist/preview/index.mjs +1 -243
- package/dist/preview/react.d.mts +1 -0
- package/dist/preview/react.mjs +34 -0
- package/dist/unplugin.d.mts +12 -17
- package/dist/unplugin.mjs +1 -500
- package/package.json +72 -8
- package/dist/_chunks/config.d.mts +0 -35
- package/dist/_chunks/entry.d.mts +0 -194
- package/dist/_chunks/libs/@oxc-project/types.d.mts +0 -1297
- package/dist/_chunks/libs/@rolldown/pluginutils.d.mts +0 -62
- package/dist/_chunks/libs/rolldown.d.mts +0 -4711
- package/dist/_chunks/output2.mjs +0 -333
- package/dist/_chunks/parse.mjs +0 -22
- package/dist/_chunks/types.mjs +0 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Entry, EntryMeta, EntryRef, EntryStatus, ForgePressEntry, ForgePressOutput, ForgePressSchema, ForgePressSchemaRegistry, OutputMeta, OutputOf, RegisteredSchema, SchemaLocale } from "./_chunks/
|
|
2
|
-
import { OutputCollection, OutputEntry, OutputIndex, OutputManifest } from "./_chunks/
|
|
3
|
-
import { ForgePressConfig, OutputConfig } from "./_chunks/config.mjs";
|
|
1
|
+
import { Entry, EntryMeta, EntryRef, EntryStatus, ForgePressConfig, ForgePressEntry, ForgePressOutput, ForgePressSchema, ForgePressSchemaRegistry, OutputConfig, OutputMeta, OutputOf, RegisteredSchema, SchemaLocale } from "./_chunks/types.mjs";
|
|
2
|
+
import { OutputCollection, OutputEntry, OutputIndex, OutputManifest } from "./_chunks/types2.mjs";
|
|
4
3
|
export declare function defineForgePressConfig(config: ForgePressConfig): ForgePressConfig;
|
|
5
4
|
type Operator = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'contains';
|
|
6
5
|
type CollectionName<TSchema extends ForgePressSchema> = keyof TSchema['collections'] & string;
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { entryKey } from "./_chunks/references.mjs";
|
|
3
|
-
import { OUTPUT_INDEX } from "./_chunks/
|
|
1
|
+
import { OUTPUT_META_KEYS, pick, quote } from "./_chunks/value.mjs";
|
|
2
|
+
import { entryKey, isEntryRef } from "./_chunks/references.mjs";
|
|
3
|
+
import { OUTPUT_INDEX } from "./_chunks/response.mjs";
|
|
4
|
+
import { keyed } from "./_chunks/once.mjs";
|
|
4
5
|
import { fetchReader } from "./_chunks/fetch.mjs";
|
|
5
6
|
import { overlaid } from "./_chunks/overlay.mjs";
|
|
6
7
|
import { reader } from "#content-reader";
|
|
@@ -8,7 +9,7 @@ function defineForgePressConfig(config) {
|
|
|
8
9
|
return config;
|
|
9
10
|
}
|
|
10
11
|
function comparable(value) {
|
|
11
|
-
return
|
|
12
|
+
return isEntryRef(value) ? value.id : value;
|
|
12
13
|
}
|
|
13
14
|
function compare(left, right) {
|
|
14
15
|
const first = comparable(left);
|
|
@@ -47,13 +48,8 @@ function evaluate(entries, plan) {
|
|
|
47
48
|
if (plan.limit !== void 0) result = result.slice(0, plan.limit);
|
|
48
49
|
return result;
|
|
49
50
|
}
|
|
50
|
-
const META = [
|
|
51
|
-
"id",
|
|
52
|
-
"createdAt",
|
|
53
|
-
"updatedAt"
|
|
54
|
-
];
|
|
55
51
|
function refsOf(value) {
|
|
56
|
-
return (Array.isArray(value) ? value : [value]).filter(
|
|
52
|
+
return (Array.isArray(value) ? value : [value]).filter(isEntryRef);
|
|
57
53
|
}
|
|
58
54
|
function listing(names) {
|
|
59
55
|
return names.map(quote).join(", ");
|
|
@@ -125,7 +121,7 @@ var Builder = class {
|
|
|
125
121
|
const manifest = await snapshot.manifest(collection, locale);
|
|
126
122
|
const unlinked = plan.with.filter((field) => manifest.links[field] === void 0);
|
|
127
123
|
if (unlinked.length > 0) throw new Error(`[forgepress] .with() loads relation and dynamic fields, and ${listing(unlinked)} ${unlinked.length === 1 ? "is not one" : "are not"} in ${quote(collection)}`);
|
|
128
|
-
const listed = /* @__PURE__ */ new Set([...
|
|
124
|
+
const listed = /* @__PURE__ */ new Set([...OUTPUT_META_KEYS, ...manifest.indexed]);
|
|
129
125
|
const unindexed = [...new Set([...plan.where, ...plan.sort].map((clause) => clause.field))].filter((field) => !listed.has(field));
|
|
130
126
|
if (unindexed.length > 0 && index.dev) console.warn(`[forgepress] query(${quote(collection)}) filters or sorts by ${listing(unindexed)}, which ${unindexed.length === 1 ? "is" : "are"} not indexed, so every entry is loaded. Add index: true to ${unindexed.length === 1 ? "the field" : "the fields"} in the schema`);
|
|
131
127
|
const selected = evaluate(unindexed.length > 0 ? await snapshot.entries(collection, locale, manifest.entries.map((entry) => entry.id)) : manifest.entries, limit === void 0 ? plan : {
|
|
@@ -135,8 +131,8 @@ var Builder = class {
|
|
|
135
131
|
const listedOnly = plan.pick !== void 0 && [...plan.pick, ...plan.with].every((field) => listed.has(field));
|
|
136
132
|
const rows = unindexed.length > 0 || listedOnly ? selected : await snapshot.entries(collection, locale, selected.map((entry) => entry.id));
|
|
137
133
|
const linked = plan.with.length > 0 ? await this.link(snapshot, manifest, rows) : rows;
|
|
138
|
-
const
|
|
139
|
-
const picked =
|
|
134
|
+
const fields = plan.pick;
|
|
135
|
+
const picked = fields === void 0 ? linked : linked.map((row) => pick(row, fields));
|
|
140
136
|
return structuredClone(picked);
|
|
141
137
|
}
|
|
142
138
|
async link(snapshot, manifest, rows) {
|
|
@@ -197,18 +193,12 @@ function manifestPath(index, collection, locale) {
|
|
|
197
193
|
return path;
|
|
198
194
|
}
|
|
199
195
|
function createLoader(read) {
|
|
200
|
-
const files =
|
|
196
|
+
const files = keyed();
|
|
201
197
|
function file(path) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return value;
|
|
207
|
-
});
|
|
208
|
-
pending.catch(() => files.delete(path));
|
|
209
|
-
files.set(path, pending);
|
|
210
|
-
}
|
|
211
|
-
return pending;
|
|
198
|
+
return files(path, () => read(path).then((value) => {
|
|
199
|
+
if (value === void 0) throw new MissingFile(path);
|
|
200
|
+
return value;
|
|
201
|
+
}));
|
|
212
202
|
}
|
|
213
203
|
async function snapshot() {
|
|
214
204
|
const index = await read(OUTPUT_INDEX);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EVENTS } from "../_chunks/routes.mjs";
|
|
2
|
+
import { settings_default } from "../_chunks/settings2.mjs";
|
|
3
|
+
const RETRY = 1e3;
|
|
4
|
+
const LONGEST_RETRY = 3e4;
|
|
5
|
+
function connect(delay) {
|
|
6
|
+
const socket = new WebSocket(`${settings_default.devServer.replace(/^http/, "ws")}${EVENTS}`);
|
|
7
|
+
let opened = false;
|
|
8
|
+
socket.addEventListener("open", () => {
|
|
9
|
+
opened = true;
|
|
10
|
+
});
|
|
11
|
+
socket.addEventListener("message", (event) => {
|
|
12
|
+
if (event.data === "reload") location.reload();
|
|
13
|
+
});
|
|
14
|
+
socket.addEventListener("close", () => {
|
|
15
|
+
const next = opened ? RETRY : Math.min(delay * 2, LONGEST_RETRY);
|
|
16
|
+
setTimeout(connect, next, next);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
connect(RETRY);
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ContentConfig, ProviderConfig, ResolvedMedia } from "../_chunks/types.mjs";
|
|
2
|
+
import "../_chunks/resolve.mjs";
|
|
3
|
+
interface EditorSettings {
|
|
4
|
+
local: boolean;
|
|
5
|
+
devServer: string;
|
|
6
|
+
provider?: ProviderConfig | undefined;
|
|
7
|
+
format?: ContentConfig | undefined;
|
|
8
|
+
contentPath: string;
|
|
9
|
+
media: ResolvedMedia;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: EditorSettings;
|
|
12
|
+
export { _default as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Options } from "../_chunks/project.mjs";
|
|
2
|
+
import { NextConfig } from "next";
|
|
3
|
+
export interface NextOptions extends Options {
|
|
4
|
+
preview?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export type NextConfigFunction = (phase: string, context: {
|
|
7
|
+
defaultConfig: NextConfig;
|
|
8
|
+
}) => NextConfig | Promise<NextConfig>;
|
|
9
|
+
export declare function withForgePress(nextConfig: NextConfig | NextConfigFunction, options?: NextOptions): (phase: string, context: {
|
|
10
|
+
defaultConfig: NextConfig;
|
|
11
|
+
}) => Promise<NextConfig>;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { isRecord } from "../_chunks/value.mjs";
|
|
2
|
+
import { keyed } from "../_chunks/once.mjs";
|
|
3
|
+
import { errorMessage } from "../_chunks/error.mjs";
|
|
4
|
+
import { buildOutput } from "../_chunks/output.mjs";
|
|
5
|
+
import { toPosix } from "../_chunks/files.mjs";
|
|
6
|
+
import { EVENTS } from "../_chunks/routes.mjs";
|
|
7
|
+
import { SETTINGS_ID, createDevContent, editorSettings, loadProject, syncTypes } from "../_chunks/settings.mjs";
|
|
8
|
+
import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
9
|
+
import process from "node:process";
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { createServer } from "node:http";
|
|
13
|
+
import { Worker, isMainThread } from "node:worker_threads";
|
|
14
|
+
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
15
|
+
import { WebSocketServer } from "ws";
|
|
16
|
+
const DEVELOPMENT = "phase-development-server";
|
|
17
|
+
const BUILD = "phase-production-build";
|
|
18
|
+
const SETTINGS_MODULE = "forgepress/next/settings";
|
|
19
|
+
const SETTINGS_VARIABLE = "__FORGEPRESS_SETTINGS__";
|
|
20
|
+
const PREVIEW_MODULE = "forgepress/next/preview";
|
|
21
|
+
const RELOAD_MODULE = "forgepress/next/reload";
|
|
22
|
+
const VUE_FLAGS = {
|
|
23
|
+
__VUE_OPTIONS_API__: true,
|
|
24
|
+
__VUE_PROD_DEVTOOLS__: false,
|
|
25
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false
|
|
26
|
+
};
|
|
27
|
+
const SERVERS = Symbol.for("forgepress:next:servers");
|
|
28
|
+
const LOCAL_ORIGIN = /^https?:\/\/(?:(?:[^/:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/;
|
|
29
|
+
const PREFLIGHT = {
|
|
30
|
+
"access-control-allow-methods": "GET, POST, DELETE",
|
|
31
|
+
"access-control-allow-headers": "content-type",
|
|
32
|
+
"access-control-max-age": "600"
|
|
33
|
+
};
|
|
34
|
+
const INDENT = /^[ \t]+(?=\S)/m;
|
|
35
|
+
const DIST = `${dirname(dirname(fileURLToPath(import.meta.url)))}${sep}`;
|
|
36
|
+
const WATCHER = new URL(`./watcher${extname(fileURLToPath(import.meta.url))}`, import.meta.url);
|
|
37
|
+
function dynamicConfigImport(warning) {
|
|
38
|
+
return Boolean(warning.module?.resource?.startsWith(DIST) && warning.message?.includes("the request of a dependency is an expression"));
|
|
39
|
+
}
|
|
40
|
+
const logger = {
|
|
41
|
+
info: (message) => process.stdout.write(`${message}\n`),
|
|
42
|
+
warn: (message) => console.warn(message),
|
|
43
|
+
error: (message) => console.error(message)
|
|
44
|
+
};
|
|
45
|
+
function localPage(request) {
|
|
46
|
+
const { origin } = request.headers;
|
|
47
|
+
const site = request.headers["sec-fetch-site"];
|
|
48
|
+
if (origin !== void 0) return LOCAL_ORIGIN.test(origin);
|
|
49
|
+
return site === void 0 || site === "none" || site === "same-origin";
|
|
50
|
+
}
|
|
51
|
+
const LOCAL_PAGES = {
|
|
52
|
+
accepts: localPage,
|
|
53
|
+
refusal: "the dev endpoint only accepts requests from pages opened on localhost"
|
|
54
|
+
};
|
|
55
|
+
function end(response, status, text) {
|
|
56
|
+
response.statusCode = status;
|
|
57
|
+
response.end(text);
|
|
58
|
+
}
|
|
59
|
+
function servers() {
|
|
60
|
+
const scope = globalThis;
|
|
61
|
+
scope[SERVERS] ??= keyed();
|
|
62
|
+
return scope[SERVERS];
|
|
63
|
+
}
|
|
64
|
+
function formatting(text) {
|
|
65
|
+
const indent = INDENT.exec(text)?.[0] ?? " ";
|
|
66
|
+
return {
|
|
67
|
+
insertSpaces: !indent.startsWith(" "),
|
|
68
|
+
tabSize: indent.length,
|
|
69
|
+
eol: text.includes("\r\n") ? "\r\n" : "\n"
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function includeContent(root, config, tsconfig) {
|
|
73
|
+
const file = resolve(root, tsconfig);
|
|
74
|
+
if (!existsSync(file)) return;
|
|
75
|
+
const folder = toPosix(relative(dirname(file), join(root, config.paths.dir)));
|
|
76
|
+
const pattern = `${folder}/**/*.ts`;
|
|
77
|
+
if (!folder.split("/").some((segment) => segment.startsWith("."))) return;
|
|
78
|
+
const text = readFileSync(file, "utf8");
|
|
79
|
+
const errors = [];
|
|
80
|
+
const parsed = parse(text, errors, { allowTrailingComma: true });
|
|
81
|
+
if (errors.length > 0 || !isRecord(parsed) || !Array.isArray(parsed.include)) {
|
|
82
|
+
logger.warn(`[forgepress] add ${JSON.stringify(pattern)} to "include" in ${basename(file)}, so TypeScript knows the schema`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (parsed.include.includes(pattern)) return;
|
|
86
|
+
writeFileSync(file, applyEdits(text, modify(text, ["include", parsed.include.length], pattern, {
|
|
87
|
+
isArrayInsertion: true,
|
|
88
|
+
formattingOptions: formatting(text)
|
|
89
|
+
})));
|
|
90
|
+
logger.info(`[forgepress] added ${JSON.stringify(pattern)} to "include" in ${basename(file)}, so TypeScript knows the schema`);
|
|
91
|
+
}
|
|
92
|
+
function watchContent(dir, schema, changed) {
|
|
93
|
+
const watcher = new Worker(WATCHER, { workerData: {
|
|
94
|
+
dir,
|
|
95
|
+
schema
|
|
96
|
+
} });
|
|
97
|
+
let watching = false;
|
|
98
|
+
return new Promise((ready, fail) => {
|
|
99
|
+
watcher.on("message", (file) => {
|
|
100
|
+
if (file !== null) return changed(file);
|
|
101
|
+
watching = true;
|
|
102
|
+
watcher.unref();
|
|
103
|
+
ready();
|
|
104
|
+
});
|
|
105
|
+
watcher.on("error", (error) => {
|
|
106
|
+
if (watching) logger.error(`[forgepress] stopped watching the content folder: ${errorMessage(error)}`);
|
|
107
|
+
else fail(error);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function listen(server) {
|
|
112
|
+
return new Promise((done, fail) => {
|
|
113
|
+
server.once("error", fail);
|
|
114
|
+
server.listen(0, "127.0.0.1", () => done(`127.0.0.1:${server.address().port}`));
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
async function startDevServer(root, config, write) {
|
|
118
|
+
const pages = new WebSocketServer({ noServer: true });
|
|
119
|
+
const dev = createDevContent(root, config, logger, () => {
|
|
120
|
+
for (const page of pages.clients) page.send("reload");
|
|
121
|
+
}, LOCAL_PAGES);
|
|
122
|
+
await watchContent(join(root, config.paths.dir), join(root, config.paths.schema), dev.changed);
|
|
123
|
+
await dev.refresh();
|
|
124
|
+
const server = createServer();
|
|
125
|
+
const host = await listen(server);
|
|
126
|
+
server.on("request", (request, response) => {
|
|
127
|
+
const { origin } = request.headers;
|
|
128
|
+
if (request.headers.host !== host) return end(response, 403);
|
|
129
|
+
if (origin !== void 0) {
|
|
130
|
+
response.setHeader("access-control-allow-origin", origin);
|
|
131
|
+
response.setHeader("vary", "origin");
|
|
132
|
+
}
|
|
133
|
+
if (request.method === "OPTIONS") {
|
|
134
|
+
if (!LOCAL_PAGES.accepts(request)) return end(response, 403, LOCAL_PAGES.refusal);
|
|
135
|
+
for (const [name, value] of Object.entries(PREFLIGHT)) response.setHeader(name, value);
|
|
136
|
+
return end(response, 204);
|
|
137
|
+
}
|
|
138
|
+
if (!write) return end(response, 404);
|
|
139
|
+
dev.endpoint(request, response, () => end(response, 404));
|
|
140
|
+
});
|
|
141
|
+
server.on("upgrade", (request, socket, head) => {
|
|
142
|
+
if (request.headers.host !== host || request.url !== EVENTS || !LOCAL_PAGES.accepts(request)) {
|
|
143
|
+
socket.destroy();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
socket.unref();
|
|
147
|
+
pages.handleUpgrade(request, socket, head, (page) => page.on("error", () => page.terminate()));
|
|
148
|
+
});
|
|
149
|
+
server.unref();
|
|
150
|
+
return `http://${host}`;
|
|
151
|
+
}
|
|
152
|
+
function devServer(root, config, write) {
|
|
153
|
+
return servers()(root, () => startDevServer(root, config, write));
|
|
154
|
+
}
|
|
155
|
+
async function prepare(phase, next, options) {
|
|
156
|
+
const project = await loadProject(process.cwd(), options);
|
|
157
|
+
const { root, config } = project;
|
|
158
|
+
const serving = phase === DEVELOPMENT && isMainThread;
|
|
159
|
+
if (isMainThread && (phase === DEVELOPMENT || phase === BUILD)) {
|
|
160
|
+
syncTypes(root, config);
|
|
161
|
+
includeContent(root, config, next.typescript?.tsconfigPath ?? "tsconfig.json");
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
...project,
|
|
165
|
+
local: phase === DEVELOPMENT && options.write !== false,
|
|
166
|
+
server: serving ? await devServer(root, config, options.write !== false) : void 0
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function extend(next, project, options) {
|
|
170
|
+
const extended = {
|
|
171
|
+
compiler: {
|
|
172
|
+
...next.compiler,
|
|
173
|
+
define: {
|
|
174
|
+
...VUE_FLAGS,
|
|
175
|
+
...next.compiler?.define,
|
|
176
|
+
[SETTINGS_VARIABLE]: JSON.stringify(editorSettings(project.local, project.config, project.server))
|
|
177
|
+
},
|
|
178
|
+
runAfterProductionCompile: async (metadata) => {
|
|
179
|
+
await buildOutput(project.root, project.config);
|
|
180
|
+
await next.compiler?.runAfterProductionCompile?.(metadata);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
turbopack: {
|
|
184
|
+
...next.turbopack,
|
|
185
|
+
resolveAlias: {
|
|
186
|
+
...next.turbopack?.resolveAlias,
|
|
187
|
+
[SETTINGS_ID]: SETTINGS_MODULE
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
webpack: (config, context) => {
|
|
191
|
+
const result = next.webpack ? next.webpack(config, context) : config;
|
|
192
|
+
result.plugins = [...result.plugins ?? [], new context.webpack.NormalModuleReplacementPlugin(/^virtual:forgepress\/settings$/, SETTINGS_MODULE)];
|
|
193
|
+
result.ignoreWarnings = [...result.ignoreWarnings ?? [], dynamicConfigImport];
|
|
194
|
+
return result;
|
|
195
|
+
},
|
|
196
|
+
instrumentationClientInject: [
|
|
197
|
+
...next.instrumentationClientInject ?? [],
|
|
198
|
+
...options.preview === false ? [] : [PREVIEW_MODULE],
|
|
199
|
+
...project.server ? [RELOAD_MODULE] : []
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
...next,
|
|
204
|
+
...extended
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function withForgePress(nextConfig, options = {}) {
|
|
208
|
+
return async (phase, context) => {
|
|
209
|
+
const found = typeof nextConfig === "function" ? await nextConfig(phase, context) : nextConfig;
|
|
210
|
+
return extend(found, await prepare(phase, found, options), options);
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
export { withForgePress };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { toPosix } from "../_chunks/files.mjs";
|
|
2
|
+
import { loadProject } from "../_chunks/settings.mjs";
|
|
3
|
+
import { configFile } from "../_chunks/config.mjs";
|
|
4
|
+
import { vitePlugin } from "../_chunks/plugin.mjs";
|
|
5
|
+
import { join, relative } from "node:path";
|
|
6
|
+
import { addPluginTemplate, addVitePlugin, defineNuxtModule } from "@nuxt/kit";
|
|
7
|
+
const PREVIEW_PLUGIN = `import { defineNuxtPlugin, refreshNuxtData, usePreviewMode } from '#app'
|
|
8
|
+
import { enablePreview, onPreviewChange, previewing } from 'forgepress/preview'
|
|
9
|
+
|
|
10
|
+
export default defineNuxtPlugin({
|
|
11
|
+
name: 'forgepress:preview',
|
|
12
|
+
setup(nuxtApp) {
|
|
13
|
+
enablePreview()
|
|
14
|
+
|
|
15
|
+
const { enabled } = usePreviewMode({ shouldEnable: previewing })
|
|
16
|
+
|
|
17
|
+
onPreviewChange(() => nuxtApp.runWithContext(() => {
|
|
18
|
+
enabled.value = previewing()
|
|
19
|
+
|
|
20
|
+
return refreshNuxtData()
|
|
21
|
+
}))
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
`;
|
|
25
|
+
const forgepress = defineNuxtModule({
|
|
26
|
+
meta: {
|
|
27
|
+
name: "forgepress",
|
|
28
|
+
configKey: "forgepress"
|
|
29
|
+
},
|
|
30
|
+
async setup(options, nuxt) {
|
|
31
|
+
const { root, config } = await loadProject(nuxt.options.rootDir, options);
|
|
32
|
+
addVitePlugin(vitePlugin({
|
|
33
|
+
...options,
|
|
34
|
+
root
|
|
35
|
+
}));
|
|
36
|
+
nuxt.hook("prepare:types", ({ tsConfig, nodeTsConfig }) => {
|
|
37
|
+
tsConfig.include ??= [];
|
|
38
|
+
tsConfig.include.push(toPosix(relative(nuxt.options.buildDir, join(root, config.paths.dir, "**/*.ts"))));
|
|
39
|
+
const file = configFile(root);
|
|
40
|
+
if (file) {
|
|
41
|
+
nodeTsConfig.include ??= [];
|
|
42
|
+
nodeTsConfig.include.push(toPosix(relative(nuxt.options.buildDir, join(root, file))));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
if (options.preview !== false) addPluginTemplate({
|
|
46
|
+
filename: "forgepress/preview.client.mjs",
|
|
47
|
+
getContents: () => PREVIEW_PLUGIN,
|
|
48
|
+
mode: "client"
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
export { forgepress as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { basename, dirname, join } from "node:path";
|
|
2
|
+
import { existsSync, watch } from "node:fs";
|
|
3
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
4
|
+
const { dir, schema } = workerData;
|
|
5
|
+
function changed(file) {
|
|
6
|
+
parentPort?.postMessage(file);
|
|
7
|
+
}
|
|
8
|
+
function start() {
|
|
9
|
+
if (!existsSync(dir)) return false;
|
|
10
|
+
watch(dir, { recursive: true }, (_, name) => {
|
|
11
|
+
if (name) changed(join(dir, name));
|
|
12
|
+
});
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (!start() && existsSync(dirname(dir))) {
|
|
16
|
+
const parent = watch(dirname(dir), (_, name) => {
|
|
17
|
+
if (name !== basename(dir) || !start()) return;
|
|
18
|
+
parent.close();
|
|
19
|
+
changed(schema);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
parentPort?.postMessage(null);
|
|
23
|
+
export {};
|
package/dist/preview/index.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import "../_chunks/
|
|
2
|
-
import "../_chunks/config.mjs";
|
|
1
|
+
import "../_chunks/types.mjs";
|
|
3
2
|
export declare function previewing(): boolean;
|
|
4
3
|
export declare function onPreviewChange(listener: () => void): () => void;
|
|
5
4
|
export declare function enablePreview(): boolean;
|