@jxrstudios/jxr 1.2.16 → 1.2.18

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/bin/jxr.js CHANGED
@@ -275,75 +275,19 @@ if (command === "init") {
275
275
  console.log(`🚀 Deploying to ${target === "auto" ? "auto-detected platform" : target}...`);
276
276
 
277
277
  try {
278
- const fs = await import("fs");
279
- const path = await import("path");
280
-
281
- // Auto-detect build output directory
282
- let buildDir = path.join(projectPath, "dist");
283
- if (!fs.existsSync(buildDir)) {
284
- buildDir = path.join(projectPath, "build");
285
- }
286
- if (!fs.existsSync(buildDir)) {
287
- buildDir = path.join(projectPath, "out");
288
- }
289
- if (!fs.existsSync(buildDir)) {
290
- // Look for any directory with index.html
291
- const dirs = fs.readdirSync(projectPath, { withFileTypes: true })
292
- .filter(d => d.isDirectory() && !d.name.startsWith(".") && !d.name === "node_modules")
293
- .map(d => path.join(projectPath, d.name));
294
-
295
- for (const dir of dirs) {
296
- if (fs.existsSync(path.join(dir, "index.html"))) {
297
- buildDir = dir;
298
- break;
299
- }
300
- }
301
- }
302
-
303
- if (!fs.existsSync(buildDir)) {
304
- console.error("❌ No build output found. Run 'jxr build' first.");
305
- process.exit(1);
306
- }
307
-
308
- // Check for jxr-manifest.json for verification
309
- const manifestPath = path.join(buildDir, "jxr-manifest.json");
310
- if (fs.existsSync(manifestPath)) {
311
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
312
- console.log(`📋 Build manifest: ${manifest.platform} platform`);
313
- console.log(` Files: ${manifest.files.length}`);
314
- console.log(` Signed: ${manifest.algorithm}`);
315
- }
316
-
317
- // Detect if running on Cloudflare Pages
318
- const isCloudflarePages = process.env.CF_PAGES === "1" || process.env.CF_PAGES_URL !== undefined;
319
-
320
- if (target === "cloudflare" || target === "auto" && isCloudflarePages) {
321
- console.log("☁️ Deploying to Cloudflare Pages...");
278
+ // Use JXRDeployer for Cloudflare Pages deployment
279
+ if (target === "cloudflare" || target === "auto") {
280
+ const deployer = new JXRDeployer(process.env.JXR_API_KEY || '', process.env.JXR_PROJECT_ID);
281
+ const result = await deployer.deployToCloudflarePages(projectPath, { environment: env });
322
282
 
323
- // Get project name from package.json or directory
324
- let projectName = process.env.CF_PAGES_PROJECT_NAME;
325
- if (!projectName) {
326
- try {
327
- const pkg = JSON.parse(fs.readFileSync(path.join(projectPath, "package.json"), "utf-8"));
328
- projectName = pkg.name;
329
- } catch {
330
- projectName = path.basename(path.resolve(projectPath));
331
- }
332
- }
333
-
334
- // On Cloudflare Pages, the build output is automatically deployed
335
- // We just need to ensure it's in the right location
336
- console.log(` Project: ${projectName}`);
337
- console.log(` Environment: ${env}`);
338
-
339
- if (isCloudflarePages) {
340
- console.log(` URL: https://${projectName}.app.jxrstudios.online`);
341
- console.log("✅ Deployment ready for Cloudflare Pages");
342
- console.log(" The build output will be deployed automatically.");
283
+ if (result.success) {
284
+ console.log("✅ Deployed successfully!");
285
+ console.log(` URL: ${result.url}`);
286
+ result.logs.forEach(log => console.log(` ${log}`));
343
287
  } else {
344
- // Manual Cloudflare Pages deployment
345
- console.log(" Run 'wrangler pages deploy' to deploy manually");
346
- console.log(" Or connect your GitHub repo to Cloudflare Pages for auto-deployment");
288
+ console.error("❌ Deploy failed");
289
+ result.logs.forEach(log => console.error(` ${log}`));
290
+ process.exit(1);
347
291
  }
348
292
 
349
293
  } else if (target === "deno") {
@@ -355,25 +299,9 @@ if (command === "init") {
355
299
  console.log(" Copy the dist/ folder to your Node.js server");
356
300
 
357
301
  } else {
358
- // Use JXRDeployer for other platforms
359
- if (!process.env.JXR_API_KEY) {
360
- console.error("❌ JXR_API_KEY environment variable required");
361
- console.error(" Get your key at: https://jxrstudios.online/dashboard");
362
- process.exit(1);
363
- }
364
-
365
- const deployer = new JXRDeployer(process.env.JXR_API_KEY, process.env.JXR_PROJECT_ID);
366
- const result = await deployer.deploy(buildDir, { environment: env });
367
-
368
- if (result.success) {
369
- console.log("✅ Deployed successfully!");
370
- console.log(` URL: ${result.url}`);
371
- result.logs.forEach(log => console.log(` ${log}`));
372
- } else {
373
- console.error("❌ Deploy failed");
374
- result.logs.forEach(log => console.error(` ${log}`));
375
- process.exit(1);
376
- }
302
+ console.error(`❌ Unknown target: ${target}`);
303
+ console.error(" Supported: cloudflare, deno, node, auto");
304
+ process.exit(1);
377
305
  }
378
306
 
379
307
  } catch (err) {
@@ -29,6 +29,23 @@ export declare class JXRDeployer {
29
29
  private apiKey;
30
30
  private projectId;
31
31
  constructor(apiKey: string, projectId?: string);
32
+ /**
33
+ * Auto-detect build output directory
34
+ * Checks dist/, build/, out/, or any directory with index.html
35
+ */
36
+ detectBuildDir(projectPath?: string): Promise<string | null>;
37
+ /**
38
+ * Detect if running on Cloudflare Pages
39
+ */
40
+ isCloudflarePages(): boolean;
41
+ /**
42
+ * Get project name from package.json or directory
43
+ */
44
+ getProjectName(projectPath?: string): Promise<string>;
45
+ /**
46
+ * Deploy to Cloudflare Pages
47
+ */
48
+ deployToCloudflarePages(projectPath?: string, config?: DeployConfig): Promise<DeployResult>;
32
49
  /**
33
50
  * Deploy the current project to JXR infrastructure
34
51
  */
@@ -1 +1 @@
1
- {"version":3,"file":"deployer.d.ts","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAK9C;;OAEG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IA+CnF;;OAEG;YACW,aAAa;IAkB3B;;OAEG;YACW,aAAa;IAgC3B;;OAEG;IACG,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAchE;;OAEG;IACG,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QACvD,EAAE,EAAE,MAAM,CAAC;QACX,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IAgBH;;OAEG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAuB3D,OAAO,CAAC,iBAAiB;CAK1B;AAED,gCAAgC;AAChC,eAAO,MAAM,WAAW,aAGvB,CAAC"}
1
+ {"version":3,"file":"deployer.d.ts","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAK9C;;;OAGG;IACG,cAAc,CAAC,WAAW,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgCvE;;OAEG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;OAEG;IACG,cAAc,CAAC,WAAW,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAsBhE;;OAEG;IACG,uBAAuB,CAAC,WAAW,GAAE,MAAY,EAAE,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IAyD1G;;OAEG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IA+CnF;;OAEG;YACW,aAAa;IAkB3B;;OAEG;YACW,aAAa;IAgC3B;;OAEG;IACG,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAchE;;OAEG;IACG,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QACvD,EAAE,EAAE,MAAM,CAAC;QACX,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IAgBH;;OAEG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAuB3D,OAAO,CAAC,iBAAiB;CAK1B;AAED,gCAAgC;AAChC,eAAO,MAAM,WAAW,aAGvB,CAAC"}
package/dist/index.js CHANGED
@@ -2042,8 +2042,9 @@ export default \`${escapedCSS}\`;
2042
2042
  };
2043
2043
 
2044
2044
  // src/deployer.ts
2045
- import { readFile as readFile2, stat } from "fs/promises";
2045
+ import { readFile as readFile2, readdir as readdir2, stat } from "fs/promises";
2046
2046
  import path2 from "path";
2047
+ import { existsSync } from "fs";
2047
2048
  import { spawn } from "child_process";
2048
2049
  var JXRDeployer = class {
2049
2050
  apiKey;
@@ -2052,6 +2053,103 @@ var JXRDeployer = class {
2052
2053
  this.apiKey = apiKey;
2053
2054
  this.projectId = projectId || this.generateProjectId();
2054
2055
  }
2056
+ /**
2057
+ * Auto-detect build output directory
2058
+ * Checks dist/, build/, out/, or any directory with index.html
2059
+ */
2060
+ async detectBuildDir(projectPath = ".") {
2061
+ const possibleDirs = ["dist", "build", "out"];
2062
+ for (const dir of possibleDirs) {
2063
+ const fullPath = path2.resolve(projectPath, dir);
2064
+ if (existsSync(fullPath)) {
2065
+ if (existsSync(path2.join(fullPath, "index.html"))) {
2066
+ return fullPath;
2067
+ }
2068
+ }
2069
+ }
2070
+ try {
2071
+ const entries = await readdir2(projectPath, { withFileTypes: true });
2072
+ for (const entry of entries) {
2073
+ if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
2074
+ const dirPath = path2.join(projectPath, entry.name);
2075
+ if (existsSync(path2.join(dirPath, "index.html"))) {
2076
+ return dirPath;
2077
+ }
2078
+ }
2079
+ }
2080
+ } catch {
2081
+ }
2082
+ return null;
2083
+ }
2084
+ /**
2085
+ * Detect if running on Cloudflare Pages
2086
+ */
2087
+ isCloudflarePages() {
2088
+ return process.env.CF_PAGES === "1" || !!process.env.CF_PAGES_URL;
2089
+ }
2090
+ /**
2091
+ * Get project name from package.json or directory
2092
+ */
2093
+ async getProjectName(projectPath = ".") {
2094
+ if (process.env.CF_PAGES_PROJECT_NAME) {
2095
+ return process.env.CF_PAGES_PROJECT_NAME;
2096
+ }
2097
+ try {
2098
+ const pkgPath = path2.join(projectPath, "package.json");
2099
+ const pkgContent = await readFile2(pkgPath, "utf-8");
2100
+ const pkg = JSON.parse(pkgContent);
2101
+ if (pkg.name) {
2102
+ return pkg.name;
2103
+ }
2104
+ } catch {
2105
+ }
2106
+ return path2.basename(path2.resolve(projectPath));
2107
+ }
2108
+ /**
2109
+ * Deploy to Cloudflare Pages
2110
+ */
2111
+ async deployToCloudflarePages(projectPath = ".", config = {}) {
2112
+ const logs = [];
2113
+ try {
2114
+ const buildDir = await this.detectBuildDir(projectPath);
2115
+ if (!buildDir) {
2116
+ throw new Error('No build output found. Run "jxr build" first.');
2117
+ }
2118
+ logs.push(`\u{1F4C1} Build directory: ${buildDir}`);
2119
+ const projectName = await this.getProjectName(projectPath);
2120
+ logs.push(`\u{1F4E6} Project: ${projectName}`);
2121
+ const manifestPath = path2.join(buildDir, "jxr-manifest.json");
2122
+ if (existsSync(manifestPath)) {
2123
+ const manifest = JSON.parse(await readFile2(manifestPath, "utf-8"));
2124
+ logs.push(`\u{1F4CB} Manifest: ${manifest.platform} platform, ${manifest.files?.length || 0} files`);
2125
+ }
2126
+ const env = config.environment || "production";
2127
+ const url = `https://${projectName}.app.jxrstudios.online`;
2128
+ logs.push(`\u{1F310} URL: ${url}`);
2129
+ if (this.isCloudflarePages()) {
2130
+ logs.push("\u2601\uFE0F Cloudflare Pages auto-detected");
2131
+ logs.push("\u2705 Deployment ready - build output will be deployed automatically");
2132
+ return {
2133
+ success: true,
2134
+ url,
2135
+ deploymentId: `cf-pages-${Date.now()}`,
2136
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2137
+ logs
2138
+ };
2139
+ }
2140
+ return await this.deploy(buildDir, { ...config, projectId: projectName });
2141
+ } catch (error) {
2142
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
2143
+ logs.push(`\u274C Error: ${errorMsg}`);
2144
+ return {
2145
+ success: false,
2146
+ url: "",
2147
+ deploymentId: "",
2148
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2149
+ logs
2150
+ };
2151
+ }
2152
+ }
2055
2153
  /**
2056
2154
  * Deploy the current project to JXR infrastructure
2057
2155
  */
@@ -2068,7 +2166,7 @@ var JXRDeployer = class {
2068
2166
  logs.push(`\u{1F4E6} Created tarball: ${tarballPath}`);
2069
2167
  const uploadResult = await this.uploadTarball(tarballPath, pid, env, branch);
2070
2168
  logs.push(`\u2601\uFE0F Uploaded to JXR`);
2071
- const url = `https://${pid}.jxr.dev`;
2169
+ const url = `https://${pid}.app.jxrstudios.online`;
2072
2170
  logs.push(`\u{1F310} Live at: ${url}`);
2073
2171
  return {
2074
2172
  success: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxrstudios/jxr",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
4
4
  "description": "JXR.js — Edge OS Runtime Framework for elite developers",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/deployer.ts CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { readFile, readdir, stat } from "fs/promises";
8
8
  import path from "path";
9
- import { createWriteStream } from "fs";
9
+ import { createWriteStream, existsSync } from "fs";
10
10
  import { spawn } from "child_process";
11
11
 
12
12
  export interface DeployConfig {
@@ -43,6 +43,134 @@ export class JXRDeployer {
43
43
  this.projectId = projectId || this.generateProjectId();
44
44
  }
45
45
 
46
+ /**
47
+ * Auto-detect build output directory
48
+ * Checks dist/, build/, out/, or any directory with index.html
49
+ */
50
+ async detectBuildDir(projectPath: string = '.'): Promise<string | null> {
51
+ const possibleDirs = ['dist', 'build', 'out'];
52
+
53
+ // Check standard build directories
54
+ for (const dir of possibleDirs) {
55
+ const fullPath = path.resolve(projectPath, dir);
56
+ if (existsSync(fullPath)) {
57
+ // Verify it has index.html
58
+ if (existsSync(path.join(fullPath, 'index.html'))) {
59
+ return fullPath;
60
+ }
61
+ }
62
+ }
63
+
64
+ // Search for any directory with index.html
65
+ try {
66
+ const entries = await readdir(projectPath, { withFileTypes: true });
67
+ for (const entry of entries) {
68
+ if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
69
+ const dirPath = path.join(projectPath, entry.name);
70
+ if (existsSync(path.join(dirPath, 'index.html'))) {
71
+ return dirPath;
72
+ }
73
+ }
74
+ }
75
+ } catch {
76
+ // Ignore errors
77
+ }
78
+
79
+ return null;
80
+ }
81
+
82
+ /**
83
+ * Detect if running on Cloudflare Pages
84
+ */
85
+ isCloudflarePages(): boolean {
86
+ return process.env.CF_PAGES === '1' || !!process.env.CF_PAGES_URL;
87
+ }
88
+
89
+ /**
90
+ * Get project name from package.json or directory
91
+ */
92
+ async getProjectName(projectPath: string = '.'): Promise<string> {
93
+ // Check CF_PAGES_PROJECT_NAME first
94
+ if (process.env.CF_PAGES_PROJECT_NAME) {
95
+ return process.env.CF_PAGES_PROJECT_NAME;
96
+ }
97
+
98
+ // Try to read from package.json
99
+ try {
100
+ const pkgPath = path.join(projectPath, 'package.json');
101
+ const pkgContent = await readFile(pkgPath, 'utf-8');
102
+ const pkg = JSON.parse(pkgContent);
103
+ if (pkg.name) {
104
+ return pkg.name;
105
+ }
106
+ } catch {
107
+ // Ignore errors
108
+ }
109
+
110
+ // Fall back to directory name
111
+ return path.basename(path.resolve(projectPath));
112
+ }
113
+
114
+ /**
115
+ * Deploy to Cloudflare Pages
116
+ */
117
+ async deployToCloudflarePages(projectPath: string = '.', config: DeployConfig = {}): Promise<DeployResult> {
118
+ const logs: string[] = [];
119
+
120
+ try {
121
+ // Auto-detect build directory
122
+ const buildDir = await this.detectBuildDir(projectPath);
123
+ if (!buildDir) {
124
+ throw new Error('No build output found. Run "jxr build" first.');
125
+ }
126
+ logs.push(`📁 Build directory: ${buildDir}`);
127
+
128
+ // Get project name
129
+ const projectName = await this.getProjectName(projectPath);
130
+ logs.push(`📦 Project: ${projectName}`);
131
+
132
+ // Check for manifest
133
+ const manifestPath = path.join(buildDir, 'jxr-manifest.json');
134
+ if (existsSync(manifestPath)) {
135
+ const manifest = JSON.parse(await readFile(manifestPath, 'utf-8'));
136
+ logs.push(`📋 Manifest: ${manifest.platform} platform, ${manifest.files?.length || 0} files`);
137
+ }
138
+
139
+ // Determine URL
140
+ const env = config.environment || 'production';
141
+ const url = `https://${projectName}.app.jxrstudios.online`;
142
+ logs.push(`🌐 URL: ${url}`);
143
+
144
+ // If running on Cloudflare Pages, the deployment is automatic
145
+ if (this.isCloudflarePages()) {
146
+ logs.push('☁️ Cloudflare Pages auto-detected');
147
+ logs.push('✅ Deployment ready - build output will be deployed automatically');
148
+
149
+ return {
150
+ success: true,
151
+ url,
152
+ deploymentId: `cf-pages-${Date.now()}`,
153
+ timestamp: new Date().toISOString(),
154
+ logs,
155
+ };
156
+ }
157
+
158
+ // Manual deployment via JXR API
159
+ return await this.deploy(buildDir, { ...config, projectId: projectName });
160
+
161
+ } catch (error) {
162
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
163
+ logs.push(`❌ Error: ${errorMsg}`);
164
+ return {
165
+ success: false,
166
+ url: '',
167
+ deploymentId: '',
168
+ timestamp: new Date().toISOString(),
169
+ logs,
170
+ };
171
+ }
172
+ }
173
+
46
174
  /**
47
175
  * Deploy the current project to JXR infrastructure
48
176
  */
@@ -69,7 +197,7 @@ export class JXRDeployer {
69
197
  logs.push(`☁️ Uploaded to JXR`);
70
198
 
71
199
  // Get deployment URL
72
- const url = `https://${pid}.jxr.dev`;
200
+ const url = `https://${pid}.app.jxrstudios.online`;
73
201
  logs.push(`🌐 Live at: ${url}`);
74
202
 
75
203
  return {