@actuallyjamez/elysian 0.9.0 → 0.10.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.
@@ -392,8 +392,7 @@ export const devCommand = defineCommand({
392
392
  }
393
393
  ui.blank();
394
394
  if (liveConfig) {
395
- console.log(` ${pc.dim("➜")} ${pc.bold("api")} ${pc.cyan(liveConfig.apiEndpoint)}`);
396
- console.log(` ${pc.dim("➜")} ${pc.bold("appsync")} ${pc.cyan(liveConfig.appSyncHttpEndpoint)}`);
395
+ console.log(` ${pc.dim("➜")} ${pc.bold("API")} ${pc.cyan(liveConfig.apiEndpoint)}`);
397
396
  }
398
397
  }
399
398
  function watchFiles() {
@@ -4,7 +4,7 @@
4
4
  import { existsSync, mkdirSync } from "fs";
5
5
  import { join } from "path";
6
6
  import { spawn } from "bun";
7
- import { configTemplate, exampleLambdaTemplate, packageJsonTemplate, gitignoreTemplate, tsconfigTemplate, } from "./templates";
7
+ import { configTemplate, exampleLambdaTemplate, packageJsonTemplate, gitignoreTemplate, tsconfigTemplate, ensurePackageJsonFields, } from "./templates";
8
8
  import { templates as tfTemplates, appendProviders, getMissingVariables, appendMain, appendOutputs, } from "./terraform";
9
9
  import { templates as tfLiveTemplates, hasAppSyncApi, appendLiveOutputs, } from "./terraform-live";
10
10
  import { ui } from "../../ui";
@@ -60,6 +60,21 @@ export async function scaffoldProject(cwd, info, answers, force) {
60
60
  await writeFile(tsconfigPath, tsconfigTemplate(), result, false);
61
61
  }
62
62
  }
63
+ else {
64
+ // For existing projects, ensure package.json has required fields
65
+ const packageJsonPath = join(cwd, "package.json");
66
+ if (existsSync(packageJsonPath)) {
67
+ const existing = await readFileOrEmpty(packageJsonPath);
68
+ const updated = ensurePackageJsonFields(existing, answers.name);
69
+ if (updated) {
70
+ await writeFile(packageJsonPath, updated, result, true);
71
+ }
72
+ }
73
+ else {
74
+ // No package.json exists, create one
75
+ await writeFile(packageJsonPath, packageJsonTemplate(answers.name), result, false);
76
+ }
77
+ }
63
78
  // Create elysian.config.ts
64
79
  const configPath = join(cwd, "elysian.config.ts");
65
80
  if (!existsSync(configPath) || force) {
@@ -21,3 +21,8 @@ export declare function gitignoreTemplate(): string;
21
21
  * tsconfig.json template
22
22
  */
23
23
  export declare function tsconfigTemplate(): string;
24
+ /**
25
+ * Ensure package.json has required fields (name, version, scripts)
26
+ * Returns the updated content if changes were made, or null if no changes needed
27
+ */
28
+ export declare function ensurePackageJsonFields(existingContent: string, name: string): string | null;
@@ -97,3 +97,66 @@ export function tsconfigTemplate() {
97
97
  exclude: ["node_modules", "dist"],
98
98
  }, null, 2);
99
99
  }
