@webtypen/webframez-core 0.3.93 → 0.3.95

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/README.md CHANGED
@@ -997,3 +997,30 @@ Metro consumers can call
997
997
  It applies `WEBFRAMEZ_BUILD_MAX_WORKERS` and `WEBFRAMEZ_METRO_CACHE_DIRECTORY`,
998
998
  preserving Expo's FileStore implementation and supporting old/new file-map option
999
999
  names. Do not pass Expo `--clear` on normal cached builds.
1000
+
1001
+
1002
+ ### Reusable build workspaces
1003
+
1004
+ `webframez compile --project tsconfig.json --dir build` compiles TypeScript without loading
1005
+ application configuration, console services or build plugins. It preserves incremental
1006
+ compiler output under `WEBFRAMEZ_BUILD_CACHE_DIRECTORY` (default `.webframez-cache`),
1007
+ invalidates deleted/renamed source files and promotes a successful output atomically.
1008
+ A failed compilation leaves the previous build intact. Include the compiler cache in
1009
+ persistent CI storage; remove it for a force-clear build.
1010
+
1011
+ `webframez dependencies --dir build` prepares an independent, frozen production pnpm
1012
+ installation, then copies its dependencies into `build/node_modules`. Development
1013
+ modules remain untouched. A pinned pnpm version and an independent lockfile are
1014
+ required; monorepos should use `pnpm deploy`. Registry settings are read from
1015
+ `NPM_CONFIG_USERCONFIG` or the source `.npmrc`, never copied into the artifact.
1016
+ Dependency install scripts follow the package's pnpm policy; `--ignore-scripts` disables
1017
+ them. Root lifecycle scripts are excluded from the separate production installation.
1018
+
1019
+ Full `webframez build` supports `build.productionDependencies: true` and
1020
+ `build.dependencyInstallScripts: false` for the same behavior. Runtime-required packages
1021
+ must be declared under dependencies, including browser or compiler packages.
1022
+
1023
+ Asset builds use a stable staging directory so bundler caches can reuse module paths.
1024
+ An exclusive per-output lock prevents concurrent builds overwriting that directory.
1025
+ After a killed local build, remove its `.webframez-build/.building-*.lock` directory
1026
+ only after confirming that no previous build is running. WSM Force Clear removes it.
@@ -22,6 +22,8 @@ export type WebframezBuildConfig = {
22
22
  dir?: string;
23
23
  tsconfig?: string;
24
24
  cacheDirectory?: string;
25
+ productionDependencies?: boolean;
26
+ dependencyInstallScripts?: boolean;
25
27
  entry?: string;
26
28
  runtimeFiles?: WebframezBuildRuntimeFile[];
27
29
  prunePaths?: string[];
@@ -54,7 +56,12 @@ export declare class BuildApplication {
54
56
  private readonly stagingDir;
55
57
  private readonly buildId;
56
58
  constructor(projectRoot: string, config: WebframezAppConfig, options: BuildApplicationOptions);
59
+ /** Compile without booting application configuration or running asset/runtime plugins. */
60
+ compile(): Promise<void>;
61
+ private withBuildLock;
62
+ private compileOnly;
57
63
  run(): Promise<void>;
64
+ private execute;
58
65
  private logBuildStep;
59
66
  private runStep;
60
67
  private createContext;
@@ -19,6 +19,7 @@ const node_path_1 = __importDefault(require("node:path"));
19
19
  const node_child_process_1 = require("node:child_process");
20
20
  const node_util_1 = require("node:util");
21
21
  const node_crypto_1 = __importDefault(require("node:crypto"));
22
+ const BuildDependencies_1 = require("./BuildDependencies");
22
23
  const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
23
24
  function timestamp() {
24
25
  return new Date().toISOString().replace(/[-:TZ.]/g, "");
@@ -52,9 +53,55 @@ class BuildApplication {
52
53
  this.outDir = node_path_1.default.resolve(projectRoot, options.outDir || ((_a = config.build) === null || _a === void 0 ? void 0 : _a.dir) || "build");
53
54
  this.buildId = timestamp();
54
55
  this.buildRoot = node_path_1.default.resolve(projectRoot, ".webframez-build");
55
- this.stagingDir = node_path_1.default.join(this.buildRoot, `.building-${this.buildId}`);
56
+ this.stagingDir = node_path_1.default.join(this.buildRoot, `.building-${node_crypto_1.default.createHash("sha256").update(this.outDir).digest("hex").slice(0, 24)}`);
57
+ }
58
+ /** Compile without booting application configuration or running asset/runtime plugins. */
59
+ compile() {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ return this.withBuildLock(() => this.compileOnly());
62
+ });
63
+ }
64
+ withBuildLock(callback) {
65
+ return __awaiter(this, void 0, void 0, function* () {
66
+ const lock = this.stagingDir + ".lock";
67
+ yield promises_1.default.mkdir(this.buildRoot, { recursive: true });
68
+ try {
69
+ yield promises_1.default.mkdir(lock);
70
+ }
71
+ catch (error) {
72
+ if (error.code === "EEXIST")
73
+ throw new Error(`Build output is locked: ${lock}. Remove the lock only after the previous build has stopped.`);
74
+ throw error;
75
+ }
76
+ try {
77
+ return yield callback();
78
+ }
79
+ finally {
80
+ yield promises_1.default.rm(lock, { recursive: true, force: true });
81
+ }
82
+ });
83
+ }
84
+ compileOnly() {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const context = this.createContext();
87
+ yield promises_1.default.rm(this.stagingDir, { recursive: true, force: true });
88
+ yield promises_1.default.mkdir(this.stagingDir, { recursive: true });
89
+ try {
90
+ yield this.runStep("typescript", () => this.runTypescriptBuild(context));
91
+ yield this.promoteBuild();
92
+ }
93
+ catch (error) {
94
+ yield promises_1.default.rm(this.stagingDir, { recursive: true, force: true });
95
+ throw error;
96
+ }
97
+ });
56
98
  }
