@titanpl/packet 6.0.0 → 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 +103 -94
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -67,6 +67,15 @@ export async function build(root = process.cwd()) {
67
67
  outDir: dist,
68
68
  });
69
69
 
70
+ const tanfigPath = path.join(root, "tanfig.json");
71
+ if (fs.existsSync(tanfigPath)) {
72
+ fs.copyFileSync(tanfigPath, path.join(dist, "tanfig.json"));
73
+ }
74
+ const titanExtPath = path.join(root, "titan.json");
75
+ if (fs.existsSync(titanExtPath)) {
76
+ fs.copyFileSync(titanExtPath, path.join(dist, "titan.json"));
77
+ }
78
+
70
79
  return dist;
71
80
  }
72
81
 
@@ -74,10 +83,19 @@ export async function build(root = process.cwd()) {
74
83
  * Release build (Production ready folder)
75
84
  */
76
85
  export async function release(root = process.cwd()) {
77
- const dist = await build(root);
78
86
  const buildDir = path.join(root, "build");
79
87
 
80
- // 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
81
99
  let config = {};
82
100
  const configPath = fs.existsSync(path.join(root, "tanfig.json"))
83
101
  ? path.join(root, "tanfig.json")
@@ -91,41 +109,63 @@ export async function release(root = process.cwd()) {
91
109
  } catch (e) { }
92
110
  }
93
111
 
94
- const filesToCopy = config.build && config.build.files ? config.build.files : ["public", "static", "db", "config"];
95
-
96
- // Clear or ensure build dir
97
- if (fs.existsSync(buildDir)) {
98
- fs.rmSync(buildDir, { recursive: true, force: true });
99
- }
100
- fs.mkdirSync(buildDir, { recursive: true });
101
-
102
- // 1. Copy dist
103
- 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]));
104
116
 
105
- // 2. Extra files/folders from root based on config
117
+ // Step 4: Copy Files & Folders from root and app folders to build
106
118
  for (const item of filesToCopy) {
119
+ // Check root first, then app/ folder
107
120
  const src = path.join(root, item);
121
+ const appSrc = path.join(root, "app", item);
122
+ const dest = path.join(buildDir, item);
123
+
108
124
  if (fs.existsSync(src)) {
109
- const dest = path.join(buildDir, item);
110
125
  copyDir(src, dest);
126
+ } else if (fs.existsSync(appSrc)) {
127
+ const appDest = path.join(buildDir, "app", item);
128
+ copyDir(appSrc, appDest);
111
129
  }
112
130
  }
113
131
 