100
+ /**
101
+ * Ensure package.json has required fields (name, version, scripts)
102
+ * Returns the updated content if changes were made, or null if no changes needed
103
+ */
104
+ export function ensurePackageJsonFields(existingContent, name) {
105
+ let pkg;
106
+ try {
107
+ pkg = JSON.parse(existingContent);
108
+ }
109
+ catch {
110
+ // Invalid JSON, can't update
111
+ return null;
112
+ }
113
+ let changed = false;
114
+ // Ensure name
115
+ if (!pkg.name) {
116
+ pkg.name = name;
117
+ changed = true;
118
+ }
119
+ // Ensure version
120
+ if (!pkg.version) {
121
+ pkg.version = "0.1.0";
122
+ changed = true;
123
+ }
124
+ // Ensure type is module
125
+ if (!pkg.type) {
126
+ pkg.type = "module";
127
+ changed = true;
128
+ }
129
+ // Ensure scripts exist with elysian commands
130
+ const scripts = pkg.scripts || {};
131
+ if (!scripts.build) {
132
+ scripts.build = "elysian build";
133
+ changed = true;
134
+ }
135
+ if (!scripts.dev) {
136
+ scripts.dev = "elysian dev";
137
+ changed = true;
138
+ }
139
+ if (changed || !pkg.scripts) {
140
+ pkg.scripts = scripts;
141
+ }
142
+ if (!changed) {
143
+ return null;
144
+ }
145
+ // Reorder keys to put name, version, type, scripts first
146
+ const ordered = {};
147
+ if (pkg.name)
148
+ ordered.name = pkg.name;
149
+ if (pkg.version)
150
+ ordered.version = pkg.version;
151
+ if (pkg.type)
152
+ ordered.type = pkg.type;
153
+ if (pkg.scripts)
154
+ ordered.scripts = pkg.scripts;
155
+ // Add remaining keys
156
+ for (const [key, value] of Object.entries(pkg)) {
157
+ if (!ordered[key]) {
158
+ ordered[key] = value;
159
+ }
160
+ }
161
+ return JSON.stringify(ordered, null, 2);
162
+ }
@@ -107,12 +107,11 @@ export class AppSyncClient extends EventEmitter {
107
107
  const message = JSON.parse(event.data);
108
108
  await this.handleMessage(message, resolve, reject, connectionTimeout);
109
109
  }
110
- catch (err) {
111
- console.error("[appsync] Failed to parse message:", err);
110
+ catch {
111
+ // Ignore parse errors - malformed messages from server
112
112
  }
113
113
  };
114
- this.ws.onerror = (error) => {
115
- console.error("[appsync] WebSocket error:", error);
114
+ this.ws.onerror = () => {
116
115
  clearTimeout(connectionTimeout);
117
116
  this.config.onError?.(new Error("WebSocket error"));
118
117
  };
@@ -158,8 +157,8 @@ export class AppSyncClient extends EventEmitter {
158
157
  const request = JSON.parse(eventStr);
159
158
  this.handleInvokeRequest(request);
160
159
  }
161
- catch (err) {
162
- console.error("[appsync] Failed to parse invoke request:", err);
160
+ catch {
161
+ // Ignore malformed invoke requests
163
162
  }
164
163
  }
165
164
  }
@@ -169,8 +168,8 @@ export class AppSyncClient extends EventEmitter {
169
168
  const request = JSON.parse(message.event);
170
169
  this.handleInvokeRequest(request);
171
170
  }
172
- catch (err) {
173
- console.error("[appsync] Failed to parse invoke request:", err);
171
+ catch {
172
+ // Ignore malformed invoke requests
174
173
  }
175
174
  }
176
175
  else if (message.payload) {
@@ -181,8 +180,10 @@ export class AppSyncClient extends EventEmitter {
181
180
  break;
182
181
  }
183
182
  case "error":
184
- console.error("[appsync] Server error:", message.payload);
185
- this.config.onError?.(new Error(JSON.stringify(message.payload)));
183
+ // Only report if there's an actual error payload
184
+ if (message.payload) {
185
+ this.config.onError?.(new Error(JSON.stringify(message.payload)));
186
+ }
186
187
  break;
187
188
  case "connection_error":
188
189
  clearTimeout(connectionTimeout);
@@ -317,19 +318,17 @@ export class AppSyncClient extends EventEmitter {
317
318
  */
318
319
  scheduleReconnect() {
319
320
  if (this.reconnectAttempts >= this.maxReconnectAttempts) {
320
- console.error("[appsync] Max reconnection attempts reached");
321
321
  this.config.onError?.(new Error("Max reconnection attempts reached"));
322
322
  return;
323
323
  }
324
324
  const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);
325
325
  this.reconnectAttempts++;
326
- console.log(`[appsync] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
327
326
  setTimeout(async () => {
328
327
  try {
329
328
  await this.connect();
330
329
  }
331
- catch (err) {
332
- console.error("[appsync] Reconnection failed:", err);
330
+ catch {
331
+ // Reconnection failed, will retry via onclose handler
333
332
  }
334
333
  }, delay);
335
334
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuallyjamez/elysian",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Automatic Lambda bundler for Elysia with API Gateway and Terraform integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",