57
99
  run() {
100
+ return __awaiter(this, void 0, void 0, function* () {
101
+ return this.withBuildLock(() => this.execute());
102
+ });
103
+ }
104
+ execute() {
58
105
  return __awaiter(this, void 0, void 0, function* () {
59
106
  const context = this.createContext();
60
107
  const plugins = this.loadPlugins();
@@ -119,34 +166,24 @@ class BuildApplication {
119
166
  }
120
167
  });
121
168
  }
122
- runTypescriptBuild(context) {
169
+ runTypescriptBuild(_context) {
123
170
  var _a, _b;
124
171
  return __awaiter(this, void 0, void 0, function* () {
125
- const tsconfig = node_path_1.default.resolve(this.projectRoot, ((_a = this.config.build) === null || _a === void 0 ? void 0 : _a.tsconfig) || "tsconfig.json");
126
- const configuredCache = ((_b = this.config.build) === null || _b === void 0 ? void 0 : _b.cacheDirectory) || process.env.WEBFRAMEZ_BUILD_CACHE_DIRECTORY;
127
- if (!configuredCache)
128
- return this.runOrFail(context, "tsc", ["-p", tsconfig, "--outDir", this.stagingDir]);
129
- const root = node_path_1.default.resolve(this.projectRoot, configuredCache);
130
- const scope = node_crypto_1.default.createHash("sha256").update(node_path_1.default.relative(root, tsconfig)).digest("hex").slice(0, 24);
131
- const cache = node_path_1.default.join(root, "typescript", scope);
132
- // Resolved options and the complete source list invalidate deleted/renamed outputs.
133
- const { stdout: config } = yield exec(this.resolveBinary("tsc"), ["-p", tsconfig, "--outDir", node_path_1.default.join(cache, "output"), "--showConfig"], { cwd: this.projectRoot, maxBuffer: 8 * 1024 * 1024 });
134
- const { stdout: version } = yield exec(this.resolveBinary("tsc"), ["--version"], { cwd: this.projectRoot });
135
- const key = node_crypto_1.default.createHash("sha256").update(config).update(version).digest("hex");
136
- const previous = yield promises_1.default.readFile(node_path_1.default.join(cache, "key"), "utf8").catch(() => "");
137
- if (previous !== key)
138
- yield promises_1.default.rm(cache, { recursive: true, force: true });
139
- const output = node_path_1.default.join(cache, "output");
140
- yield promises_1.default.mkdir(output, { recursive: true });
141
- try {
142
- yield this.runOrFail(context, "tsc", ["-p", tsconfig, "--outDir", output, "--incremental", "--tsBuildInfoFile", node_path_1.default.join(cache, "build.tsbuildinfo")]);
143
- yield this.copyTree(output, this.stagingDir);
144
- yield promises_1.default.writeFile(node_path_1.default.join(cache, "key"), key);
145
- }
146
- catch (error) {
147
- yield promises_1.default.rm(cache, { recursive: true, force: true });
148
- throw error;
149
- }
172
+ const options = {
173
+ projectRoot: this.projectRoot,
174
+ tsconfig: node_path_1.default.resolve(this.projectRoot, ((_a = this.config.build) === null || _a === void 0 ? void 0 : _a.tsconfig) || "tsconfig.json"),
175
+ outDir: this.outDir,
176
+ buildRoot: this.buildRoot,
177
+ root: node_path_1.default.resolve(this.projectRoot, ((_b = this.config.build) === null || _b === void 0 ? void 0 : _b.cacheDirectory) || process.env.WEBFRAMEZ_BUILD_CACHE_DIRECTORY || node_path_1.default.join(this.buildRoot, "cache")),
178
+ stagingDir: this.stagingDir,
179
+ };
180
+ yield new Promise((resolve, reject) => {
181
+ const child = (0, node_child_process_1.spawn)(process.execPath, [node_path_1.default.join(__dirname, "BuildCompiler.js"), JSON.stringify(options)], {
182
+ cwd: this.projectRoot, stdio: "inherit", env: process.env,
183
+ });
184
+ child.once("error", reject);
185
+ child.once("exit", (code, signal) => code === 0 ? resolve() : reject(new Error(`tsc exited with code ${code}${signal ? ` (${signal})` : ""}`)));
186
+ });
150
187
  });
151
188
  }
152
189
  copyTree(source, target) {
@@ -162,7 +199,7 @@ class BuildApplication {
162
199
  });
163
200
  }
