@titanpl/packet 7.0.0-beta → 7.0.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.
Files changed (2) hide show
  1. package/index.js +94 -102
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -83,10 +83,19 @@ export async function build(root = process.cwd()) {
83
83
  * Release build (Production ready folder)
84
84
  */
85
85
  export async function release(root = process.cwd()) {
86
- const dist = await build(root);
87
86
  const buildDir = path.join(root, "build");
88
87
 
89
- // Read config
88
+ // Step 1: Pre-build (Production mode)
89
+ // Run production build to generate 'dist' folder
90
+ const dist = await build(root);
91
+
92
+ // Step 2: Clear or ensure build dir
93
+ if (fs.existsSync(buildDir)) {
94
+ fs.rmSync(buildDir, { recursive: true, force: true });
95
+ }
96
+ fs.mkdirSync(buildDir, { recursive: true });
97
+
98
+ // Step 3: Read config and files list
90
99
  let config = {};
91
100
  const configPath = fs.existsSync(path.join(root, "tanfig.json"))
92
101
  ? path.join(root, "tanfig.json")
@@ -100,49 +109,63 @@ export async function release(root = process.cwd()) {
100
109
  } catch (e) { }
101
110
  }
102
111
 
103
- const filesToCopy = config.build && config.build.files ? config.build.files : ["public", "static", "db", "config", "tanfig.json", "titan.json"];
104
-
105
- // Clear or ensure build dir
106
- if (fs.existsSync(buildDir)) {
107
- fs.rmSync(buildDir, { recursive: true, force: true });
108
- }
109
- fs.mkdirSync(buildDir, { recursive: true });
110
-
111
- // 1. Copy dist
112
- copyDir(dist, path.join(buildDir, "dist"));
112
+ // Default files to copy from root
113
+ const defaultFiles = ["public", "static", "db", "config", "views", "auth"];
114
+ const userFiles = config.build && Array.isArray(config.build.files) ? config.build.files : [];
115
+ const filesToCopy = Array.from(new Set([...defaultFiles, ...userFiles]));
113
116
 
114
- // 2. Extra files/folders from root based on config
117
+ // Step 4: Copy Files & Folders from root and app folders to build
115
118
  for (const item of filesToCopy) {
119
+ // Check root first, then app/ folder
116
120
  const src = path.join(root, item);
121
+ const appSrc = path.join(root, "app", item);
122
+ const dest = path.join(buildDir, item);
123
+
117
124
  if (fs.existsSync(src)) {
118
- const dest = path.join(buildDir, item);
119
125
  copyDir(src, dest);
126
+ } else if (fs.existsSync(appSrc)) {
127
+ const appDest = path.join(buildDir, "app", item);
128
+ copyDir(appSrc, appDest);
120
129
  }
121
130
  }
122
131
 
123
- // 3. Copy package.json & tanfig.json
124
- const pkgPath = path.join(root, "package.json");
125
- if (fs.existsSync(pkgPath)) {
126
- fs.copyFileSync(pkgPath, path.join(buildDir, "package.json"));
127
- }
128
- const tanfigPath = path.join(root, "tanfig.json");
129
- if (fs.existsSync(tanfigPath)) {
130
- fs.copyFileSync(tanfigPath, path.join(buildDir, "tanfig.json"));
131
- }
132
- const titanConfigPath = path.join(root, "titan.json");
133
- if (fs.existsSync(titanConfigPath)) {
134
- fs.copyFileSync(titanConfigPath, path.join(buildDir, "titan.json"));
132
+ // Step 5: Copy generated 'dist' (static routes/actions metadata)
133
+ copyDir(dist, path.join(buildDir, "dist"));
134
+
135
+ // Step 6: Copy essential config files (mandatory for runtime)
136
+ const essentials = ["package.json", "tanfig.json", "titan.json"];
137
+ for (const f of essentials) {
138
+ const src = path.join(root, f);
139
+ if (fs.existsSync(src)) {
140
+ fs.copyFileSync(src, path.join(buildDir, f));
141
+ }
135
142
  }
136
143
 
137
- // 4. Create .env
144
+ // Step 7: Create .env for production
138
145
  fs.writeFileSync(path.join(buildDir, ".env"), "TITAN_DEV=0\n");
139
146
 
140
- // 5. Extract extensions
147
+ // Step 8: Extract Extensions
141
148
  const extDir = path.join(buildDir, ".ext");
142
149
  fs.mkdirSync(extDir, { recursive: true });
143
150
 
144
151
  const nodeModules = path.join(root, "node_modules");
145
152
  if (fs.existsSync(nodeModules)) {
153
+ const localPkgs = path.resolve(root, "../../packages");
154
+ if (fs.existsSync(localPkgs)) {
155
+ const pkgs = fs.readdirSync(localPkgs);
156
+ for (const pkg of pkgs) {
157
+ const pkgPath = path.join(localPkgs, pkg);
158
+ const titanJsonPath = path.join(pkgPath, "titan.json");
159
+ if (fs.existsSync(titanJsonPath)) {
160
+ try {
161
+ const config = JSON.parse(fs.readFileSync(titanJsonPath, "utf8"));
162
+ const extName = config.name;
163
+ const dest = path.join(extDir, extName.includes("/") ? extName : extName);
164
+ copyDir(pkgPath, dest);
165
+ } catch(e) {}
166
+ }
167
+ }
168
+ }
146
169
  const findExtensions = (dir, depth = 0) => {
147
170
  if (depth > 2) return;
148
171
  if (!fs.existsSync(dir)) return;
@@ -164,6 +187,8 @@ export async function release(root = process.cwd()) {
164
187
  }
165
188
 
166
189
  const destPath = path.join(extDir, targetPkgName);
190
+ if (fs.existsSync(destPath)) continue; // Don't overwrite monorepo packages
191
+
167
192
  fs.mkdirSync(path.dirname(destPath), { recursive: true });
168
193
 
169
194
  copyDir(fullPath, destPath, (src) => {
@@ -178,98 +203,65 @@ export async function release(root = process.cwd()) {
178
203
  }
179
204
  };
180
205
  findExtensions(nodeModules);
181
- }
182
-
183
- // 6. Copy Engine binaries
184
- if (fs.existsSync(path.join(nodeModules, "@titanpl"))) {
185
- const scopeDir = path.join(nodeModules, "@titanpl");
186
- const folders = fs.readdirSync(scopeDir);
187
- for (const folder of folders) {
188
- if (folder.startsWith("engine-")) {
189
- const engineDest = path.join(extDir, "@titanpl", folder);
190
- copyDir(path.join(scopeDir, folder), engineDest);
191
- }
192
- }
193
- }
194
206
 
195
- // 7. Create node_modules junction to .ext for engine resolution
196
- // If env is 'deploy' or 'production', we might want to skip this for a cleaner build
197
- const buildEnv = config.build && (config.build.env || config.build.purpose) ? (config.build.env || config.build.purpose) : "test";
198
-
199
- if (buildEnv !== "deploy" && buildEnv !== "production") {
200
- const nmSymlink = path.join(buildDir, "node_modules");
201
- if (!fs.existsSync(nmSymlink)) {
202
- try {
203
- // Junctions don't require admin on Windows
204
- fs.symlinkSync(".ext", nmSymlink, "junction");
205
- } catch (e) {
206
- try {
207
- fs.symlinkSync(".ext", nmSymlink, "dir");
208
- } catch (e2) {
209
- // Fallback or ignore if symlink creation is totally restricted
207
+ // Also copy engine binaries if they exist in node_modules
208
+ if (fs.existsSync(path.join(nodeModules, "@titanpl"))) {
209
+ const scopeDir = path.join(nodeModules, "@titanpl");
210
+ const folders = fs.readdirSync(scopeDir);
211
+ for (const folder of folders) {
212
+ if (folder.startsWith("engine-") || folder.startsWith("runtime-")) {
213
+ const engineDest = path.join(extDir, "@titanpl", folder);
214
+ copyDir(path.join(scopeDir, folder), engineDest);
210
215
  }
211
216
  }
212
217
  }
213
218
  }
214
219
 
215
- // 8. Create 'titan' executable link in the build root for easy starting
220
+ // Step 9: Copy/Extract titan-server binary to build root
216
221
  const binName = process.platform === "win32" ? "titan-server.exe" : "titan-server";
217
222
  let engineBin = null;
218
223
 
219
- // Strategy A: Search in the .ext we just populated
220
- const findInExt = (dir) => {
221
- if (!fs.existsSync(dir)) return null;
222
- const entries = fs.readdirSync(dir);
223
- for (const entry of entries) {
224
- const full = path.join(dir, entry);
225
- if (fs.statSync(full).isDirectory()) {
226
- // Check both pkgRoot/bin/titan-server and pkgRoot/titan-server (some layouts differ)
227
- const p1 = path.join(full, "bin", binName);
228
- if (fs.existsSync(p1)) return p1;
229
- const p2 = path.join(full, binName);
230
- if (fs.existsSync(p2)) return p2;
231
-
232
- const found = findInExt(full);
233
- if (found) return found;
234
- }
235
- }
236
- return null;
224
+ // Search in .ext
225
+ const searchBin = (dir) => {
226
+ if (!fs.existsSync(dir)) return null;
227
+ const entries = fs.readdirSync(dir);
228
+ for (const e of entries) {
229
+ const full = path.join(dir, e);
230
+ if (fs.statSync(full).isDirectory()) {
231
+ const p1 = path.join(full, "bin", binName);
232
+ if (fs.existsSync(p1)) return p1;
233
+ const p2 = path.join(full, binName);
234
+ if (fs.existsSync(p2)) return p2;
235
+ const found = searchBin(full);
236
+ if (found) return found;
237
+ }
238
+ }
239
+ return null;
237
240
  };
241
+ engineBin = searchBin(extDir);
238
242
 
239
- engineBin = findInExt(extDir);
240
-
241
- // Strategy B: Monorepo fallback (if building inside the titanpl repo)
243
+ // Fallback to monorepo binary (if building in repo)
242
244
  if (!engineBin) {
243
- let current = root;
244
- for (let i = 0; i < 5; i++) {
245
- const potential = path.join(current, "engine", "target", "release", binName);
246
- if (fs.existsSync(potential)) {
247
- engineBin = potential;
248
- break;
249
- }
250
- const parent = path.dirname(current);
251
- if (parent === current) break;
252
- current = parent;
245
+ let curr = root;
246
+ for(let i=0; i<3; i++) {
247
+ const potential = path.join(curr, "engine", "target", "release", binName);
248
+ if (fs.existsSync(potential)) {
249
+ engineBin = potential;
250
+ break;
251
+ }
252
+ curr = path.dirname(curr);
253
253
  }
254
254
  }
255
255
 
256
256
  if (engineBin) {
257
- const linkName = binName; // Keep the original name 'titan-server'
258
- const linkPath = path.join(buildDir, linkName);
259
-
260
- if (!fs.existsSync(linkPath)) {
261
- try {
262
- // Always copy the binary to the root for maximum portability in the 'build' folder
263
- fs.copyFileSync(engineBin, linkPath);
264
- if (process.platform !== "win32") {
265
- fs.chmodSync(linkPath, 0o755);
266
- }
267
- } catch (e) {
268
- console.error(`[Titan] Failed to create titan binary: ${e.message}`);
269
- }
270
- }
257
+ const destBin = path.join(buildDir, binName);
258
+ fs.copyFileSync(engineBin, destBin);
259
+ if (process.platform !== "win32") fs.chmodSync(destBin, 0o755);
271
260
  }
272
261
 
262
+ // Step 10: In production builds, we DON'T use symlinks for node_modules.
263
+ // Instead, the engine knows to look in .ext.
264
+
273
265
  return buildDir;
274
266
  }
275
267
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@titanpl/packet",
3
- "version": "7.0.0-beta",
3
+ "version": "7.0.0",
4
4
  "description": "The bundler for TitanPl servers.",
5
5
  "keywords": [
6
6
  "bundler",