@jxrstudios/jxr 1.0.2 → 1.0.4

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
@@ -98,6 +98,53 @@ const manifest = await jxrCrypto.signManifest({
98
98
  }, 'your-private-key');
99
99
  ```
100
100
 
101
+ ## Deployment (Wranglerless)
102
+
103
+ Deploy to JXR Studios' Cloudflare infrastructure without configuring wrangler or having a Cloudflare account.
104
+
105
+ ```typescript
106
+ import { JXRDeployer, jxrDeployer } from '@jxrstudios/jxr';
107
+
108
+ // Using your JXR API key
109
+ const deployer = new JXRDeployer('your-jxr-api-key', 'my-project');
110
+
111
+ // Deploy your built project
112
+ const result = await deployer.deploy('./dist', {
113
+ environment: 'production', // or 'staging', 'preview'
114
+ branch: 'main',
115
+ });
116
+
117
+ if (result.success) {
118
+ console.log(`Deployed to: ${result.url}`);
119
+ }
120
+ ```
121
+
122
+ ### Environment Variables
123
+
124
+ ```bash
125
+ # Set your JXR API key
126
+ export JXR_API_KEY=jxr_live_xxxxx
127
+
128
+ # Optional: Set default project ID
129
+ export JXR_PROJECT_ID=my-project
130
+ ```
131
+
132
+ ### Deployment Commands
133
+
134
+ ```typescript
135
+ // Get deployment status
136
+ const status = await deployer.getStatus('deployment-id');
137
+
138
+ // List all deployments
139
+ const deployments = await deployer.listDeployments();
140
+
141
+ // Rollback to previous deployment
142
+ await deployer.rollback('deployment-id');
143
+
144
+ // Delete a deployment
145
+ await deployer.deleteDeployment('deployment-id');
146
+ ```
147
+
101
148
  ## API Reference
102
149
 
103
150
  See the TypeScript definitions for full API documentation.
package/bin/jxr.js ADDED
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from "child_process";
3
+ import { fileURLToPath } from "url";
4
+ import path from "path";
5
+ import { readFileSync } from "fs";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const command = process.argv[2];
11
+ const isDev = command === "dev" || process.argv.includes("--dev");
12
+
13
+ // Show help if no command
14
+ if (!command || command === "--help" || command === "-h") {
15
+ console.log(`
16
+ JXR.js CLI
17
+
18
+ Usage: jxr <command> [options]
19
+
20
+ Commands:
21
+ dev Start development server with JXR runtime (zero build)
22
+ start Start production server
23
+ deploy Deploy to JXR Cloudflare infrastructure
24
+
25
+ Options:
26
+ --port <port> Port to run on (default: 3000)
27
+ --host <host> Host to bind to (default: localhost)
28
+ --help, -h Show this help message
29
+
30
+ Examples:
31
+ jxr dev
32
+ jxr dev --port 8080
33
+ jxr deploy
34
+ `);
35
+ process.exit(0);
36
+ }
37
+
38
+ // Development mode - use JXR Runtime dev server (zero build)
39
+ if (isDev) {
40
+ const port = process.argv.find((arg, i) => process.argv[i - 1] === "--port") || "3000";
41
+ const host = process.argv.find((arg, i) => process.argv[i - 1] === "--host") || "localhost";
42
+
43
+ console.log(`🚀 Starting JXR Dev Server on http://${host}:${port}/`);
44
+
45
+ // Run the JXR dev server with experimental TypeScript support (no build needed)
46
+ const serverPath = path.resolve(__dirname, "..", "server", "jxr-serve.mjs");
47
+ const node = spawn("node", ["--experimental-strip-types", serverPath, "--port", port, "--host", host], {
48
+ stdio: "inherit",
49
+ cwd: path.resolve(__dirname, ".."),
50
+ shell: true,
51
+ env: { ...process.env, NODE_ENV: "development", PORT: port },
52
+ });
53
+ node.on("close", (code) => process.exit(code));
54
+ }
55
+ // Production mode
56
+ else if (command === "start") {
57
+ console.log("🚀 Starting JXR Production Server...");
58
+
59
+ const serverPath = path.resolve(__dirname, "..", "server", "jxr-serve.mjs");
60
+ const node = spawn("node", ["--experimental-strip-types", serverPath], {
61
+ stdio: "inherit",
62
+ cwd: path.resolve(__dirname, ".."),
63
+ shell: true,
64
+ env: { ...process.env, NODE_ENV: "production" },
65
+ });
66
+ node.on("close", (code) => process.exit(code));
67
+ }
68
+ // Deploy mode
69
+ else if (command === "deploy") {
70
+ console.log("🚀 Deploying with JXR Deployer...");
71
+
72
+ const deployPath = path.resolve(__dirname, "..", "deploy-landing.mjs");
73
+ const node = spawn("node", ["--experimental-strip-types", deployPath, ...process.argv.slice(3)], {
74
+ stdio: "inherit",
75
+ cwd: path.resolve(__dirname, ".."),
76
+ shell: true,
77
+ env: { ...process.env, NODE_ENV: "production" },
78
+ });
79
+ node.on("close", (code) => process.exit(code));
80
+ }
81
+ // Unknown command
82
+ else {
83
+ console.error(`❌ Unknown command: ${command}`);
84
+ console.log("Run 'jxr --help' for usage information.");
85
+ process.exit(1);
86
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * JXR.js — Wranglerless Deployer
3
+ * ─────────────────────────────────────────────────────────────────────────────
4
+ * Deploy projects to JXR Studios' Cloudflare infrastructure without wrangler.
5
+ * Users only need a JXR API key - no Cloudflare account required.
6
+ * ─────────────────────────────────────────────────────────────────────────────
7
+ */
8
+ export interface DeployConfig {
9
+ projectId?: string;
10
+ environment?: 'production' | 'staging' | 'preview';
11
+ branch?: string;
12
+ }
13
+ export interface DeployResult {
14
+ success: boolean;
15
+ url: string;
16
+ deploymentId: string;
17
+ timestamp: string;
18
+ logs: string[];
19
+ }
20
+ export interface DeploymentStatus {
21
+ status: 'pending' | 'building' | 'deployed' | 'failed';
22
+ progress: number;
23
+ url?: string;
24
+ error?: string;
25
+ }
26
+ /**
27
+ * JXRDeployer — Deploy to JXR Cloudflare infrastructure
28
+ * No wrangler config needed. Just your JXR API key.
29
+ */
30
+ export declare class JXRDeployer {
31
+ private apiKey;
32
+ private apiUrl;
33
+ private projectId;
34
+ constructor(apiKey: string, projectId?: string);
35
+ /**
36
+ * Deploy the current project to JXR infrastructure
37
+ * @param projectPath Path to the built project (dist/ folder)
38
+ * @param config Deployment configuration
39
+ */
40
+ deploy(projectPath: string, config?: DeployConfig): Promise<DeployResult>;
41
+ /**
42
+ * Get deployment status
43
+ */
44
+ getStatus(deploymentId: string): Promise<DeploymentStatus>;
45
+ /**
46
+ * List all deployments for a project
47
+ */
48
+ listDeployments(projectId?: string): Promise<Array<{
49
+ id: string;
50
+ url: string;
51
+ environment: string;
52
+ createdAt: string;
53
+ status: string;
54
+ }>>;
55
+ /**
56
+ * Rollback to a previous deployment
57
+ */
58
+ rollback(deploymentId: string): Promise<DeployResult>;
59
+ /**
60
+ * Delete a deployment
61
+ */
62
+ deleteDeployment(deploymentId: string): Promise<void>;
63
+ private uploadBuild;
64
+ private triggerDeployment;
65
+ private pollDeployment;
66
+ private generateProjectId;
67
+ }
68
+ /** Global deployer singleton */
69
+ export declare const jxrDeployer: JXRDeployer;
70
+ //# sourceMappingURL=deployer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployer.d.ts","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,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,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAM9C;;;;OAIG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IA+CnF;;OAEG;IACG,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAehE;;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;IAwB3D;;OAEG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAe7C,WAAW;YAkCX,iBAAiB;YAyBjB,cAAc;IAuB5B,OAAO,CAAC,iBAAiB;CAM1B;AAED,gCAAgC;AAChC,eAAO,MAAM,WAAW,aAGvB,CAAC"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * JXR.js — Wranglerless Deployer
3
+ * ─────────────────────────────────────────────────────────────────────────────
4
+ * Deploy projects to JXR Studios' Cloudflare infrastructure without wrangler.
5
+ * Users only need a JXR API key - no Cloudflare account required.
6
+ * ─────────────────────────────────────────────────────────────────────────────
7
+ */
8
+ /**
9
+ * JXRDeployer — Deploy to JXR Cloudflare infrastructure
10
+ * No wrangler config needed. Just your JXR API key.
11
+ */
12
+ export class JXRDeployer {
13
+ apiKey;
14
+ apiUrl;
15
+ projectId;
16
+ constructor(apiKey, projectId) {
17
+ this.apiKey = apiKey;
18
+ this.apiUrl = 'https://api.jxrstudios.online/v1';
19
+ this.projectId = projectId || this.generateProjectId();
20
+ }
21
+ /**
22
+ * Deploy the current project to JXR infrastructure
23
+ * @param projectPath Path to the built project (dist/ folder)
24
+ * @param config Deployment configuration
25
+ */
26
+ async deploy(projectPath, config = {}) {
27
+ const env = config.environment || 'production';
28
+ const branch = config.branch || 'main';
29
+ console.log(`🚀 Deploying to JXR ${env}...`);
30
+ try {
31
+ // Step 1: Upload build files
32
+ const uploadResult = await this.uploadBuild(projectPath, {
33
+ projectId: config.projectId || this.projectId,
34
+ environment: env,
35
+ branch,
36
+ });
37
+ if (!uploadResult.success) {
38
+ throw new Error(`Upload failed: ${uploadResult.error}`);
39
+ }
40
+ // Step 2: Trigger deployment
41
+ const deployment = await this.triggerDeployment({
42
+ projectId: config.projectId || this.projectId,
43
+ environment: env,
44
+ uploadId: uploadResult.uploadId,
45
+ });
46
+ // Step 3: Poll for completion
47
+ const result = await this.pollDeployment(deployment.deploymentId);
48
+ return {
49
+ success: result.status === 'deployed',
50
+ url: result.url || `https://${this.projectId}.jxr.dev`,
51
+ deploymentId: deployment.deploymentId,
52
+ timestamp: new Date().toISOString(),
53
+ logs: result.logs || [],
54
+ };
55
+ }
56
+ catch (error) {
57
+ return {
58
+ success: false,
59
+ url: '',
60
+ deploymentId: '',
61
+ timestamp: new Date().toISOString(),
62
+ logs: [`Error: ${error instanceof Error ? error.message : 'Unknown error'}`],
63
+ };
64
+ }
65
+ }
66
+ /**
67
+ * Get deployment status
68
+ */
69
+ async getStatus(deploymentId) {
70
+ const response = await fetch(`${this.apiUrl}/deployments/${deploymentId}`, {
71
+ headers: {
72
+ 'Authorization': `Bearer ${this.apiKey}`,
73
+ 'Content-Type': 'application/json',
74
+ },
75
+ });
76
+ if (!response.ok) {
77
+ throw new Error(`Failed to get status: ${response.statusText}`);
78
+ }
79
+ return response.json();
80
+ }
81
+ /**
82
+ * List all deployments for a project
83
+ */
84
+ async listDeployments(projectId) {
85
+ const pid = projectId || this.projectId;
86
+ const response = await fetch(`${this.apiUrl}/projects/${pid}/deployments`, {
87
+ headers: {
88
+ 'Authorization': `Bearer ${this.apiKey}`,
89
+ },
90
+ });
91
+ if (!response.ok) {
92
+ throw new Error(`Failed to list deployments: ${response.statusText}`);
93
+ }
94
+ return response.json();
95
+ }
96
+ /**
97
+ * Rollback to a previous deployment
98
+ */
99
+ async rollback(deploymentId) {
100
+ const response = await fetch(`${this.apiUrl}/deployments/${deploymentId}/rollback`, {
101
+ method: 'POST',
102
+ headers: {
103
+ 'Authorization': `Bearer ${this.apiKey}`,
104
+ 'Content-Type': 'application/json',
105
+ },
106
+ });
107
+ if (!response.ok) {
108
+ throw new Error(`Rollback failed: ${response.statusText}`);
109
+ }
110
+ const result = await response.json();
111
+ return {
112
+ success: true,
113
+ url: result.url,
114
+ deploymentId: result.deploymentId,
115
+ timestamp: new Date().toISOString(),
116
+ logs: ['Rollback successful'],
117
+ };
118
+ }
119
+ /**
120
+ * Delete a deployment
121
+ */
122
+ async deleteDeployment(deploymentId) {
123
+ const response = await fetch(`${this.apiUrl}/deployments/${deploymentId}`, {
124
+ method: 'DELETE',
125
+ headers: {
126
+ 'Authorization': `Bearer ${this.apiKey}`,
127
+ },
128
+ });
129
+ if (!response.ok) {
130
+ throw new Error(`Delete failed: ${response.statusText}`);
131
+ }
132
+ }
133
+ // ─── Private Methods ────────────────────────────────────────────────────────
134
+ async uploadBuild(projectPath, options) {
135
+ // In a real implementation, this would:
136
+ // 1. Create a tarball of the build files
137
+ // 2. Upload to JXR's blob storage
138
+ // 3. Return an upload ID
139
+ // For now, simulate the API call
140
+ const formData = new FormData();
141
+ formData.append('projectId', options.projectId);
142
+ formData.append('environment', options.environment);
143
+ formData.append('branch', options.branch);
144
+ // TODO: Actually create and append tarball
145
+ // formData.append('build', tarballBlob);
146
+ const response = await fetch(`${this.apiUrl}/uploads`, {
147
+ method: 'POST',
148
+ headers: {
149
+ 'Authorization': `Bearer ${this.apiKey}`,
150
+ },
151
+ body: formData,
152
+ });
153
+ if (!response.ok) {
154
+ return { success: false, uploadId: '', error: response.statusText };
155
+ }
156
+ const data = await response.json();
157
+ return { success: true, uploadId: data.uploadId };
158
+ }
159
+ async triggerDeployment(options) {
160
+ const response = await fetch(`${this.apiUrl}/deployments`, {
161
+ method: 'POST',
162
+ headers: {
163
+ 'Authorization': `Bearer ${this.apiKey}`,
164
+ 'Content-Type': 'application/json',
165
+ },
166
+ body: JSON.stringify({
167
+ projectId: options.projectId,
168
+ environment: options.environment,
169
+ uploadId: options.uploadId,
170
+ }),
171
+ });
172
+ if (!response.ok) {
173
+ throw new Error(`Failed to trigger deployment: ${response.statusText}`);
174
+ }
175
+ return response.json();
176
+ }
177
+ async pollDeployment(deploymentId, maxAttempts = 60) {
178
+ for (let i = 0; i < maxAttempts; i++) {
179
+ const status = await this.getStatus(deploymentId);
180
+ if (status.status === 'deployed') {
181
+ return { status: 'deployed', url: status.url, logs: [] };
182
+ }
183
+ if (status.status === 'failed') {
184
+ return { status: 'failed', logs: [status.error || 'Deployment failed'] };
185
+ }
186
+ // Wait 2 seconds before next poll
187
+ await new Promise(resolve => setTimeout(resolve, 2000));
188
+ }
189
+ throw new Error('Deployment timed out');
190
+ }
191
+ generateProjectId() {
192
+ // Generate a unique project ID from the current directory or package.json
193
+ const timestamp = Date.now().toString(36);
194
+ const random = Math.random().toString(36).substring(2, 8);
195
+ return `jxr-${timestamp}-${random}`;
196
+ }
197
+ }
198
+ /** Global deployer singleton */
199
+ export const jxrDeployer = new JXRDeployer(process.env.JXR_API_KEY || '', process.env.JXR_PROJECT_ID);
200
+ //# sourceMappingURL=deployer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployer.js","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuBH;;;GAGG;AACH,MAAM,OAAO,WAAW;IACd,MAAM,CAAS;IACf,MAAM,CAAS;IACf,SAAS,CAAS;IAE1B,YAAY,MAAc,EAAE,SAAkB;QAC5C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,kCAAkC,CAAC;QACjD,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,WAAmB,EAAE,SAAuB,EAAE;QACzD,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,IAAI,YAAY,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC;QAEvC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,6BAA6B;YAC7B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE;gBACvD,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS;gBAC7C,WAAW,EAAE,GAAG;gBAChB,MAAM;aACP,CAAC,CAAC;YAEH,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,kBAAkB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC;YAC1D,CAAC;YAED,6BAA6B;YAC7B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;gBAC9C,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS;gBAC7C,WAAW,EAAE,GAAG;gBAChB,QAAQ,EAAE,YAAY,CAAC,QAAQ;aAChC,CAAC,CAAC;YAEH,8BAA8B;YAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAElE,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,UAAU;gBACrC,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,WAAW,IAAI,CAAC,SAAS,UAAU;gBACtD,YAAY,EAAE,UAAU,CAAC,YAAY;gBACrC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;aACxB,CAAC;QAEJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,GAAG,EAAE,EAAE;gBACP,YAAY,EAAE,EAAE;gBAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,IAAI,EAAE,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;aAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,YAAoB;QAClC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,gBAAgB,YAAY,EAAE,EAAE;YACzE,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,SAAkB;QAOtC,MAAM,GAAG,GAAG,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC;QAExC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,aAAa,GAAG,cAAc,EAAE;YACzE,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACzC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,YAAoB;QACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,gBAAgB,YAAY,WAAW,EAAE;YAClF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAErC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,CAAC,qBAAqB,CAAC;SAC9B,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,YAAoB;QACzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,gBAAgB,YAAY,EAAE,EAAE;YACzE,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACzC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,kBAAkB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,+EAA+E;IAEvE,KAAK,CAAC,WAAW,CACvB,WAAmB,EACnB,OAAmE;QAEnE,wCAAwC;QACxC,yCAAyC;QACzC,kCAAkC;QAClC,yBAAyB;QAEzB,iCAAiC;QACjC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;QAChC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAChD,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE1C,2CAA2C;QAC3C,yCAAyC;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,UAAU,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpD,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAI/B;QACC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,cAAc,EAAE;YACzD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;aAC3B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,YAAoB,EAAE,WAAW,GAAG,EAAE;QAKjE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YAElD,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAC3D,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC,EAAE,CAAC;YAC3E,CAAC;YAED,kCAAkC;YAClC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAEO,iBAAiB;QACvB,0EAA0E;QAC1E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO,OAAO,SAAS,IAAI,MAAM,EAAE,CAAC;IACtC,CAAC;CACF;AAED,gCAAgC;AAChC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,CACxC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,EAC7B,OAAO,CAAC,GAAG,CAAC,cAAc,CAC3B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -17,4 +17,6 @@ export { VirtualFS, JSXTransformer, ImportMapBuilder, ModuleCache, DEFAULT_PROJE
17
17
  export type { VirtualFile, VirtualDirectory, ResolvedModule, ImportMap, } from './module-resolver.js';
18
18
  export { JXRRuntime, jxrRuntime } from './runtime.js';
19
19
  export type { JXRRuntimeConfig, JXRRuntimeMetrics } from './runtime.js';
20
+ export { JXRDeployer, jxrDeployer } from './deployer.js';
21
+ export type { DeployConfig, DeployResult, DeploymentStatus } from './deployer.js';
20
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,SAAS,GACV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,SAAS,GACV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAExE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -1032,16 +1032,197 @@ var JXRRuntime = class {
1032
1032
  }
1033
1033
  };
