@ahmedrowaihi/pdf-forge-cli 1.1.0 → 1.2.0-canary.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.
- package/CHANGELOG.md +11 -0
- package/dist/index.js +157 -369
- package/package.json +6 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @ahmedrowaihi/pdf-forge-cli
|
|
2
2
|
|
|
3
|
+
## 1.2.0-canary.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5e324d8: All In Bun and Printer Pool
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [5e324d8]
|
|
12
|
+
- @ahmedrowaihi/pdf-forge-toolbox@1.2.0-canary.0
|
|
13
|
+
|
|
3
14
|
## 1.1.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
import { createRequire } from "node:module";
|
|
1
|
+
#!/usr/bin/env bun
|
|
3
2
|
import { program } from "commander";
|
|
4
|
-
import fs, { existsSync, promises,
|
|
3
|
+
import fs, { existsSync, promises, unlinkSync, writeFileSync } from "node:fs";
|
|
5
4
|
import path from "node:path";
|
|
5
|
+
import { createDependencyGraph, escapeStringForRegex, getTemplatesDirectoryMetadata, registerSpinnerAutostopping, styleText } from "@ahmedrowaihi/pdf-forge-toolbox";
|
|
6
6
|
import logSymbols from "log-symbols";
|
|
7
7
|
import { addDevDependency, installDependencies, runScript } from "nypm";
|
|
8
8
|
import ora from "ora";
|
|
9
|
-
import url from "node:url";
|
|
10
|
-
import { createJiti } from "jiti";
|
|
11
9
|
import prompts from "prompts";
|
|
12
10
|
import { watch } from "chokidar";
|
|
13
11
|
import debounce from "debounce";
|
|
14
12
|
import { Server } from "socket.io";
|
|
15
|
-
import { parse } from "@babel/parser";
|
|
16
|
-
import traverseModule from "@babel/traverse";
|
|
17
|
-
import { createMatchPath, loadConfig } from "tsconfig-paths";
|
|
18
13
|
import http from "node:http";
|
|
19
|
-
import
|
|
14
|
+
import url from "node:url";
|
|
20
15
|
import { lookup } from "mime-types";
|
|
21
16
|
import os from "node:os";
|
|
22
|
-
import { build } from "esbuild";
|
|
23
17
|
import { glob } from "glob";
|
|
24
18
|
import normalize from "normalize-path";
|
|
25
19
|
import { spawn } from "node:child_process";
|
|
@@ -27,7 +21,7 @@ import { spawn } from "node:child_process";
|
|
|
27
21
|
//#region package.json
|
|
28
22
|
var package_default = {
|
|
29
23
|
name: "@ahmedrowaihi/pdf-forge-cli",
|
|
30
|
-
version: "1.
|
|
24
|
+
version: "1.2.0-canary.0",
|
|
31
25
|
description: "A live preview of your PDF templates right in your browser.",
|
|
32
26
|
bin: { "pdf-dev": "./dist/index.js" },
|
|
33
27
|
type: "module",
|
|
@@ -43,17 +37,14 @@ var package_default = {
|
|
|
43
37
|
"directory": "packages/react-pdf"
|
|
44
38
|
},
|
|
45
39
|
keywords: ["react", "pdf"],
|
|
46
|
-
engines: { "
|
|
40
|
+
engines: { "bun": ">=1.0.0" },
|
|
47
41
|
dependencies: {
|
|
48
|
-
"@
|
|
49
|
-
"@babel/traverse": "^7.27.0",
|
|
42
|
+
"@ahmedrowaihi/pdf-forge-toolbox": "workspace:*",
|
|
50
43
|
"chokidar": "^4.0.3",
|
|
51
44
|
"commander": "^13.0.0",
|
|
52
45
|
"conf": "^15.0.2",
|
|
53
46
|
"debounce": "^2.0.0",
|
|
54
|
-
"esbuild": "^0.25.0",
|
|
55
47
|
"glob": "^11.0.0",
|
|
56
|
-
"jiti": "2.4.2",
|
|
57
48
|
"log-symbols": "^7.0.0",
|
|
58
49
|
"mime-types": "^3.0.0",
|
|
59
50
|
"normalize-path": "^3.0.0",
|
|
@@ -66,10 +57,10 @@ var package_default = {
|
|
|
66
57
|
devDependencies: {
|
|
67
58
|
"@ahmedrowaihi/pdf-forge-components": "workspace:*",
|
|
68
59
|
"@ahmedrowaihi/pdf-forge-core": "workspace:*",
|
|
69
|
-
"@types/
|
|
70
|
-
"@types/babel__traverse": "7.20.7",
|
|
60
|
+
"@types/bun": "^1.3.5",
|
|
71
61
|
"@types/mime-types": "2.1.4",
|
|
72
62
|
"@types/prompts": "2.4.9",
|
|
63
|
+
"@types/normalize-path": "3.0.2",
|
|
73
64
|
"next": "16.0.10",
|
|
74
65
|
"react": "19.0.0",
|
|
75
66
|
"react-dom": "19.0.0",
|
|
@@ -112,104 +103,33 @@ const findWorkspacePreviewServer = () => {
|
|
|
112
103
|
}
|
|
113
104
|
return null;
|
|
114
105
|
};
|
|
106
|
+
/**
|
|
107
|
+
* Finds the location of the preview server
|
|
108
|
+
* 1. Checks if the preview server is installed in the workspace
|
|
109
|
+
* 2. If not, checks if the preview server is installed in the cwd
|
|
110
|
+
* 3. If not, prompts the user to install it
|
|
111
|
+
* 4. If the user installs it, it will return the location of the preview server
|
|
112
|
+
* 5. If the user does not install it, it will exit the process
|
|
113
|
+
* @returns The location of the preview server
|
|
114
|
+
*/
|
|
115
115
|
const getPreviewServerLocation = async () => {
|
|
116
|
-
const usersProject = createJiti(process.cwd());
|
|
117
116
|
let previewServerLocation;
|
|
118
117
|
const workspacePath = findWorkspacePreviewServer();
|
|
119
118
|
if (workspacePath) previewServerLocation = workspacePath;
|
|
120
119
|
else try {
|
|
121
|
-
previewServerLocation = path.dirname(
|
|
120
|
+
previewServerLocation = path.dirname(Bun.resolveSync("@ahmedrowaihi/pdf-forge-preview", process.cwd()));
|
|
122
121
|
} catch {
|
|
123
122
|
await ensurePreviewServerInstalled("To run the preview server, the package \"@ahmedrowaihi/pdf-forge-preview\" must be installed. Would you like to install it?");
|
|
124
123
|
}
|
|
125
124
|
if (!workspacePath) try {
|
|
126
|
-
const
|
|
127
|
-
if (version
|
|
125
|
+
const packagePath = Bun.resolveSync("@ahmedrowaihi/pdf-forge-preview/package.json", process.cwd());
|
|
126
|
+
if (JSON.parse(await Bun.file(packagePath).text()).version !== package_default.version) await ensurePreviewServerInstalled(`To run the preview server, the version of "@ahmedrowaihi/pdf-forge-preview" must match the version of "@ahmedrowaihi/pdf-forge-cli" (${package_default.version}). Would you like to install it?`);
|
|
128
127
|
} catch {
|
|
129
128
|
await ensurePreviewServerInstalled("To run the preview server, the package \"@ahmedrowaihi/pdf-forge-preview\" must be installed. Would you like to install it?");
|
|
130
129
|
}
|
|
131
130
|
return previewServerLocation;
|
|
132
131
|
};
|
|
133
132
|
|
|
134
|
-
//#endregion
|
|
135
|
-
//#region src/utils/get-templates-directory-metadata.ts
|
|
136
|
-
const isFileATemplate = async (fullPath) => {
|
|
137
|
-
let fileHandle;
|
|
138
|
-
try {
|
|
139
|
-
fileHandle = await fs.promises.open(fullPath, "r");
|
|
140
|
-
} catch (exception) {
|
|
141
|
-
console.warn(exception);
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
if ((await fileHandle.stat()).isDirectory()) {
|
|
145
|
-
await fileHandle.close();
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
const { ext } = path.parse(fullPath);
|
|
149
|
-
if (![
|
|
150
|
-
".js",
|
|
151
|
-
".tsx",
|
|
152
|
-
".jsx"
|
|
153
|
-
].includes(ext)) {
|
|
154
|
-
await fileHandle.close();
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
const fileContents = await fileHandle.readFile("utf8");
|
|
158
|
-
await fileHandle.close();
|
|
159
|
-
const hasES6DefaultExport = /\bexport\s+default\b/gm.test(fileContents);
|
|
160
|
-
const hasCommonJSExport = /\bmodule\.exports\s*=/gm.test(fileContents);
|
|
161
|
-
const hasNamedExport = /\bexport\s+\{[^}]*\bdefault\b[^}]*\}/gm.test(fileContents);
|
|
162
|
-
return hasES6DefaultExport || hasCommonJSExport || hasNamedExport;
|
|
163
|
-
};
|
|
164
|
-
const mergeDirectoriesWithSubDirectories = (templatesDirectoryMetadata) => {
|
|
165
|
-
let currentResultingMergedDirectory = templatesDirectoryMetadata;
|
|
166
|
-
while (currentResultingMergedDirectory.templateFilenames.length === 0 && currentResultingMergedDirectory.subDirectories.length === 1) {
|
|
167
|
-
const onlySubDirectory = currentResultingMergedDirectory.subDirectories[0];
|
|
168
|
-
currentResultingMergedDirectory = {
|
|
169
|
-
...onlySubDirectory,
|
|
170
|
-
directoryName: path.join(currentResultingMergedDirectory.directoryName, onlySubDirectory.directoryName)
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
return currentResultingMergedDirectory;
|
|
174
|
-
};
|
|
175
|
-
const getTemplatesDirectoryMetadata = async (absolutePathToTemplatesDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToTemplatesDirectory) => {
|
|
176
|
-
if (!fs.existsSync(absolutePathToTemplatesDirectory)) return;
|
|
177
|
-
const dirents = await fs.promises.readdir(absolutePathToTemplatesDirectory, { withFileTypes: true });
|
|
178
|
-
const isTemplatePredicates = await Promise.all(dirents.map((dirent) => isFileATemplate(path.join(absolutePathToTemplatesDirectory, dirent.name))));
|
|
179
|
-
const templateFilenames = dirents.filter((_, i) => isTemplatePredicates[i]).map((dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path.extname(dirent.name), ""));
|
|
180
|
-
const subDirectories = await Promise.all(dirents.filter((dirent) => dirent.isDirectory() && !dirent.name.startsWith("_") && dirent.name !== "static").map((dirent) => {
|
|
181
|
-
return getTemplatesDirectoryMetadata(path.join(absolutePathToTemplatesDirectory, dirent.name), keepFileExtensions, true, baseDirectoryPath);
|
|
182
|
-
}));
|
|
183
|
-
const templatesMetadata = {
|
|
184
|
-
absolutePath: absolutePathToTemplatesDirectory,
|
|
185
|
-
relativePath: path.relative(baseDirectoryPath, absolutePathToTemplatesDirectory),
|
|
186
|
-
directoryName: absolutePathToTemplatesDirectory.split(path.sep).pop(),
|
|
187
|
-
templateFilenames,
|
|
188
|
-
subDirectories
|
|
189
|
-
};
|
|
190
|
-
return isSubDirectory ? mergeDirectoriesWithSubDirectories(templatesMetadata) : templatesMetadata;
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/utils/register-spinner-autostopping.ts
|
|
195
|
-
const spinners = /* @__PURE__ */ new Set();
|
|
196
|
-
process.on("SIGINT", () => {
|
|
197
|
-
spinners.forEach((spinner) => {
|
|
198
|
-
if (spinner.isSpinning) spinner.stop();
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
process.on("exit", (code) => {
|
|
202
|
-
if (code !== 0) spinners.forEach((spinner) => {
|
|
203
|
-
if (spinner.isSpinning) spinner.stopAndPersist({
|
|
204
|
-
symbol: logSymbols.error,
|
|
205
|
-
text: "Process exited with error"
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
const registerSpinnerAutostopping = (spinner) => {
|
|
210
|
-
spinners.add(spinner);
|
|
211
|
-
};
|
|
212
|
-
|
|
213
133
|
//#endregion
|
|
214
134
|
//#region src/commands/build.ts
|
|
215
135
|
const setNextEnvironmentVariablesForBuild = async (templatesDirRelativePath, builtPreviewAppPath) => {
|
|
@@ -228,7 +148,7 @@ const nextConfig = {
|
|
|
228
148
|
USER_PROJECT_LOCATION: userProjectLocation
|
|
229
149
|
},
|
|
230
150
|
outputFileTracingRoot: previewServerLocation,
|
|
231
|
-
serverExternalPackages: [
|
|
151
|
+
serverExternalPackages: ["playwright", "playwright-core", "sharp"],
|
|
232
152
|
typescript: {
|
|
233
153
|
ignoreBuildErrors: true
|
|
234
154
|
},
|
|
@@ -263,6 +183,37 @@ export function generateStaticParams() {
|
|
|
263
183
|
);
|
|
264
184
|
}`, "utf8");
|
|
265
185
|
};
|
|
186
|
+
const findWorkspaceRoot = (startPath) => {
|
|
187
|
+
let currentPath = startPath;
|
|
188
|
+
while (currentPath !== path.dirname(currentPath)) {
|
|
189
|
+
const pnpmWorkspace = path.join(currentPath, "pnpm-workspace.yaml");
|
|
190
|
+
if (fs.existsSync(pnpmWorkspace)) return currentPath;
|
|
191
|
+
currentPath = path.dirname(currentPath);
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
};
|
|
195
|
+
const findWorkspacePackage = (packageName, workspaceRoot) => {
|
|
196
|
+
const searchDirs = [path.join(workspaceRoot, "packages"), path.join(workspaceRoot, "apps")];
|
|
197
|
+
for (const baseDir of searchDirs) {
|
|
198
|
+
if (!fs.existsSync(baseDir)) continue;
|
|
199
|
+
const packageDirs = fs.readdirSync(baseDir, { withFileTypes: true });
|
|
200
|
+
for (const dirent of packageDirs) if (dirent.isDirectory()) {
|
|
201
|
+
const packagePath = path.join(baseDir, dirent.name);
|
|
202
|
+
const packageJsonPath = path.join(packagePath, "package.json");
|
|
203
|
+
if (fs.existsSync(packageJsonPath)) try {
|
|
204
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
205
|
+
if (pkg.name === packageName) {
|
|
206
|
+
if (pkg.main?.includes("dist")) {
|
|
207
|
+
const distPath = path.join(packagePath, "dist");
|
|
208
|
+
if (!fs.existsSync(distPath)) console.warn(`Warning: Package ${packageName} has not been built (dist/ missing). It may need to be built first.`);
|
|
209
|
+
}
|
|
210
|
+
return packagePath;
|
|
211
|
+
}
|
|
212
|
+
} catch {}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
};
|
|
266
217
|
const updatePackageJson = async (builtPreviewAppPath) => {
|
|
267
218
|
const packageJsonPath = path.resolve(builtPreviewAppPath, "./package.json");
|
|
268
219
|
const packageJson = JSON.parse(await fs.promises.readFile(packageJsonPath, "utf8"));
|
|
@@ -270,13 +221,38 @@ const updatePackageJson = async (builtPreviewAppPath) => {
|
|
|
270
221
|
packageJson.scripts.start = "next start";
|
|
271
222
|
delete packageJson.scripts.postbuild;
|
|
272
223
|
packageJson.name = "preview-server";
|
|
273
|
-
|
|
224
|
+
const workspaceRoot = findWorkspaceRoot(process.cwd());
|
|
225
|
+
if (packageJson.dependencies && workspaceRoot) {
|
|
226
|
+
for (const [dependency, version$1] of Object.entries(packageJson.dependencies)) if (typeof version$1 === "string" && version$1.startsWith("workspace:")) {
|
|
227
|
+
const packagePath = findWorkspacePackage(dependency, workspaceRoot);
|
|
228
|
+
if (packagePath) {
|
|
229
|
+
const packageJsonPath$1 = path.join(packagePath, "package.json");
|
|
230
|
+
try {
|
|
231
|
+
if (JSON.parse(fs.readFileSync(packageJsonPath$1, "utf8")).main?.includes("dist")) {
|
|
232
|
+
const distPath = path.join(packagePath, "dist");
|
|
233
|
+
if (!fs.existsSync(distPath)) throw new Error(`Package ${dependency} has not been built. Please run 'pnpm build:packages' first.`);
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
if (error instanceof Error && error.message.includes("built")) throw error;
|
|
237
|
+
}
|
|
238
|
+
const normalizedPath = path.resolve(packagePath).replace(/\\/g, "/");
|
|
239
|
+
packageJson.dependencies[dependency] = `file:${normalizedPath}`;
|
|
240
|
+
} else {
|
|
241
|
+
console.warn(`Warning: Could not find workspace package ${dependency}, removing from dependencies.`);
|
|
242
|
+
delete packageJson.dependencies[dependency];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} else if (packageJson.dependencies && !workspaceRoot) {
|
|
246
|
+
console.warn("Warning: Could not find workspace root. Workspace dependencies will be removed.");
|
|
247
|
+
for (const [dependency, version$1] of Object.entries(packageJson.dependencies)) if (typeof version$1 === "string" && version$1.startsWith("workspace:")) delete packageJson.dependencies[dependency];
|
|
248
|
+
}
|
|
249
|
+
for (const [dependency, version$1] of Object.entries(packageJson.devDependencies || {})) packageJson.devDependencies[dependency] = version$1.replace("workspace:", "");
|
|
274
250
|
delete packageJson.devDependencies["@ahmedrowaihi/pdf-forge-components"];
|
|
275
251
|
delete packageJson.devDependencies["@ahmedrowaihi/pdf-forge-core"];
|
|
276
252
|
delete packageJson.scripts.prepare;
|
|
277
253
|
await fs.promises.writeFile(packageJsonPath, JSON.stringify(packageJson), "utf8");
|
|
278
254
|
};
|
|
279
|
-
const build
|
|
255
|
+
const build = async ({ dir: templatesDirRelativePath, packageManager }) => {
|
|
280
256
|
try {
|
|
281
257
|
const previewServerLocation = await getPreviewServerLocation();
|
|
282
258
|
const spinner = ora({
|
|
@@ -331,217 +307,6 @@ const build$1 = async ({ dir: templatesDirRelativePath, packageManager }) => {
|
|
|
331
307
|
}
|
|
332
308
|
};
|
|
333
309
|
|
|
334
|
-
//#endregion
|
|
335
|
-
//#region src/utils/preview/hot-reloading/get-imported-modules.ts
|
|
336
|
-
const traverse = typeof traverseModule === "function" ? traverseModule : traverseModule.default;
|
|
337
|
-
const getImportedModules = (contents) => {
|
|
338
|
-
const importedPaths = [];
|
|
339
|
-
traverse(parse(contents, {
|
|
340
|
-
sourceType: "unambiguous",
|
|
341
|
-
strictMode: false,
|
|
342
|
-
errorRecovery: true,
|
|
343
|
-
plugins: [
|
|
344
|
-
"jsx",
|
|
345
|
-
"typescript",
|
|
346
|
-
"decorators"
|
|
347
|
-
]
|
|
348
|
-
}), {
|
|
349
|
-
ImportDeclaration({ node }) {
|
|
350
|
-
importedPaths.push(node.source.value);
|
|
351
|
-
},
|
|
352
|
-
ExportAllDeclaration({ node }) {
|
|
353
|
-
importedPaths.push(node.source.value);
|
|
354
|
-
},
|
|
355
|
-
ExportNamedDeclaration({ node }) {
|
|
356
|
-
if (node.source) importedPaths.push(node.source.value);
|
|
357
|
-
},
|
|
358
|
-
TSExternalModuleReference({ node }) {
|
|
359
|
-
importedPaths.push(node.expression.value);
|
|
360
|
-
},
|
|
361
|
-
CallExpression({ node }) {
|
|
362
|
-
if ("name" in node.callee && node.callee.name === "require") {
|
|
363
|
-
if (node.arguments.length === 1) {
|
|
364
|
-
const importPathNode = node.arguments[0];
|
|
365
|
-
if (importPathNode.type === "StringLiteral") importedPaths.push(importPathNode.value);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
return importedPaths;
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
//#endregion
|
|
374
|
-
//#region src/utils/preview/hot-reloading/resolve-path-aliases.ts
|
|
375
|
-
const resolvePathAliases = (importPaths, projectPath) => {
|
|
376
|
-
const configLoadResult = loadConfig(projectPath);
|
|
377
|
-
if (configLoadResult.resultType === "success") {
|
|
378
|
-
const matchPath = createMatchPath(configLoadResult.absoluteBaseUrl, configLoadResult.paths);
|
|
379
|
-
return importPaths.map((importedPath) => {
|
|
380
|
-
const unaliasedPath = matchPath(importedPath, void 0, void 0, [
|
|
381
|
-
".tsx",
|
|
382
|
-
".ts",
|
|
383
|
-
".js",
|
|
384
|
-
".jsx",
|
|
385
|
-
".cjs",
|
|
386
|
-
".mjs"
|
|
387
|
-
]);
|
|
388
|
-
if (unaliasedPath) return `./${path.relative(projectPath, unaliasedPath)}`;
|
|
389
|
-
return importedPath;
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
return importPaths;
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
//#endregion
|
|
396
|
-
//#region src/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
397
|
-
const readAllFilesInsideDirectory = async (directory) => {
|
|
398
|
-
let allFilePaths = [];
|
|
399
|
-
const topLevelDirents = await promises.readdir(directory, { withFileTypes: true });
|
|
400
|
-
for (const dirent of topLevelDirents) {
|
|
401
|
-
const pathToDirent = path.join(directory, dirent.name);
|
|
402
|
-
if (dirent.isDirectory()) allFilePaths = allFilePaths.concat(await readAllFilesInsideDirectory(pathToDirent));
|
|
403
|
-
else allFilePaths.push(pathToDirent);
|
|
404
|
-
}
|
|
405
|
-
return allFilePaths;
|
|
406
|
-
};
|
|
407
|
-
const javascriptExtensions = [
|
|
408
|
-
".js",
|
|
409
|
-
".ts",
|
|
410
|
-
".jsx",
|
|
411
|
-
".tsx",
|
|
412
|
-
".mjs",
|
|
413
|
-
".cjs"
|
|
414
|
-
];
|
|
415
|
-
const isJavascriptModule = (filePath) => {
|
|
416
|
-
const extensionName = path.extname(filePath);
|
|
417
|
-
return javascriptExtensions.includes(extensionName);
|
|
418
|
-
};
|
|
419
|
-
const checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
|
|
420
|
-
if (existsSync(`${pathWithoutExtension}.ts`)) return `${pathWithoutExtension}.ts`;
|
|
421
|
-
if (existsSync(`${pathWithoutExtension}.tsx`)) return `${pathWithoutExtension}.tsx`;
|
|
422
|
-
if (existsSync(`${pathWithoutExtension}.js`)) return `${pathWithoutExtension}.js`;
|
|
423
|
-
if (existsSync(`${pathWithoutExtension}.jsx`)) return `${pathWithoutExtension}.jsx`;
|
|
424
|
-
if (existsSync(`${pathWithoutExtension}.mjs`)) return `${pathWithoutExtension}.mjs`;
|
|
425
|
-
if (existsSync(`${pathWithoutExtension}.cjs`)) return `${pathWithoutExtension}.cjs`;
|
|
426
|
-
};
|
|
427
|
-
/**
|
|
428
|
-
* Creates a stateful dependency graph that is structured in a way that you can get
|
|
429
|
-
* the dependents of a module from its path.
|
|
430
|
-
*
|
|
431
|
-
* Stateful in the sense that it provides a `getter` and an "`updater`". The updater
|
|
432
|
-
* will receive changes to the files, that can be perceived through some file watching mechanism,
|
|
433
|
-
* so that it doesn't need to recompute the entire dependency graph but only the parts changed.
|
|
434
|
-
*/
|
|
435
|
-
const createDependencyGraph = async (directory) => {
|
|
436
|
-
const modulePaths = (await readAllFilesInsideDirectory(directory)).filter(isJavascriptModule);
|
|
437
|
-
const graph = Object.fromEntries(modulePaths.map((path$1) => [path$1, {
|
|
438
|
-
path: path$1,
|
|
439
|
-
dependencyPaths: [],
|
|
440
|
-
dependentPaths: [],
|
|
441
|
-
moduleDependencies: []
|
|
442
|
-
}]));
|
|
443
|
-
const getDependencyPaths = async (filePath) => {
|
|
444
|
-
const contents = await promises.readFile(filePath, "utf8");
|
|
445
|
-
const importedPathsRelativeToDirectory = (isJavascriptModule(filePath) ? resolvePathAliases(getImportedModules(contents), path.dirname(filePath)) : []).map((dependencyPath) => {
|
|
446
|
-
if (!dependencyPath.startsWith(".") || path.isAbsolute(dependencyPath)) return dependencyPath;
|
|
447
|
-
let pathToDependencyFromDirectory = path.resolve(path.dirname(filePath), dependencyPath);
|
|
448
|
-
let isDirectory = false;
|
|
449
|
-
try {
|
|
450
|
-
isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
|
|
451
|
-
} catch {}
|
|
452
|
-
if (isDirectory) {
|
|
453
|
-
const pathWithExtension = checkFileExtensionsUntilItExists(`${pathToDependencyFromDirectory}/index`);
|
|
454
|
-
if (pathWithExtension) pathToDependencyFromDirectory = pathWithExtension;
|
|
455
|
-
else console.warn(`Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`);
|
|
456
|
-
}
|
|
457
|
-
const extension = path.extname(pathToDependencyFromDirectory);
|
|
458
|
-
const pathWithEnsuredExtension = (() => {
|
|
459
|
-
if (extension.length > 0 && existsSync(pathToDependencyFromDirectory)) return pathToDependencyFromDirectory;
|
|
460
|
-
if (javascriptExtensions.includes(extension)) return checkFileExtensionsUntilItExists(pathToDependencyFromDirectory.replace(extension, ""));
|
|
461
|
-
return checkFileExtensionsUntilItExists(pathToDependencyFromDirectory);
|
|
462
|
-
})();
|
|
463
|
-
if (pathWithEnsuredExtension) pathToDependencyFromDirectory = pathWithEnsuredExtension;
|
|
464
|
-
else console.warn(`Could not find file at ${pathToDependencyFromDirectory}`);
|
|
465
|
-
return pathToDependencyFromDirectory;
|
|
466
|
-
});
|
|
467
|
-
const moduleDependencies = importedPathsRelativeToDirectory.filter((dependencyPath) => !dependencyPath.startsWith(".") && !path.isAbsolute(dependencyPath));
|
|
468
|
-
return {
|
|
469
|
-
dependencyPaths: importedPathsRelativeToDirectory.filter((dependencyPath) => dependencyPath.startsWith(".") || path.isAbsolute(dependencyPath)),
|
|
470
|
-
moduleDependencies
|
|
471
|
-
};
|
|
472
|
-
};
|
|
473
|
-
const updateModuleDependenciesInGraph = async (moduleFilePath) => {
|
|
474
|
-
if (graph[moduleFilePath] === void 0) graph[moduleFilePath] = {
|
|
475
|
-
path: moduleFilePath,
|
|
476
|
-
dependencyPaths: [],
|
|
477
|
-
dependentPaths: [],
|
|
478
|
-
moduleDependencies: []
|
|
479
|
-
};
|
|
480
|
-
const { moduleDependencies, dependencyPaths: newDependencyPaths } = await getDependencyPaths(moduleFilePath);
|
|
481
|
-
graph[moduleFilePath].moduleDependencies = moduleDependencies;
|
|
482
|
-
for (const dependencyPath of graph[moduleFilePath].dependencyPaths) {
|
|
483
|
-
if (newDependencyPaths.includes(dependencyPath)) continue;
|
|
484
|
-
const dependencyModule = graph[dependencyPath];
|
|
485
|
-
if (dependencyModule !== void 0) dependencyModule.dependentPaths = dependencyModule.dependentPaths.filter((dependentPath) => dependentPath !== moduleFilePath);
|
|
486
|
-
}
|
|
487
|
-
graph[moduleFilePath].dependencyPaths = newDependencyPaths;
|
|
488
|
-
for (const dependencyPath of newDependencyPaths) {
|
|
489
|
-
if (graph[dependencyPath] === void 0) await updateModuleDependenciesInGraph(dependencyPath);
|
|
490
|
-
const dependencyModule = graph[dependencyPath];
|
|
491
|
-
if (dependencyModule === void 0) throw new Error(`Loading the dependency path ${dependencyPath} did not initialize it at all. This is a bug in React PDF.`);
|
|
492
|
-
if (!dependencyModule.dependentPaths.includes(moduleFilePath)) dependencyModule.dependentPaths.push(moduleFilePath);
|
|
493
|
-
}
|
|
494
|
-
};
|
|
495
|
-
for (const filePath of modulePaths) await updateModuleDependenciesInGraph(filePath);
|
|
496
|
-
const removeModuleFromGraph = (filePath) => {
|
|
497
|
-
const module = graph[filePath];
|
|
498
|
-
if (module) {
|
|
499
|
-
for (const dependencyPath of module.dependencyPaths) if (graph[dependencyPath]) graph[dependencyPath].dependentPaths = graph[dependencyPath].dependentPaths.filter((dependentPath) => dependentPath !== filePath);
|
|
500
|
-
delete graph[filePath];
|
|
501
|
-
}
|
|
502
|
-
};
|
|
503
|
-
return [
|
|
504
|
-
graph,
|
|
505
|
-
async (event, pathToModified) => {
|
|
506
|
-
switch (event) {
|
|
507
|
-
case "change":
|
|
508
|
-
if (isJavascriptModule(pathToModified)) await updateModuleDependenciesInGraph(pathToModified);
|
|
509
|
-
break;
|
|
510
|
-
case "add":
|
|
511
|
-
if (isJavascriptModule(pathToModified)) await updateModuleDependenciesInGraph(pathToModified);
|
|
512
|
-
break;
|
|
513
|
-
case "addDir": {
|
|
514
|
-
const modulesInsideAddedDirectory = (await readAllFilesInsideDirectory(pathToModified)).filter(isJavascriptModule);
|
|
515
|
-
for (const filePath of modulesInsideAddedDirectory) await updateModuleDependenciesInGraph(filePath);
|
|
516
|
-
break;
|
|
517
|
-
}
|
|
518
|
-
case "unlink":
|
|
519
|
-
if (isJavascriptModule(pathToModified)) removeModuleFromGraph(pathToModified);
|
|
520
|
-
break;
|
|
521
|
-
case "unlinkDir": {
|
|
522
|
-
const modulesInsideDeletedDirectory = (await readAllFilesInsideDirectory(pathToModified)).filter(isJavascriptModule);
|
|
523
|
-
for (const filePath of modulesInsideDeletedDirectory) removeModuleFromGraph(filePath);
|
|
524
|
-
break;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
},
|
|
528
|
-
{ resolveDependentsOf: function resolveDependentsOf(pathToModule) {
|
|
529
|
-
const dependentPaths = /* @__PURE__ */ new Set();
|
|
530
|
-
const stack = [pathToModule];
|
|
531
|
-
while (stack.length > 0) {
|
|
532
|
-
const moduleEntry = graph[stack.pop()];
|
|
533
|
-
if (!moduleEntry) continue;
|
|
534
|
-
for (const dependentPath of moduleEntry.dependentPaths) {
|
|
535
|
-
if (dependentPaths.has(dependentPath) || dependentPath === pathToModule) continue;
|
|
536
|
-
dependentPaths.add(dependentPath);
|
|
537
|
-
stack.push(dependentPath);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
return [...dependentPaths.values()];
|
|
541
|
-
} }
|
|
542
|
-
];
|
|
543
|
-
};
|
|
544
|
-
|
|
545
310
|
//#endregion
|
|
546
311
|
//#region src/utils/preview/hot-reloading/setup-hot-reloading.ts
|
|
547
312
|
const setupHotreloading = async (devServer$1, templatesDirRelativePath) => {
|
|
@@ -594,10 +359,6 @@ const setupHotreloading = async (devServer$1, templatesDirRelativePath) => {
|
|
|
594
359
|
return watcher;
|
|
595
360
|
};
|
|
596
361
|
|
|
597
|
-
//#endregion
|
|
598
|
-
//#region src/utils/style-text.ts
|
|
599
|
-
const styleText = nodeUtil.styleText ? nodeUtil.styleText : (_, text) => text;
|
|
600
|
-
|
|
601
362
|
//#endregion
|
|
602
363
|
//#region src/utils/preview/get-env-variables-for-preview-app.ts
|
|
603
364
|
const getEnvVariablesForPreviewApp = (relativePathToTemplatesDirectory, previewServerLocation, cwd) => {
|
|
@@ -700,13 +461,11 @@ const safeAsyncServerListen = (server, port) => {
|
|
|
700
461
|
});
|
|
701
462
|
};
|
|
702
463
|
const startDevServer = async (templatesDirRelativePath, staticBaseDirRelativePath, port) => {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
console.error(` ${logSymbols.error} Node ${majorNodeVersion} is not supported. Please upgrade to Node 20 or higher.`);
|
|
464
|
+
if (typeof Bun === "undefined") {
|
|
465
|
+
console.error(` ${logSymbols.error} Bun runtime is required. Please run with: bun run pdf-dev dev`);
|
|
706
466
|
process.exit(1);
|
|
707
467
|
}
|
|
708
468
|
const previewServerLocation = await getPreviewServerLocation();
|
|
709
|
-
const previewServer = createJiti(previewServerLocation);
|
|
710
469
|
devServer = http.createServer((req, res) => {
|
|
711
470
|
if (!req.url) {
|
|
712
471
|
res.end(404);
|
|
@@ -759,7 +518,8 @@ const startDevServer = async (templatesDirRelativePath, staticBaseDirRelativePat
|
|
|
759
518
|
...process.env,
|
|
760
519
|
...getEnvVariablesForPreviewApp(path.normalize(templatesDirRelativePath), previewServerLocation, process.cwd())
|
|
761
520
|
};
|
|
762
|
-
const
|
|
521
|
+
const nextModule = await import(Bun.resolveSync("next", previewServerLocation));
|
|
522
|
+
const app = (nextModule.default ?? nextModule)({
|
|
763
523
|
dev: false,
|
|
764
524
|
conf: { images: { unoptimized: true } },
|
|
765
525
|
hostname: "localhost",
|
|
@@ -867,15 +627,9 @@ const dev = async ({ dir: templatesDirRelativePath, port }) => {
|
|
|
867
627
|
};
|
|
868
628
|
|
|
869
629
|
//#endregion
|
|
870
|
-
//#region src/utils/
|
|
871
|
-
function escapeStringForRegex(string) {
|
|
872
|
-
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
//#endregion
|
|
876
|
-
//#region src/utils/esbuild/renderring-utilities-exporter.ts
|
|
630
|
+
//#region src/utils/bun/rendering-utilities-exporter.ts
|
|
877
631
|
/**
|
|
878
|
-
*
|
|
632
|
+
* Bun plugin to export the `render` function out of the user's PDF template
|
|
879
633
|
* so that React version mismatches don't happen.
|
|
880
634
|
*
|
|
881
635
|
* This also exports the `createElement` from the user's React version as well
|
|
@@ -886,28 +640,35 @@ function escapeStringForRegex(string) {
|
|
|
886
640
|
*/
|
|
887
641
|
const renderingUtilitiesExporter = (pdfTemplates) => ({
|
|
888
642
|
name: "rendering-utilities-exporter",
|
|
889
|
-
setup
|
|
890
|
-
|
|
643
|
+
setup(builder) {
|
|
644
|
+
const templateRegex = new RegExp(pdfTemplates.map((templatePath) => escapeStringForRegex(templatePath)).join("|"));
|
|
645
|
+
builder.onLoad({ filter: templateRegex }, async (args) => {
|
|
646
|
+
const code = await promises.readFile(args.path, "utf8");
|
|
647
|
+
const ext = path.extname(args.path).slice(1);
|
|
891
648
|
return {
|
|
892
|
-
contents: `${
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
loader:
|
|
649
|
+
contents: `${code}
|
|
650
|
+
export { render } from 'react-pdf-module-that-will-export-render';
|
|
651
|
+
export { createElement as reactPDFCreateReactElement } from 'react';
|
|
652
|
+
`,
|
|
653
|
+
loader: ext === "tsx" || ext === "jsx" ? "tsx" : ext
|
|
897
654
|
};
|
|
898
655
|
});
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
656
|
+
builder.onResolve({ filter: /^react-pdf-module-that-will-export-render$/ }, async (args) => {
|
|
657
|
+
try {
|
|
658
|
+
return {
|
|
659
|
+
path: await Bun.resolve("@ahmedrowaihi/pdf-forge-core", args.importer),
|
|
660
|
+
namespace: "file"
|
|
661
|
+
};
|
|
662
|
+
} catch {
|
|
663
|
+
try {
|
|
664
|
+
return {
|
|
665
|
+
path: await Bun.resolve("@ahmedrowaihi/pdf-forge-components", args.importer),
|
|
666
|
+
namespace: "file"
|
|
667
|
+
};
|
|
668
|
+
} catch (_error) {
|
|
669
|
+
throw new Error("Failed trying to import `render` from either `@ahmedrowaihi/pdf-forge-core` or `@ahmedrowaihi/pdf-forge-components` to be able to render your PDF template.\n Maybe you don't have either of them installed?");
|
|
670
|
+
}
|
|
671
|
+
}
|
|
911
672
|
});
|
|
912
673
|
}
|
|
913
674
|
});
|
|
@@ -920,7 +681,6 @@ const getTemplatesFromDirectory = (templateDirectory) => {
|
|
|
920
681
|
for (const directory of templateDirectory.subDirectories) templatePaths.push(...getTemplatesFromDirectory(directory));
|
|
921
682
|
return templatePaths;
|
|
922
683
|
};
|
|
923
|
-
const require = createRequire(url.fileURLToPath(import.meta.url));
|
|
924
684
|
const exportTemplates = async (pathToWhereTemplateMarkupShouldBeDumped, templatesDirectoryPath, options) => {
|
|
925
685
|
if (fs.existsSync(pathToWhereTemplateMarkupShouldBeDumped)) fs.rmSync(pathToWhereTemplateMarkupShouldBeDumped, { recursive: true });
|
|
926
686
|
let spinner;
|
|
@@ -937,27 +697,54 @@ const exportTemplates = async (pathToWhereTemplateMarkupShouldBeDumped, template
|
|
|
937
697
|
return;
|
|
938
698
|
}
|
|
939
699
|
const allTemplates = getTemplatesFromDirectory(templatesDirectoryMetadata);
|
|
700
|
+
const templateBaseDir = path.resolve(process.cwd(), templatesDirectoryPath);
|
|
701
|
+
const assetTransformPlugin = {
|
|
702
|
+
name: "asset-to-import-transform",
|
|
703
|
+
setup(builder) {
|
|
704
|
+
builder.onLoad({ filter: /\.(tsx?|jsx?)$/ }, async (args) => {
|
|
705
|
+
const filePath = args.path;
|
|
706
|
+
if (!filePath.startsWith(templateBaseDir)) return;
|
|
707
|
+
const code = await Bun.file(filePath).text();
|
|
708
|
+
const { transformAssetsToImports } = await import("@ahmedrowaihi/pdf-forge-toolbox");
|
|
709
|
+
const { code: transformedCode } = await transformAssetsToImports(code, filePath);
|
|
710
|
+
if (transformedCode !== code) return {
|
|
711
|
+
contents: transformedCode,
|
|
712
|
+
loader: "tsx"
|
|
713
|
+
};
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
};
|
|
940
717
|
try {
|
|
941
|
-
await build({
|
|
942
|
-
|
|
943
|
-
entryPoints: allTemplates,
|
|
944
|
-
format: "cjs",
|
|
945
|
-
jsx: "automatic",
|
|
946
|
-
loader: { ".js": "jsx" },
|
|
947
|
-
logLevel: "silent",
|
|
948
|
-
outExtension: { ".js": ".cjs" },
|
|
718
|
+
const buildResult = await Bun.build({
|
|
719
|
+
entrypoints: allTemplates,
|
|
949
720
|
outdir: pathToWhereTemplateMarkupShouldBeDumped,
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
721
|
+
target: "node",
|
|
722
|
+
format: "cjs",
|
|
723
|
+
plugins: [assetTransformPlugin, renderingUtilitiesExporter(allTemplates)],
|
|
724
|
+
jsx: {
|
|
725
|
+
runtime: "automatic",
|
|
726
|
+
importSource: "react"
|
|
727
|
+
},
|
|
728
|
+
minify: false,
|
|
729
|
+
sourcemap: "external",
|
|
730
|
+
splitting: false
|
|
953
731
|
});
|
|
732
|
+
if (!buildResult.success) {
|
|
733
|
+
const errorMessages = buildResult.logs.map((log) => log.message).join("\n");
|
|
734
|
+
throw new Error(`Bun build failed: ${errorMessages}`);
|
|
735
|
+
}
|
|
736
|
+
const builtFiles = buildResult.outputs.filter((output) => output.path.endsWith(".js"));
|
|
737
|
+
for (const file of builtFiles) {
|
|
738
|
+
const newPath = file.path.replace(/\.js$/, ".cjs");
|
|
739
|
+
await promises.rename(file.path, newPath);
|
|
740
|
+
}
|
|
954
741
|
} catch (exception) {
|
|
955
742
|
if (spinner) spinner.stopAndPersist({
|
|
956
743
|
symbol: logSymbols.error,
|
|
957
744
|
text: "Failed to build PDF templates"
|
|
958
745
|
});
|
|
959
|
-
const
|
|
960
|
-
console.error(`\n${
|
|
746
|
+
const error = exception;
|
|
747
|
+
console.error(`\n${error.message}`);
|
|
961
748
|
process.exit(1);
|
|
962
749
|
}
|
|
963
750
|
if (spinner) spinner.succeed();
|
|
@@ -967,9 +754,10 @@ const exportTemplates = async (pathToWhereTemplateMarkupShouldBeDumped, template
|
|
|
967
754
|
spinner.text = `rendering ${template.split("/").pop()}`;
|
|
968
755
|
spinner.render();
|
|
969
756
|
}
|
|
970
|
-
|
|
971
|
-
const
|
|
972
|
-
const
|
|
757
|
+
const templateModule = await new Function("path", "return import(path)")(`file://${template}`);
|
|
758
|
+
const TemplateComponent = templateModule.default;
|
|
759
|
+
const previewProps = TemplateComponent && "PreviewProps" in TemplateComponent ? TemplateComponent.PreviewProps : {};
|
|
760
|
+
const rendered = await templateModule.render(templateModule.reactPDFCreateReactElement(TemplateComponent, previewProps), options);
|
|
973
761
|
writeFileSync(template.replace(".cjs", options.plainText ? ".txt" : ".html"), rendered);
|
|
974
762
|
unlinkSync(template);
|
|
975
763
|
} catch (exception) {
|
|
@@ -1047,7 +835,7 @@ const start = async () => {
|
|
|
1047
835
|
//#region src/index.ts
|
|
1048
836
|
program.name("react-pdf").description("A live preview of your PDF templates right in your browser").version(package_default.version);
|
|
1049
837
|
program.command("dev").description("Starts the preview PDF development app").option("-d, --dir <path>", "Directory with your PDF templates", "./templates").option("-p --port <port>", "Port to run dev server on", "3000").action(dev);
|
|
1050
|
-
program.command("build").description("Copies the preview app for onto .react-pdf and builds it").option("-d, --dir <path>", "Directory with your PDF templates", "./templates").option("-p --packageManager <name>", "Package name to use on installation on `.react-pdf`", "npm").action(build
|
|
838
|
+
program.command("build").description("Copies the preview app for onto .react-pdf and builds it").option("-d, --dir <path>", "Directory with your PDF templates", "./templates").option("-p --packageManager <name>", "Package name to use on installation on `.react-pdf`", "npm").action(build);
|
|
1051
839
|
program.command("start").description("Runs the built preview app that is inside of \".react-pdf\"").action(start);
|
|
1052
840
|
program.command("export").description("Build the templates to the `out` directory").option("--outDir <path>", "Output directory", "out").option("-p, --pretty", "Pretty print the output", false).option("-t, --plainText", "Set output format as plain text", false).option("-d, --dir <path>", "Directory with your PDF templates", "./templates").option("-s, --silent", "To, or not to show a spinner with process information", false).action(({ outDir, pretty, plainText, silent, dir: srcDir }) => exportTemplates(outDir, srcDir, {
|
|
1053
841
|
silent,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahmedrowaihi/pdf-forge-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-canary.0",
|
|
4
4
|
"description": "A live preview of your PDF templates right in your browser.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"pdf-dev": "./dist/index.js"
|
|
@@ -17,18 +17,14 @@
|
|
|
17
17
|
"pdf"
|
|
18
18
|
],
|
|
19
19
|
"engines": {
|
|
20
|
-
"
|
|
20
|
+
"bun": ">=1.0.0"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@babel/parser": "^7.27.0",
|
|
24
|
-
"@babel/traverse": "^7.27.0",
|
|
25
23
|
"chokidar": "^4.0.3",
|
|
26
24
|
"commander": "^13.0.0",
|
|
27
25
|
"conf": "^15.0.2",
|
|
28
26
|
"debounce": "^2.0.0",
|
|
29
|
-
"esbuild": "^0.25.0",
|
|
30
27
|
"glob": "^11.0.0",
|
|
31
|
-
"jiti": "2.4.2",
|
|
32
28
|
"log-symbols": "^7.0.0",
|
|
33
29
|
"mime-types": "^3.0.0",
|
|
34
30
|
"normalize-path": "^3.0.0",
|
|
@@ -36,13 +32,14 @@
|
|
|
36
32
|
"ora": "^8.0.0",
|
|
37
33
|
"prompts": "2.4.2",
|
|
38
34
|
"socket.io": "^4.8.1",
|
|
39
|
-
"tsconfig-paths": "4.2.0"
|
|
35
|
+
"tsconfig-paths": "4.2.0",
|
|
36
|
+
"@ahmedrowaihi/pdf-forge-toolbox": "1.2.0-canary.0"
|
|
40
37
|
},
|
|
41
38
|
"devDependencies": {
|
|
42
|
-
"@types/
|
|
43
|
-
"@types/babel__traverse": "7.20.7",
|
|
39
|
+
"@types/bun": "^1.3.5",
|
|
44
40
|
"@types/mime-types": "2.1.4",
|
|
45
41
|
"@types/prompts": "2.4.9",
|
|
42
|
+
"@types/normalize-path": "3.0.2",
|
|
46
43
|
"next": "16.0.10",
|
|
47
44
|
"react": "19.0.0",
|
|
48
45
|
"react-dom": "19.0.0",
|