@executor-js/cli 0.1.0 → 0.2.2

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/dist/index.js CHANGED
@@ -3,775 +3,12 @@
3
3
  // src/index.ts
4
4
  import { Command as Command2 } from "commander";
5
5
 
6
- // src/commands/generate.ts
7
- import { existsSync as existsSync3 } from "fs";
6
+ // src/commands/schema.ts
7
+ import { existsSync as existsSync2 } from "fs";
8
8
  import fs from "fs/promises";
9
9
  import path2 from "path";
10
10
  import { Command } from "commander";
11
-
12
- // ../sdk/src/index.ts
13
- import { Context as Context2, Effect as Effect14, Layer, Schema as Schema14, Data as Data6, Option as Option2 } from "effect";
14
- import {
15
- HttpApi,
16
- HttpApiBuilder,
17
- HttpApiClient,
18
- HttpApiEndpoint,
19
- HttpApiGroup,
20
- HttpApiMiddleware,
21
- HttpApiSchema
22
- } from "effect/unstable/httpapi";
23
-
24
- // ../storage-core/src/factory.ts
25
- import { Effect } from "effect";
26
-
27
- // ../storage-core/src/errors.ts
28
- import { Data } from "effect";
29
- var StorageError = class extends Data.TaggedError("StorageError") {
30
- };
31
- var UniqueViolationError = class extends Data.TaggedError(
32
- "UniqueViolationError"
33
- ) {
34
- };
35
-
36
- // ../sdk/src/ids.ts
37
- import { Schema } from "effect";
38
- var ScopeId = Schema.String.pipe(Schema.brand("ScopeId"));
39
- var ToolId = Schema.String.pipe(Schema.brand("ToolId"));
40
- var SecretId = Schema.String.pipe(Schema.brand("SecretId"));
41
- var PolicyId = Schema.String.pipe(Schema.brand("PolicyId"));
42
- var ConnectionId = Schema.String.pipe(Schema.brand("ConnectionId"));
43
-
44
- // ../sdk/src/scope.ts
45
- import { Schema as Schema2 } from "effect";
46
- var Scope = class extends Schema2.Class("Scope")({
47
- id: ScopeId,
48
- name: Schema2.String,
49
- createdAt: Schema2.Date
50
- }) {
51
- };
52
-
53
- // ../sdk/src/errors.ts
54
- import { Data as Data2, Schema as Schema3 } from "effect";
55
- var ToolNotFoundError = class extends Schema3.TaggedErrorClass()(
56
- "ToolNotFoundError",
57
- { toolId: ToolId }
58
- ) {
59
- };
60
- var ToolInvocationError = class extends Data2.TaggedError("ToolInvocationError") {
61
- };
62
- var PluginNotLoadedError = class extends Schema3.TaggedErrorClass()(
63
- "PluginNotLoadedError",
64
- {
65
- pluginId: Schema3.String,
66
- toolId: ToolId
67
- }
68
- ) {
69
- };
70
- var NoHandlerError = class extends Schema3.TaggedErrorClass()(
71
- "NoHandlerError",
72
- {
73
- toolId: ToolId,
74
- pluginId: Schema3.String
75
- }
76
- ) {
77
- };
78
- var ToolBlockedError = class extends Schema3.TaggedErrorClass()(
79
- "ToolBlockedError",
80
- {
81
- toolId: ToolId,
82
- pattern: Schema3.String
83
- }
84
- ) {
85
- };
86
- var SourceNotFoundError = class extends Schema3.TaggedErrorClass()(
87
- "SourceNotFoundError",
88
- { sourceId: Schema3.String }
89
- ) {
90
- };
91
- var SourceRemovalNotAllowedError = class extends Schema3.TaggedErrorClass()(
92
- "SourceRemovalNotAllowedError",
93
- { sourceId: Schema3.String }
94
- ) {
95
- };
96
- var SecretNotFoundError = class extends Schema3.TaggedErrorClass()(
97
- "SecretNotFoundError",
98
- { secretId: SecretId }
99
- ) {
100
- };
101
- var SecretResolutionError = class extends Schema3.TaggedErrorClass()(
102
- "SecretResolutionError",
103
- {
104
- secretId: SecretId,
105
- message: Schema3.String
106
- }
107
- ) {
108
- };
109
- var SecretOwnedByConnectionError = class extends Schema3.TaggedErrorClass()(
110
- "SecretOwnedByConnectionError",
111
- {
112
- secretId: SecretId,
113
- connectionId: ConnectionId
114
- }
115
- ) {
116
- };
117
- var ConnectionNotFoundError = class extends Schema3.TaggedErrorClass()(
118
- "ConnectionNotFoundError",
119
- { connectionId: ConnectionId }
120
- ) {
121
- };
122
- var ConnectionProviderNotRegisteredError = class extends Schema3.TaggedErrorClass()(
123
- "ConnectionProviderNotRegisteredError",
124
- {
125
- provider: Schema3.String,
126
- connectionId: Schema3.optional(ConnectionId)
127
- }
128
- ) {
129
- };
130
- var ConnectionRefreshNotSupportedError = class extends Schema3.TaggedErrorClass()(
131
- "ConnectionRefreshNotSupportedError",
132
- {
133
- connectionId: ConnectionId,
134
- provider: Schema3.String
135
- }
136
- ) {
137
- };
138
- var ConnectionReauthRequiredError = class extends Schema3.TaggedErrorClass()(
139
- "ConnectionReauthRequiredError",
140
- {
141
- connectionId: ConnectionId,
142
- provider: Schema3.String,
143
- message: Schema3.String
144
- }
145
- ) {
146
- };
147
-
148
- // ../sdk/src/types.ts
149
- import { Schema as Schema4 } from "effect";
150
- var ToolSchema = class extends Schema4.Class("ToolSchema")({
151
- id: ToolId,
152
- name: Schema4.optional(Schema4.String),
153
- description: Schema4.optional(Schema4.String),
154
- inputSchema: Schema4.optional(Schema4.Unknown),
155
- outputSchema: Schema4.optional(Schema4.Unknown),
156
- inputTypeScript: Schema4.optional(Schema4.String),
157
- outputTypeScript: Schema4.optional(Schema4.String),
158
- typeScriptDefinitions: Schema4.optional(
159
- Schema4.Record(Schema4.String, Schema4.String)
160
- )
161
- }) {
162
- };
163
- var SourceDetectionResult = class extends Schema4.Class(
164
- "SourceDetectionResult"
165
- )({
166
- /** Plugin id that recognized the URL (e.g. "openapi", "graphql"). */
167
- kind: Schema4.String,
168
- /** Confidence tier — UI uses this to pick a winner when multiple
169
- * plugins claim a URL. */
170
- confidence: Schema4.Literals(["high", "medium", "low"]),
171
- /** The (possibly normalized) endpoint the plugin will use. */
172
- endpoint: Schema4.String,
173
- /** Human-readable name suggestion, typically derived from spec title
174
- * or URL hostname. */
175
- name: Schema4.String,
176
- /** Namespace suggestion — the plugin's recommendation for the source
177
- * id. UI may override. */
178
- namespace: Schema4.String
179
- }) {
180
- };
181
-
182
- // ../sdk/src/core-schema.ts
183
- var coreSchema = {
184
- source: {
185
- fields: {
186
- id: { type: "string", required: true },
187
- scope_id: { type: "string", required: true, index: true },
188
- plugin_id: { type: "string", required: true, index: true },
189
- kind: { type: "string", required: true },
190
- name: { type: "string", required: true },
191
- url: { type: "string", required: false },
192
- can_remove: {
193
- type: "boolean",
194
- required: true,
195
- defaultValue: true
196
- },
197
- can_refresh: {
198
- type: "boolean",
199
- required: true,
200
- defaultValue: false
201
- },
202
- can_edit: {
203
- type: "boolean",
204
- required: true,
205
- defaultValue: false
206
- },
207
- created_at: { type: "date", required: true },
208
- updated_at: { type: "date", required: true }
209
- }
210
- },
211
- tool: {
212
- fields: {
213
- id: { type: "string", required: true },
214
- scope_id: { type: "string", required: true, index: true },
215
- source_id: { type: "string", required: true, index: true },
216
- plugin_id: { type: "string", required: true, index: true },
217
- name: { type: "string", required: true },
218
- description: { type: "string", required: true },
219
- input_schema: { type: "json", required: false },
220
- output_schema: { type: "json", required: false },
221
- // NOTE: tool annotations (requiresApproval, approvalDescription,
222
- // mayElicit) are NOT stored on this row. They're derived at read
223
- // time from plugin-owned data via `plugin.resolveAnnotations`,
224
- // because the source of truth already lives in each plugin's own
225
- // storage (openapi's OperationBinding, etc.) and duplicating it
226
- // here would just mean bulk-rewriting rows every time the
227
- // derivation logic changes.
228
- created_at: { type: "date", required: true },
229
- updated_at: { type: "date", required: true }
230
- }
231
- },
232
- // Shared JSON-schema `$defs` stored once per source. Tool input/output
233
- // schemas carry `$ref: "#/$defs/X"` pointers; the read path attaches
234
- // matching defs under `$defs` before returning. Keyed by synthetic id
235
- // `${source_id}.${name}` so cleanup on source removal is a single
236
- // deleteMany by source_id.
237
- definition: {
238
- fields: {
239
- id: { type: "string", required: true },
240
- scope_id: { type: "string", required: true, index: true },
241
- source_id: { type: "string", required: true, index: true },
242
- plugin_id: { type: "string", required: true, index: true },
243
- name: { type: "string", required: true },
244
- schema: { type: "json", required: true },
245
- created_at: { type: "date", required: true }
246
- }
247
- },
248
- // Secrets live in the core surface as metadata (id, display name,
249
- // provider key). Actual values never touch this table — they live in
250
- // the secret provider (keychain, 1password, file, etc.) and are
251
- // resolved on demand via `ctx.secrets.get(id)`.
252
- //
253
- // `owned_by_connection_id` ties the row to a connection. Connection-
254
- // owned secrets are plumbing, not user-facing values: `ctx.secrets.list`
255
- // filters them out (the user sees the Connection instead), and
256
- // `ctx.secrets.remove` refuses to delete them (Connection.remove is
257
- // the single owner of the lifecycle). The FK is nullable so existing
258
- // "bare" secrets (API keys entered by the user, pre-connection OAuth
259
- // rows during migration) remain visible and removable unchanged.
260
- secret: {
261
- fields: {
262
- id: { type: "string", required: true },
263
- scope_id: { type: "string", required: true, index: true },
264
- name: { type: "string", required: true },
265
- provider: { type: "string", required: true, index: true },
266
- owned_by_connection_id: {
267
- type: "string",
268
- required: false,
269
- index: true
270
- },
271
- created_at: { type: "date", required: true }
272
- }
273
- },
274
- // Connections — sign-in state for one identity against one remote
275
- // provider. A Connection owns one or more `secret` rows (access +
276
- // refresh tokens, etc.) via `secret.owned_by_connection_id`, and the
277
- // SDK exposes `ctx.connections.accessToken(id)` which transparently
278
- // refreshes the backing secrets when they're near expiry. Plugins
279
- // contribute refresh behavior via `plugin.connectionProviders[].refresh`
280
- // keyed by `provider`, same pattern as `secretProviders`.
281
- //
282
- // `provider_state` is plugin-owned opaque JSON — token endpoint URL,
283
- // scopes, issuer, auth-server metadata — whatever the provider's
284
- // refresh handler needs to re-hit the token endpoint. It's NOT
285
- // sensitive (all secrets go through the provider-backed secret rows);
286
- // it's just enough metadata to drive a refresh without re-running
287
- // discovery.
288
- connection: {
289
- fields: {
290
- id: { type: "string", required: true },
291
- scope_id: { type: "string", required: true, index: true },
292
- /** Routing key into `plugin.connectionProviders`. Typical shape
293
- * is `${pluginId}:${kind}` (e.g. `openapi:oauth2`, `mcp:oauth2`,
294
- * `google-discovery:google`). Mirrors `secret.provider`. */
295
- provider: { type: "string", required: true, index: true },
296
- /** Display label shown in the Connections UI. Usually the account
297
- * email / handle / org name the user signed in as. */
298
- identity_label: { type: "string", required: false },
299
- /** Stable id of the access-token secret. Always present. */
300
- access_token_secret_id: { type: "string", required: true },
301
- /** Stable id of the refresh-token secret. Null for flows that
302
- * don't mint a refresh token (client_credentials, etc.). */
303
- refresh_token_secret_id: { type: "string", required: false },
304
- /** Epoch ms when the access token expires. Null if the provider
305
- * didn't declare an expiry. Used as the refresh trigger. Stored as
306
- * `bigint` because `Date.now()` overflows int32. */
307
- expires_at: { type: "number", required: false, bigint: true },
308
- /** Scope string as returned by the token endpoint. */
309
- scope: { type: "string", required: false },
310
- /** Opaque plugin-owned JSON — token endpoint URL, scopes list,
311
- * discovery hints, etc. Never sensitive. */
312
- provider_state: { type: "json", required: false },
313
- created_at: { type: "date", required: true },
314
- updated_at: { type: "date", required: true }
315
- }
316
- },
317
- // Pending OAuth authorization rows shared by every OAuth-capable plugin.
318
- // Rows are short-lived and deleted after completion/cancel; the resulting
319
- // `connection` row is the durable sign-in state.
320
- oauth2_session: {
321
- fields: {
322
- id: { type: "string", required: true },
323
- scope_id: { type: "string", required: true, index: true },
324
- plugin_id: { type: "string", required: true, index: true },
325
- strategy: { type: "string", required: true },
326
- connection_id: { type: "string", required: true, index: true },
327
- token_scope: { type: "string", required: true },
328
- redirect_url: { type: "string", required: true },
329
- payload: { type: "json", required: true },
330
- expires_at: { type: "number", required: true, bigint: true },
331
- created_at: { type: "date", required: true }
332
- }
333
- },
334
- // User-authored overrides for tool permissions. Each row is one rule:
335
- // a glob-ish pattern + an action (approve / require_approval / block).
336
- // Resolution walks the scope stack innermost-first, then `position`
337
- // ascending within each scope; first match wins. Plugin-derived
338
- // annotations from `resolveAnnotations` apply only when no rule
339
- // matches.
340
- //
341
- // Pattern grammar (v1):
342
- // - `*` every tool id (universal)
343
- // - `vercel.dns.create` exact tool id
344
- // - `vercel.dns.*` any tool whose id starts with `vercel.dns.`
345
- // - `vercel.*` plugin-wide
346
- // No `**`, no brace expansion, no leading-`*` prefixes (`*foo`, `*.foo`).
347
- tool_policy: {
348
- fields: {
349
- id: { type: "string", required: true },
350
- scope_id: { type: "string", required: true, index: true },
351
- pattern: { type: "string", required: true },
352
- /** "approve" | "require_approval" | "block". */
353
- action: { type: "string", required: true },
354
- /** Fractional-indexing key (Jira lexorank style). Lower lex order =
355
- * higher precedence. New rules default to a key generated above
356
- * the current minimum. Strings instead of numbers so we can
357
- * always lengthen the key to insert between two adjacent rows
358
- * without precision loss; see `fractional-indexing` in
359
- * `policies.ts`. */
360
- position: { type: "string", required: true, index: true },
361
- created_at: { type: "date", required: true },
362
- updated_at: { type: "date", required: true }
363
- }
364
- }
365
- };
366
-
367
- // ../sdk/src/policies.ts
368
- import { Schema as Schema5 } from "effect";
369
- var ToolPolicyActionSchema = Schema5.Literals([
370
- "approve",
371
- "require_approval",
372
- "block"
373
- ]);
374
-
375
- // ../sdk/src/secrets.ts
376
- import { Schema as Schema6 } from "effect";
377
- var SecretRef = class extends Schema6.Class("SecretRef")({
378
- id: SecretId,
379
- scopeId: ScopeId,
380
- /** Human-readable label (e.g. "Cloudflare API Token") */
381
- name: Schema6.String,
382
- /** Which provider holds the value */
383
- provider: Schema6.String,
384
- createdAt: Schema6.Date
385
- }) {
386
- };
387
- var SetSecretInput = class extends Schema6.Class(
388
- "SetSecretInput"
389
- )({
390
- id: SecretId,
391
- /** Scope id to own this secret. Must be one of the executor's
392
- * configured scopes. */
393
- scope: ScopeId,
394
- /** Display name shown in secret-list UI. */
395
- name: Schema6.String,
396
- /** The secret value itself — never persisted outside the provider. */
397
- value: Schema6.String,
398
- /** Optional provider routing. If unset the executor picks the first
399
- * writable provider in registration order. */
400
- provider: Schema6.optional(Schema6.String)
401
- }) {
402
- };
403
-
404
- // ../sdk/src/secret-backed-value.ts
405
- import { Effect as Effect3, Schema as Schema7 } from "effect";
406
- var SecretBackedValue = Schema7.Union([
407
- Schema7.String,
408
- Schema7.Struct({
409
- secretId: Schema7.String,
410
- prefix: Schema7.optional(Schema7.String)
411
- })
412
- ]);
413
- var SecretBackedMap = Schema7.Record(Schema7.String, SecretBackedValue);
414
-
415
- // ../sdk/src/connections.ts
416
- import { Data as Data3, Schema as Schema8 } from "effect";
417
- var ConnectionProviderState = Schema8.Record(Schema8.String, Schema8.Unknown);
418
- var ConnectionRef = class extends Schema8.Class("ConnectionRef")({
419
- id: ConnectionId,
420
- scopeId: ScopeId,
421
- provider: Schema8.String,
422
- identityLabel: Schema8.NullOr(Schema8.String),
423
- accessTokenSecretId: SecretId,
424
- refreshTokenSecretId: Schema8.NullOr(SecretId),
425
- /** Epoch ms when the access token expires; null if not declared. */
426
- expiresAt: Schema8.NullOr(Schema8.Number),
427
- /** OAuth-style scope string as returned by the token endpoint. Named
428
- * `oauthScope` to avoid collision with the executor scope id. */
429
- oauthScope: Schema8.NullOr(Schema8.String),
430
- providerState: Schema8.NullOr(ConnectionProviderState),
431
- createdAt: Schema8.Date,
432
- updatedAt: Schema8.Date
433
- }) {
434
- };
435
- var TokenMaterial = class extends Schema8.Class("TokenMaterial")({
436
- /** Target secret id. Plugins typically derive this from the source id
437
- * + a stable suffix (e.g. `${sourceId}.access_token`). */
438
- secretId: SecretId,
439
- /** Display name stamped on the secret row. Only visible to code — the
440
- * Connections UI hides connection-owned secrets. */
441
- name: Schema8.String,
442
- value: Schema8.String
443
- }) {
444
- };
445
- var CreateConnectionInput = class extends Schema8.Class(
446
- "CreateConnectionInput"
447
- )({
448
- id: ConnectionId,
449
- /** Executor scope id that will own this connection + its backing
450
- * secrets. This is the sharing boundary: a user scope is personal,
451
- * an org/workspace scope is shared with descendants. */
452
- scope: ScopeId,
453
- provider: Schema8.String,
454
- identityLabel: Schema8.NullOr(Schema8.String),
455
- accessToken: TokenMaterial,
456
- refreshToken: Schema8.NullOr(TokenMaterial),
457
- expiresAt: Schema8.NullOr(Schema8.Number),
458
- /** OAuth-style scope string. Distinct from the executor scope above. */
459
- oauthScope: Schema8.NullOr(Schema8.String),
460
- providerState: Schema8.NullOr(ConnectionProviderState)
461
- }) {
462
- };
463
- var ConnectionRefreshError = class extends Data3.TaggedError(
464
- "ConnectionRefreshError"
465
- ) {
466
- };
467
- var UpdateConnectionTokensInput = class extends Schema8.Class(
468
- "UpdateConnectionTokensInput"
469
- )({
470
- id: ConnectionId,
471
- accessToken: Schema8.String,
472
- refreshToken: Schema8.optional(Schema8.NullOr(Schema8.String)),
473
- expiresAt: Schema8.optional(Schema8.NullOr(Schema8.Number)),
474
- oauthScope: Schema8.optional(Schema8.NullOr(Schema8.String)),
475
- providerState: Schema8.optional(Schema8.NullOr(ConnectionProviderState)),
476
- identityLabel: Schema8.optional(Schema8.NullOr(Schema8.String))
477
- }) {
478
- };
479
-
480
- // ../sdk/src/elicitation.ts
481
- import { Schema as Schema9 } from "effect";
482
- var FormElicitation = class extends Schema9.TaggedClass()("FormElicitation", {
483
- message: Schema9.String,
484
- /** JSON Schema describing the fields to collect */
485
- requestedSchema: Schema9.Record(Schema9.String, Schema9.Unknown)
486
- }) {
487
- };
488
- var UrlElicitation = class extends Schema9.TaggedClass()("UrlElicitation", {
489
- message: Schema9.String,
490
- url: Schema9.String,
491
- /** Unique ID so the host can correlate the callback */
492
- elicitationId: Schema9.String
493
- }) {
494
- };
495
- var ElicitationAction = Schema9.Literals(["accept", "decline", "cancel"]);
496
- var ElicitationResponse = class extends Schema9.Class("ElicitationResponse")({
497
- action: ElicitationAction,
498
- /** Present when action is "accept" — the data the user provided */
499
- content: Schema9.optional(Schema9.Record(Schema9.String, Schema9.Unknown))
500
- }) {
501
- };
502
- var ElicitationDeclinedError = class extends Schema9.TaggedErrorClass()(
503
- "ElicitationDeclinedError",
504
- {
505
- toolId: ToolId,
506
- action: Schema9.Literals(["decline", "cancel"])
507
- }
508
- ) {
509
- };
510
-
511
- // ../sdk/src/blob.ts
512
- import { Effect as Effect6 } from "effect";
513
-
514
- // ../sdk/src/oauth.ts
515
- import { Effect as Effect7, Schema as Schema10 } from "effect";
516
- var OAuthDynamicDcrStrategy = Schema10.Struct({
517
- kind: Schema10.Literal("dynamic-dcr"),
518
- /** Scopes to request. Defaults to whatever `scopes_supported`
519
- * advertises; caller can narrow or extend. */
520
- scopes: Schema10.optional(Schema10.Array(Schema10.String))
521
- });
522
- var OAuthAuthorizationCodeStrategy = Schema10.Struct({
523
- kind: Schema10.Literal("authorization-code"),
524
- authorizationEndpoint: Schema10.String,
525
- tokenEndpoint: Schema10.String,
526
- /** Expected authorization-server issuer for ID token validation. Some
527
- * providers use a token endpoint host that differs from issuer, or a
528
- * path-scoped issuer such as Okta custom authorization servers. */
529
- issuerUrl: Schema10.optional(Schema10.NullOr(Schema10.String)),
530
- /** Secret id holding the `client_id`. Using a secret row rather than
531
- * an inline string so the value lives at the scope where the caller
532
- * configured it and shadowing behaves consistently. */
533
- clientIdSecretId: Schema10.String,
534
- /** Secret id for `client_secret`. Null for public clients using
535
- * PKCE without a confidential secret. */
536
- clientSecretSecretId: Schema10.NullOr(Schema10.String),
537
- scopes: Schema10.Array(Schema10.String),
538
- /** Separator between scopes. RFC 6749 says space; some providers
539
- * (GitHub classic) use comma. */
540
- scopeSeparator: Schema10.optional(Schema10.String),
541
- /** Provider-specific params injected at authorization URL build time
542
- * (Google's `access_type=offline`, `prompt=consent`, ...). */
543
- extraAuthorizationParams: Schema10.optional(
544
- Schema10.Record(Schema10.String, Schema10.String)
545
- ),
546
- /** `"body"` (default) sends client creds in the form body; `"basic"`
547
- * uses HTTP Basic auth. Stripe-style servers require basic. */
548
- clientAuth: Schema10.optional(Schema10.Literals(["body", "basic"]))
549
- });
550
- var OAuthClientCredentialsStrategy = Schema10.Struct({
551
- kind: Schema10.Literal("client-credentials"),
552
- tokenEndpoint: Schema10.String,
553
- clientIdSecretId: Schema10.String,
554
- clientSecretSecretId: Schema10.String,
555
- scopes: Schema10.optional(Schema10.Array(Schema10.String)),
556
- scopeSeparator: Schema10.optional(Schema10.String),
557
- clientAuth: Schema10.optional(Schema10.Literals(["body", "basic"]))
558
- });
559
- var OAuthStrategy = Schema10.Union([
560
- OAuthDynamicDcrStrategy,
561
- OAuthAuthorizationCodeStrategy,
562
- OAuthClientCredentialsStrategy
563
- ]);
564
- var OAuthProviderState = Schema10.Union([
565
- Schema10.Struct({
566
- kind: Schema10.Literal("dynamic-dcr"),
567
- tokenEndpoint: Schema10.String,
568
- issuerUrl: Schema10.optional(Schema10.NullOr(Schema10.String)),
569
- authorizationServerUrl: Schema10.optional(Schema10.NullOr(Schema10.String)),
570
- authorizationServerMetadataUrl: Schema10.NullOr(Schema10.String),
571
- idTokenSigningAlgValuesSupported: Schema10.optional(
572
- Schema10.Array(Schema10.String)
573
- ),
574
- /** DCR-minted client_id. Embedded inline (not a secret) — DCR
575
- * clients are public-ish by design; the secret part (if the AS
576
- * issued one) is a separate secret row. */
577
- clientId: Schema10.String,
578
- clientSecretSecretId: Schema10.NullOr(Schema10.String),
579
- clientAuth: Schema10.Literals(["body", "basic"]),
580
- scopes: Schema10.Array(Schema10.String).pipe(Schema10.withDecodingDefaultType(Effect7.succeed([]))),
581
- scopeSeparator: Schema10.optional(Schema10.String),
582
- scope: Schema10.NullOr(Schema10.String)
583
- }),
584
- Schema10.Struct({
585
- kind: Schema10.Literal("authorization-code"),
586
- tokenEndpoint: Schema10.String,
587
- issuerUrl: Schema10.optional(Schema10.NullOr(Schema10.String)),
588
- clientIdSecretId: Schema10.String,
589
- clientSecretSecretId: Schema10.NullOr(Schema10.String),
590
- clientAuth: Schema10.Literals(["body", "basic"]),
591
- scopes: Schema10.Array(Schema10.String).pipe(Schema10.withDecodingDefaultType(Effect7.succeed([]))),
592
- scopeSeparator: Schema10.optional(Schema10.String),
593
- scope: Schema10.NullOr(Schema10.String)
594
- }),
595
- Schema10.Struct({
596
- kind: Schema10.Literal("client-credentials"),
597
- tokenEndpoint: Schema10.String,
598
- clientIdSecretId: Schema10.String,
599
- clientSecretSecretId: Schema10.String,
600
- scopes: Schema10.Array(Schema10.String),
601
- scopeSeparator: Schema10.optional(Schema10.String),
602
- clientAuth: Schema10.Literals(["body", "basic"]),
603
- scope: Schema10.NullOr(Schema10.String)
604
- })
605
- ]);
606
- var OAuthProbeError = class extends Schema10.TaggedErrorClass()(
607
- "OAuthProbeError",
608
- {
609
- message: Schema10.String
610
- }
611
- ) {
612
- static annotations = { httpApiStatus: 400 };
613
- };
614
- var OAuthStartError = class extends Schema10.TaggedErrorClass()(
615
- "OAuthStartError",
616
- {
617
- message: Schema10.String
618
- }
619
- ) {
620
- static annotations = { httpApiStatus: 400 };
621
- };
622
- var OAuthCompleteError = class extends Schema10.TaggedErrorClass()(
623
- "OAuthCompleteError",
624
- {
625
- message: Schema10.String,
626
- /** RFC 6749 §5.2 error code, when the token endpoint returned one.
627
- * Callers distinguish terminal failures (`invalid_grant` ⇒
628
- * re-auth required) from transient ones. */
629
- code: Schema10.optional(Schema10.String)
630
- }
631
- ) {
632
- static annotations = { httpApiStatus: 400 };
633
- };
634
- var OAuthSessionNotFoundError = class extends Schema10.TaggedErrorClass()(
635
- "OAuthSessionNotFoundError",
636
- {
637
- sessionId: Schema10.String
638
- }
639
- ) {
640
- static annotations = { httpApiStatus: 404 };
641
- };
642
- var OAUTH2_SESSION_TTL_MS = 15 * 60 * 1e3;
643
-
644
- // ../sdk/src/oauth-helpers.ts
645
- import { Data as Data4, Effect as Effect8 } from "effect";
646
- var OAuth2Error = class extends Data4.TaggedError("OAuth2Error") {
647
- };
648
-
649
- // ../sdk/src/oauth-service.ts
650
- import { Effect as Effect10, Schema as Schema12 } from "effect";
651
-
652
- // ../sdk/src/oauth-discovery.ts
653
- import { Data as Data5, Effect as Effect9, Result, Schema as Schema11 } from "effect";
654
- var OAuthDiscoveryError = class extends Data5.TaggedError(
655
- "OAuthDiscoveryError"
656
- ) {
657
- };
658
- var StringArray = Schema11.Array(Schema11.String);
659
- var OAuthProtectedResourceMetadataSchema = Schema11.Struct({
660
- resource: Schema11.optional(Schema11.String),
661
- authorization_servers: Schema11.optional(StringArray),
662
- scopes_supported: Schema11.optional(StringArray),
663
- bearer_methods_supported: Schema11.optional(StringArray),
664
- resource_documentation: Schema11.optional(Schema11.String)
665
- }).annotate({ identifier: "OAuthProtectedResourceMetadata" });
666
- var OAuthAuthorizationServerMetadataSchema = Schema11.Struct({
667
- issuer: Schema11.String,
668
- authorization_endpoint: Schema11.String,
669
- token_endpoint: Schema11.String,
670
- registration_endpoint: Schema11.optional(Schema11.String),
671
- scopes_supported: Schema11.optional(StringArray),
672
- response_types_supported: Schema11.optional(StringArray),
673
- grant_types_supported: Schema11.optional(StringArray),
674
- code_challenge_methods_supported: Schema11.optional(StringArray),
675
- token_endpoint_auth_methods_supported: Schema11.optional(StringArray),
676
- revocation_endpoint: Schema11.optional(Schema11.String),
677
- introspection_endpoint: Schema11.optional(Schema11.String),
678
- userinfo_endpoint: Schema11.optional(Schema11.String),
679
- id_token_signing_alg_values_supported: Schema11.optional(StringArray)
680
- }).annotate({ identifier: "OAuthAuthorizationServerMetadata" });
681
- var OAuthClientInformationSchema = Schema11.Struct({
682
- client_id: Schema11.String,
683
- client_secret: Schema11.optional(Schema11.String),
684
- client_id_issued_at: Schema11.optional(Schema11.Number),
685
- client_secret_expires_at: Schema11.optional(Schema11.Number),
686
- registration_access_token: Schema11.optional(Schema11.String),
687
- registration_client_uri: Schema11.optional(Schema11.String),
688
- token_endpoint_auth_method: Schema11.optional(Schema11.String),
689
- grant_types: Schema11.optional(StringArray),
690
- response_types: Schema11.optional(StringArray),
691
- redirect_uris: Schema11.optional(StringArray),
692
- client_name: Schema11.optional(Schema11.String),
693
- scope: Schema11.optional(Schema11.String)
694
- }).annotate({ identifier: "OAuthClientInformation" });
695
- var decodeResourceMetadata = Schema11.decodeUnknownEffect(
696
- OAuthProtectedResourceMetadataSchema
697
- );
698
- var decodeAuthServerMetadata = Schema11.decodeUnknownEffect(
699
- OAuthAuthorizationServerMetadataSchema
700
- );
701
- var decodeClientInformation = Schema11.decodeUnknownEffect(
702
- OAuthClientInformationSchema
703
- );
704
- var DcrErrorBody = class extends Data5.TaggedError("DcrErrorBody") {
705
- };
706
- var DcrTransport = class extends Data5.TaggedError("DcrTransport") {
707
- };
708
-
709
- // ../sdk/src/oauth-service.ts
710
- var OAuthAuthorizationServerMetadataJson = Schema12.Record(Schema12.String, Schema12.Unknown);
711
- var OAuthClientInformationJson = Schema12.Record(Schema12.String, Schema12.Unknown);
712
- var DynamicDcrSessionPayload = Schema12.Struct({
713
- kind: Schema12.Literal("dynamic-dcr"),
714
- identityLabel: Schema12.NullOr(Schema12.String),
715
- codeVerifier: Schema12.String,
716
- authorizationServerUrl: Schema12.String,
717
- authorizationServerMetadataUrl: Schema12.String,
718
- authorizationServerMetadata: OAuthAuthorizationServerMetadataJson,
719
- clientInformation: OAuthClientInformationJson,
720
- resourceMetadataUrl: Schema12.NullOr(Schema12.String),
721
- resourceMetadata: Schema12.NullOr(
722
- Schema12.Record(Schema12.String, Schema12.Unknown)
723
- ),
724
- scopes: Schema12.Array(Schema12.String)
725
- });
726
- var AuthorizationCodeSessionPayload = Schema12.Struct({
727
- kind: Schema12.Literal("authorization-code"),
728
- identityLabel: Schema12.NullOr(Schema12.String),
729
- codeVerifier: Schema12.String,
730
- authorizationEndpoint: Schema12.String,
731
- tokenEndpoint: Schema12.String,
732
- issuerUrl: Schema12.NullOr(Schema12.String).pipe(Schema12.withDecodingDefaultType(Effect10.succeed(null))),
733
- clientIdSecretId: Schema12.String,
734
- clientSecretSecretId: Schema12.NullOr(Schema12.String),
735
- scopes: Schema12.Array(Schema12.String),
736
- scopeSeparator: Schema12.optional(Schema12.String),
737
- clientAuth: Schema12.Literals(["body", "basic"])
738
- });
739
- var OAuthSessionPayload = Schema12.Union([
740
- DynamicDcrSessionPayload,
741
- AuthorizationCodeSessionPayload
742
- ]);
743
- var decodeSessionPayload = Schema12.decodeUnknownSync(OAuthSessionPayload);
744
- var encodeSessionPayload = Schema12.encodeSync(OAuthSessionPayload);
745
-
746
- // ../sdk/src/executor.ts
747
- import { Context, Deferred, Effect as Effect12, Option, Result as Result2, Schema as Schema13, Semaphore } from "effect";
748
-
749
- // ../sdk/src/scoped-adapter.ts
750
- import { Effect as Effect11 } from "effect";
751
-
752
- // ../sdk/src/executor.ts
753
- var collectSchemas = (plugins) => {
754
- const merged = { ...coreSchema };
755
- for (const plugin of plugins) {
756
- if (!plugin.schema) continue;
757
- for (const [modelKey, model] of Object.entries(plugin.schema)) {
758
- if (merged[modelKey]) {
759
- throw new Error(
760
- `Duplicate model "${modelKey}" contributed by plugin "${plugin.id}" (reserved by core or another plugin)`
761
- );
762
- }
763
- merged[modelKey] = model;
764
- }
765
- }
766
- return merged;
767
- };
768
- var activeAdapterRef = Context.Reference(
769
- "executor/ActiveAdapter",
770
- { defaultValue: () => null }
771
- );
772
-
773
- // ../storage-core/src/testing/memory.ts
774
- import { Effect as Effect13 } from "effect";
11
+ import { collectTables } from "@executor-js/sdk/core";
775
12
 