1034
1034
  var jxrRuntime = new JXRRuntime();
1035
+
1036
+ // src/deployer.ts
1037
+ var JXRDeployer = class {
1038
+ apiKey;
1039
+ apiUrl;
1040
+ projectId;
1041
+ constructor(apiKey, projectId) {
1042
+ this.apiKey = apiKey;
1043
+ this.apiUrl = "https://api.jxrstudios.online/v1";
1044
+ this.projectId = projectId || this.generateProjectId();
1045
+ }
1046
+ /**
1047
+ * Deploy the current project to JXR infrastructure
1048
+ * @param projectPath Path to the built project (dist/ folder)
1049
+ * @param config Deployment configuration
1050
+ */
1051
+ async deploy(projectPath, config = {}) {
1052
+ const env = config.environment || "production";
1053
+ const branch = config.branch || "main";
1054
+ console.log(`\u{1F680} Deploying to JXR ${env}...`);
1055
+ try {
1056
+ const uploadResult = await this.uploadBuild(projectPath, {
1057
+ projectId: config.projectId || this.projectId,
1058
+ environment: env,
1059
+ branch
1060
+ });
1061
+ if (!uploadResult.success) {
1062
+ throw new Error(`Upload failed: ${uploadResult.error}`);
1063
+ }
1064
+ const deployment = await this.triggerDeployment({
1065
+ projectId: config.projectId || this.projectId,
1066
+ environment: env,
1067
+ uploadId: uploadResult.uploadId
1068
+ });
1069
+ const result = await this.pollDeployment(deployment.deploymentId);
1070
+ return {
1071
+ success: result.status === "deployed",
1072
+ url: result.url || `https://${this.projectId}.jxr.dev`,
1073
+ deploymentId: deployment.deploymentId,
1074
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1075
+ logs: result.logs || []
1076
+ };
1077
+ } catch (error) {
1078
+ return {
1079
+ success: false,
1080
+ url: "",
1081
+ deploymentId: "",
1082
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1083
+ logs: [`Error: ${error instanceof Error ? error.message : "Unknown error"}`]
1084
+ };
1085
+ }
1086
+ }
1087
+ /**
1088
+ * Get deployment status
1089
+ */
1090
+ async getStatus(deploymentId) {
1091
+ const response = await fetch(`${this.apiUrl}/deployments/${deploymentId}`, {
1092
+ headers: {
1093
+ "Authorization": `Bearer ${this.apiKey}`,
1094
+ "Content-Type": "application/json"
1095
+ }
1096
+ });
1097
+ if (!response.ok) {
1098
+ throw new Error(`Failed to get status: ${response.statusText}`);
1099
+ }
1100
+ return response.json();
1101
+ }
1102
+ /**
1103
+ * List all deployments for a project
1104
+ */
1105
+ async listDeployments(projectId) {
1106
+ const pid = projectId || this.projectId;
1107
+ const response = await fetch(`${this.apiUrl}/projects/${pid}/deployments`, {
1108
+ headers: {
1109
+ "Authorization": `Bearer ${this.apiKey}`
1110
+ }
1111
+ });
1112
+ if (!response.ok) {
1113
+ throw new Error(`Failed to list deployments: ${response.statusText}`);
1114
+ }
1115
+ return response.json();
1116
+ }
1117
+ /**
1118
+ * Rollback to a previous deployment
1119
+ */
1120
+ async rollback(deploymentId) {
1121
+ const response = await fetch(`${this.apiUrl}/deployments/${deploymentId}/rollback`, {
1122
+ method: "POST",
1123
+ headers: {
1124
+ "Authorization": `Bearer ${this.apiKey}`,
1125
+ "Content-Type": "application/json"
1126
+ }
1127
+ });
1128
+ if (!response.ok) {
1129
+ throw new Error(`Rollback failed: ${response.statusText}`);
1130
+ }
1131
+ const result = await response.json();
1132
+ return {
1133
+ success: true,
1134
+ url: result.url,
1135
+ deploymentId: result.deploymentId,
1136
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1137
+ logs: ["Rollback successful"]
1138
+ };
1139
+ }
1140
+ /**
1141
+ * Delete a deployment
1142
+ */
1143
+ async deleteDeployment(deploymentId) {
1144
+ const response = await fetch(`${this.apiUrl}/deployments/${deploymentId}`, {
1145
+ method: "DELETE",
1146
+ headers: {
1147
+ "Authorization": `Bearer ${this.apiKey}`
1148
+ }
1149
+ });
1150
+ if (!response.ok) {
1151
+ throw new Error(`Delete failed: ${response.statusText}`);
1152
+ }
1153
+ }
1154
+ // ─── Private Methods ────────────────────────────────────────────────────────
1155
+ async uploadBuild(projectPath, options) {
1156
+ const formData = new FormData();
1157
+ formData.append("projectId", options.projectId);
1158
+ formData.append("environment", options.environment);
1159
+ formData.append("branch", options.branch);
1160
+ const response = await fetch(`${this.apiUrl}/uploads`, {
1161
+ method: "POST",
1162
+ headers: {
1163
+ "Authorization": `Bearer ${this.apiKey}`
1164
+ },
1165
+ body: formData
1166
+ });
1167
+ if (!response.ok) {
1168
+ return { success: false, uploadId: "", error: response.statusText };
1169
+ }
1170
+ const data = await response.json();
1171
+ return { success: true, uploadId: data.uploadId };
1172
+ }
1173
+ async triggerDeployment(options) {
1174
+ const response = await fetch(`${this.apiUrl}/deployments`, {
1175
+ method: "POST",
1176
+ headers: {
1177
+ "Authorization": `Bearer ${this.apiKey}`,
1178
+ "Content-Type": "application/json"
1179
+ },
1180
+ body: JSON.stringify({
1181
+ projectId: options.projectId,
1182
+ environment: options.environment,
1183
+ uploadId: options.uploadId
1184
+ })
1185
+ });
1186
+ if (!response.ok) {
1187
+ throw new Error(`Failed to trigger deployment: ${response.statusText}`);
1188
+ }
1189
+ return response.json();
1190
+ }
1191
+ async pollDeployment(deploymentId, maxAttempts = 60) {
1192
+ for (let i = 0; i < maxAttempts; i++) {
1193
+ const status = await this.getStatus(deploymentId);
1194
+ if (status.status === "deployed") {
1195
+ return { status: "deployed", url: status.url, logs: [] };
1196
+ }
1197
+ if (status.status === "failed") {
1198
+ return { status: "failed", logs: [status.error || "Deployment failed"] };
1199
+ }
1200
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
1201
+ }
1202
+ throw new Error("Deployment timed out");
1203
+ }
1204
+ generateProjectId() {
1205
+ const timestamp = Date.now().toString(36);
1206
+ const random = Math.random().toString(36).substring(2, 8);
1207
+ return `jxr-${timestamp}-${random}`;
1208
+ }
1209
+ };
1210
+ var jxrDeployer = new JXRDeployer(
1211
+ process.env.JXR_API_KEY || "",
1212
+ process.env.JXR_PROJECT_ID
1213
+ );
1035
1214
  export {
1036
1215
  DEFAULT_PROJECT_FILES,
1037
1216
  ImportMapBuilder,
1038
1217
  JSXTransformer,
1039
1218
  JXRCrypto,
1219
+ JXRDeployer,
1040
1220
  JXRRuntime,
1041
1221
  MoQTransport,
1042
1222
  ModuleCache,
1043
1223
  VirtualFS,
1044
1224
  WorkerPool,
1045
1225
  jxrCrypto,
1226
+ jxrDeployer,
1046
1227
  jxrRuntime
1047
1228
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQ9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQ9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@jxrstudios/jxr",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "JXR.js — Edge OS Runtime Framework for elite developers",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "main": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "jxr": "./bin/jxr.js"
11
+ },
9
12
  "exports": {
10
13
  ".": {
11
14
  "import": "./dist/index.js",
@@ -14,6 +17,7 @@
14
17
  },
15
18
  "files": [
16
19
  "dist/",
20
+ "bin/",
17
21
  "README.md",
18
22
  "LICENSE"
19
23
  ],
@@ -39,6 +43,7 @@
39
43
  "check": "tsc --noEmit"
40
44
  },
41
45
  "dependencies": {
46
+ "@babel/standalone": "^7.29.1",
42
47
  "nanoid": "^5.1.5"
43
48
  },
44
49
  "devDependencies": {