164
201
  copyRuntimeFiles() {
165
- var _a, _b;
202
+ var _a, _b, _c;
166
203
  return __awaiter(this, void 0, void 0, function* () {
167
204
  const runtimeFiles = ((_a = this.config.build) === null || _a === void 0 ? void 0 : _a.runtimeFiles) || [
168
205
  { from: ".env", optional: true },
@@ -181,6 +218,10 @@ class BuildApplication {
181
218
  }
182
219
  throw new Error(`Runtime file does not exist: ${from}`);
183
220
  }
221
+ if (from === "node_modules" && to === "node_modules" && ((_b = this.config.build) === null || _b === void 0 ? void 0 : _b.productionDependencies)) {
222
+ yield (0, BuildDependencies_1.buildProductionDependencies)(this.projectRoot, this.stagingDir, this.config.build.dependencyInstallScripts === false);
223
+ continue;
224
+ }
184
225
  yield promises_1.default.rm(targetPath, { recursive: true, force: true });
185
226
  yield promises_1.default.mkdir(node_path_1.default.dirname(targetPath), { recursive: true });
186
227
  if ((yield promises_1.default.lstat(sourcePath)).isDirectory())
@@ -188,7 +229,7 @@ class BuildApplication {
188
229
  else
189
230
  yield promises_1.default.cp(sourcePath, targetPath, { dereference: false, mode: node_fs_1.default.constants.COPYFILE_FICLONE });
190
231
  }
191
- for (const prunePath of ((_b = this.config.build) === null || _b === void 0 ? void 0 : _b.prunePaths) || []) {
232
+ for (const prunePath of ((_c = this.config.build) === null || _c === void 0 ? void 0 : _c.prunePaths) || []) {
192
233
  yield promises_1.default.rm(node_path_1.default.resolve(this.stagingDir, prunePath), { recursive: true, force: true });
193
234
  }
194
235
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const node_fs_1 = __importDefault(require("node:fs"));
16
+ const promises_1 = __importDefault(require("node:fs/promises"));
17
+ const node_path_1 = __importDefault(require("node:path"));
18
+ const node_crypto_1 = __importDefault(require("node:crypto"));
19
+ /** A separate process releases the compiler AST before runtime copies and bundling. */
20
+ function compile({ projectRoot, tsconfig, outDir, buildRoot, root, stagingDir }) {
21
+ var _a;
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const ts = require(require.resolve("typescript", { paths: [projectRoot, __dirname] }));
24
+ const scope = node_crypto_1.default.createHash("sha256").update(tsconfig).digest("hex").slice(0, 24);
25
+ const cache = node_path_1.default.join(root, "typescript", scope), output = node_path_1.default.join(cache, "output");
26
+ const loaded = ts.readConfigFile(tsconfig, ts.sys.readFile);
27
+ const parsed = ts.parseJsonConfigFileContent(loaded.config || {}, ts.sys, node_path_1.default.dirname(tsconfig), undefined, tsconfig);
28
+ if (parsed.options.noEmit)
29
+ throw new Error("Build compilation requires emitted output; remove noEmit from the build configuration.");
30
+ // Resolve the original project before redirecting output. Otherwise allowJs
31
+ // projects accidentally compile their previous build into build/build/.
32
+ const generated = [outDir, buildRoot, root, parsed.options.outDir].filter(Boolean);
33
+ const inside = (parent, file) => file === parent || file.startsWith(parent + node_path_1.default.sep);
34
+ const files = parsed.fileNames.filter((file) => !generated.some(directory => inside(directory, file)));
35
+ const key = node_crypto_1.default.createHash("sha256").update(JSON.stringify([files, parsed.options, ts.version])).digest("hex");
36
+ const previous = yield promises_1.default.readFile(node_path_1.default.join(cache, "key"), "utf8").catch(() => "");
37
+ if (previous !== key)
38
+ yield promises_1.default.rm(cache, { recursive: true, force: true });
39
+ yield promises_1.default.mkdir(output, { recursive: true });
40
+ console.log(`[webframez] TypeScript cache: ${previous === key ? "reuse" : "cold"} (${files.length} source files)`);
41
+ try {
42
+ const builder = ts.createIncrementalProgram({ rootNames: files, options: Object.assign(Object.assign({}, parsed.options), { outDir: output, incremental: true, tsBuildInfoFile: node_path_1.default.join(cache, "build.tsbuildinfo") }), projectReferences: parsed.projectReferences });
43
+ const diagnostics = [...(loaded.error ? [loaded.error] : []), ...parsed.errors, ...builder.getOptionsDiagnostics(), ...builder.getGlobalDiagnostics(), ...builder.getSyntacticDiagnostics(), ...builder.getSemanticDiagnostics()];
44
+ if (diagnostics.length)
45
+ console.error(ts.formatDiagnosticsWithColorAndContext(diagnostics, { getCanonicalFileName: (name) => name, getCurrentDirectory: () => projectRoot, getNewLine: () => "\n" }));
46
+ if (diagnostics.some((entry) => entry.category === ts.DiagnosticCategory.Error))
47
+ throw new Error("tsc exited with code 1");
48
+ const emitted = builder.emit();
49
+ if ((_a = emitted.diagnostics) === null || _a === void 0 ? void 0 : _a.length) {
50
+ console.error(ts.formatDiagnosticsWithColorAndContext(emitted.diagnostics, { getCanonicalFileName: (name) => name, getCurrentDirectory: () => projectRoot, getNewLine: () => "\n" }));
51
+ if (emitted.diagnostics.some((entry) => entry.category === ts.DiagnosticCategory.Error))
52
+ throw new Error("tsc exited with code 1");
53
+ }
54
+ if (emitted.emitSkipped)
55
+ throw new Error("tsc exited without emitting output");
56
+ yield promises_1.default.cp(output, stagingDir, { recursive: true, mode: node_fs_1.default.constants.COPYFILE_FICLONE });
57
+ yield promises_1.default.writeFile(node_path_1.default.join(cache, "key"), key);
58
+ }
59
+ catch (error) {
60
+ yield promises_1.default.rm(cache, { recursive: true, force: true });
61
+ throw error;
62
+ }
63
+ });
64
+ }
65
+ if (require.main === module) {
66
+ compile(JSON.parse(process.argv[2])).catch(error => {
67
+ console.error((error === null || error === void 0 ? void 0 : error.stack) || error);
68
+ process.exitCode = 1;
69
+ });
70
+ }
@@ -0,0 +1,2 @@
1
+ /** Prepare an independent production install without pruning the development tree. */
2
+ export declare function buildProductionDependencies(projectRoot: string, outDir: string, ignoreScripts?: boolean): Promise<void>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.buildProductionDependencies = void 0;
16
+ const promises_1 = __importDefault(require("node:fs/promises"));
17
+ const node_path_1 = __importDefault(require("node:path"));
18
+ const node_crypto_1 = __importDefault(require("node:crypto"));
19
+ const node_child_process_1 = require("node:child_process");
20
+ const node_util_1 = require("node:util");
21
+ /** Prepare an independent production install without pruning the development tree. */
22
+ function buildProductionDependencies(projectRoot, outDir, ignoreScripts = false) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ const manifest = JSON.parse(yield promises_1.default.readFile(node_path_1.default.join(projectRoot, "package.json"), "utf8"));
25
+ if (!/^pnpm@\d+\.\d+\.\d+(?:\+sha\d+\.[a-f0-9]+)?$/.test(manifest.packageManager || "")) {
26
+ throw new Error("Production dependencies require a pinned pnpm packageManager.");
27
+ }
28
+ if (manifest.workspaces || Object.values(Object.assign(Object.assign(Object.assign({}, manifest.dependencies), manifest.devDependencies), manifest.optionalDependencies)).some(value => /^(file:|link:|workspace:|\.\.?\/)/.test(String(value)))) {
29
+ throw new Error("Workspace/local dependencies require pnpm deploy instead.");
30
+ }
31
+ const output = node_path_1.default.resolve(projectRoot, outDir);
32
+ const relative = node_path_1.default.relative(projectRoot, output);
33
+ if (!relative || relative.startsWith("..") || node_path_1.default.isAbsolute(relative) || relative.split(node_path_1.default.sep).some(part => [".git", "node_modules", ".webframez-cache"].includes(part))) {
34
+ throw new Error("Production output must be a separate directory inside the project.");
35
+ }
36
+ const metadata = { "package.json": JSON.stringify(Object.assign(Object.assign({}, manifest), { scripts: undefined })) };
37
+ metadata["pnpm-lock.yaml"] = yield promises_1.default.readFile(node_path_1.default.join(projectRoot, "pnpm-lock.yaml"), "utf8");
38
+ for (const name of ["pnpm-workspace.yaml"]) {
39
+ const content = yield promises_1.default.readFile(node_path_1.default.join(projectRoot, name), "utf8").catch(() => "");
40
+ if (content)
41
+ metadata[name] = content;
42
+ }
43
+ if (/^\s*packages\s*:/m.test(metadata["pnpm-workspace.yaml"] || "") || /(?:^|[\s\x22\x27@])(?:file|link|workspace):/m.test(metadata["pnpm-lock.yaml"])) {
44
+ throw new Error("Workspace/local dependencies require pnpm deploy instead.");
45
+ }
46
+ const userconfig = process.env.NPM_CONFIG_USERCONFIG || process.env.npm_config_userconfig || node_path_1.default.join(projectRoot, ".npmrc");
47
+ const registry = yield promises_1.default.readFile(userconfig, "utf8").catch(() => "");
48
+ const scope = node_crypto_1.default.createHash("sha256").update(projectRoot).digest("hex").slice(0, 24);
49
+ const cache = node_path_1.default.join(node_path_1.default.resolve(projectRoot, process.env.WEBFRAMEZ_BUILD_CACHE_DIRECTORY || ".webframez-cache"), "production", scope);
50
+ const key = node_crypto_1.default.createHash("sha256").update(JSON.stringify([metadata, registry, ignoreScripts, process.version, process.platform, process.arch])).digest("hex");
51
+ const previous = yield promises_1.default.readFile(node_path_1.default.join(cache, "fingerprint"), "utf8").catch(() => "");
52
+ if (previous !== key)
53
+ yield promises_1.default.rm(cache, { recursive: true, force: true });
54
+ yield promises_1.default.mkdir(cache, { recursive: true });
55
+ for (const [name, content] of Object.entries(metadata))
56
+ yield promises_1.default.writeFile(node_path_1.default.join(cache, name), content);
57
+ const started = Date.now();
58
+ console.log(`[webframez] production dependencies: ${previous === key ? "reuse" : "cold"}`);
59
+ try {
60
+ const expected = manifest.packageManager.split("@")[1].split("+")[0];
61
+ const { stdout } = yield (0, node_util_1.promisify)(node_child_process_1.execFile)("pnpm", ["--version"], { cwd: projectRoot });
62
+ if (stdout.trim() !== expected)
63
+ throw new Error(`Expected pnpm ${expected}, got ${stdout.trim()}`);
64
+ yield new Promise((resolve, reject) => {
65
+ const child = (0, node_child_process_1.spawn)("pnpm", ["install", "--frozen-lockfile", "--prod", ...(ignoreScripts ? ["--ignore-scripts"] : [])], {
66
+ cwd: cache, stdio: "inherit", env: Object.assign(Object.assign({}, process.env), { NODE_ENV: "production", NPM_CONFIG_USERCONFIG: userconfig }),
67
+ });
68
+ child.once("error", reject);
69
+ child.once("exit", code => code === 0 ? resolve() : reject(new Error(`pnpm production install exited with code ${code}`)));
70
+ });
71
+ const modules = node_path_1.default.join(cache, "node_modules"), destination = node_path_1.default.join(output, "node_modules");
72
+ yield promises_1.default.mkdir(output, { recursive: true });
73
+ yield promises_1.default.rm(destination, { recursive: true, force: true });
74
+ if (yield promises_1.default.stat(modules).catch(() => null)) {
75
+ if (process.platform === "linux")
76
+ yield (0, node_util_1.promisify)(node_child_process_1.execFile)("cp", ["-a", "--reflink=auto", "--", modules, destination]);
77
+ else
78
+ yield promises_1.default.cp(modules, destination, { recursive: true });
79
+ }
80
+ yield promises_1.default.writeFile(node_path_1.default.join(cache, "fingerprint"), key);
81
+ console.log(`[webframez] production dependencies: ready (${((Date.now() - started) / 1000).toFixed(2)}s)`);
82
+ }
83
+ catch (error) {
84
+ yield promises_1.default.rm(cache, { recursive: true, force: true });
85
+ throw error;
86
+ }
87
+ });
88
+ }
89
+ exports.buildProductionDependencies = buildProductionDependencies;
package/dist/Cli.js CHANGED
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -15,7 +38,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
38
  exports.runWebframezCli = void 0;