776
13
  // src/utils/get-config.ts
777
14
  import { existsSync } from "fs";
@@ -811,339 +48,10 @@ var getConfig = async (opts) => {
811
48
  return config;
812
49
  };
813
50
 
814
- // src/generators/drizzle.ts
815
- import { existsSync as existsSync2 } from "fs";
816
- var getModelName = (key, def) => def.modelName ?? key;
817
- var getType = (name, field, dialect) => {
818
- if (field.references?.field === "id") {
819
- return `text('${name}')`;
820
- }
821
- const type = field.type;
822
- if (typeof type !== "string") {
823
- if (Array.isArray(type) && type.every((x) => typeof x === "string")) {
824
- return {
825
- sqlite: `text({ enum: [${type.map((x) => `'${x}'`).join(", ")}] })`,
826
- pg: `text('${name}', { enum: [${type.map((x) => `'${x}'`).join(", ")}] })`,
827
- mysql: `mysqlEnum([${type.map((x) => `'${x}'`).join(", ")}])`
828
- }[dialect];
829
- }
830
- throw new TypeError(
831
- `Invalid field type for field ${name}`
832
- );
833
- }
834
- const typeMap = {
835
- string: {
836
- sqlite: `text('${name}')`,
837
- pg: `text('${name}')`,
838
- mysql: field.unique ? `varchar('${name}', { length: 255 })` : field.references ? `varchar('${name}', { length: 36 })` : field.sortable ? `varchar('${name}', { length: 255 })` : field.index ? `varchar('${name}', { length: 255 })` : `text('${name}')`
839
- },
840
- boolean: {
841
- sqlite: `integer('${name}', { mode: 'boolean' })`,
842
- pg: `boolean('${name}')`,
843
- mysql: `boolean('${name}')`
844
- },
845
- number: {
846
- sqlite: `integer('${name}')`,
847
- pg: field.bigint ? `bigint('${name}', { mode: 'number' })` : `integer('${name}')`,
848
- mysql: field.bigint ? `bigint('${name}', { mode: 'number' })` : `int('${name}')`
849
- },
850
- date: {
851
- sqlite: `integer('${name}', { mode: 'timestamp_ms' })`,
852
- pg: `timestamp('${name}')`,
853
- mysql: `timestamp('${name}', { fsp: 3 })`
854
- },
855
- "number[]": {
856
- sqlite: `text('${name}', { mode: "json" })`,
857
- pg: field.bigint ? `bigint('${name}', { mode: 'number' }).array()` : `integer('${name}').array()`,
858
- mysql: `text('${name}', { mode: 'json' })`
859
- },
860
- "string[]": {
861
- sqlite: `text('${name}', { mode: "json" })`,
862
- pg: `text('${name}').array()`,
863
- mysql: `text('${name}', { mode: "json" })`
864
- },
865
- json: {
866
- sqlite: `text('${name}', { mode: "json" })`,
867
- pg: `jsonb('${name}')`,
868
- mysql: `json('${name}', { mode: "json" })`
869
- }
870
- };
871
- const dbTypeMap = typeMap[type];
872
- if (!dbTypeMap) {
873
- throw new Error(
874
- `Unsupported field type '${field.type}' for field '${name}'.`
875
- );
876
- }
877
- return dbTypeMap[dialect];
878
- };
879
- var generateDrizzleSchema = async ({
880
- schema,
881
- dialect,
882
- file
883
- }) => {
884
- const filePath = file || "./executor-schema.ts";
885
- const fileExist = existsSync2(filePath);
886
- let code = generateImport({ dialect, schema });
887
- for (const [tableKey, tableDef] of Object.entries(schema)) {
888
- const modelName = getModelName(tableKey, tableDef);
889
- const fields = tableDef.fields;
890
- const hasScopeId = Object.prototype.hasOwnProperty.call(fields, "scope_id");
891
- const id = hasScopeId ? `text('id').notNull()` : `text('id').primaryKey()`;
892
- const extras = [];
893
- const assignExtras = (items) => {
894
- if (!items.length) return "";
895
- const lines = [`, (table) => [`];
896
- for (const item of items) {
897
- if (item.kind === "primaryKey") {
898
- const cols = item.columns.map((c) => `table.${c}`).join(", ");
899
- lines.push(` primaryKey({ columns: [${cols}] }),`);
900
- } else {
901
- const cols = Array.isArray(item.on) ? item.on.map((c) => `table.${c}`).join(", ") : `table.${item.on}`;
902
- lines.push(` ${item.kind}("${item.name}").on(${cols}),`);
903
- }
904
- }
905
- lines.push(`]`);
906
- return lines.join("\n");
907
- };
908
- if (hasScopeId) {
909
- extras.push({ kind: "primaryKey", columns: ["scope_id", "id"] });
910
- }
911
- const fieldLines = Object.entries(fields).filter(([fieldName]) => fieldName !== "id").map(([fieldName, attr]) => {
912
- const physical = attr.fieldName ?? fieldName;
913
- const isToolPolicyCompositeField = tableKey === "tool_policy" && (physical === "scope_id" || physical === "position");
914
- if (attr.index && !attr.unique && !isToolPolicyCompositeField) {
915
- extras.push({
916
- kind: "index",
917
- name: `${tableKey}_${physical}_idx`,
918
- on: physical
919
- });
920
- } else if (attr.index && attr.unique) {
921
- extras.push({
922
- kind: "uniqueIndex",
923
- name: `${tableKey}_${physical}_uidx`,
924
- on: physical
925
- });
926
- }
927
- let col = getType(physical, attr, dialect);
928
- if (attr.defaultValue !== null && typeof attr.defaultValue !== "undefined") {
929
- if (typeof attr.defaultValue === "function") {
930
- if (attr.type === "date" && attr.defaultValue.toString().includes("new Date()")) {
931
- if (dialect === "sqlite") {
932
- col += `.default(sql\`(cast(unixepoch('subsecond') * 1000 as integer))\`)`;
933
- } else {
934
- col += `.defaultNow()`;
935
- }
936
- }
937
- } else if (typeof attr.defaultValue === "string") {
938
- col += `.default("${attr.defaultValue}")`;
939
- } else {
940
- col += `.default(${attr.defaultValue})`;
941
- }
942
- }
943
- if (attr.onUpdate && attr.type === "date") {
944
- if (typeof attr.onUpdate === "function") {
945
- col += `.$onUpdate(${attr.onUpdate})`;
946
- }
947
- }
948
- return `${physical}: ${col}${attr.required !== false ? ".notNull()" : ""}${attr.unique ? ".unique()" : ""}${attr.references ? `.references(()=> ${attr.references.model}.${attr.references.field ?? "id"}, { onDelete: '${attr.references.onDelete || "cascade"}' })` : ""}`;
949
- }).join(",\n ");
950
- if (tableKey === "tool_policy") {
951
- extras.push({
952
- kind: "index",
953
- name: "tool_policy_scope_id_position_idx",
954
- on: ["scope_id", "position"]
955
- });
956
- }
957
- const tableSchema = `export const ${tableKey} = ${dialect}Table("${modelName}", {
958
- id: ${id},
959
- ${fieldLines}
960
- }${assignExtras(extras)});`;
961
- code += `
962
- ${tableSchema}
963
- `;
964
- }
965
- let relationsString = "";
966
- for (const [tableKey, tableDef] of Object.entries(schema)) {
967
- const modelName = tableKey;
968
- const oneRelations = [];
969
- const manyRelations = [];
970
- const manyRelationsSet = /* @__PURE__ */ new Set();
971
- for (const [fieldName, field] of Object.entries(tableDef.fields)) {
972
- if (!field.references) continue;
973
- const referencedModel = field.references.model;
974
- const physical = field.fieldName ?? fieldName;
975
- const fieldRef = `${tableKey}.${physical}`;
976
- const referenceRef = `${referencedModel}.${field.references.field || "id"}`;
977
- oneRelations.push({
978
- key: referencedModel,
979
- model: referencedModel,
980
- type: "one",
981
- reference: {
982
- field: fieldRef,
983
- references: referenceRef,
984
- fieldName
985
- }
986
- });
987
- }
988
- for (const [otherKey, otherDef] of Object.entries(schema)) {
989
- if (otherKey === tableKey) continue;
990
- const hasFK = Object.values(otherDef.fields).some(
991
- (field) => field.references?.model === tableKey
992
- );
993
- if (!hasFK) continue;
994
- const relationKey = `${otherKey}s`;
995
- if (!manyRelationsSet.has(relationKey)) {
996
- manyRelationsSet.add(relationKey);
997
- manyRelations.push({
998
- key: relationKey,
999
- model: otherKey,
1000
- type: "many"
1001
- });
1002
- }
1003
- }
1004
- const relationsByModel = /* @__PURE__ */ new Map();
1005
- for (const rel of oneRelations) {
1006
- if (!rel.reference) continue;
1007
- const arr = relationsByModel.get(rel.key) ?? [];
1008
- arr.push(rel);
1009
- relationsByModel.set(rel.key, arr);
1010
- }
1011
- const duplicateRelations = [];
1012
- const singleRelations = [];
1013
- for (const [, rels] of relationsByModel.entries()) {
1014
- if (rels.length > 1) {
1015
- duplicateRelations.push(...rels);
1016
- } else {
1017
- singleRelations.push(rels[0]);
1018
- }
1019
- }
1020
- for (const rel of duplicateRelations) {
1021
- if (!rel.reference) continue;
1022
- const relExportName = `${modelName}${rel.reference.fieldName.charAt(0).toUpperCase() + rel.reference.fieldName.slice(1)}Relations`;
1023
- const block = `export const ${relExportName} = relations(${modelName}, ({ one }) => ({
1024
- ${rel.key}: one(${rel.model}, {
1025
- fields: [${rel.reference.field}],
1026
- references: [${rel.reference.references}],
1027
- })
1028
- }))`;
1029
- relationsString += `
1030
- ${block}
1031
- `;
1032
- }
1033
- const hasOne = singleRelations.length > 0;
1034
- const hasMany = manyRelations.length > 0;
1035
- if (hasOne || hasMany) {
1036
- const destructured = [
1037
- hasOne ? "one" : "",
1038
- hasMany ? "many" : ""
1039
- ].filter(Boolean).join(", ");
1040
- const body = [
1041
- ...singleRelations.filter((r) => r.reference).map(
1042
- (r) => ` ${r.key}: one(${r.model}, {
1043
- fields: [${r.reference.field}],
1044
- references: [${r.reference.references}],
1045
- })`
1046
- ),
1047
- ...manyRelations.map(
1048
- ({ key, model }) => ` ${key}: many(${model})`
1049
- )
1050
- ].join(",\n");
1051
- const block = `export const ${modelName}Relations = relations(${modelName}, ({ ${destructured} }) => ({
1052
- ${body}
1053
- }))`;
1054
- relationsString += `
1055
- ${block}
1056
- `;
1057
- }
1058
- }
1059
- code += `
1060
- ${relationsString}`;
1061
- return {
1062
- code,
1063
- fileName: filePath,
1064
- overwrite: fileExist
1065
- };
1066
- };
1067
- function generateImport({
1068
- dialect,
1069
- schema
1070
- }) {
1071
- const rootImports = [];
1072
- const coreImports = [];
1073
- let hasBigint = false;
1074
- let hasJson = false;
1075
- let hasBoolean = false;
1076
- let hasNumber = false;
1077
- let hasDate = false;
1078
- let hasIndex = false;
1079
- let hasUniqueIndex = false;
1080
- let hasReferences = false;
1081
- let hasCompositePrimaryKey = false;
1082
- for (const [tableKey, table] of Object.entries(schema)) {
1083
- for (const field of Object.values(table.fields)) {
1084
- if (field.bigint) hasBigint = true;
1085
- if (field.type === "json") hasJson = true;
1086
- if (field.type === "boolean") hasBoolean = true;
1087
- if (field.type === "number" && !field.bigint || field.type === "number[]") {
1088
- hasNumber = true;
1089
- }
1090
- if (field.type === "date") hasDate = true;
1091
- if (field.index && !field.unique) hasIndex = true;
1092
- if (field.index && field.unique) hasUniqueIndex = true;
1093
- if (field.references) hasReferences = true;
1094
- }
1095
- if (Object.prototype.hasOwnProperty.call(table.fields, "scope_id")) {
1096
- hasCompositePrimaryKey = true;
1097
- }
1098
- void tableKey;
1099
- }
1100
- coreImports.push(`${dialect}Table`);
1101
- coreImports.push("text");
1102
- if (hasBoolean && dialect !== "sqlite") coreImports.push("boolean");
1103
- if (hasDate) {
1104
- if (dialect === "pg") coreImports.push("timestamp");
1105
- }
1106
- if (hasNumber || dialect === "sqlite") {
1107
- if (dialect === "pg") coreImports.push("integer");
1108
- else if (dialect === "mysql") coreImports.push("int");
1109
- else coreImports.push("integer");
1110
- }
1111
- if (hasBigint && dialect !== "sqlite") coreImports.push("bigint");
1112
- if (hasJson) {
1113
- if (dialect === "pg") coreImports.push("jsonb");
1114
- else if (dialect === "mysql") coreImports.push("json");
1115
- }
1116
- if (hasIndex) coreImports.push("index");
1117
- if (hasUniqueIndex) coreImports.push("uniqueIndex");
1118
- if (hasCompositePrimaryKey) coreImports.push("primaryKey");
1119
- if (dialect === "sqlite" && (hasBoolean || hasDate)) {
1120
- if (!coreImports.includes("integer")) coreImports.push("integer");
1121
- }
1122
- if (dialect === "sqlite" && hasNumber) {
1123
- }
1124
- const hasSqliteTimestamp = dialect === "sqlite" && Object.values(schema).some(
1125
- (table) => Object.values(table.fields).some(
1126
- (field) => field.type === "date" && field.defaultValue && typeof field.defaultValue === "function" && field.defaultValue.toString().includes("new Date()")
1127
- )
1128
- );
1129
- if (hasSqliteTimestamp) {
1130
- rootImports.push("sql");
1131
- }
1132
- if (hasReferences || dialect === "mysql") {
1133
- }
1134
- if (hasReferences) rootImports.push("relations");
1135
- const filteredCore = coreImports.map((x) => x.trim()).filter((x) => x !== "");
1136
- const uniqueCore = [...new Set(filteredCore)];
1137
- const uniqueRoot = [...new Set(rootImports)];
1138
- return `${uniqueRoot.length > 0 ? `import { ${uniqueRoot.join(", ")} } from "drizzle-orm";
1139
- ` : ""}import { ${uniqueCore.join(", ")} } from "drizzle-orm/${dialect}-core";
1140
- `;
1141
- }
1142
-
1143
- // src/commands/generate.ts
1144
- async function generateAction(opts) {
51
+ // src/commands/schema.ts
52
+ var schemaGenerateAction = async (opts) => {
1145
53
  const cwd = path2.resolve(opts.cwd);
1146
- if (!existsSync3(cwd)) {
54
+ if (!existsSync2(cwd)) {
1147
55
  console.error(`The directory "${cwd}" does not exist.`);
1148
56
  process.exit(1);
1149
57
  }
@@ -1154,39 +62,48 @@ async function generateAction(opts) {
1154
62
  );
1155
63
  process.exit(1);
1156
64
  }
1157
- const schema = collectSchemas(config.plugins());
1158
- const result = await generateDrizzleSchema({
1159
- schema,
1160
- dialect: config.dialect,
1161
- file: opts.output
1162
- });
1163
- if (!result.code) {
1164
- console.log("Schema is already up to date.");
1165
- process.exit(0);
65
+ if (opts.adapter !== "drizzle") {
66
+ console.error(`Unsupported schema adapter "${opts.adapter}". Supported adapters: drizzle.`);
67
+ process.exit(1);
1166
68
  }
1167
- const outPath = path2.resolve(cwd, result.fileName);
1168
- const outDir = path2.dirname(outPath);
1169
- if (!existsSync3(outDir)) {
1170
- await fs.mkdir(outDir, { recursive: true });
69
+ if (opts.provider !== "mysql" && opts.provider !== "postgresql" && opts.provider !== "sqlite") {
70
+ console.error(
71
+ `Unsupported drizzle provider "${opts.provider}". Supported providers: mysql, postgresql, sqlite.`
72
+ );
73
+ process.exit(1);
1171
74
  }
1172
- await fs.writeFile(outPath, result.code);
75
+ const [{ fumadb }, { drizzleAdapter }, { schema: fumaSchema }] = await Promise.all([
76
+ import("fumadb"),
77
+ import("fumadb/adapters/drizzle"),
78
+ import("fumadb/schema")
79
+ ]);
80
+ const schema2 = fumaSchema({
81
+ version: opts.version,
82
+ tables: collectTables(config.plugins())
83
+ });
84
+ const factory = fumadb({
85
+ namespace: opts.namespace,
86
+ schemas: [schema2]
87
+ });
88
+ const generated = factory.client(
89
+ drizzleAdapter({
90
+ db: {},
91
+ provider: opts.provider
92
+ })
93
+ ).generateSchema("latest", opts.namespace);
94
+ const output = opts.output ?? generated.path;
95
+ const outPath = path2.resolve(cwd, output);
96
+ await fs.mkdir(path2.dirname(outPath), { recursive: true });
97
+ await fs.writeFile(outPath, generated.code);
1173
98
  console.log(`Schema generated: ${path2.relative(cwd, outPath)}`);
1174
- }
1175
- var generate = new Command("generate").description("Generate a drizzle schema file from the executor config").option(
1176
- "-c, --cwd <cwd>",
1177
- "the working directory",
1178
- process.cwd()
1179
- ).option(
1180
- "--config <config>",
1181
- "path to the executor config file"
1182
- ).option(
1183
- "--output <output>",
1184
- "output file path for the generated schema"
1185
- ).action(generateAction);
99
+ };
100
+ var schema = new Command("schema").description("Database schema utilities").addCommand(
101
+ new Command("generate").description("Generate an ORM schema file from the executor config").option("-c, --cwd <cwd>", "the working directory", process.cwd()).option("--config <config>", "path to the executor config file").option("--output <output>", "output file path for the generated schema").option("--namespace <namespace>", "FumaDB namespace", "executor").option("--adapter <adapter>", "FumaDB adapter", "drizzle").option("--provider <provider>", "database provider", "postgresql").option("--version <version>", "FumaDB schema version", "1.0.0").action(schemaGenerateAction)
102
+ );
1186
103
 
1187
104
  // src/index.ts
1188
105
  process.on("SIGINT", () => process.exit(0));
1189
106
  process.on("SIGTERM", () => process.exit(0));
1190
- var program = new Command2("executor").version("0.0.1").description("Executor CLI").addCommand(generate).action(() => program.help());
1191
- program.parse();
107
+ var program = new Command2("executor-sdk").version("0.0.1").description("Executor SDK CLI").addCommand(schema).action(() => program.help());
108
+ await program.parseAsync();
1192
109
  //# sourceMappingURL=index.js.map