114
- // 3. Copy package.json
115
- const pkgPath = path.join(root, "package.json");
116
- if (fs.existsSync(pkgPath)) {
117
- fs.copyFileSync(pkgPath, path.join(buildDir, "package.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
+ }
118
142
  }
119
143
 
120
- // 4. Create .env
144
+ // Step 7: Create .env for production
121
145
  fs.writeFileSync(path.join(buildDir, ".env"), "TITAN_DEV=0\n");
122
146
 
123
- // 5. Extract extensions
147
+ // Step 8: Extract Extensions
124
148
  const extDir = path.join(buildDir, ".ext");
125
149
  fs.mkdirSync(extDir, { recursive: true });
126
150
 
127
151
  const nodeModules = path.join(root, "node_modules");
128
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
+ }
129
169
  const findExtensions = (dir, depth = 0) => {
130
170
  if (depth > 2) return;
131
171
  if (!fs.existsSync(dir)) return;
@@ -147,6 +187,8 @@ export async function release(root = process.cwd()) {
147
187
  }
148
188
 
149
189
  const destPath = path.join(extDir, targetPkgName);
190
+ if (fs.existsSync(destPath)) continue; // Don't overwrite monorepo packages
191
+
150
192
  fs.mkdirSync(path.dirname(destPath), { recursive: true });
151
193
 
152
194
  copyDir(fullPath, destPath, (src) => {
@@ -161,98 +203,65 @@ export async function release(root = process.cwd()) {
161
203
  }
162
204
  };
163
205
  findExtensions(nodeModules);
164
- }
165
206
 
166
- // 6. Copy Engine binaries
167
- if (fs.existsSync(path.join(nodeModules, "@titanpl"))) {
168
- const scopeDir = path.join(nodeModules, "@titanpl");
169
- const folders = fs.readdirSync(scopeDir);
170
- for (const folder of folders) {
171
- if (folder.startsWith("engine-")) {
172
- const engineDest = path.join(extDir, "@titanpl", folder);
173
- copyDir(path.join(scopeDir, folder), engineDest);
174
- }
175
- }
176
- }
177
-
178
- // 7. Create node_modules junction to .ext for engine resolution
179
- // If env is 'deploy' or 'production', we might want to skip this for a cleaner build
180
- const buildEnv = config.build && (config.build.env || config.build.purpose) ? (config.build.env || config.build.purpose) : "test";
181
-
182
- if (buildEnv !== "deploy" && buildEnv !== "production") {
183
- const nmSymlink = path.join(buildDir, "node_modules");
184
- if (!fs.existsSync(nmSymlink)) {
185
- try {
186
- // Junctions don't require admin on Windows
187
- fs.symlinkSync(".ext", nmSymlink, "junction");
188
- } catch (e) {
189
- try {
190
- fs.symlinkSync(".ext", nmSymlink, "dir");
191
- } catch (e2) {
192
- // 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);
193
215
  }
194
216
  }
195
217
  }
196
218
  }
197
219
 
198
- // 8. Create 'titan' executable link in the build root for easy starting
220
+ // Step 9: Copy/Extract titan-server binary to build root
199
221
  const binName = process.platform === "win32" ? "titan-server.exe" : "titan-server";
200
222
  let engineBin = null;
201
223
 
202
- // Strategy A: Search in the .ext we just populated
203
- const findInExt = (dir) => {
204
- if (!fs.existsSync(dir)) return null;
205
- const entries = fs.readdirSync(dir);
206
- for (const entry of entries) {
207
- const full = path.join(dir, entry);
208
- if (fs.statSync(full).isDirectory()) {
209
- // Check both pkgRoot/bin/titan-server and pkgRoot/titan-server (some layouts differ)
210
- const p1 = path.join(full, "bin", binName);
211
- if (fs.existsSync(p1)) return p1;
212
- const p2 = path.join(full, binName);
213
- if (fs.existsSync(p2)) return p2;
214
-
215
- const found = findInExt(full);
216
- if (found) return found;
217
- }
218
- }
219
- 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;
220
240
  };
241
+ engineBin = searchBin(extDir);
221
242
 
222
- engineBin = findInExt(extDir);
223
-
224
- // Strategy B: Monorepo fallback (if building inside the titanpl repo)
243
+ // Fallback to monorepo binary (if building in repo)
225
244
  if (!engineBin) {
226
- let current = root;
227
- for (let i = 0; i < 5; i++) {
228
- const potential = path.join(current, "engine", "target", "release", binName);
229
- if (fs.existsSync(potential)) {
230
- engineBin = potential;
231
- break;
232
- }
233
- const parent = path.dirname(current);
234
- if (parent === current) break;
235
- 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);
236
253
  }
237
254
  }
238
255
 
239
256
  if (engineBin) {
240
- const linkName = binName; // Keep the original name 'titan-server'
241
- const linkPath = path.join(buildDir, linkName);
242
-
243
- if (!fs.existsSync(linkPath)) {
244
- try {
245
- // Always copy the binary to the root for maximum portability in the 'build' folder
246
- fs.copyFileSync(engineBin, linkPath);
247
- if (process.platform !== "win32") {
248
- fs.chmodSync(linkPath, 0o755);
249
- }
250
- } catch (e) {
251
- console.error(`[Titan] Failed to create titan binary: ${e.message}`);
252
- }
253
- }
257
+ const destBin = path.join(buildDir, binName);
258
+ fs.copyFileSync(engineBin, destBin);
259
+ if (process.platform !== "win32") fs.chmodSync(destBin, 0o755);
254
260
  }
255
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
+
256
265
  return buildDir;
257
266
  }
258
267
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@titanpl/packet",
3
- "version": "6.0.0",
3
+ "version": "7.0.0",
4
4
  "description": "The bundler for TitanPl servers.",
5
5
  "keywords": [
6
6
  "bundler",