durable-actors 0.5.2 → 0.5.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 +23 -26
- package/dist/actor/sandbox.d.ts +40 -0
- package/dist/actor/sandbox.d.ts.map +1 -0
- package/dist/actor/sandbox.js +32 -0
- package/dist/actor/sandbox.js.map +1 -0
- package/dist/actor/schema.d.ts +2 -0
- package/dist/actor/schema.d.ts.map +1 -1
- package/dist/actor/schema.js.map +1 -1
- package/dist/cli/actor-source-watcher.d.ts +18 -4
- package/dist/cli/actor-source-watcher.d.ts.map +1 -1
- package/dist/cli/actor-source-watcher.js +104 -34
- package/dist/cli/actor-source-watcher.js.map +1 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +12 -1
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +25 -6
- package/dist/cli/generate.js.map +1 -1
- package/dist/cli/python.d.ts +6 -0
- package/dist/cli/python.d.ts.map +1 -0
- package/dist/cli/python.js +50 -0
- package/dist/cli/python.js.map +1 -0
- package/dist/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/client/remoteClient.d.ts.map +1 -1
- package/dist/client/remoteClient.js +1 -10
- package/dist/client/remoteClient.js.map +1 -1
- package/dist/client-runtime/client.d.ts +0 -2
- package/dist/client-runtime/client.d.ts.map +1 -1
- package/dist/client-runtime/client.js +0 -3
- package/dist/client-runtime/client.js.map +1 -1
- package/dist/compiler/actor-compiler.d.ts +2 -0
- package/dist/compiler/actor-compiler.d.ts.map +1 -1
- package/dist/compiler/actor-compiler.js +9 -0
- package/dist/compiler/actor-compiler.js.map +1 -1
- package/dist/compiler/deployment-build.js +7 -0
- package/dist/compiler/deployment-build.js.map +1 -1
- package/dist/compiler/features/sandbox.d.ts +9 -0
- package/dist/compiler/features/sandbox.d.ts.map +1 -0
- package/dist/compiler/features/sandbox.js +50 -0
- package/dist/compiler/features/sandbox.js.map +1 -0
- package/dist/compiler/types.d.ts +8 -1
- package/dist/compiler/types.d.ts.map +1 -1
- package/dist/compiler/types.js +1 -0
- package/dist/compiler/types.js.map +1 -1
- package/dist/compiler/validate-public-contract.d.ts.map +1 -1
- package/dist/compiler/validate-public-contract.js +4 -0
- package/dist/compiler/validate-public-contract.js.map +1 -1
- package/dist/generated/client-runtime.d.ts.map +1 -1
- package/dist/generated/client-runtime.js +1 -1
- package/dist/generated/client-runtime.js.map +1 -1
- package/dist/host/actor-runtime.d.ts.map +1 -1
- package/dist/host/actor-runtime.js +2 -3
- package/dist/host/actor-runtime.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/templates/actor/package.json +1 -1
- package/dist/templates/ai-chat/README.md +3 -25
- package/dist/templates/ai-chat/package.json +1 -1
- package/dist/templates/ai-chat/src/Chat.tsx +9 -2
- package/dist/templates/ai-chat/src/actors.ts +2 -3
- package/dist/templates/ai-chat/src/backend.ts +7 -2
- package/dist/templates/chat/README.md +1 -1
- package/dist/templates/chat/package.json +1 -1
- package/dist/templates/documents/README.md +1 -1
- package/dist/templates/documents/package.json +1 -1
- package/dist/templates/python/.env.example +1 -0
- package/dist/templates/python/README.md +7 -0
- package/dist/templates/python/gitignore +6 -0
- package/dist/templates/python/package.json +11 -0
- package/dist/templates/python/pnpm-workspace.yaml +2 -0
- package/dist/templates/python/pyproject.toml +8 -0
- package/dist/templates/python/src/actors.py +9 -0
- package/dist/wire/public-contract.d.ts +4 -0
- package/dist/wire/public-contract.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/actor/invocationContext.d.ts +0 -4
- package/dist/actor/invocationContext.d.ts.map +0 -1
- package/dist/actor/invocationContext.js +0 -10
- package/dist/actor/invocationContext.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div align="
|
|
1
|
+
<div align="left">
|
|
2
2
|
<a href="https://github.com/TerseAI/durable-actors/blob/main/.github/assets/team-agent.gif">
|
|
3
3
|
<picture>
|
|
4
4
|
<source media="(prefers-reduced-motion: reduce)" srcset="https://raw.githubusercontent.com/TerseAI/durable-actors/main/.github/assets/team-agent.png">
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<h1>Durable Actors</h1>
|
|
10
10
|
|
|
11
11
|
<p><strong>Durable state for collaborative apps and AI agents.</strong></p>
|
|
12
|
-
<p>TypeScript actors. Rust runtime
|
|
12
|
+
<p>TypeScript actors. Rust runtime.</p>
|
|
13
13
|
|
|
14
14
|
<p>
|
|
15
15
|
<a href="https://github.com/TerseAI/durable-actors/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/TerseAI/durable-actors?style=flat&logo=github&color=f5a623"></a>
|
|
@@ -97,17 +97,9 @@ console.log(await counter.increment())
|
|
|
97
97
|
|
|
98
98
|
For complete sample applications, see [AI Chat](https://github.com/TerseAI/durable-actors/tree/main/examples/ai-chat), [Collaborative documents](https://github.com/TerseAI/durable-actors/tree/main/examples/documents), and [Chatroom](https://github.com/TerseAI/durable-actors/tree/main/examples/chat).
|
|
99
99
|
|
|
100
|
-
## Define an
|
|
100
|
+
## Define an actor
|
|
101
101
|
|
|
102
|
-
Install `ai` in your actor project:
|
|
103
|
-
|
|
104
|
-
```sh
|
|
105
|
-
pnpm install ai
|
|
106
|
-
# Or with npm:
|
|
107
|
-
npm install ai
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Define and export actors in your actor project’s `src/actors.ts`, the default entrypoint loaded by `durable-actors dev`. For example, a chat history actor:
|
|
102
|
+
Install `ai` in your actor project, then define actors in `src/actors.ts`. This chat history stores completed exchanges in one persisted array:
|
|
111
103
|
|
|
112
104
|
```ts
|
|
113
105
|
import type { UIMessage } from "ai"
|
|
@@ -120,16 +112,15 @@ export class ChatHistory extends Actor {
|
|
|
120
112
|
return this.messages
|
|
121
113
|
}
|
|
122
114
|
|
|
123
|
-
async append(
|
|
124
|
-
this.messages.push(
|
|
125
|
-
return this.messages
|
|
115
|
+
async append(...messages: UIMessage[]) {
|
|
116
|
+
this.messages.push(...messages)
|
|
126
117
|
}
|
|
127
118
|
}
|
|
128
119
|
```
|
|
129
120
|
|
|
130
|
-
## Stream from
|
|
121
|
+
## Stream from your backend
|
|
131
122
|
|
|
132
|
-
|
|
123
|
+
Generate a type-safe client with `npx durable-actors generate`. In your Express backend, load the conversation, stream a reply, and save the prompt and reply together when the stream succeeds:
|
|
133
124
|
|
|
134
125
|
```ts
|
|
135
126
|
import { openai } from "@ai-sdk/openai"
|
|
@@ -149,7 +140,8 @@ app.post("/api/chat", async (request, response) => {
|
|
|
149
140
|
const [message] = await validateUIMessages({ messages: [request.body.messages.at(-1)] })
|
|
150
141
|
if (message.role !== "user") return response.sendStatus(400)
|
|
151
142
|
const chat = actors.ChatHistory.get(request.body.id)
|
|
152
|
-
const messages = await chat.
|
|
143
|
+
const messages = [...(await chat.load()), message]
|
|
144
|
+
let failed = false
|
|
153
145
|
const result = streamText({
|
|
154
146
|
model: openai("gpt-5-mini"),
|
|
155
147
|
messages: await convertToModelMessages(messages)
|
|
@@ -160,15 +152,23 @@ app.post("/api/chat", async (request, response) => {
|
|
|
160
152
|
stream: result.stream,
|
|
161
153
|
originalMessages: messages,
|
|
162
154
|
generateMessageId: generateId,
|
|
155
|
+
onError: () => {
|
|
156
|
+
failed = true
|
|
157
|
+
return "Reply failed. Check the API key and try again."
|
|
158
|
+
},
|
|
163
159
|
onEnd: async ({ responseMessage, outcome }) => {
|
|
164
|
-
if (outcome.status === "completed") await chat.append(responseMessage)
|
|
160
|
+
if (!failed && outcome.status === "completed") await chat.append(message, responseMessage)
|
|
165
161
|
}
|
|
166
162
|
})
|
|
167
163
|
})
|
|
168
164
|
})
|
|
169
165
|
```
|
|
170
166
|
|
|
171
|
-
|
|
167
|
+
Failed or interrupted attempts are not saved. Each completed exchange is persisted in one actor call.
|
|
168
|
+
|
|
169
|
+
## Connect the frontend
|
|
170
|
+
|
|
171
|
+
The AI SDK's `useChat` handles streaming and retries:
|
|
172
172
|
|
|
173
173
|
```tsx
|
|
174
174
|
import { useChat } from "@ai-sdk/react"
|
|
@@ -177,7 +177,7 @@ import type { UIMessage } from "ai"
|
|
|
177
177
|
const history: UIMessage[] = await fetch("/api/chat/lobby").then(response => response.json())
|
|
178
178
|
|
|
179
179
|
function Chat() {
|
|
180
|
-
const { messages, sendMessage, status } = useChat({ id: "lobby", messages: history })
|
|
180
|
+
const { messages, sendMessage, regenerate, status, error } = useChat({ id: "lobby", messages: history })
|
|
181
181
|
const busy = status === "submitted" || status === "streaming"
|
|
182
182
|
|
|
183
183
|
return (
|
|
@@ -187,14 +187,11 @@ function Chat() {
|
|
|
187
187
|
{message.role}: {message.parts.map(part => (part.type === "text" ? part.text : "")).join("")}
|
|
188
188
|
</p>
|
|
189
189
|
))}
|
|
190
|
-
<form
|
|
191
|
-
action={async form => {
|
|
192
|
-
await sendMessage({ text: String(form.get("message")) })
|
|
193
|
-
}}
|
|
194
|
-
>
|
|
190
|
+
<form action={async form => { await sendMessage({ text: String(form.get("message")) }) }}>
|
|
195
191
|
<input name="message" aria-label="Message" required disabled={busy} />
|
|
196
192
|
<button disabled={busy}>Send</button>
|
|
197
193
|
</form>
|
|
194
|
+
{error && <p role="alert">{error.message} <button onClick={() => regenerate()} disabled={busy}>Retry</button></p>}
|
|
198
195
|
</>
|
|
199
196
|
)
|
|
200
197
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const sandboxRegion: z.ZodEnum<{
|
|
3
|
+
canada: "canada";
|
|
4
|
+
"north-america-east": "north-america-east";
|
|
5
|
+
"north-america-central": "north-america-central";
|
|
6
|
+
"north-america-south": "north-america-south";
|
|
7
|
+
"north-america-west": "north-america-west";
|
|
8
|
+
"europe-west": "europe-west";
|
|
9
|
+
"asia-southeast": "asia-southeast";
|
|
10
|
+
}>;
|
|
11
|
+
declare const sandboxOptionsSchema: z.ZodObject<{
|
|
12
|
+
cpu: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
memoryMiB: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
idleTimeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
regions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
16
|
+
canada: "canada";
|
|
17
|
+
"north-america-east": "north-america-east";
|
|
18
|
+
"north-america-central": "north-america-central";
|
|
19
|
+
"north-america-south": "north-america-south";
|
|
20
|
+
"north-america-west": "north-america-west";
|
|
21
|
+
"europe-west": "europe-west";
|
|
22
|
+
"asia-southeast": "asia-southeast";
|
|
23
|
+
}>>>;
|
|
24
|
+
}, z.core.$strict>;
|
|
25
|
+
type SandboxRegion = z.infer<typeof sandboxRegion>;
|
|
26
|
+
interface SandboxOptions {
|
|
27
|
+
/** CPU cores, from 0.1 to 64 in increments of 0.001. */
|
|
28
|
+
readonly cpu?: number;
|
|
29
|
+
/** Memory request and cap, from 128 to 262144 MiB. */
|
|
30
|
+
readonly memoryMiB?: number;
|
|
31
|
+
/** Inactivity before eviction, from 1 to 86400000 ms. Inherits the server default (normally 10000). */
|
|
32
|
+
readonly idleTimeoutMs?: number;
|
|
33
|
+
/** Allowed compute regions, without priority order. Existing actors remain in their saved region. */
|
|
34
|
+
readonly regions?: readonly SandboxRegion[];
|
|
35
|
+
}
|
|
36
|
+
/** Overrides the deployment's sandbox defaults for this actor class. */
|
|
37
|
+
declare function Sandbox(options: SandboxOptions): (_value: Function, context: Pick<ClassDecoratorContext, "kind">) => void;
|
|
38
|
+
export { Sandbox, sandboxOptionsSchema };
|
|
39
|
+
export type { SandboxOptions, SandboxRegion };
|
|
40
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/actor/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,QAAA,MAAM,aAAa;;;;;;;;EAQjB,CAAA;AAEF,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;kBAUxB,CAAA;AAEF,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAClD,UAAU,cAAc;IACpB,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,uGAAuG;IACvG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,qGAAqG;IACrG,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;CAC9C;AAED,wEAAwE;AACxE,iBAAS,OAAO,CAAC,OAAO,EAAE,cAAc,IAE5B,QAAQ,QAAQ,EAAE,SAAS,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAAG,IAAI,CAGhF;AAED,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAA;AACxC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ActorDefinitionError } from "../errors.js";
|
|
3
|
+
const sandboxRegion = z.enum([
|
|
4
|
+
"canada",
|
|
5
|
+
"north-america-east",
|
|
6
|
+
"north-america-central",
|
|
7
|
+
"north-america-south",
|
|
8
|
+
"north-america-west",
|
|
9
|
+
"europe-west",
|
|
10
|
+
"asia-southeast"
|
|
11
|
+
]);
|
|
12
|
+
const sandboxOptionsSchema = z.strictObject({
|
|
13
|
+
cpu: z.number().min(0.1).max(64).multipleOf(0.001).optional(),
|
|
14
|
+
memoryMiB: z.number().int().min(128).max(262144).optional(),
|
|
15
|
+
idleTimeoutMs: z.number().int().min(1).max(86400000).optional(),
|
|
16
|
+
regions: z
|
|
17
|
+
.array(sandboxRegion)
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(sandboxRegion.options.length)
|
|
20
|
+
.refine(regions => new Set(regions).size === regions.length, "regions must be unique")
|
|
21
|
+
.optional()
|
|
22
|
+
});
|
|
23
|
+
/** Overrides the deployment's sandbox defaults for this actor class. */
|
|
24
|
+
function Sandbox(options) {
|
|
25
|
+
sandboxOptionsSchema.parse(options);
|
|
26
|
+
return (_value, context) => {
|
|
27
|
+
if (context.kind !== "class")
|
|
28
|
+
throw new ActorDefinitionError("@Sandbox requires an actor class");
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export { Sandbox, sandboxOptionsSchema };
|
|
32
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/actor/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,MAAM,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC;IACzB,QAAQ;IACR,oBAAoB;IACpB,uBAAuB;IACvB,qBAAqB;IACrB,oBAAoB;IACpB,aAAa;IACb,gBAAgB;CACnB,CAAC,CAAA;AAEF,MAAM,oBAAoB,GAAG,CAAC,CAAC,YAAY,CAAC;IACxC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IAC7D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;IAC3D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;IAC/D,OAAO,EAAE,CAAC;SACL,KAAK,CAAC,aAAa,CAAC;SACpB,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC;SACjC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,EAAE,wBAAwB,CAAC;SACrF,QAAQ,EAAE;CAClB,CAAC,CAAA;AAcF,wEAAwE;AACxE,SAAS,OAAO,CAAC,OAAuB;IACpC,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACnC,OAAO,CAAC,MAAgB,EAAE,OAA4C,EAAQ,EAAE;QAC5E,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,IAAI,oBAAoB,CAAC,kCAAkC,CAAC,CAAA;IACpG,CAAC,CAAA;AACL,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAA"}
|
package/dist/actor/schema.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SocketContract } from "../wire/contract.js";
|
|
2
|
+
import type { SandboxOptions } from "./sandbox.js";
|
|
2
3
|
declare const ACTOR_ARTIFACT_VERSION = 1;
|
|
3
4
|
declare enum Persistence {
|
|
4
5
|
Persisted = "persisted",
|
|
@@ -14,6 +15,7 @@ interface ActorFieldSchema {
|
|
|
14
15
|
interface ActorSchema {
|
|
15
16
|
readonly actorName: string;
|
|
16
17
|
readonly fields: readonly ActorFieldSchema[];
|
|
18
|
+
readonly sandbox?: SandboxOptions;
|
|
17
19
|
readonly reentrantMethods?: readonly string[];
|
|
18
20
|
readonly contract?: SocketContract;
|
|
19
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,QAAA,MAAM,sBAAsB,IAAI,CAAA;AAEhC,aAAK,WAAW;IACZ,SAAS,cAAc;IACvB,SAAS,cAAc;CAC1B;AAED,UAAU,gBAAgB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,UAAU,WAAW;IACjB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CACrC;AAED,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA;AAC9C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,QAAA,MAAM,sBAAsB,IAAI,CAAA;AAEhC,aAAK,WAAW;IACZ,SAAS,cAAc;IACvB,SAAS,cAAc;CAC1B;AAED,UAAU,gBAAgB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,UAAU,WAAW;IACjB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CACrC;AAED,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA;AAC9C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAA"}
|
package/dist/actor/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAIA,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC,IAAK,WAGJ;AAHD,WAAK,WAAW;IACZ,sCAAuB,CAAA;IACvB,sCAAuB,CAAA;AAC3B,CAAC,EAHI,WAAW,KAAX,WAAW,QAGf;AAkBD,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -1,11 +1,25 @@
|
|
|
1
|
+
import { watch } from "chokidar";
|
|
1
2
|
interface ActorSourceWatcherOptions {
|
|
2
3
|
projectDirectory: string;
|
|
3
4
|
dataDirectory?: string;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
+
declare function watchActorSources(options: ActorSourceWatcherOptions, refresh: () => Promise<void>): Promise<ActorSourceWatcher>;
|
|
7
|
+
declare class ActorSourceWatcher {
|
|
8
|
+
private readonly options;
|
|
9
|
+
private readonly refresh;
|
|
10
|
+
private readonly createWatcher;
|
|
11
|
+
private readonly warn;
|
|
12
|
+
private watcher?;
|
|
13
|
+
private timer?;
|
|
14
|
+
private updates;
|
|
15
|
+
private closing?;
|
|
16
|
+
private disabled;
|
|
17
|
+
constructor(options: ActorSourceWatcherOptions, refresh: () => Promise<void>, createWatcher: typeof watch, warn: (message: string) => void);
|
|
18
|
+
start(): Promise<void>;
|
|
6
19
|
close(): Promise<void>;
|
|
20
|
+
private scheduleRefresh;
|
|
21
|
+
private waitUntilReady;
|
|
22
|
+
private disable;
|
|
7
23
|
}
|
|
8
|
-
|
|
9
|
-
export { watchActorSources };
|
|
10
|
-
export type { ActorSourceWatcher };
|
|
24
|
+
export { ActorSourceWatcher, watchActorSources };
|
|
11
25
|
//# sourceMappingURL=actor-source-watcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor-source-watcher.d.ts","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"actor-source-watcher.d.ts","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,EAAE,MAAM,UAAU,CAAA;AAIhD,UAAU,yBAAyB;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,iBAAe,iBAAiB,CAC5B,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAI7B;AAED,cAAM,kBAAkB;IAQhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAVzB,OAAO,CAAC,OAAO,CAAC,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAC,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAC,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAQ;gBAGH,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC5B,aAAa,EAAE,OAAO,KAAK,EAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAG9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,cAAc;YAgBR,OAAO;CAUxB;AA0CD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -1,46 +1,115 @@
|
|
|
1
1
|
import { watch } from "chokidar";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
async function watchActorSources(options, refresh) {
|
|
4
|
-
const watcher =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
const watcher = new ActorSourceWatcher(options, refresh, watch, message => console.warn(message));
|
|
6
|
+
await watcher.start();
|
|
7
|
+
return watcher;
|
|
8
|
+
}
|
|
9
|
+
class ActorSourceWatcher {
|
|
10
|
+
options;
|
|
11
|
+
refresh;
|
|
12
|
+
createWatcher;
|
|
13
|
+
warn;
|
|
14
|
+
watcher;
|
|
15
|
+
timer;
|
|
16
|
+
updates = Promise.resolve();
|
|
17
|
+
closing;
|
|
18
|
+
disabled = false;
|
|
19
|
+
constructor(options, refresh, createWatcher, warn) {
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.refresh = refresh;
|
|
22
|
+
this.createWatcher = createWatcher;
|
|
23
|
+
this.warn = warn;
|
|
24
|
+
}
|
|
25
|
+
async start() {
|
|
26
|
+
try {
|
|
27
|
+
this.watcher = this.createWatcher(this.options.projectDirectory, {
|
|
28
|
+
ignored: (watchedPath, stats) => ignoredActorPath(watchedPath, this.options) ||
|
|
29
|
+
(stats?.isDirectory() === true && existsSync(path.join(watchedPath, "pyvenv.cfg"))) ||
|
|
30
|
+
(stats !== undefined && !stats.isDirectory() && (!stats.isFile() || !isActorSource(watchedPath))),
|
|
31
|
+
ignoreInitial: true,
|
|
32
|
+
followSymlinks: false,
|
|
33
|
+
atomic: true,
|
|
34
|
+
awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 20 }
|
|
35
|
+
});
|
|
36
|
+
this.watcher.on("all", (_event, changedPath) => this.scheduleRefresh(changedPath));
|
|
37
|
+
await this.waitUntilReady(this.watcher);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (isWatchLimit(error))
|
|
41
|
+
await this.disable(error);
|
|
42
|
+
else {
|
|
43
|
+
await this.close();
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async close() {
|
|
49
|
+
this.disabled = true;
|
|
50
|
+
clearTimeout(this.timer);
|
|
51
|
+
if (!this.closing) {
|
|
52
|
+
this.closing = this.watcher?.close() ?? Promise.resolve();
|
|
53
|
+
// Chokidar removes listeners on close, but pending filesystem operations can still emit errors.
|
|
54
|
+
this.watcher?.on("error", () => { });
|
|
55
|
+
}
|
|
56
|
+
await this.closing;
|
|
57
|
+
await this.updates;
|
|
58
|
+
}
|
|
59
|
+
scheduleRefresh(changedPath) {
|
|
60
|
+
if (this.disabled || !isActorSource(changedPath))
|
|
16
61
|
return;
|
|
17
|
-
clearTimeout(timer);
|
|
18
|
-
timer = setTimeout(() => {
|
|
19
|
-
updates = updates.then(refresh).catch(reportWatchError);
|
|
62
|
+
clearTimeout(this.timer);
|
|
63
|
+
this.timer = setTimeout(() => {
|
|
64
|
+
this.updates = this.updates.then(this.refresh).catch(reportWatchError);
|
|
20
65
|
}, 75);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
66
|
+
}
|
|
67
|
+
waitUntilReady(watcher) {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
let ready = false;
|
|
70
|
+
watcher.once("ready", () => {
|
|
71
|
+
ready = true;
|
|
72
|
+
resolve();
|
|
73
|
+
});
|
|
74
|
+
watcher.on("error", error => {
|
|
75
|
+
if (this.disabled)
|
|
76
|
+
return;
|
|
77
|
+
if (isWatchLimit(error))
|
|
78
|
+
void this.disable(error).then(resolve, reject);
|
|
79
|
+
else if (!ready)
|
|
80
|
+
reject(error);
|
|
81
|
+
else
|
|
82
|
+
reportWatchError(error);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async disable(error) {
|
|
87
|
+
if (!this.disabled)
|
|
88
|
+
this.warn(`Actor source watcher reached the OS file/watch limit (${error.code}). Automatic reload is disabled; ` +
|
|
89
|
+
"the development server will continue running. Restart it to apply source changes. " +
|
|
90
|
+
"Close other watchers or raise your OS file/watch limit, then restart to restore automatic reload. " +
|
|
91
|
+
"Use --no-watch to disable watching explicitly.");
|
|
92
|
+
await this.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function isWatchLimit(error) {
|
|
96
|
+
return error instanceof Error && "code" in error && ["EMFILE", "ENFILE", "ENOSPC"].includes(String(error.code));
|
|
37
97
|
}
|
|
38
98
|
function ignoredActorPath(candidate, options) {
|
|
39
99
|
const relative = path.relative(options.projectDirectory, candidate);
|
|
40
100
|
if (!relative || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
|
|
41
101
|
return false;
|
|
42
102
|
const components = relative.split(path.sep);
|
|
43
|
-
if (components.
|
|
103
|
+
if (components.some(component => [
|
|
104
|
+
".git",
|
|
105
|
+
"node_modules",
|
|
106
|
+
".venv",
|
|
107
|
+
"venv",
|
|
108
|
+
"__pycache__",
|
|
109
|
+
".mypy_cache",
|
|
110
|
+
".pytest_cache",
|
|
111
|
+
".ruff_cache"
|
|
112
|
+
].includes(component)))
|
|
44
113
|
return true;
|
|
45
114
|
if ([".durable-actors", "generated"].includes(components[0]))
|
|
46
115
|
return true;
|
|
@@ -50,10 +119,11 @@ function ignoredActorPath(candidate, options) {
|
|
|
50
119
|
return candidate === state || candidate.startsWith(`${state}${path.sep}`);
|
|
51
120
|
}
|
|
52
121
|
function isActorSource(candidate) {
|
|
53
|
-
return /\.(?:[cm]?[jt]sx?|json|ya?ml)$/u.test(candidate) ||
|
|
122
|
+
return (/\.(?:[cm]?[jt]sx?|json|ya?ml|py|toml)$/u.test(candidate) ||
|
|
123
|
+
["bun.lock", "uv.lock", "requirements.txt"].includes(path.basename(candidate)));
|
|
54
124
|
}
|
|
55
125
|
function reportWatchError(error) {
|
|
56
126
|
console.error(`Actor source update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
57
127
|
}
|
|
58
|
-
export { watchActorSources };
|
|
128
|
+
export { ActorSourceWatcher, watchActorSources };
|
|
59
129
|
//# sourceMappingURL=actor-source-watcher.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor-source-watcher.js","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"actor-source-watcher.js","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/dev.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AAgBjE,UAAU,UAAU;IAChB,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,OAAO,GAAG,KAAK,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2BzD;AA+BD,iBAAe,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAM1D;AA8GD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,CAAA"}
|
package/dist/cli/dev.js
CHANGED
|
@@ -9,6 +9,7 @@ import { projectSdkModule } from "../projectSdk.js";
|
|
|
9
9
|
import { fetchRuntimeExecutablePath } from "../runtimeInstaller.js";
|
|
10
10
|
import { watchActorSources } from "./actor-source-watcher.js";
|
|
11
11
|
import { ControlPlaneClient } from "./control-plane.js";
|
|
12
|
+
import { checkPython, pythonExecutable } from "./python.js";
|
|
12
13
|
import { runtimeConnection, runtimeEnvironment, startRustRuntime } from "./rust-runtime.js";
|
|
13
14
|
export function registerDevCommand(program) {
|
|
14
15
|
program
|
|
@@ -25,6 +26,9 @@ No configuration is required. Optional overrides in .env:
|
|
|
25
26
|
DURABLE_ACTORS_PROJECT project directory (default: current directory)
|
|
26
27
|
DURABLE_ACTORS_ENTRYPOINT actor source file, relative to the project (default: src/actors.ts)
|
|
27
28
|
|
|
29
|
+
Python projects: durable-actors init my-project --template python
|
|
30
|
+
DURABLE_ACTORS_PYTHON selects an interpreter; otherwise dev uses the project .venv.
|
|
31
|
+
|
|
28
32
|
Create a project with: durable-actors init my-project`)
|
|
29
33
|
.action(async (options) => {
|
|
30
34
|
process.exitCode = await runDev(developmentOptions(options, process.env));
|
|
@@ -58,6 +62,8 @@ const developmentEnvironment = z.object({
|
|
|
58
62
|
});
|
|
59
63
|
async function runDev(options) {
|
|
60
64
|
const project = await developmentProject(options);
|
|
65
|
+
if (options.entrypoint.endsWith(".py"))
|
|
66
|
+
return runDevRuntime(options, project);
|
|
61
67
|
const local = await projectSdkModule(project, "./cli/dev.js", import.meta.url, options.sdkResolveFrom);
|
|
62
68
|
if (local !== undefined)
|
|
63
69
|
return (await import(local)).runDev({ ...options, project });
|
|
@@ -85,8 +91,11 @@ async function developmentPathStats(candidate) {
|
|
|
85
91
|
});
|
|
86
92
|
}
|
|
87
93
|
async function runDevRuntime(options, project) {
|
|
94
|
+
const python = options.entrypoint.endsWith(".py") ? await pythonExecutable(project) : undefined;
|
|
95
|
+
if (python)
|
|
96
|
+
await checkPython(project, [options.entrypoint], python);
|
|
88
97
|
const executable = await fetchRuntimeExecutablePath();
|
|
89
|
-
const runtime = startRustRuntime(executable, [...devArguments(options), "--ready-fd", "3"], runtimeEnvironment(executable), true, true);
|
|
98
|
+
const runtime = startRustRuntime(executable, [...devArguments(options), "--ready-fd", "3"], { ...runtimeEnvironment(executable), ...(python ? { DURABLE_ACTORS_PYTHON: python } : {}) }, true, true);
|
|
90
99
|
const connection = runtimeConnection(runtime.readiness, runtime.exited);
|
|
91
100
|
const settings = connection.then(value => configuredSettings(z
|
|
92
101
|
.object({
|
|
@@ -118,6 +127,8 @@ async function runDevRuntime(options, project) {
|
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
async function publishLocalCode(options, project, client) {
|
|
130
|
+
if (options.entrypoint.endsWith(".py"))
|
|
131
|
+
await checkPython(project, [options.entrypoint]);
|
|
121
132
|
await client.registerDeployment({
|
|
122
133
|
imageRef: "local",
|
|
123
134
|
workingDirectory: project,
|
package/dist/cli/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,oBAAoB,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACjE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AAEnE,OAAO,EAA2B,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAe3F,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IAC/C,OAAO;SACF,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,YAAY,EAAE,+BAA+B,CAAC;SACrD,SAAS,CACN,IAAI,MAAM,CAAC,iBAAiB,EAAE,wCAAwC,CAAC;SAClE,GAAG,CAAC,qBAAqB,CAAC;SAC1B,SAAS,CAAC,UAAU,CAAC;SACrB,OAAO,CAAC,IAAI,CAAC,CACrB;SACA,WAAW,CACR,OAAO,EACP
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;AAe3C,iBAAS,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgBvD;AAyDD,OAAO,EAAE,uBAAuB,EAAE,CAAA"}
|
package/dist/cli/generate.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import { Option } from "commander";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
import { connectionHelp } from "./connection.js";
|
|
4
5
|
import { createControlPlaneClient } from "./control-plane.js";
|
|
6
|
+
import { compilePythonContract, generatePythonClient } from "./python.js";
|
|
5
7
|
function registerGenerateCommand(program) {
|
|
6
8
|
program
|
|
7
9
|
.command("generate")
|
|
8
10
|
.argument("[entrypoint]", "actor source file to compile instead of fetching from the server")
|
|
9
11
|
.description("Generate actor clients from the running server or an explicit source file")
|
|
10
|
-
.option("--out-dir <directory>", "generated
|
|
12
|
+
.option("--out-dir <directory>", "generated client directory", "generated")
|
|
13
|
+
.addOption(new Option("--language <language>", "client language (inferred from the contract)").choices([
|
|
14
|
+
"typescript",
|
|
15
|
+
"python"
|
|
16
|
+
]))
|
|
11
17
|
.option("--config <file>", "TypeScript configuration file (local source only)")
|
|
12
18
|
.option("--control-plane-url <url>", "control-plane origin (overrides DURABLE_ACTORS_CONTROL_PLANE_URL)")
|
|
13
19
|
.addHelpText("after", connectionHelp)
|
|
@@ -15,13 +21,23 @@ function registerGenerateCommand(program) {
|
|
|
15
21
|
}
|
|
16
22
|
async function generate(entrypoint, options) {
|
|
17
23
|
validateOptions(entrypoint, options);
|
|
18
|
-
const
|
|
19
|
-
const contract = entrypoint
|
|
24
|
+
const source = entrypoint
|
|
20
25
|
? await localContract(entrypoint, options.config)
|
|
21
26
|
: await remoteContract(options.controlPlaneUrl);
|
|
22
27
|
const directory = path.resolve(options.outDir);
|
|
28
|
+
const summary = z.object({ actors: z.array(z.unknown()), typescript: z.unknown().optional() }).parse(source);
|
|
29
|
+
const language = options.language ?? (summary.typescript === undefined ? "python" : "typescript");
|
|
30
|
+
if (language === "python")
|
|
31
|
+
await generatePythonClient(source, directory);
|
|
32
|
+
else
|
|
33
|
+
await generateTypeScriptClient(source, directory);
|
|
34
|
+
console.log(`Generated ${summary.actors.length} actor contract(s) in ${directory}.`);
|
|
35
|
+
}
|
|
36
|
+
async function generateTypeScriptClient(source, directory) {
|
|
37
|
+
const { generateClient } = await import("../compiler/generators/client-generator.js");
|
|
38
|
+
const { parsePublicContract } = await import("../compiler/validate-public-contract.js");
|
|
39
|
+
const contract = parsePublicContract(source);
|
|
23
40
|
await generateClient(contract, directory);
|
|
24
|
-
console.log(`Generated ${contract.actors.length} actor contract(s) in ${directory}.`);
|
|
25
41
|
const dependencies = Object.entries(contract.typescript.dependencies);
|
|
26
42
|
if (dependencies.length)
|
|
27
43
|
console.log(`Type dependencies: ${dependencies.map(([name, version]) => `${name}@${version}`).join(", ")}. Install compatible versions in the calling project.`);
|
|
@@ -29,21 +45,24 @@ async function generate(entrypoint, options) {
|
|
|
29
45
|
function validateOptions(entrypoint, options) {
|
|
30
46
|
if (entrypoint && options.controlPlaneUrl !== undefined)
|
|
31
47
|
throw new Error("--control-plane-url cannot be combined with a source entrypoint.");
|
|
48
|
+
if (options.config && entrypoint?.endsWith(".py"))
|
|
49
|
+
throw new Error("--config applies to TypeScript source only.");
|
|
32
50
|
if (options.config && !entrypoint)
|
|
33
51
|
throw new Error("--config requires a source entrypoint.");
|
|
34
52
|
}
|
|
35
53
|
async function localContract(entrypoint, configFile) {
|
|
54
|
+
if (entrypoint.endsWith(".py"))
|
|
55
|
+
return compilePythonContract(entrypoint);
|
|
36
56
|
const { ActorCompiler } = await import("../compiler/actor-compiler.js");
|
|
37
57
|
return new ActorCompiler().compileContract(entrypoint, { configFile });
|
|
38
58
|
}
|
|
39
59
|
async function remoteContract(controlPlaneUrl) {
|
|
40
|
-
const { parsePublicContract } = await import("../compiler/validate-public-contract.js");
|
|
41
60
|
const client = createControlPlaneClient({
|
|
42
61
|
...process.env,
|
|
43
62
|
DURABLE_ACTORS_CONTROL_PLANE_URL: controlPlaneUrl ?? process.env.DURABLE_ACTORS_CONTROL_PLANE_URL
|
|
44
63
|
}, fetch);
|
|
45
64
|
const publication = publicationSchema.parse(await client.getContract());
|
|
46
|
-
return
|
|
65
|
+
return publication.contract;
|
|
47
66
|
}
|
|
48
67
|
const publicationSchema = z.strictObject({
|
|
49
68
|
contractHash: z.string().regex(/^sha256:[a-f0-9]{64}$/u),
|