@astami/temporal-functions 0.1.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.
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # Temporal Functions
2
+
3
+ A lightweight TypeScript framework that provides a **lambda-like developer experience** on top of **Temporal's durable execution engine**.
4
+
5
+ Write only function bodies and trigger bindings — the framework handles all Temporal boilerplate (workers, activities, workflows, serialization).
6
+
7
+ ## Why Temporal Functions?
8
+
9
+ | Aspect | Lambda/Serverless | Raw Temporal | Temporal Functions |
10
+ |--------|-------------------|--------------|-------------------|
11
+ | Function definition | Simple | Verbose | Simple |
12
+ | Durable execution | No | Yes | Yes |
13
+ | Retries/timeouts | Limited | Powerful | Powerful |
14
+ | Worker management | Managed | Manual | Abstracted |
15
+ | Type safety | Varies | Yes | Yes |
16
+
17
+ ## Quick Example
18
+
19
+ ```typescript
20
+ import { tfn } from 'temporal-functions';
21
+
22
+ // Define functions (activities)
23
+ export const validateOrder = tfn.fn('validateOrder', async (order: Order) => {
24
+ // validation logic
25
+ });
26
+
27
+ export const chargePayment = tfn.fn('chargePayment', async (order: ValidatedOrder) => {
28
+ // payment logic
29
+ });
30
+
31
+ // Define workflow
32
+ export const processOrder = tfn.workflow('processOrder', async (ctx, order: Order) => {
33
+ const validated = await ctx.run(validateOrder, order);
34
+ const paid = await ctx.run(chargePayment, validated);
35
+ return { orderId: paid.id, status: 'complete' };
36
+ });
37
+ ```
38
+
39
+ **That's it.** No worker setup, no activity proxies, no boilerplate.
40
+
41
+ ## Key Principles
42
+
43
+ 1. **Lambda-like DX** — Write functions, not infrastructure
44
+ 2. **Temporal underneath** — Get durability, retries, exactly-once semantics for free
45
+ 3. **TypeScript native** — Full type safety, great IDE support
46
+ 4. **Client-Worker separation** — Scale triggers and executors independently
47
+ 5. **Minimal abstraction** — Thin layer, not a new platform
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ npm install temporal-functions
53
+ ```
54
+
55
+ ## Usage
56
+
57
+ ### Define Functions
58
+
59
+ ```typescript
60
+ import { tfn } from 'temporal-functions';
61
+
62
+ export const sendEmail = tfn.fn(
63
+ 'sendEmail',
64
+ async (params: EmailParams): Promise<EmailResult> => {
65
+ return await emailService.send(params);
66
+ },
67
+ {
68
+ timeout: '30s',
69
+ retries: 3,
70
+ }
71
+ );
72
+ ```
73
+
74
+ ### Define Workflows
75
+
76
+ ```typescript
77
+ export const processOrder = tfn.workflow(
78
+ 'processOrder',
79
+ async (ctx, order: Order) => {
80
+ const validated = await ctx.run(validateOrder, order);
81
+
82
+ // Parallel execution
83
+ const [inventory, pricing] = await Promise.all([
84
+ ctx.run(checkInventory, validated.items),
85
+ ctx.run(calculatePricing, validated.items),
86
+ ]);
87
+
88
+ // Durable sleep
89
+ await ctx.sleep('5 minutes');
90
+
91
+ const payment = await ctx.run(processPayment, {
92
+ amount: pricing.total,
93
+ orderId: order.id,
94
+ });
95
+
96
+ return { orderId: order.id, status: 'complete' };
97
+ }
98
+ );
99
+ ```
100
+
101
+ ### Client (Trigger Workflows)
102
+
103
+ ```typescript
104
+ import { tfn } from 'temporal-functions/client';
105
+ import { processOrder } from '@myproject/functions';
106
+
107
+ const client = tfn.client({
108
+ temporal: {
109
+ address: 'localhost:7233',
110
+ namespace: 'default',
111
+ },
112
+ taskQueue: 'orders',
113
+ });
114
+
115
+ // Fire and wait
116
+ const result = await client.invoke(processOrder, order);
117
+
118
+ // Fire and forget
119
+ const handle = await client.start(processOrder, order, {
120
+ workflowId: `order-${order.id}`,
121
+ });
122
+ ```
123
+
124
+ ### Worker (Execute Functions)
125
+
126
+ ```typescript
127
+ import { tfn } from 'temporal-functions/worker';
128
+ import { validateOrder, chargePayment, processOrder } from '@myproject/functions';
129
+
130
+ const worker = tfn.worker({
131
+ temporal: {
132
+ address: 'localhost:7233',
133
+ namespace: 'default',
134
+ },
135
+ taskQueue: 'orders',
136
+ });
137
+
138
+ worker.register(validateOrder);
139
+ worker.register(chargePayment);
140
+ worker.register(processOrder);
141
+
142
+ await worker.start();
143
+ ```
144
+
145
+ ## Triggers
146
+
147
+ ```typescript
148
+ // HTTP
149
+ tfn.http('POST', '/api/orders', processOrder);
150
+
151
+ // Cron
152
+ tfn.cron('0 9 * * *', dailyReport);
153
+
154
+ // Signal
155
+ tfn.signal('order.cancel', handleCancellation);
156
+ ```
157
+
158
+ ## Project Structure
159
+
160
+ ```
161
+ my-project/
162
+ ├── packages/
163
+ │ ├── functions/ # Shared function definitions
164
+ │ │ └── src/
165
+ │ │ ├── orders/
166
+ │ │ └── notifications/
167
+ │ ├── worker/ # Worker service
168
+ │ │ └── src/index.ts
169
+ │ └── api/ # API/Client service
170
+ │ └── src/index.ts
171
+ └── package.json
172
+ ```
173
+
174
+ ## Architecture
175
+
176
+ ```
177
+ ┌─────────────────────────────────────────────────────────────┐
178
+ │ TEMPORAL FUNCTIONS │
179
+ ├─────────────────────────────────────────────────────────────┤
180
+ │ │
181
+ │ SHARED: Function Definitions │
182
+ │ tfn.fn() tfn.workflow() Types & Interfaces │
183
+ │ │
184
+ │ │ │ │
185
+ │ ▼ ▼ │
186
+ │ ┌──────────────┐ ┌──────────────┐ │
187
+ │ │ CLIENT │ │ WORKER │ │
188
+ │ │ Lightweight │ │ Full SDK │ │
189
+ │ │ ~20KB │ │ ~2MB │ │
190
+ │ │ │ │ │ │
191
+ │ │ • start() │ │ • register()│ │
192
+ │ │ • invoke() │ │ • start() │ │
193
+ │ │ • signal() │ │ │ │
194
+ │ └──────┬───────┘ └──────┬───────┘ │
195
+ │ │ │ │
196
+ │ └───────────┬───────────────┘ │
197
+ │ ▼ │
198
+ │ ┌─────────────────┐ │
199
+ │ │ TEMPORAL CLUSTER │ │
200
+ │ └─────────────────┘ │
201
+ │ │
202
+ └─────────────────────────────────────────────────────────────┘
203
+ ```
204
+
205
+ ## Documentation
206
+
207
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full architecture document.
208
+
209
+ ## Status
210
+
211
+ **Design Phase** — This project is currently in the design and early implementation phase.
212
+
213
+ ## License
214
+
215
+ MIT
@@ -0,0 +1,34 @@
1
+ import { g as ClientConfig, j as TFNClient } from '../types-C-cNq1Id.mjs';
2
+ export { S as StartWorkflowOptions, i as WorkflowHandle } from '../types-C-cNq1Id.mjs';
3
+
4
+ /**
5
+ * Temporal Functions - Client Package
6
+ *
7
+ * Lightweight client for triggering workflows.
8
+ * Import from 'temporal-functions/client'.
9
+ */
10
+
11
+ /**
12
+ * Create a Temporal Functions client
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { tfn } from 'temporal-functions/client';
17
+ *
18
+ * const client = tfn.client({
19
+ * temporal: {
20
+ * address: 'localhost:7233',
21
+ * namespace: 'default',
22
+ * },
23
+ * taskQueue: 'my-queue',
24
+ * });
25
+ *
26
+ * const result = await client.invoke(myWorkflow, { data: 'hello' });
27
+ * ```
28
+ */
29
+ declare function createClient(config: ClientConfig): TFNClient;
30
+ declare const tfn: {
31
+ client: typeof createClient;
32
+ };
33
+
34
+ export { ClientConfig, TFNClient, createClient, tfn as default, tfn };
@@ -0,0 +1,34 @@
1
+ import { g as ClientConfig, j as TFNClient } from '../types-C-cNq1Id.js';
2
+ export { S as StartWorkflowOptions, i as WorkflowHandle } from '../types-C-cNq1Id.js';
3
+
4
+ /**
5
+ * Temporal Functions - Client Package
6
+ *
7
+ * Lightweight client for triggering workflows.
8
+ * Import from 'temporal-functions/client'.
9
+ */
10
+
11
+ /**
12
+ * Create a Temporal Functions client
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { tfn } from 'temporal-functions/client';
17
+ *
18
+ * const client = tfn.client({
19
+ * temporal: {
20
+ * address: 'localhost:7233',
21
+ * namespace: 'default',
22
+ * },
23
+ * taskQueue: 'my-queue',
24
+ * });
25
+ *
26
+ * const result = await client.invoke(myWorkflow, { data: 'hello' });
27
+ * ```
28
+ */
29
+ declare function createClient(config: ClientConfig): TFNClient;
30
+ declare const tfn: {
31
+ client: typeof createClient;
32
+ };
33
+
34
+ export { ClientConfig, TFNClient, createClient, tfn as default, tfn };
@@ -0,0 +1,168 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var client = require('@temporalio/client');
6
+
7
+ // src/client/index.ts
8
+ var TemporalFunctionsClient = class {
9
+ client = null;
10
+ config;
11
+ connectionPromise = null;
12
+ constructor(config) {
13
+ this.config = {
14
+ ...config,
15
+ temporal: {
16
+ namespace: "default",
17
+ ...config.temporal
18
+ },
19
+ taskQueue: config.taskQueue || "default"
20
+ };
21
+ }
22
+ /**
23
+ * Lazily connect to Temporal
24
+ */
25
+ async getClient() {
26
+ if (this.client) {
27
+ return this.client;
28
+ }
29
+ if (this.connectionPromise) {
30
+ return this.connectionPromise;
31
+ }
32
+ this.connectionPromise = (async () => {
33
+ const connection = await client.Connection.connect({
34
+ address: this.config.temporal.address,
35
+ tls: this.config.temporal.tls ? {
36
+ clientCertPair: this.config.temporal.tls.clientCertPath ? {
37
+ crt: await import('fs').then(
38
+ (fs) => fs.promises.readFile(this.config.temporal.tls.clientCertPath)
39
+ ),
40
+ key: await import('fs').then(
41
+ (fs) => fs.promises.readFile(this.config.temporal.tls.clientKeyPath)
42
+ )
43
+ } : void 0
44
+ } : void 0
45
+ });
46
+ this.client = new client.Client({
47
+ connection,
48
+ namespace: this.config.temporal.namespace
49
+ });
50
+ return this.client;
51
+ })();
52
+ return this.connectionPromise;
53
+ }
54
+ /**
55
+ * Generate a workflow ID if not provided
56
+ */
57
+ generateWorkflowId(workflowName) {
58
+ const timestamp = Date.now();
59
+ const random = Math.random().toString(36).substring(2, 8);
60
+ return `${workflowName}-${timestamp}-${random}`;
61
+ }
62
+ /**
63
+ * Start a workflow and wait for the result
64
+ */
65
+ async invoke(workflow, input, options = {}) {
66
+ const handle = await this.start(workflow, input, options);
67
+ return handle.result();
68
+ }
69
+ /**
70
+ * Start a workflow without waiting (fire and forget)
71
+ */
72
+ async start(workflow, input, options = {}) {
73
+ const client = await this.getClient();
74
+ const workflowId = options.workflowId || this.generateWorkflowId(workflow.name);
75
+ const taskQueue = options.taskQueue || workflow.options.taskQueue || this.config.taskQueue || "default";
76
+ const handle = await client.workflow.start(workflow.name, {
77
+ workflowId,
78
+ taskQueue,
79
+ args: [input],
80
+ workflowExecutionTimeout: options.workflowExecutionTimeout,
81
+ memo: options.memo
82
+ // searchAttributes requires specific types, omit for now if not properly typed
83
+ });
84
+ return this.wrapHandle(handle);
85
+ }
86
+ /**
87
+ * Get a handle to an existing workflow
88
+ */
89
+ getHandle(workflowId) {
90
+ return {
91
+ workflowId,
92
+ runId: "",
93
+ // Will be populated when we fetch
94
+ result: async () => {
95
+ const client = await this.getClient();
96
+ const handle = client.workflow.getHandle(workflowId);
97
+ return handle.result();
98
+ },
99
+ query: async (queryName) => {
100
+ const client = await this.getClient();
101
+ const handle = client.workflow.getHandle(workflowId);
102
+ return handle.query(queryName);
103
+ },
104
+ signal: async (signalName, payload) => {
105
+ const client = await this.getClient();
106
+ const handle = client.workflow.getHandle(workflowId);
107
+ await handle.signal(signalName, payload);
108
+ },
109
+ cancel: async () => {
110
+ const client = await this.getClient();
111
+ const handle = client.workflow.getHandle(workflowId);
112
+ await handle.cancel();
113
+ },
114
+ terminate: async (reason) => {
115
+ const client = await this.getClient();
116
+ const handle = client.workflow.getHandle(workflowId);
117
+ await handle.terminate(reason);
118
+ }
119
+ };
120
+ }
121
+ /**
122
+ * Signal an existing workflow
123
+ */
124
+ async signal(workflowId, signalName, payload) {
125
+ const client = await this.getClient();
126
+ const handle = client.workflow.getHandle(workflowId);
127
+ await handle.signal(signalName, payload);
128
+ }
129
+ /**
130
+ * Query an existing workflow
131
+ */
132
+ async query(workflowId, queryName) {
133
+ const client = await this.getClient();
134
+ const handle = client.workflow.getHandle(workflowId);
135
+ return handle.query(queryName);
136
+ }
137
+ /**
138
+ * Wrap a Temporal workflow handle in our interface
139
+ */
140
+ wrapHandle(handle) {
141
+ return {
142
+ workflowId: handle.workflowId,
143
+ runId: handle.firstExecutionRunId,
144
+ result: () => handle.result(),
145
+ query: (queryName) => handle.query(queryName),
146
+ signal: (signalName, payload) => handle.signal(signalName, payload),
147
+ cancel: async () => {
148
+ await handle.cancel();
149
+ },
150
+ terminate: async (reason) => {
151
+ await handle.terminate(reason);
152
+ }
153
+ };
154
+ }
155
+ };
156
+ function createClient(config) {
157
+ return new TemporalFunctionsClient(config);
158
+ }
159
+ var tfn = {
160
+ client: createClient
161
+ };
162
+ var client_default = tfn;
163
+
164
+ exports.createClient = createClient;
165
+ exports.default = client_default;
166
+ exports.tfn = tfn;
167
+ //# sourceMappingURL=index.js.map
168
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.ts"],"names":["Connection","Client"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Temporal Functions - Client Package\n *\n * Lightweight client for triggering workflows.\n * Import from 'temporal-functions/client'.\n */\n\nimport { Client, Connection } from '@temporalio/client';\nimport type {\n ClientConfig,\n WorkflowDef,\n StartWorkflowOptions,\n WorkflowHandle,\n TFNClient,\n} from '../types.js';\n\n// =============================================================================\n// Client Implementation\n// =============================================================================\n\nclass TemporalFunctionsClient implements TFNClient {\n private client: Client | null = null;\n private config: ClientConfig;\n private connectionPromise: Promise<Client> | null = null;\n\n constructor(config: ClientConfig) {\n this.config = {\n ...config,\n temporal: {\n namespace: 'default',\n ...config.temporal,\n },\n taskQueue: config.taskQueue || 'default',\n };\n }\n\n /**\n * Lazily connect to Temporal\n */\n private async getClient(): Promise<Client> {\n if (this.client) {\n return this.client;\n }\n\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n this.connectionPromise = (async () => {\n const connection = await Connection.connect({\n address: this.config.temporal.address,\n tls: this.config.temporal.tls\n ? {\n clientCertPair: this.config.temporal.tls.clientCertPath\n ? {\n crt: await import('fs').then((fs) =>\n fs.promises.readFile(this.config.temporal.tls!.clientCertPath!)\n ),\n key: await import('fs').then((fs) =>\n fs.promises.readFile(this.config.temporal.tls!.clientKeyPath!)\n ),\n }\n : undefined,\n }\n : undefined,\n });\n\n this.client = new Client({\n connection,\n namespace: this.config.temporal.namespace,\n });\n\n return this.client;\n })();\n\n return this.connectionPromise;\n }\n\n /**\n * Generate a workflow ID if not provided\n */\n private generateWorkflowId(workflowName: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 8);\n return `${workflowName}-${timestamp}-${random}`;\n }\n\n /**\n * Start a workflow and wait for the result\n */\n async invoke<TInput, TOutput>(\n workflow: WorkflowDef<TInput, TOutput>,\n input: TInput,\n options: StartWorkflowOptions = {}\n ): Promise<TOutput> {\n const handle = await this.start(workflow, input, options);\n return handle.result();\n }\n\n /**\n * Start a workflow without waiting (fire and forget)\n */\n async start<TInput, TOutput>(\n workflow: WorkflowDef<TInput, TOutput>,\n input: TInput,\n options: StartWorkflowOptions = {}\n ): Promise<WorkflowHandle<TOutput>> {\n const client = await this.getClient();\n\n const workflowId = options.workflowId || this.generateWorkflowId(workflow.name);\n const taskQueue = options.taskQueue || workflow.options.taskQueue || this.config.taskQueue || 'default';\n\n const handle = await client.workflow.start(workflow.name, {\n workflowId,\n taskQueue,\n args: [input],\n workflowExecutionTimeout: options.workflowExecutionTimeout,\n memo: options.memo,\n // searchAttributes requires specific types, omit for now if not properly typed\n });\n\n return this.wrapHandle<TOutput>(handle);\n }\n\n /**\n * Get a handle to an existing workflow\n */\n getHandle<TOutput = unknown>(workflowId: string): WorkflowHandle<TOutput> {\n // Create a lazy handle that connects when needed\n return {\n workflowId,\n runId: '', // Will be populated when we fetch\n result: async () => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n return handle.result() as Promise<TOutput>;\n },\n query: async <TResult = unknown>(queryName: string) => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n return handle.query<TResult>(queryName);\n },\n signal: async <TPayload = unknown>(signalName: string, payload: TPayload) => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.signal(signalName, payload);\n },\n cancel: async () => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.cancel();\n },\n terminate: async (reason?: string) => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.terminate(reason);\n },\n };\n }\n\n /**\n * Signal an existing workflow\n */\n async signal<TPayload = unknown>(\n workflowId: string,\n signalName: string,\n payload: TPayload\n ): Promise<void> {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.signal(signalName, payload);\n }\n\n /**\n * Query an existing workflow\n */\n async query<TResult = unknown>(\n workflowId: string,\n queryName: string\n ): Promise<TResult> {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n return handle.query<TResult>(queryName);\n }\n\n /**\n * Wrap a Temporal workflow handle in our interface\n */\n private wrapHandle<TOutput>(\n handle: Awaited<ReturnType<Client['workflow']['start']>>\n ): WorkflowHandle<TOutput> {\n return {\n workflowId: handle.workflowId,\n runId: handle.firstExecutionRunId,\n result: () => handle.result() as Promise<TOutput>,\n query: <TResult = unknown>(queryName: string) =>\n handle.query<TResult>(queryName),\n signal: <TPayload = unknown>(signalName: string, payload: TPayload) =>\n handle.signal(signalName, payload),\n cancel: async () => {\n await handle.cancel();\n },\n terminate: async (reason?: string) => {\n await handle.terminate(reason);\n },\n };\n }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create a Temporal Functions client\n *\n * @example\n * ```typescript\n * import { tfn } from 'temporal-functions/client';\n *\n * const client = tfn.client({\n * temporal: {\n * address: 'localhost:7233',\n * namespace: 'default',\n * },\n * taskQueue: 'my-queue',\n * });\n *\n * const result = await client.invoke(myWorkflow, { data: 'hello' });\n * ```\n */\nfunction createClient(config: ClientConfig): TFNClient {\n return new TemporalFunctionsClient(config);\n}\n\n// =============================================================================\n// Export\n// =============================================================================\n\nexport const tfn = {\n client: createClient,\n};\n\nexport { createClient };\nexport type { ClientConfig, TFNClient, WorkflowHandle, StartWorkflowOptions };\nexport default tfn;\n"]}
@@ -0,0 +1,162 @@
1
+ import { Connection, Client } from '@temporalio/client';
2
+
3
+ // src/client/index.ts
4
+ var TemporalFunctionsClient = class {
5
+ client = null;
6
+ config;
7
+ connectionPromise = null;
8
+ constructor(config) {
9
+ this.config = {
10
+ ...config,
11
+ temporal: {
12
+ namespace: "default",
13
+ ...config.temporal
14
+ },
15
+ taskQueue: config.taskQueue || "default"
16
+ };
17
+ }
18
+ /**
19
+ * Lazily connect to Temporal
20
+ */
21
+ async getClient() {
22
+ if (this.client) {
23
+ return this.client;
24
+ }
25
+ if (this.connectionPromise) {
26
+ return this.connectionPromise;
27
+ }
28
+ this.connectionPromise = (async () => {
29
+ const connection = await Connection.connect({
30
+ address: this.config.temporal.address,
31
+ tls: this.config.temporal.tls ? {
32
+ clientCertPair: this.config.temporal.tls.clientCertPath ? {
33
+ crt: await import('fs').then(
34
+ (fs) => fs.promises.readFile(this.config.temporal.tls.clientCertPath)
35
+ ),
36
+ key: await import('fs').then(
37
+ (fs) => fs.promises.readFile(this.config.temporal.tls.clientKeyPath)
38
+ )
39
+ } : void 0
40
+ } : void 0
41
+ });
42
+ this.client = new Client({
43
+ connection,
44
+ namespace: this.config.temporal.namespace
45
+ });
46
+ return this.client;
47
+ })();
48
+ return this.connectionPromise;
49
+ }
50
+ /**
51
+ * Generate a workflow ID if not provided
52
+ */
53
+ generateWorkflowId(workflowName) {
54
+ const timestamp = Date.now();
55
+ const random = Math.random().toString(36).substring(2, 8);
56
+ return `${workflowName}-${timestamp}-${random}`;
57
+ }
58
+ /**
59
+ * Start a workflow and wait for the result
60
+ */
61
+ async invoke(workflow, input, options = {}) {
62
+ const handle = await this.start(workflow, input, options);
63
+ return handle.result();
64
+ }
65
+ /**
66
+ * Start a workflow without waiting (fire and forget)
67
+ */
68
+ async start(workflow, input, options = {}) {
69
+ const client = await this.getClient();
70
+ const workflowId = options.workflowId || this.generateWorkflowId(workflow.name);
71
+ const taskQueue = options.taskQueue || workflow.options.taskQueue || this.config.taskQueue || "default";
72
+ const handle = await client.workflow.start(workflow.name, {
73
+ workflowId,
74
+ taskQueue,
75
+ args: [input],
76
+ workflowExecutionTimeout: options.workflowExecutionTimeout,
77
+ memo: options.memo
78
+ // searchAttributes requires specific types, omit for now if not properly typed
79
+ });
80
+ return this.wrapHandle(handle);
81
+ }
82
+ /**
83
+ * Get a handle to an existing workflow
84
+ */
85
+ getHandle(workflowId) {
86
+ return {
87
+ workflowId,
88
+ runId: "",
89
+ // Will be populated when we fetch
90
+ result: async () => {
91
+ const client = await this.getClient();
92
+ const handle = client.workflow.getHandle(workflowId);
93
+ return handle.result();
94
+ },
95
+ query: async (queryName) => {
96
+ const client = await this.getClient();
97
+ const handle = client.workflow.getHandle(workflowId);
98
+ return handle.query(queryName);
99
+ },
100
+ signal: async (signalName, payload) => {
101
+ const client = await this.getClient();
102
+ const handle = client.workflow.getHandle(workflowId);
103
+ await handle.signal(signalName, payload);
104
+ },
105
+ cancel: async () => {
106
+ const client = await this.getClient();
107
+ const handle = client.workflow.getHandle(workflowId);
108
+ await handle.cancel();
109
+ },
110
+ terminate: async (reason) => {
111
+ const client = await this.getClient();
112
+ const handle = client.workflow.getHandle(workflowId);
113
+ await handle.terminate(reason);
114
+ }
115
+ };
116
+ }
117
+ /**
118
+ * Signal an existing workflow
119
+ */
120
+ async signal(workflowId, signalName, payload) {
121
+ const client = await this.getClient();
122
+ const handle = client.workflow.getHandle(workflowId);
123
+ await handle.signal(signalName, payload);
124
+ }
125
+ /**
126
+ * Query an existing workflow
127
+ */
128
+ async query(workflowId, queryName) {
129
+ const client = await this.getClient();
130
+ const handle = client.workflow.getHandle(workflowId);
131
+ return handle.query(queryName);
132
+ }
133
+ /**
134
+ * Wrap a Temporal workflow handle in our interface
135
+ */
136
+ wrapHandle(handle) {
137
+ return {
138
+ workflowId: handle.workflowId,
139
+ runId: handle.firstExecutionRunId,
140
+ result: () => handle.result(),
141
+ query: (queryName) => handle.query(queryName),
142
+ signal: (signalName, payload) => handle.signal(signalName, payload),
143
+ cancel: async () => {
144
+ await handle.cancel();
145
+ },
146
+ terminate: async (reason) => {
147
+ await handle.terminate(reason);
148
+ }
149
+ };
150
+ }
151
+ };
152
+ function createClient(config) {
153
+ return new TemporalFunctionsClient(config);
154
+ }
155
+ var tfn = {
156
+ client: createClient
157
+ };
158
+ var client_default = tfn;
159
+
160
+ export { createClient, client_default as default, tfn };
161
+ //# sourceMappingURL=index.mjs.map
162
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Temporal Functions - Client Package\n *\n * Lightweight client for triggering workflows.\n * Import from 'temporal-functions/client'.\n */\n\nimport { Client, Connection } from '@temporalio/client';\nimport type {\n ClientConfig,\n WorkflowDef,\n StartWorkflowOptions,\n WorkflowHandle,\n TFNClient,\n} from '../types.js';\n\n// =============================================================================\n// Client Implementation\n// =============================================================================\n\nclass TemporalFunctionsClient implements TFNClient {\n private client: Client | null = null;\n private config: ClientConfig;\n private connectionPromise: Promise<Client> | null = null;\n\n constructor(config: ClientConfig) {\n this.config = {\n ...config,\n temporal: {\n namespace: 'default',\n ...config.temporal,\n },\n taskQueue: config.taskQueue || 'default',\n };\n }\n\n /**\n * Lazily connect to Temporal\n */\n private async getClient(): Promise<Client> {\n if (this.client) {\n return this.client;\n }\n\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n this.connectionPromise = (async () => {\n const connection = await Connection.connect({\n address: this.config.temporal.address,\n tls: this.config.temporal.tls\n ? {\n clientCertPair: this.config.temporal.tls.clientCertPath\n ? {\n crt: await import('fs').then((fs) =>\n fs.promises.readFile(this.config.temporal.tls!.clientCertPath!)\n ),\n key: await import('fs').then((fs) =>\n fs.promises.readFile(this.config.temporal.tls!.clientKeyPath!)\n ),\n }\n : undefined,\n }\n : undefined,\n });\n\n this.client = new Client({\n connection,\n namespace: this.config.temporal.namespace,\n });\n\n return this.client;\n })();\n\n return this.connectionPromise;\n }\n\n /**\n * Generate a workflow ID if not provided\n */\n private generateWorkflowId(workflowName: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 8);\n return `${workflowName}-${timestamp}-${random}`;\n }\n\n /**\n * Start a workflow and wait for the result\n */\n async invoke<TInput, TOutput>(\n workflow: WorkflowDef<TInput, TOutput>,\n input: TInput,\n options: StartWorkflowOptions = {}\n ): Promise<TOutput> {\n const handle = await this.start(workflow, input, options);\n return handle.result();\n }\n\n /**\n * Start a workflow without waiting (fire and forget)\n */\n async start<TInput, TOutput>(\n workflow: WorkflowDef<TInput, TOutput>,\n input: TInput,\n options: StartWorkflowOptions = {}\n ): Promise<WorkflowHandle<TOutput>> {\n const client = await this.getClient();\n\n const workflowId = options.workflowId || this.generateWorkflowId(workflow.name);\n const taskQueue = options.taskQueue || workflow.options.taskQueue || this.config.taskQueue || 'default';\n\n const handle = await client.workflow.start(workflow.name, {\n workflowId,\n taskQueue,\n args: [input],\n workflowExecutionTimeout: options.workflowExecutionTimeout,\n memo: options.memo,\n // searchAttributes requires specific types, omit for now if not properly typed\n });\n\n return this.wrapHandle<TOutput>(handle);\n }\n\n /**\n * Get a handle to an existing workflow\n */\n getHandle<TOutput = unknown>(workflowId: string): WorkflowHandle<TOutput> {\n // Create a lazy handle that connects when needed\n return {\n workflowId,\n runId: '', // Will be populated when we fetch\n result: async () => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n return handle.result() as Promise<TOutput>;\n },\n query: async <TResult = unknown>(queryName: string) => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n return handle.query<TResult>(queryName);\n },\n signal: async <TPayload = unknown>(signalName: string, payload: TPayload) => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.signal(signalName, payload);\n },\n cancel: async () => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.cancel();\n },\n terminate: async (reason?: string) => {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.terminate(reason);\n },\n };\n }\n\n /**\n * Signal an existing workflow\n */\n async signal<TPayload = unknown>(\n workflowId: string,\n signalName: string,\n payload: TPayload\n ): Promise<void> {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n await handle.signal(signalName, payload);\n }\n\n /**\n * Query an existing workflow\n */\n async query<TResult = unknown>(\n workflowId: string,\n queryName: string\n ): Promise<TResult> {\n const client = await this.getClient();\n const handle = client.workflow.getHandle(workflowId);\n return handle.query<TResult>(queryName);\n }\n\n /**\n * Wrap a Temporal workflow handle in our interface\n */\n private wrapHandle<TOutput>(\n handle: Awaited<ReturnType<Client['workflow']['start']>>\n ): WorkflowHandle<TOutput> {\n return {\n workflowId: handle.workflowId,\n runId: handle.firstExecutionRunId,\n result: () => handle.result() as Promise<TOutput>,\n query: <TResult = unknown>(queryName: string) =>\n handle.query<TResult>(queryName),\n signal: <TPayload = unknown>(signalName: string, payload: TPayload) =>\n handle.signal(signalName, payload),\n cancel: async () => {\n await handle.cancel();\n },\n terminate: async (reason?: string) => {\n await handle.terminate(reason);\n },\n };\n }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create a Temporal Functions client\n *\n * @example\n * ```typescript\n * import { tfn } from 'temporal-functions/client';\n *\n * const client = tfn.client({\n * temporal: {\n * address: 'localhost:7233',\n * namespace: 'default',\n * },\n * taskQueue: 'my-queue',\n * });\n *\n * const result = await client.invoke(myWorkflow, { data: 'hello' });\n * ```\n */\nfunction createClient(config: ClientConfig): TFNClient {\n return new TemporalFunctionsClient(config);\n}\n\n// =============================================================================\n// Export\n// =============================================================================\n\nexport const tfn = {\n client: createClient,\n};\n\nexport { createClient };\nexport type { ClientConfig, TFNClient, WorkflowHandle, StartWorkflowOptions };\nexport default tfn;\n"]}