16
39
  const node_fs_1 = __importDefault(require("node:fs"));
17
40
  const node_path_1 = __importDefault(require("node:path"));
18
- const ConsoleApplication_1 = require("./ConsoleApplication");
41
+ const BuildDependencies_1 = require("./BuildDependencies");
19
42
  const BuildApplication_1 = require("./BuildApplication");
20
43
  function printHelp() {
21
44
  console.log([
@@ -73,7 +96,8 @@ function runConsole(projectRoot, cliArgs) {
73
96
  if (config.setup) {
74
97
  yield config.setup({ mode: "console", projectRoot });
75
98
  }
76
- const app = new ConsoleApplication_1.ConsoleApplication();
99
+ const { ConsoleApplication } = yield Promise.resolve().then(() => __importStar(require("./ConsoleApplication")));
100
+ const app = new ConsoleApplication();
77
101
  const originalArgv = process.argv;
78
102
  process.argv = [process.argv[0], "webframez", ...cliArgs];
79
103
  try {
@@ -115,6 +139,22 @@ function runWebframezCli(argv = process.argv.slice(2), projectRoot = process.cwd
115
139
  yield runConsole(projectRoot, argv.slice(1));
116
140
  return;
117
141
  }
142
+ if (command === "compile") {
143
+ const tsconfig = readOption(argv, "project") || "tsconfig.json";
144
+ const outDir = readOption(argv, "dir") || "build";
145
+ const relative = node_path_1.default.relative(projectRoot, node_path_1.default.resolve(projectRoot, outDir));
146
+ if (!relative || relative.startsWith("..") || node_path_1.default.isAbsolute(relative) || relative.split(node_path_1.default.sep).some(part => [".git", "node_modules", ".webframez-cache"].includes(part)))
147
+ throw new Error("Compile output must be a separate project directory.");
148
+ yield new BuildApplication_1.BuildApplication(projectRoot, { build: { tsconfig, cacheDirectory: process.env.WEBFRAMEZ_BUILD_CACHE_DIRECTORY || ".webframez-cache" } }, { outDir }).compile();
149
+ return;
150
+ }
151
+ if (command === "dependencies") {
152
+ const outDir = readOption(argv, "dir");
153
+ if (!outDir)
154
+ throw new Error("Production dependencies require --dir.");
155
+ yield (0, BuildDependencies_1.buildProductionDependencies)(projectRoot, outDir, argv.includes("--ignore-scripts"));
156
+ return;
157
+ }
118
158
  if (command === "build" || command === "buid") {
119
159
  yield runBuild(projectRoot, argv.slice(1));
120
160
  return;
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export * from "./Database/Model";
12
12
  export * from "./Database/DBConnection";
13
13
  export * from "./ConsoleApplication";
14
14
  export * from "./BuildApplication";
15
+ export * from "./BuildDependencies";
15
16
  export * from "./LambdaApplication";
16
17
  export * from "./WebApplication";
17
18
  export * from "./Router/Route";
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ __exportStar(require("./Database/Model"), exports);
29
29
  __exportStar(require("./Database/DBConnection"), exports);
30
30
  __exportStar(require("./ConsoleApplication"), exports);
31
31
  __exportStar(require("./BuildApplication"), exports);
32
+ __exportStar(require("./BuildDependencies"), exports);
32
33
  __exportStar(require("./LambdaApplication"), exports);
33
34
  __exportStar(require("./WebApplication"), exports);
34
35
  __exportStar(require("./Router/Route"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-core",
3
- "version": "0.3.93",
3
+ "version": "0.3.95",
4
4
  "description": "The core package of the typescript based webframez (web-framework) by webtypen.de",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "license": "MIT",