diff --git a/package.json b/package.json index a8cd5e6c8..127ab55c5 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "packages/components/*", "packages/misc/*", "packages/frameworks/*", - "examples/*" + "examples/*", + "templates/*" ], "scripts": { "start": "npx turbo watch build", diff --git a/packages/actor-core-cli/src/utils/platforms.ts b/packages/actor-core-cli/src/utils/platforms.ts index c793ffbd2..3c521c029 100644 --- a/packages/actor-core-cli/src/utils/platforms.ts +++ b/packages/actor-core-cli/src/utils/platforms.ts @@ -101,7 +101,7 @@ const PLATFORMS = { ...pkgJson, scripts: { ...pkgJson.scripts, - deploy: "actor-core deploy rivet actors/app.ts", + deploy: "npx @actor-core/cli deploy rivet actors/app.ts", }, devDependencies: { "@actor-core/cli": version, @@ -256,9 +256,12 @@ serve(app); }, }, noop: { - modify: ({ files }) => { - // Do nothing - return { files }; + modify: ({ files, pkgJson }) => { + files["package.json"] = stringifyJson(pkgJson); + + return { + files, + }; }, }, } satisfies Record; diff --git a/packages/actor-core/src/actor/instance.ts b/packages/actor-core/src/actor/instance.ts index 13fc55e6d..c9acf68d9 100644 --- a/packages/actor-core/src/actor/instance.ts +++ b/packages/actor-core/src/actor/instance.ts @@ -1,6 +1,6 @@ import type { PersistedConn } from "./connection"; import type { Logger } from "@/common//log"; -import { type ActorTags, isJsonSerializable } from "@/common//utils"; +import { type ActorTags, isJsonSerializable, stringifyError } from "@/common//utils"; import onChange from "on-change"; import type { ActorConfig } from "./config"; import { Conn, type ConnId } from "./connection"; @@ -346,7 +346,7 @@ export class ActorInstance { this.#config.onStateChange(this.actorContext, this.#persistRaw.s); } catch (error) { logger().error("error in `_onStateChange`", { - error: `${error}`, + error: stringifyError(error), }); } } @@ -473,13 +473,13 @@ export class ActorInstance { // Handle promise but don't await it to prevent blocking result.catch((error) => { logger().error("error in `onDisconnect`", { - error: `${error}`, + error: stringifyError(error), }); }); } } catch (error) { logger().error("error in `onDisconnect`", { - error: `${error}`, + error: stringifyError(error), }); } } @@ -591,7 +591,7 @@ export class ActorInstance { } } catch (error) { logger().error("error in `onConnect`", { - error: `${error}`, + error: stringifyError(error), }); conn?.disconnect("`onConnect` failed"); } @@ -768,7 +768,7 @@ export class ActorInstance { } } catch (error) { logger().error("error in `onBeforeRpcResponse`", { - error: `${error}`, + error: stringifyError(error), }); } } @@ -908,7 +908,7 @@ export class ActorInstance { }) .catch((error) => { logger().error("background promise failed", { - error: `${error}`, + error: stringifyError(error), }); }); this.#backgroundPromises.push(nonfailablePromise); diff --git a/packages/actor-core/src/actor/router.ts b/packages/actor-core/src/actor/router.ts index ccb252c53..3e2c655b8 100644 --- a/packages/actor-core/src/actor/router.ts +++ b/packages/actor-core/src/actor/router.ts @@ -11,7 +11,7 @@ import { type SSEStreamingApi, streamSSE } from "hono/streaming"; import { cors } from "hono/cors"; import { assertUnreachable } from "./utils"; import { handleRouteError, handleRouteNotFound } from "@/common/router"; -import { deconstructError } from "@/common/utils"; +import { deconstructError, stringifyError } from "@/common/utils"; import type { DriverConfig } from "@/driver-helpers/config"; import type { AppConfig } from "@/app/config"; import { @@ -186,7 +186,9 @@ export function createActorRouter( // Actors don't need to know about this, since it's abstracted // away - logger().warn("websocket error", { error: `${error}` }); + logger().warn("websocket error", { + error: stringifyError(error), + }); } catch (error) { deconstructError(error, logger(), { wsEvent: "error" }); } @@ -238,7 +240,7 @@ export function createActorRouter( async (error) => { // Actors don't need to know about this, since it's abstracted // away - logger().warn("sse error", { error: `${error}` }); + logger().warn("sse error", { error: stringifyError(error) }); }, ); }); @@ -407,7 +409,7 @@ function getRequestConnParams( return typeof paramsStr === "string" ? JSON.parse(paramsStr) : undefined; } catch (error) { logger().warn("malformed connection parameters", { - error: `${error}`, + error: stringifyError(error), }); throw new errors.MalformedConnParams(error); } diff --git a/packages/actor-core/src/actor/schedule.ts b/packages/actor-core/src/actor/schedule.ts index 4796b30d4..4b2f6f639 100644 --- a/packages/actor-core/src/actor/schedule.ts +++ b/packages/actor-core/src/actor/schedule.ts @@ -2,6 +2,7 @@ import type { AnyActorInstance } from "./instance"; import type { ActorDriver } from "./driver"; import { KEYS } from "./keys"; import { logger } from "./log"; +import { stringifyError } from "@/common/utils"; interface ScheduleState { // Sorted by timestamp asc @@ -151,7 +152,7 @@ export class Schedule { } catch (err) { logger().error("failed to run scheduled event", { fn: event.fn, - error: `${err}`, + error: stringifyError(err), }); // Write internal error @@ -159,7 +160,7 @@ export class Schedule { this.#actor.id, KEYS.SCHEDULE.alarmError(event.fn), { - error: `${err}`, + error: stringifyError(err), timestamp: now, }, ); diff --git a/packages/actor-core/src/client/handle.ts b/packages/actor-core/src/client/handle.ts index cb5cb8232..e863d10e0 100644 --- a/packages/actor-core/src/client/handle.ts +++ b/packages/actor-core/src/client/handle.ts @@ -3,7 +3,7 @@ import type { Encoding } from "@/actor/protocol/serde"; import type * as wsToClient from "@/actor/protocol/message/to-client"; import type * as wsToServer from "@/actor/protocol/message/to-server"; import { MAX_CONN_PARAMS_SIZE } from "@/common/network"; -import { assertUnreachable } from "@/common/utils"; +import { assertUnreachable, stringifyError } from "@/common/utils"; import * as cbor from "cbor-x"; import * as errors from "./errors"; import { logger } from "./log"; @@ -186,7 +186,7 @@ enc onFailedAttempt: (error) => { logger().warn("failed to reconnect", { attempt: error.attemptNumber, - error: `${error}`, + error: stringifyError(error), }); }, diff --git a/packages/actor-core/src/common/utils.ts b/packages/actor-core/src/common/utils.ts index 8530f67d6..3678ba3e1 100644 --- a/packages/actor-core/src/common/utils.ts +++ b/packages/actor-core/src/common/utils.ts @@ -158,3 +158,23 @@ export function deconstructError( return { statusCode, code, message, metadata }; } + +export function stringifyError(error: unknown): string { + if (error instanceof Error) { + if (process.env._ACTOR_CORE_ERROR_STACK === "1") { + return `${error.name}: ${error.message}${error.stack ? `\n${error.stack}` : ""}`; + } else { + return `${error.name}: ${error.message}`; + } + } else if (typeof error === "string") { + return error; + } else if (typeof error === "object" && error !== null) { + try { + return `${JSON.stringify(error)}`; + } catch { + return "[cannot stringify error]"; + } + } else { + return `Unknown error: ${String(error)}`; + } +} diff --git a/yarn.lock b/yarn.lock index f6916473e..fd0e94c98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 8 cacheKey: 10c0 -"@actor-core/bun@workspace:packages/platforms/bun": +"@actor-core/bun@workspace:*, @actor-core/bun@workspace:packages/platforms/bun": version: 0.0.0-use.local resolution: "@actor-core/bun@workspace:packages/platforms/bun" dependencies: @@ -69,7 +69,7 @@ __metadata: languageName: unknown linkType: soft -"@actor-core/cloudflare-workers@workspace:packages/platforms/cloudflare-workers": +"@actor-core/cloudflare-workers@workspace:*, @actor-core/cloudflare-workers@workspace:packages/platforms/cloudflare-workers": version: 0.0.0-use.local resolution: "@actor-core/cloudflare-workers@workspace:packages/platforms/cloudflare-workers" dependencies: @@ -129,7 +129,7 @@ __metadata: languageName: unknown linkType: soft -"@actor-core/nodejs@workspace:^, @actor-core/nodejs@workspace:packages/platforms/nodejs": +"@actor-core/nodejs@workspace:*, @actor-core/nodejs@workspace:^, @actor-core/nodejs@workspace:packages/platforms/nodejs": version: 0.0.0-use.local resolution: "@actor-core/nodejs@workspace:packages/platforms/nodejs" dependencies: @@ -182,7 +182,7 @@ __metadata: languageName: unknown linkType: soft -"@actor-core/rivet@workspace:packages/platforms/rivet": +"@actor-core/rivet@workspace:*, @actor-core/rivet@workspace:packages/platforms/rivet": version: 0.0.0-use.local resolution: "@actor-core/rivet@workspace:packages/platforms/rivet" dependencies: @@ -2581,7 +2581,7 @@ __metadata: languageName: node linkType: hard -"@types/bun@npm:^1.2.2": +"@types/bun@npm:^1.2.2, @types/bun@npm:^1.2.4": version: 1.2.8 resolution: "@types/bun@npm:1.2.8" dependencies: @@ -2599,7 +2599,7 @@ __metadata: languageName: node linkType: hard -"@types/deno@npm:^2.0.0": +"@types/deno@npm:^2.0.0, @types/deno@npm:^2.2.0": version: 2.2.0 resolution: "@types/deno@npm:2.2.0" checksum: 10c0/cb45bbffe66a3008224a509c6bcb338921cc68b9045363f77ba5d84650d879b8fd4c810db24369a93fbce4a8e2855808bb141c0447feb47d911a7512ba374bde @@ -3608,6 +3608,89 @@ __metadata: languageName: node linkType: hard +"chat-room-bun@workspace:templates/chat-room-bun": + version: 0.0.0-use.local + resolution: "chat-room-bun@workspace:templates/chat-room-bun" + dependencies: + "@actor-core/bun": "workspace:*" + "@actor-core/cli": "workspace:*" + "@types/bun": "npm:^1.2.4" + "@types/node": "npm:^22.13.9" + "@types/prompts": "npm:^2" + actor-core: "workspace:*" + prompts: "npm:^2.4.2" + tsx: "npm:^3.12.7" + typescript: "npm:^5.5.2" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + +"chat-room-cloudflare-workers@workspace:templates/chat-room-cloudflare-workers": + version: 0.0.0-use.local + resolution: "chat-room-cloudflare-workers@workspace:templates/chat-room-cloudflare-workers" + dependencies: + "@actor-core/cli": "workspace:*" + "@actor-core/cloudflare-workers": "workspace:*" + "@cloudflare/workers-types": "npm:^4.20250129.0" + "@types/node": "npm:^22.13.9" + "@types/prompts": "npm:^2" + actor-core: "workspace:*" + prompts: "npm:^2.4.2" + tsx: "npm:^3.12.7" + typescript: "npm:^5.5.2" + vitest: "npm:^3.0.9" + wrangler: "npm:^3.101.0" + languageName: unknown + linkType: soft + +"chat-room-nodejs@workspace:templates/chat-room-nodejs": + version: 0.0.0-use.local + resolution: "chat-room-nodejs@workspace:templates/chat-room-nodejs" + dependencies: + "@actor-core/cli": "workspace:*" + "@actor-core/nodejs": "workspace:*" + "@types/node": "npm:^22.13.9" + "@types/prompts": "npm:^2" + actor-core: "workspace:*" + prompts: "npm:^2.4.2" + tsx: "npm:^3.12.7" + typescript: "npm:^5.5.2" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + +"chat-room-noop@workspace:templates/chat-room-noop": + version: 0.0.0-use.local + resolution: "chat-room-noop@workspace:templates/chat-room-noop" + dependencies: + "@actor-core/cli": "workspace:*" + "@types/node": "npm:^22.13.9" + "@types/prompts": "npm:^2" + actor-core: "workspace:*" + prompts: "npm:^2.4.2" + tsx: "npm:^3.12.7" + typescript: "npm:^5.5.2" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + +"chat-room-rivet@workspace:templates/chat-room-rivet": + version: 0.0.0-use.local + resolution: "chat-room-rivet@workspace:templates/chat-room-rivet" + dependencies: + "@actor-core/cli": "workspace:*" + "@actor-core/rivet": "workspace:*" + "@types/deno": "npm:^2.2.0" + "@types/node": "npm:^22.13.9" + "@types/prompts": "npm:^2" + actor-core: "workspace:*" + prompts: "npm:^2.4.2" + tsx: "npm:^3.12.7" + typescript: "npm:^5.5.2" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + "chat-room@workspace:examples/chat-room": version: 0.0.0-use.local resolution: "chat-room@workspace:examples/chat-room" @@ -3881,6 +3964,79 @@ __metadata: languageName: node linkType: hard +"counter-bun@workspace:templates/counter-bun": + version: 0.0.0-use.local + resolution: "counter-bun@workspace:templates/counter-bun" + dependencies: + "@actor-core/bun": "workspace:*" + "@actor-core/cli": "workspace:*" + "@types/bun": "npm:^1.2.4" + "@types/node": "npm:^22.13.9" + actor-core: "workspace:*" + tsx: "npm:^3.12.7" + typescript: "npm:^5.7.3" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + +"counter-cloudflare-workers@workspace:templates/counter-cloudflare-workers": + version: 0.0.0-use.local + resolution: "counter-cloudflare-workers@workspace:templates/counter-cloudflare-workers" + dependencies: + "@actor-core/cli": "workspace:*" + "@actor-core/cloudflare-workers": "workspace:*" + "@cloudflare/workers-types": "npm:^4.20250129.0" + "@types/node": "npm:^22.13.9" + actor-core: "workspace:*" + tsx: "npm:^3.12.7" + typescript: "npm:^5.7.3" + vitest: "npm:^3.0.9" + wrangler: "npm:^3.101.0" + languageName: unknown + linkType: soft + +"counter-nodejs@workspace:templates/counter-nodejs": + version: 0.0.0-use.local + resolution: "counter-nodejs@workspace:templates/counter-nodejs" + dependencies: + "@actor-core/cli": "workspace:*" + "@actor-core/nodejs": "workspace:*" + "@types/node": "npm:^22.13.9" + actor-core: "workspace:*" + tsx: "npm:^3.12.7" + typescript: "npm:^5.7.3" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + +"counter-noop@workspace:templates/counter-noop": + version: 0.0.0-use.local + resolution: "counter-noop@workspace:templates/counter-noop" + dependencies: + "@actor-core/cli": "workspace:*" + "@types/node": "npm:^22.13.9" + actor-core: "workspace:*" + tsx: "npm:^3.12.7" + typescript: "npm:^5.7.3" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + +"counter-rivet@workspace:templates/counter-rivet": + version: 0.0.0-use.local + resolution: "counter-rivet@workspace:templates/counter-rivet" + dependencies: + "@actor-core/cli": "workspace:*" + "@actor-core/rivet": "workspace:*" + "@types/deno": "npm:^2.2.0" + "@types/node": "npm:^22.13.9" + actor-core: "workspace:*" + tsx: "npm:^3.12.7" + typescript: "npm:^5.7.3" + vitest: "npm:^3.0.9" + languageName: unknown + linkType: soft + "counter@workspace:examples/counter": version: 0.0.0-use.local resolution: "counter@workspace:examples/counter"