* Run cloud's real auth/billing against WorkOS + Autumn emulators; delete all hand-rolled test layers - WORKOS_API_URL / AUTUMN_API_URL env seams point the REAL SDKs (incl. the vault plugin via credentials.apiUrl) at the vendored emulators. Production composition is unconditional again — the EXECUTOR_E2E_STUB layer swap and every *.test-layer.ts are deleted. - e2e cloud target: identities minted through the REAL login flow (login → emulator-hosted AuthKit, headless via login_hint → callback → genuine sealed-session cookie), orgs through the real create-organization route. - MCP_AUTHKIT_DOMAIN points at the emulator's OAuth authorization server — cloud MCP OAuth e2e now RUNS (was capability-skipped): 19/19 scenarios, zero skips across both targets. - Readiness probes wait for /api/auth/login to actually 302 (vite serves the SPA for /api/* during cold compile); submenu interactions wait for the loaded sub-content before clicking. * Type the optional apiUrl on cloud's workosCredentials dep * Pin emulate fork: OAuth refresh grant + hosted WorkOS/Autumn on the worker * e2e: consume published @executor-js/emulate and @executor-js/mcporter Import the WorkOS/Autumn emulators and the mcporter MCP client from their published npm packages instead of the vendored submodule dist. The submodules remain for fork development, but nothing imports from vendor/ at runtime, so a fresh clone (and CI) resolves these via the registry — which lets e2e typecheck in CI without building the submodules.
Unified · Split
| @@ -31,6 +31,8 @@ interface CloudPluginDeps { · 30 unmodified lines | |||
| 31 | readonly workosCredentials?: { | 31 | readonly workosCredentials?: { |
| 32 | readonly apiKey: string; | 32 | readonly apiKey: string; |
| 33 | readonly clientId: string; | 33 | readonly clientId: string; |
| 34 | /** Optional WorkOS API base-URL override (WorkOS emulator in tests/dev). */ | ||
| 35 | readonly apiUrl?: string; | ||
| 34 | }; | 36 | }; |
| 35 | /** Pluggable WorkOS Vault HTTP client — set by the test harness to | 37 | /** Pluggable WorkOS Vault HTTP client — set by the test harness to |
| 36 | * bypass the real WorkOS API. Production leaves this undefined and | 38 | * bypass the real WorkOS API. Production leaves this undefined and |
| @@ -5,7 +5,6 @@ import { DbProvider, ExecutorApp } from "@executor-js/api/server"; · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | import { cloudPlugins } from "./plugins"; | 6 | import { cloudPlugins } from "./plugins"; |
| 7 | import { CoreSharedServices } from "./auth/workos"; | 7 | import { CoreSharedServices } from "./auth/workos"; |
| 8 | import { E2E_STUB, E2EStubWorkOSLayer } from "./testing/e2e-stub"; | ||
| 9 | import { makeCloudExtensionRoutes } from "./extensions/routes"; | 8 | import { makeCloudExtensionRoutes } from "./extensions/routes"; |
| 10 | import { RequestScopedServicesLive } from "./api/layers"; | 9 | import { RequestScopedServicesLive } from "./api/layers"; |
| 11 | import { CloudMeteringEngineDecorator } from "./engine/execution-stack-metered"; | 10 | import { CloudMeteringEngineDecorator } from "./engine/execution-stack-metered"; |
| @@ -56,12 +55,10 @@ import { WorkerTelemetryLive } from "./observability/telemetry"; · 44 unmodified lines | |||
| 56 | // the account provider + MCP seam, AND by the per-request identity layer below). | 55 | // the account provider + MCP seam, AND by the per-request identity layer below). |
| 57 | // Lives in `boot`, so `workosIdentityLayer`'s residual `WorkOSClient | | 56 | // Lives in `boot`, so `workosIdentityLayer`'s residual `WorkOSClient | |
| 58 | // ApiKeyService` (the long-lived control plane it reads) resolves from there. | 57 | // ApiKeyService` (the long-lived control plane it reads) resolves from there. |
| 59 | // EXECUTOR_E2E_STUB swaps the WorkOS control plane for an in-memory stub whose | 58 | // Tests point the REAL client at a WorkOS emulator via WORKOS_API_URL — no |
| 60 | // `authenticateSealedSession` resolves to user_1 — so the whole app (session + | 59 | // layer substitution. |
| 61 | // account + SSR) is logged in with no real WorkOS. Off in production. | 60 | const apiKeyService = ApiKeyService.WorkOS.pipe(Layer.provide(CoreSharedServices)); |
| 62 | const workOSBase = E2E_STUB ? E2EStubWorkOSLayer : CoreSharedServices; | 61 | const controlPlane = Layer.mergeAll(CoreSharedServices, apiKeyService); |
| 63 | const apiKeyService = ApiKeyService.WorkOS.pipe(Layer.provide(workOSBase)); | ||
| 64 | const controlPlane = Layer.mergeAll(workOSBase, apiKeyService); | ||
| 65 | 62 | ||
| 66 | // `CloudDbProvider` only reads the per-request `DbService` at runtime; we widen | 63 | // `CloudDbProvider` only reads the per-request `DbService` at runtime; we widen |
| 67 | // its residual type to also carry the boot `AutumnService` the metering | 64 | // its residual type to also carry the boot `AutumnService` the metering |
| @@ -1,11 +0,0 @@ | |||
| 1 | import { Effect, Layer } from "effect"; | ||
| 2 | |||
| 3 | import { ApiKeyService } from "./api-keys"; | ||
| 4 | import { ApiKeyManagementError } from "./errors"; | ||
| 5 | |||
| 6 | export const ApiKeyServiceTestLayer = Layer.succeed(ApiKeyService)({ | ||
| 7 | validate: () => Effect.succeed(null), | ||
| 8 | listUserKeys: () => Effect.succeed([]), | ||
| 9 | createUserKey: () => Effect.fail(new ApiKeyManagementError({ cause: "unstubbed" })), | ||
| 10 | revokeUserKey: () => Effect.void, | ||
| 11 | }); | ||
| @@ -1,90 +0,0 @@ | |||
| 1 | import { requestHandler } from "@tanstack/react-start/server"; | ||
| 2 | import { Context, Effect, Layer } from "effect"; | ||
| 3 | import { FetchHttpClient, HttpRouter, HttpServer } from "effect/unstable/http"; | ||
| 4 | import { HttpApiBuilder, HttpApiClient } from "effect/unstable/httpapi"; | ||
| 5 | |||
| 6 | import { | ||
| 7 | AutumnTestLayer, | ||
| 8 | makeAutumnTestState, | ||
| 9 | type AutumnTestState, | ||
| 10 | } from "../extensions/billing/service.test-layer"; | ||
| 11 | import { ApiKeyServiceTestLayer } from "./api-keys.test-layer"; | ||
| 12 | import { | ||
| 13 | makeUserStoreTestState, | ||
| 14 | UserStoreTestLayer, | ||
| 15 | type UserStoreTestState, | ||
| 16 | } from "./context.test-layer"; | ||
| 17 | import { CloudAuthPublicHandlers, CloudSessionAuthHandlers, NonProtectedApi } from "./handlers"; | ||
| 18 | import { | ||
| 19 | makeSessionTestContext, | ||
| 20 | SessionAuthTestLayer, | ||
| 21 | type SessionTestContext, | ||
| 22 | } from "./middleware.test-layer"; | ||
| 23 | import { makeWorkOSTestState, WorkOSTestLayer, type WorkOSTestState } from "./workos.test-layer"; | ||
| 24 | |||
| 25 | const TEST_BASE_URL = "http://test.local"; | ||
| 26 | const SESSION_COOKIE = "wos-session=test_session"; | ||
| 27 | |||
| 28 | export type CloudAuthApiTestState = { | ||
| 29 | readonly workos: WorkOSTestState; | ||
| 30 | readonly autumn: AutumnTestState; | ||
| 31 | readonly userStore: UserStoreTestState; | ||
| 32 | readonly session: SessionTestContext; | ||
| 33 | }; | ||
| 34 | |||
| 35 | export const makeCloudAuthApiTestState = ( | ||
| 36 | overrides: Partial<CloudAuthApiTestState> = {}, | ||
| 37 | ): CloudAuthApiTestState => ({ | ||
| 38 | workos: makeWorkOSTestState(), | ||
| 39 | autumn: makeAutumnTestState(), | ||
| 40 | userStore: makeUserStoreTestState(), | ||
| 41 | session: makeSessionTestContext(), | ||
| 42 | ...overrides, | ||
| 43 | }); | ||
| 44 | |||
| 45 | const makeCloudAuthApiTestClient = (state: CloudAuthApiTestState) => { | ||
| 46 | const ApiLive = HttpApiBuilder.layer(NonProtectedApi).pipe( | ||
| 47 | Layer.provide(Layer.mergeAll(CloudAuthPublicHandlers, CloudSessionAuthHandlers)), | ||
| 48 | Layer.provide(SessionAuthTestLayer(state.session)), | ||
| 49 | Layer.provideMerge(WorkOSTestLayer(state.workos)), | ||
| 50 | Layer.provideMerge(AutumnTestLayer(state.autumn)), | ||
| 51 | Layer.provideMerge(UserStoreTestLayer(state.userStore)), | ||
| 52 | Layer.provideMerge(ApiKeyServiceTestLayer), | ||
| 53 | Layer.provideMerge(HttpServer.layerServices), | ||
| 54 | Layer.provideMerge(Layer.succeed(HttpRouter.RouterConfig)({ maxParamLength: 1000 })), | ||
| 55 | ); | ||
| 56 | |||
| 57 | const handler = HttpRouter.toWebHandler(ApiLive, { disableLogger: true }).handler; | ||
| 58 | const startHandler = requestHandler((request) => handler(request, undefined)); | ||
| 59 | const fetchViaHandler: typeof globalThis.fetch = async (input, init) => { | ||
| 60 | const request = input instanceof Request ? input : new Request(input, init); | ||
| 61 | request.headers.set("cookie", SESSION_COOKIE); | ||
| 62 | return await startHandler(request, undefined); | ||
| 63 | }; | ||
| 64 | const clientLayer = FetchHttpClient.layer.pipe( | ||
| 65 | Layer.provide(Layer.succeed(FetchHttpClient.Fetch)(fetchViaHandler)), | ||
| 66 | ); | ||
| 67 | |||
| 68 | return HttpApiClient.make(NonProtectedApi, { baseUrl: TEST_BASE_URL }).pipe( | ||
| 69 | Effect.provide(clientLayer), | ||
| 70 | ); | ||
| 71 | }; | ||
| 72 | |||
| 73 | export type CloudAuthApiTestClient = Effect.Success<ReturnType<typeof makeCloudAuthApiTestClient>>; | ||
| 74 | |||
| 75 | export class CloudAuthApiTestContext extends Context.Service< | ||
| 76 | CloudAuthApiTestContext, | ||
| 77 | { | ||
| 78 | readonly state: CloudAuthApiTestState; | ||
| 79 | readonly client: CloudAuthApiTestClient; | ||
| 80 | } | ||
| 81 | >()("CloudAuthApiTestContext") {} | ||
| 82 | |||
| 83 | export const CloudAuthApiTestContextLayer = (state = makeCloudAuthApiTestState()) => | ||
| 84 | Layer.effect( | ||
| 85 | CloudAuthApiTestContext, | ||
| 86 | Effect.gen(function* () { | ||
| 87 | const client = yield* makeCloudAuthApiTestClient(state); | ||
| 88 | return { state, client }; | ||
| 89 | }), | ||
| 90 | ); | ||
| @@ -1,41 +0,0 @@ | |||
| 1 | import { Effect, Layer } from "effect"; | ||
| 2 | |||
| 3 | import { UserStoreService } from "./context"; | ||
| 4 | |||
| 5 | type UserStore = Parameters<Parameters<UserStoreService["Service"]["use"]>[0]>[0]; | ||
| 6 | |||
| 7 | export type UserStoreTestState = { | ||
| 8 | readonly upsertedOrganizations: Array<{ readonly id: string; readonly name: string }>; | ||
| 9 | }; | ||
| 10 | |||
| 11 | export const makeUserStoreTestState = ( | ||
| 12 | overrides: Partial<UserStoreTestState> = {}, | ||
| 13 | ): UserStoreTestState => ({ | ||
| 14 | upsertedOrganizations: [], | ||
| 15 | ...overrides, | ||
| 16 | }); | ||
| 17 | |||
| 18 | const testDate = () => new Date("2026-01-01T00:00:00.000Z"); | ||
| 19 | |||
| 20 | const makeUserStoreTestService = (state: UserStoreTestState): UserStoreService["Service"] => { | ||
| 21 | const store = { | ||
| 22 | ensureAccount: async (id: string) => ({ id, createdAt: testDate() }), | ||
| 23 | getAccount: async (id: string) => ({ id, createdAt: testDate() }), | ||
| 24 | upsertOrganization: async (org: { readonly id: string; readonly name: string }) => { | ||
| 25 | state.upsertedOrganizations.push(org); | ||
| 26 | return { ...org, createdAt: testDate() }; | ||
| 27 | }, | ||
| 28 | getOrganization: async (id: string) => ({ | ||
| 29 | id, | ||
| 30 | name: id, | ||
| 31 | createdAt: testDate(), | ||
| 32 | }), | ||
| 33 | } satisfies UserStore; | ||
| 34 | |||
| 35 | return { | ||
| 36 | use: (fn) => Effect.promise(() => fn(store)), | ||
| 37 | }; | ||
| 38 | }; | ||
| 39 | |||
| 40 | export const UserStoreTestLayer = (state: UserStoreTestState) => | ||
| 41 | Layer.succeed(UserStoreService)(makeUserStoreTestService(state)); | ||
| @@ -1,103 +0,0 @@ | |||
| 1 | import { assert, describe, it } from "@effect/vitest"; | ||
| 2 | import { Effect, Exit } from "effect"; | ||
| 3 | |||
| 4 | import { | ||
| 5 | CloudAuthApiTestContext, | ||
| 6 | CloudAuthApiTestContextLayer, | ||
| 7 | makeCloudAuthApiTestState, | ||
| 8 | } from "./cloud-auth-api.test-context"; | ||
| 9 | import { makeWorkOSTestMembership, makeWorkOSTestState } from "./workos.test-layer"; | ||
| 10 | import { makeAutumnTestState } from "../extensions/billing/service.test-layer"; | ||
| 11 | |||
| 12 | describe("create organization API", () => { | ||
| 13 | it.effect("lets a paid user create another organization through the HTTP API client", () => { | ||
| 14 | const state = makeCloudAuthApiTestState({ | ||
| 15 | workos: makeWorkOSTestState({ | ||
| 16 | memberships: [ | ||
| 17 | makeWorkOSTestMembership("org_free_1", "active"), | ||
| 18 | makeWorkOSTestMembership("org_free_2", "active"), | ||
| 19 | makeWorkOSTestMembership("org_paid", "active"), | ||
| 20 | ], | ||
| 21 | }), | ||
| 22 | autumn: makeAutumnTestState({ | ||
| 23 | subscriptionsByOrgId: { | ||
| 24 | org_paid: [{ planId: "team", status: "active" }], | ||
| 25 | }, | ||
| 26 | }), | ||
| 27 | }); | ||
| 28 | |||
| 29 | return Effect.gen(function* () { | ||
| 30 | const { client } = yield* CloudAuthApiTestContext; | ||
| 31 | |||
| 32 | const result = yield* client.cloudAuth.createOrganization({ | ||
| 33 | payload: { name: "Paid Extra Org" }, | ||
| 34 | }); | ||
| 35 | |||
| 36 | assert.deepEqual(result, { id: "org_created", name: "Paid Extra Org" }); | ||
| 37 | assert.deepEqual(state.workos.createdOrganizations, [ | ||
| 38 | { id: "org_created", name: "Paid Extra Org" }, | ||
| 39 | ]); | ||
| 40 | assert.deepEqual(state.workos.createdMemberships, [ | ||
| 41 | { organizationId: "org_created", userId: "user_1", roleSlug: "admin" }, | ||
| 42 | ]); | ||
| 43 | assert.deepEqual(state.userStore.upsertedOrganizations, [ | ||
| 44 | { id: "org_created", name: "Paid Extra Org" }, | ||
| 45 | ]); | ||
| 46 | }).pipe(Effect.provide(CloudAuthApiTestContextLayer(state))); | ||
| 47 | }); | ||
| 48 | |||
| 49 | it.effect( | ||
| 50 | "rejects a free-only user at the free organization limit through the HTTP API client", | ||
| 51 | () => { | ||
| 52 | const state = makeCloudAuthApiTestState({ | ||
| 53 | workos: makeWorkOSTestState({ | ||
| 54 | memberships: [ | ||
| 55 | makeWorkOSTestMembership("org_free_1", "active"), | ||
| 56 | makeWorkOSTestMembership("org_free_2", "active"), | ||
| 57 | makeWorkOSTestMembership("org_free_3", "active"), | ||
| 58 | ], | ||
| 59 | }), | ||
| 60 | }); | ||
| 61 | |||
| 62 | return Effect.gen(function* () { | ||
| 63 | const { client } = yield* CloudAuthApiTestContext; | ||
| 64 | |||
| 65 | const exit = yield* Effect.exit( | ||
| 66 | client.cloudAuth.createOrganization({ | ||
| 67 | payload: { name: "Blocked Org" }, | ||
| 68 | }), | ||
| 69 | ); | ||
| 70 | |||
| 71 | assert.isTrue(Exit.isFailure(exit)); | ||
| 72 | assert.deepEqual(state.workos.createdOrganizations, []); | ||
| 73 | assert.deepEqual(state.workos.createdMemberships, []); | ||
| 74 | assert.deepEqual(state.userStore.upsertedOrganizations, []); | ||
| 75 | }).pipe(Effect.provide(CloudAuthApiTestContextLayer(state))); | ||
| 76 | }, | ||
| 77 | ); | ||
| 78 | |||
| 79 | it.effect("does not count pending memberships toward the free organization limit", () => { | ||
| 80 | const state = makeCloudAuthApiTestState({ | ||
| 81 | workos: makeWorkOSTestState({ | ||
| 82 | memberships: [ | ||
| 83 | makeWorkOSTestMembership("org_free_1", "active"), | ||
| 84 | makeWorkOSTestMembership("org_free_2", "active"), | ||
| 85 | makeWorkOSTestMembership("org_invited", "pending"), | ||
| 86 | ], | ||
| 87 | }), | ||
| 88 | }); | ||
| 89 | |||
| 90 | return Effect.gen(function* () { | ||
| 91 | const { client } = yield* CloudAuthApiTestContext; | ||
| 92 | |||
| 93 | const result = yield* client.cloudAuth.createOrganization({ | ||
| 94 | payload: { name: "Below Active Limit" }, | ||
| 95 | }); | ||
| 96 | |||
| 97 | assert.deepEqual(result, { id: "org_created", name: "Below Active Limit" }); | ||
| 98 | assert.deepEqual(state.workos.createdOrganizations, [ | ||
| 99 | { id: "org_created", name: "Below Active Limit" }, | ||
| 100 | ]); | ||
| 101 | }).pipe(Effect.provide(CloudAuthApiTestContextLayer(state))); | ||
| 102 | }); | ||
| 103 | }); | ||
| @@ -1,29 +0,0 @@ | |||
| 1 | import { Effect, Layer } from "effect"; | ||
| 2 | |||
| 3 | import { SessionAuth, SessionContext, SessionCookies, type Session } from "./middleware"; | ||
| 4 | |||
| 5 | export type SessionTestContext = Session; | ||
| 6 | |||
| 7 | export const makeSessionTestContext = ( | ||
| 8 | overrides: Partial<SessionTestContext> = {}, | ||
| 9 | ): SessionTestContext => ({ | ||
| 10 | accountId: "user_1", | ||
| 11 | email: "test@example.com", | ||
| 12 | name: "Test User", | ||
| 13 | avatarUrl: null, | ||
| 14 | organizationId: "org_existing_1", | ||
| 15 | sealedSession: "test_session", | ||
| 16 | refreshedSession: null, | ||
| 17 | ...overrides, | ||
| 18 | }); | ||
| 19 | |||
| 20 | export const SessionAuthTestLayer = (session: Session = makeSessionTestContext()) => | ||
| 21 | Layer.succeed(SessionAuth)({ | ||
| 22 | cookie: (httpEffect) => | ||
| 23 | httpEffect.pipe( | ||
| 24 | Effect.provideService(SessionContext, session), | ||
| 25 | // The session handlers driven via this layer don't assert cookie output; | ||
| 26 | // a no-op setter satisfies the SessionCookies the middleware provides. | ||
| 27 | Effect.provideService(SessionCookies, { set: () => {} }), | ||
| 28 | ), | ||
| 29 | }); | ||
| @@ -1,206 +0,0 @@ | |||
| 1 | import { Data, Effect, Layer } from "effect"; | ||
| 2 | import type { Organization, OrganizationMembership, OrganizationRole } from "@workos-inc/node"; | ||
| 3 | |||
| 4 | import { WorkOSClient, type WorkOSCollectedList } from "./workos"; | ||
| 5 | |||
| 6 | export type WorkOSTestState = { | ||
| 7 | readonly memberships: readonly OrganizationMembership[]; | ||
| 8 | // When set, a successful create adds a unique org id + an active membership, | ||
| 9 | // so a running server's free-org limit trips live across requests. Off by | ||
| 10 | // default — existing tests keep the fixed `org_created` id and static list. | ||
| 11 | readonly growMembershipsOnCreate?: boolean; | ||
| 12 | // When set, the user is resolved from the `wos-session` cookie value and | ||
| 13 | // memberships are keyed per user — so each test/browser picks its own user id | ||
| 14 | // and is isolated on a shared instance (no reset needed), matching the | ||
| 15 | // in-process per-org harness. Implies grow-on-create. | ||
| 16 | readonly multiUser?: boolean; | ||
| 17 | readonly createdOrganizations: Array<{ readonly id: string; readonly name: string }>; | ||
| 18 | readonly createdMemberships: Array<{ | ||
| 19 | readonly organizationId: string; | ||
| 20 | readonly userId: string; | ||
| 21 | readonly roleSlug: string | undefined; | ||
| 22 | }>; | ||
| 23 | }; | ||
| 24 | |||
| 25 | export class UnstubbedWorkOSMethod extends Data.TaggedError("UnstubbedWorkOSMethod")<{ | ||
| 26 | readonly method: string; | ||
| 27 | }> {} | ||
| 28 | |||
| 29 | export const makeWorkOSTestState = (overrides: Partial<WorkOSTestState> = {}): WorkOSTestState => ({ | ||
| 30 | memberships: [], | ||
| 31 | createdOrganizations: [], | ||
| 32 | createdMemberships: [], | ||
| 33 | ...overrides, | ||
| 34 | }); | ||
| 35 | |||
| 36 | export const WorkOSTestRole: OrganizationRole = { | ||
| 37 | object: "role", | ||
| 38 | id: "role_admin", | ||
| 39 | name: "Admin", | ||
| 40 | slug: "admin", | ||
| 41 | description: null, | ||
| 42 | permissions: [], | ||
| 43 | resourceTypeSlug: "organization", | ||
| 44 | type: "OrganizationRole", | ||
| 45 | createdAt: "2026-01-01T00:00:00.000Z", | ||
| 46 | updatedAt: "2026-01-01T00:00:00.000Z", | ||
| 47 | }; | ||
| 48 | |||
| 49 | export const makeWorkOSTestOrganization = (id: string, name = id): Organization => ({ | ||
| 50 | object: "organization", | ||
| 51 | id, | ||
| 52 | name, | ||
| 53 | allowProfilesOutsideOrganization: false, | ||
| 54 | domains: [], | ||
| 55 | createdAt: "2026-01-01T00:00:00.000Z", | ||
| 56 | updatedAt: "2026-01-01T00:00:00.000Z", | ||
| 57 | externalId: null, | ||
| 58 | metadata: {}, | ||
| 59 | }); | ||
| 60 | |||
| 61 | export const makeWorkOSTestMembership = ( | ||
| 62 | organizationId: string, | ||
| 63 | status: OrganizationMembership["status"], | ||
| 64 | ) => | ||
| 65 | ({ | ||
| 66 | object: "organization_membership", | ||
| 67 | id: `membership_${organizationId}`, | ||
| 68 | organizationId, | ||
| 69 | organizationName: organizationId, | ||
| 70 | status, | ||
| 71 | userId: "user_1", | ||
| 72 | role: WorkOSTestRole, | ||
| 73 | directoryManaged: false, | ||
| 74 | createdAt: "2026-01-01T00:00:00.000Z", | ||
| 75 | updatedAt: "2026-01-01T00:00:00.000Z", | ||
| 76 | customAttributes: {}, | ||
| 77 | }) satisfies OrganizationMembership; | ||
| 78 | |||
| 79 | const decode = (value: string): string => { | ||
| 80 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: tolerate non-URL-encoded cookie values from direct API callers | ||
| 81 | try { | ||
| 82 | return decodeURIComponent(value); | ||
| 83 | } catch { | ||
| 84 | return value; | ||
| 85 | } | ||
| 86 | }; | ||
| 87 | |||
| 88 | const collected = <A>(data: readonly A[]): WorkOSCollectedList<A> => ({ | ||
| 89 | object: "list", | ||
| 90 | data: [...data], | ||
| 91 | listMetadata: { | ||
| 92 | before: null, | ||
| 93 | after: null, | ||
| 94 | }, | ||
| 95 | }); | ||
| 96 | |||
| 97 | const makeWorkOSTestService = (state: WorkOSTestState): WorkOSClient["Service"] => { | ||
| 98 | const nextOrgId = "org_created"; | ||
| 99 | let orgCounter = 0; | ||
| 100 | // Per-user membership buckets (multi-user mode). Closure-scoped, so they live | ||
| 101 | // for the layer's lifetime (= the running server) and isolate users from each | ||
| 102 | // other without a reset. | ||
| 103 | const byUser = new Map<string, OrganizationMembership[]>(); | ||
| 104 | const memsFor = (userId: string) => { | ||
| 105 | let m = byUser.get(userId); | ||
| 106 | if (!m) byUser.set(userId, (m = [])); | ||
| 107 | return m; | ||
| 108 | }; | ||
| 109 | const grows = state.multiUser || state.growMembershipsOnCreate; | ||
| 110 | const service: Partial<WorkOSClient["Service"]> = { | ||
| 111 | listUserMemberships: (userId: string) => | ||
| 112 | Effect.succeed(collected(state.multiUser ? memsFor(userId) : state.memberships)), | ||
| 113 | createOrganization: (name) => | ||
| 114 | Effect.sync(() => { | ||
| 115 | const id = grows ? `${nextOrgId}_${++orgCounter}` : nextOrgId; | ||
| 116 | const org = makeWorkOSTestOrganization(id, name); | ||
| 117 | state.createdOrganizations.push({ id: org.id, name: org.name }); | ||
| 118 | return org; | ||
| 119 | }), | ||
| 120 | createMembership: (organizationId, userId, roleSlug) => | ||
| 121 | Effect.sync(() => { | ||
| 122 | state.createdMemberships.push({ organizationId, userId, roleSlug }); | ||
| 123 | const membership = makeWorkOSTestMembership(organizationId, "active"); | ||
| 124 | if (state.multiUser) memsFor(userId).push(membership); | ||
| 125 | else if (state.growMembershipsOnCreate) { | ||
| 126 | (state.memberships as OrganizationMembership[]).push(membership); | ||
| 127 | } | ||
| 128 | return membership; | ||
| 129 | }), | ||
| 130 | getOrganization: (organizationId: string) => | ||
| 131 | Effect.succeed(makeWorkOSTestOrganization(organizationId)), | ||
| 132 | // The create-org page polls pending invitations; no invitation flows in | ||
| 133 | // the stub world, so the list is always empty. | ||
| 134 | listInvitationsByEmail: (_email: string) => Effect.succeed(collected([])), | ||
| 135 | getUserOrgMembership: (organizationId: string, _userId: string) => | ||
| 136 | Effect.succeed(makeWorkOSTestMembership(organizationId, "active")), | ||
| 137 | // Multi-user refresh carries the user id forward + the switched-to org, so the | ||
| 138 | // create-org handler's `verified.organizationId === org.id` check passes and | ||
| 139 | // the user stays consistent across the refresh. The incoming sealed session | ||
| 140 | // may be URL-encoded (set-cookie round-trip through a real browser) and may | ||
| 141 | // already carry an `|org:` suffix from a previous switch — normalize both. | ||
| 142 | refreshSession: (sealedSession, organizationId) => | ||
| 143 | Effect.succeed( | ||
| 144 | state.multiUser | ||
| 145 | ? `${userOf(sealedSession)}|org:${organizationId}` | ||
| 146 | : `session_${organizationId}`, | ||
| 147 | ), | ||
| 148 | authenticateSealedSession: (sealedSession) => Effect.sync(() => sessionOf(sealedSession)), | ||
| 149 | // The protected-API identity path (`resolveSessionPrincipal`) authenticates | ||
| 150 | // from the Request; mirror the real client's cookie-parse + delegate. | ||
| 151 | authenticateRequest: (request: Request) => | ||
| 152 | Effect.sync(() => { | ||
| 153 | const match = /(?:^|;\s*)wos-session=([^;]+)/.exec(request.headers.get("cookie") ?? ""); | ||
| 154 | return match ? sessionOf(decodeURIComponent(match[1]!)) : null; | ||
| 155 | }), | ||
| 156 | }; | ||
| 157 | |||
| 158 | function userOf(sealedSession: string): string { | ||
| 159 | return decode(sealedSession).split("|org:")[0] || "user_1"; | ||
| 160 | } | ||
| 161 | |||
| 162 | function sessionOf(sealedSession: string) { | ||
| 163 | if (state.multiUser) { | ||
| 164 | // Cookie is `<userId>` (initial) or `<userId>|org:<orgId>` (after refresh); | ||
| 165 | // a browser round-trip URL-encodes it. The LAST org segment is current. | ||
| 166 | const parts = decode(sealedSession).split("|org:"); | ||
| 167 | const userPart = parts[0]; | ||
| 168 | const orgPart = parts.length > 1 ? parts[parts.length - 1] : undefined; | ||
| 169 | return { | ||
| 170 | userId: userPart || "user_1", | ||
| 171 | email: "test@example.com", | ||
| 172 | firstName: "Test", | ||
| 173 | lastName: "User", | ||
| 174 | avatarUrl: null, | ||
| 175 | organizationId: orgPart ?? "", | ||
| 176 | sessionId: "session_id", | ||
| 177 | refreshedSession: undefined, | ||
| 178 | }; | ||
| 179 | } | ||
| 180 | return { | ||
| 181 | userId: "user_1", | ||
| 182 | email: "test@example.com", | ||
| 183 | firstName: "Test", | ||
| 184 | lastName: "User", | ||
| 185 | avatarUrl: null, | ||
| 186 | organizationId: sealedSession.replace("session_", ""), | ||
| 187 | sessionId: "session_id", | ||
| 188 | refreshedSession: undefined, | ||
| 189 | }; | ||
| 190 | } | ||
| 191 | |||
| 192 | return new Proxy(service as WorkOSClient["Service"], { | ||
| 193 | get: (target, prop) => { | ||
| 194 | if (prop in target) return target[prop as keyof typeof target]; | ||
| 195 | return () => | ||
| 196 | Effect.fail( | ||
| 197 | new UnstubbedWorkOSMethod({ | ||
| 198 | method: typeof prop === "string" ? prop : (prop.description ?? "symbol"), | ||
| 199 | }), | ||
| 200 | ); | ||
| 201 | }, | ||
| 202 | }); | ||
| 203 | }; | ||
| 204 | |||
| 205 | export const WorkOSTestLayer = (state: WorkOSTestState) => | ||
| 206 | Layer.succeed(WorkOSClient)(makeWorkOSTestService(state)); | ||
| @@ -110,6 +110,25 @@ class WorkOSConfigurationError extends Data.TaggedError("WorkOSConfigurationErro · 109 unmodified lines | |||
| 110 | readonly message: string; | 110 | readonly message: string; |
| 111 | }> {} | 111 | }> {} |
| 112 | 112 | ||
| 113 | /** | ||
| 114 | * Optional base-URL override for the WorkOS API (`WORKOS_API_URL`) — points | ||
| 115 | * the REAL SDK at a WorkOS emulator in tests/dev. Unset in production, where | ||
| 116 | * the SDK uses api.workos.com. Sealed-session crypto, JWKS verification, and | ||
| 117 | * every endpoint follow this host, so the whole auth stack runs against the | ||
| 118 | * emulator with zero code substitution. | ||
| 119 | */ | ||
| 120 | export const workosApiUrlOptions = ( | ||
| 121 | url: string | undefined, | ||
| 122 | ): { apiHostname?: string; port?: number; https?: boolean } => { | ||
| 123 | if (!url) return {}; | ||
| 124 | const parsed = new URL(url); | ||
| 125 | return { | ||
| 126 | apiHostname: parsed.hostname, | ||
| 127 | ...(parsed.port ? { port: Number(parsed.port) } : {}), | ||
| 128 | https: parsed.protocol === "https:", | ||
| 129 | }; | ||
| 130 | }; | ||
| 131 | |||
| 113 | // --------------------------------------------------------------------------- | 132 | // --------------------------------------------------------------------------- |
| 114 | // Service | 133 | // Service |
| 115 | // --------------------------------------------------------------------------- | 134 | // --------------------------------------------------------------------------- |
| @@ -125,7 +144,7 @@ const make = Effect.gen(function* () { · 9 unmodified lines | |||
| 125 | }); | 144 | }); |
| 126 | } | 145 | } |
| 127 | 146 | ||
| 128 | const workos = new WorkOS({ apiKey, clientId }); | 147 | const workos = new WorkOS({ apiKey, clientId, ...workosApiUrlOptions(env.WORKOS_API_URL) }); |
| 129 | 148 | ||
| 130 | const use = <A>(fn: (wos: WorkOS) => Promise<A>) => | 149 | const use = <A>(fn: (wos: WorkOS) => Promise<A>) => |
| 131 | withServiceLogging( | 150 | withServiceLogging( |
| @@ -62,6 +62,7 @@ export const CloudPluginsProvider: Layer.Layer<PluginsProvider> = Layer.succeed( · 61 unmodified lines | |||
| 62 | workosCredentials: { | 62 | workosCredentials: { |
| 63 | apiKey: env.WORKOS_API_KEY, | 63 | apiKey: env.WORKOS_API_KEY, |
| 64 | clientId: env.WORKOS_CLIENT_ID, | 64 | clientId: env.WORKOS_CLIENT_ID, |
| 65 | apiUrl: env.WORKOS_API_URL, | ||
| 65 | }, | 66 | }, |
| 66 | }), | 67 | }), |
| 67 | }); | 68 | }); |
| @@ -26,6 +26,11 @@ declare global { · 25 unmodified lines | |||
| 26 | 26 | ||
| 27 | // Billing | 27 | // Billing |
| 28 | AUTUMN_SECRET_KEY?: string; | 28 | AUTUMN_SECRET_KEY?: string; |
| 29 | /** Optional Autumn base-URL override (Autumn emulator in tests/dev). */ | ||
| 30 | AUTUMN_API_URL?: string; | ||
| 31 | |||
| 32 | /** Optional WorkOS base-URL override (WorkOS emulator in tests/dev). */ | ||
| 33 | WORKOS_API_URL?: string; | ||
| 29 | 34 | ||
| 30 | // MCP | 35 | // MCP |
| 31 | EXECUTOR_MCP_DEBUG?: string; | 36 | EXECUTOR_MCP_DEBUG?: string; |
| @@ -57,6 +57,7 @@ const handler = Effect.gen(function* () { · 56 unmodified lines | |||
| 57 | }, | 57 | }, |
| 58 | clientOptions: { | 58 | clientOptions: { |
| 59 | secretKey: env.AUTUMN_SECRET_KEY ?? "", | 59 | secretKey: env.AUTUMN_SECRET_KEY ?? "", |
| 60 | ...(env.AUTUMN_API_URL ? { serverURL: env.AUTUMN_API_URL } : {}), | ||
| 60 | }, | 61 | }, |
| 61 | pathPrefix: "/api/billing", | 62 | pathPrefix: "/api/billing", |
| 62 | }), | 63 | }), |
| @@ -1,36 +0,0 @@ | |||
| 1 | import { Effect, Layer } from "effect"; | ||
| 2 | import type { Autumn } from "autumn-js"; | ||
| 3 | |||
| 4 | import { AutumnService, type IAutumnService } from "./service"; | ||
| 5 | |||
| 6 | export type AutumnTestSubscriptionSummary = { | ||
| 7 | readonly planId?: string | null; | ||
| 8 | readonly status?: string | null; | ||
| 9 | }; | ||
| 10 | |||
| 11 | export type AutumnTestState = { | ||
| 12 | readonly subscriptionsByOrgId: Readonly<Record<string, readonly AutumnTestSubscriptionSummary[]>>; | ||
| 13 | }; | ||
| 14 | |||
| 15 | export const makeAutumnTestState = (overrides: Partial<AutumnTestState> = {}): AutumnTestState => ({ | ||
| 16 | subscriptionsByOrgId: {}, | ||
| 17 | ...overrides, | ||
| 18 | }); | ||
| 19 | |||
| 20 | const makeAutumnTestService = (state: AutumnTestState): IAutumnService => { | ||
| 21 | const fakeClient = { | ||
| 22 | customers: { | ||
| 23 | getOrCreate: async ({ customerId }: { readonly customerId: string }) => ({ | ||
| 24 | subscriptions: state.subscriptionsByOrgId[customerId] ?? [], | ||
| 25 | }), | ||
| 26 | }, | ||
| 27 | } as Autumn; | ||
| 28 | |||
| 29 | return { | ||
| 30 | use: (fn) => Effect.promise(() => fn(fakeClient)), | ||
| 31 | trackExecution: () => Effect.void, | ||
| 32 | }; | ||
| 33 | }; | ||
| 34 | |||
| 35 | export const AutumnTestLayer = (state: AutumnTestState) => | ||
| 36 | Layer.succeed(AutumnService)(makeAutumnTestService(state)); | ||
| @@ -48,7 +48,11 @@ const make = Effect.sync(() => { · 47 unmodified lines | |||
| 48 | } satisfies IAutumnService; | 48 | } satisfies IAutumnService; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | const client = new Autumn({ secretKey }); | 51 | // AUTUMN_API_URL points the real SDK at an Autumn emulator in tests/dev. |
| 52 | const client = new Autumn({ | ||
| 53 | secretKey, | ||
| 54 | ...(env.AUTUMN_API_URL ? { serverURL: env.AUTUMN_API_URL } : {}), | ||
| 55 | }); | ||
| 52 | 56 | ||
| 53 | const use = <A>(fn: (client: Autumn) => Promise<A>) => | 57 | const use = <A>(fn: (client: Autumn) => Promise<A>) => |
| 54 | Effect.tryPromise({ | 58 | Effect.tryPromise({ |
| @@ -34,7 +34,6 @@ import { · 33 unmodified lines | |||
| 34 | } from "../auth/handlers"; | 34 | } from "../auth/handlers"; |
| 35 | import { CloudAuthApi, CloudAuthPublicApi } from "../auth/api"; | 35 | import { CloudAuthApi, CloudAuthPublicApi } from "../auth/api"; |
| 36 | import { OrgAuthLive, SessionAuthLive } from "../auth/middleware-live"; | 36 | import { OrgAuthLive, SessionAuthLive } from "../auth/middleware-live"; |
| 37 | import { E2E_STUB, E2EStubAutumnLayer } from "../testing/e2e-stub"; | ||
| 38 | import { OrgApi, OrgHttpApi } from "../org/api"; | 37 | import { OrgApi, OrgHttpApi } from "../org/api"; |
| 39 | import { OrgHandlers } from "../org/handlers"; | 38 | import { OrgHandlers } from "../org/handlers"; |
| 40 | import { AutumnService } from "../extensions/billing/service"; | 39 | import { AutumnService } from "../extensions/billing/service"; |
| @@ -75,11 +74,8 @@ export const makeCloudExtensionRoutes = (rsLive: Layer.Layer<DbService | UserSto · 34 unmodified lines | |||
| 75 | const SessionRoutes = HttpApiBuilder.layer(NonProtectedApi).pipe( | 74 | const SessionRoutes = HttpApiBuilder.layer(NonProtectedApi).pipe( |
| 76 | Layer.provide(Layer.mergeAll(CloudAuthPublicHandlers, CloudSessionAuthHandlers)), | 75 | Layer.provide(Layer.mergeAll(CloudAuthPublicHandlers, CloudSessionAuthHandlers)), |
| 77 | Layer.provide(requestScopedMiddleware(rsLive).layer), | 76 | Layer.provide(requestScopedMiddleware(rsLive).layer), |
| 78 | // SessionAuthLive resolves the user from the wos-session cookie via WorkOSClient | ||
| 79 | // — which is the stub under EXECUTOR_E2E_STUB (app.ts), so the user is the cookie | ||
| 80 | // value. Only Autumn is swapped to the free-plan stub here. Off in production. | ||
| 81 | Layer.provideMerge(SessionAuthLive), | 77 | Layer.provideMerge(SessionAuthLive), |
| 82 | Layer.provideMerge(E2E_STUB ? E2EStubAutumnLayer : AutumnService.Default), | 78 | Layer.provideMerge(AutumnService.Default), |
| 83 | Layer.provide(apiPrefixedRouter), | 79 | Layer.provide(apiPrefixedRouter), |
| 84 | ); | 80 | ); |
| 85 | 81 | ||
| @@ -1,21 +0,0 @@ | |||
| 1 | // Env-gated stub layers that turn `vite dev` into a fully-stubbed, logged-in | ||
| 2 | // instance — one target every surface (browser / API / MCP / CLI) can drive, | ||
| 3 | // replacing the bespoke in-process harnesses + e2e-server wiring. | ||
| 4 | // | ||
| 5 | // Enabled by `EXECUTOR_E2E_STUB=1`. NEVER set in production — when unset, the | ||
| 6 | // served route composition is byte-for-byte the real `*Live` layers. | ||
| 7 | import { WorkOSTestLayer, makeWorkOSTestState } from "../auth/workos.test-layer"; | ||
| 8 | import { AutumnTestLayer, makeAutumnTestState } from "../extensions/billing/service.test-layer"; | ||
| 9 | |||
| 10 | export const E2E_STUB = process.env.EXECUTOR_E2E_STUB === "1"; | ||
| 11 | |||
| 12 | // Multi-user stub WorkOS: the `wos-session` cookie value IS the user id, with | ||
| 13 | // per-user membership buckets — so each test/browser picks a fresh user and is | ||
| 14 | // isolated on the one shared instance (no reset). Swapped in for | ||
| 15 | // `CoreSharedServices`, it authenticates every surface (session routes, | ||
| 16 | // /account/me, SSR) with no real WorkOS. | ||
| 17 | const workos = makeWorkOSTestState({ memberships: [], multiUser: true }); | ||
| 18 | const autumn = makeAutumnTestState({}); // no paid subscription → free plan → 3-org limit applies | ||
| 19 | |||
| 20 | export const E2EStubWorkOSLayer = WorkOSTestLayer(workos); | ||
| 21 | export const E2EStubAutumnLayer = AutumnTestLayer(autumn); | ||
| @@ -321,6 +321,8 @@ · 320 unmodified lines | |||
| 321 | "version": "0.0.3", | 321 | "version": "0.0.3", |
| 322 | "dependencies": { | 322 | "dependencies": { |
| 323 | "@executor-js/api": "workspace:*", | 323 | "@executor-js/api": "workspace:*", |
| 324 | "@executor-js/emulate": "^0.6.0", | ||
| 325 | "@executor-js/mcporter": "^0.11.4", | ||
| 324 | "@executor-js/plugin-graphql": "workspace:*", | 326 | "@executor-js/plugin-graphql": "workspace:*", |
| 325 | "@executor-js/plugin-mcp": "workspace:*", | 327 | "@executor-js/plugin-mcp": "workspace:*", |
| 326 | "@executor-js/plugin-openapi": "workspace:*", | 328 | "@executor-js/plugin-openapi": "workspace:*", |
| @@ -1515,6 +1517,8 @@ · 1188 unmodified lines | |||
| 1515 | 1517 | ||
| 1516 | "@executor-js/e2e": ["@executor-js/e2e@workspace:e2e"], | 1518 | "@executor-js/e2e": ["@executor-js/e2e@workspace:e2e"], |
| 1517 | 1519 | ||
| 1520 | "@executor-js/emulate": ["@executor-js/emulate@0.6.0", "", { "dependencies": { "commander": "^14", "graphql": "^16.9.0", "jose": "^6", "picocolors": "^1.1.1", "yaml": "^2" }, "bin": { "emulate": "dist/index.js" } }, "sha512-GtQsuLRZhD8LKu57IuHsHlLpTgho+JMhkvdFfj/DGsFlm7Gs4KzlUP7fuuZ/zrf/c7ue1urdUNEO1I2y0/a2pg=="], | ||
| 1521 | |||
| 1518 | "@executor-js/example-all-plugins": ["@executor-js/example-all-plugins@workspace:examples/all-plugins"], | 1522 | "@executor-js/example-all-plugins": ["@executor-js/example-all-plugins@workspace:examples/all-plugins"], |
| 1519 | 1523 | ||
| 1520 | "@executor-js/example-docs-sdk-quickstart": ["@executor-js/example-docs-sdk-quickstart@workspace:examples/docs-sdk-quickstart"], | 1524 | "@executor-js/example-docs-sdk-quickstart": ["@executor-js/example-docs-sdk-quickstart@workspace:examples/docs-sdk-quickstart"], |
| @@ -1539,6 +1543,8 @@ · 18 unmodified lines | |||
| 1539 | 1543 | ||
| 1540 | "@executor-js/marketing": ["@executor-js/marketing@workspace:apps/marketing"], | 1544 | "@executor-js/marketing": ["@executor-js/marketing@workspace:apps/marketing"], |
| 1541 | 1545 | ||
| 1546 | "@executor-js/mcporter": ["@executor-js/mcporter@0.11.4", "", { "dependencies": { "@iarna/toml": "^2.2.5", "@modelcontextprotocol/sdk": "^1.29.0", "acorn": "^8.16.0", "commander": "^14.0.3", "es-toolkit": "^1.47.0", "jsonc-parser": "^3.3.1", "ora": "^9.4.0", "rolldown": "1.0.1", "zod": "^4.3.6" }, "bin": { "mcporter": "dist/cli.js" } }, "sha512-KewlNnqmzSkJAH7JS/2le9WxPWzL/ND7Pt/G5KGgfrSK9K9cE8UPIsEYZYZUJYoFnbCBzhlU9ugg59ptv1h3Ow=="], | ||
| 1547 | |||
| 1542 | "@executor-js/plugin-desktop-settings": ["@executor-js/plugin-desktop-settings@workspace:packages/plugins/desktop-settings"], | 1548 | "@executor-js/plugin-desktop-settings": ["@executor-js/plugin-desktop-settings@workspace:packages/plugins/desktop-settings"], |
| 1543 | 1549 | ||
| 1544 | "@executor-js/plugin-encrypted-secrets": ["@executor-js/plugin-encrypted-secrets@workspace:packages/plugins/encrypted-secrets"], | 1550 | "@executor-js/plugin-encrypted-secrets": ["@executor-js/plugin-encrypted-secrets@workspace:packages/plugins/encrypted-secrets"], |
| @@ -1607,6 +1613,8 @@ · 62 unmodified lines | |||
| 1607 | 1613 | ||
| 1608 | "@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="], | 1614 | "@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="], |
| 1609 | 1615 | ||
| 1616 | "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], | ||
| 1617 | |||
| 1610 | "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], | 1618 | "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], |
| 1611 | 1619 | ||
| 1612 | "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="], | 1620 | "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="], |
| @@ -3301,7 +3309,7 @@ · 1688 unmodified lines | |||
| 3301 | 3309 | ||
| 3302 | "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], | 3310 | "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], |
| 3303 | 3311 | ||
| 3304 | "es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="], | 3312 | "es-toolkit": ["es-toolkit@1.47.0", "", {}, "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw=="], |
| 3305 | 3313 | ||
| 3306 | "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], | 3314 | "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], |
| 3307 | 3315 | ||
| @@ -3851,7 +3859,7 @@ · 543 unmodified lines | |||
| 3851 | 3859 | ||
| 3852 | "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], | 3860 | "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], |
| 3853 | 3861 | ||
| 3854 | "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], | 3862 | "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="], |
| 3855 | 3863 | ||
| 3856 | "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], | 3864 | "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], |
| 3857 | 3865 | ||
| @@ -4147,7 +4155,7 @@ · 289 unmodified lines | |||
| 4147 | 4155 | ||
| 4148 | "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], | 4156 | "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], |
| 4149 | 4157 | ||
| 4150 | "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], | 4158 | "ora": ["ora@9.4.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.3.2", "string-width": "^8.1.0" } }, "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ=="], |
| 4151 | 4159 | ||
| 4152 | "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], | 4160 | "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], |
| 4153 | 4161 | ||
| @@ -4685,7 +4693,7 @@ · 531 unmodified lines | |||
| 4685 | 4693 | ||
| 4686 | "std-env": ["std-env@4.1.0", "", {}, "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ=="], | 4694 | "std-env": ["std-env@4.1.0", "", {}, "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ=="], |
| 4687 | 4695 | ||
| 4688 | "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], | 4696 | "stdin-discarder": ["stdin-discarder@0.3.2", "", {}, "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A=="], |
| 4689 | 4697 | ||
| 4690 | "streamdown": ["streamdown@2.5.0", "", { "dependencies": { "clsx": "^2.1.1", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", "marked": "^17.0.1", "mermaid": "^11.12.2", "rehype-harden": "^1.1.8", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remend": "1.3.0", "tailwind-merge": "^3.4.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-/tTnURfIOxZK/pqJAxsfCvETG/XCJHoWnk3jq9xLcuz6CSpnjjuxSRBTTL4PKGhxiZQf0lqPxGhImdpwcZ2XwA=="], | 4698 | "streamdown": ["streamdown@2.5.0", "", { "dependencies": { "clsx": "^2.1.1", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", "marked": "^17.0.1", "mermaid": "^11.12.2", "rehype-harden": "^1.1.8", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remend": "1.3.0", "tailwind-merge": "^3.4.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-/tTnURfIOxZK/pqJAxsfCvETG/XCJHoWnk3jq9xLcuz6CSpnjjuxSRBTTL4PKGhxiZQf0lqPxGhImdpwcZ2XwA=="], |
| 4691 | 4699 | ||
| @@ -5135,12 +5143,20 @@ · 443 unmodified lines | |||
| 5135 | 5143 | ||
| 5136 | "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], | 5144 | "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], |
| 5137 | 5145 | ||
| 5146 | "@executor-js/emulate/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], | ||
| 5147 | |||
| 5148 | "@executor-js/emulate/jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="], | ||
| 5149 | |||
| 5138 | "@executor-js/example-all-plugins/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], | 5150 | "@executor-js/example-all-plugins/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], |
| 5139 | 5151 | ||
| 5140 | "@executor-js/example-promise-sdk/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], | 5152 | "@executor-js/example-promise-sdk/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], |
| 5141 | 5153 | ||
| 5142 | "@executor-js/fumadb/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], | 5154 | "@executor-js/fumadb/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], |
| 5143 | 5155 | ||
| 5156 | "@executor-js/mcporter/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], | ||
| 5157 | |||
| 5158 | "@executor-js/mcporter/rolldown": ["rolldown@1.0.1", "", { "dependencies": { "@oxc-project/types": "=0.130.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.1", "@rolldown/binding-darwin-arm64": "1.0.1", "@rolldown/binding-darwin-x64": "1.0.1", "@rolldown/binding-freebsd-x64": "1.0.1", "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", "@rolldown/binding-linux-arm64-gnu": "1.0.1", "@rolldown/binding-linux-arm64-musl": "1.0.1", "@rolldown/binding-linux-ppc64-gnu": "1.0.1", "@rolldown/binding-linux-s390x-gnu": "1.0.1", "@rolldown/binding-linux-x64-gnu": "1.0.1", "@rolldown/binding-linux-x64-musl": "1.0.1", "@rolldown/binding-openharmony-arm64": "1.0.1", "@rolldown/binding-wasm32-wasi": "1.0.1", "@rolldown/binding-win32-arm64-msvc": "1.0.1", "@rolldown/binding-win32-x64-msvc": "1.0.1" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ=="], | ||
| 5159 | |||
| 5144 | "@graphql-tools/executor/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], | 5160 | "@graphql-tools/executor/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], |
| 5145 | 5161 | ||
| 5146 | "@graphql-tools/merge/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], | 5162 | "@graphql-tools/merge/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], |
| @@ -5161,14 +5177,20 @@ · 14 unmodified lines | |||
| 5161 | 5177 | ||
| 5162 | "@lobehub/fluent-emoji/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], | 5178 | "@lobehub/fluent-emoji/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], |
| 5163 | 5179 | ||
| 5180 | "@lobehub/fluent-emoji/es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="], | ||
| 5181 | |||
| 5164 | "@lobehub/fluent-emoji/lucide-react": ["lucide-react@0.562.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw=="], | 5182 | "@lobehub/fluent-emoji/lucide-react": ["lucide-react@0.562.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw=="], |
| 5165 | 5183 | ||
| 5184 | "@lobehub/icons/es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="], | ||
| 5185 | |||
| 5166 | "@lobehub/icons/lucide-react": ["lucide-react@0.469.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw=="], | 5186 | "@lobehub/icons/lucide-react": ["lucide-react@0.469.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw=="], |
| 5167 | 5187 | ||
| 5168 | "@lobehub/ui/@base-ui/react": ["@base-ui/react@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@base-ui/utils": "0.2.3", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "tabbable": "^6.3.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-4USBWz++DUSLTuIYpbYkSgy1F9ZmNG9S/lXvlUN6qMK0P0RlW+6eQmDUB4DgZ7HVvtXl4pvi4z5J2fv6Z3+9hg=="], | 5188 | "@lobehub/ui/@base-ui/react": ["@base-ui/react@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@base-ui/utils": "0.2.3", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "tabbable": "^6.3.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-4USBWz++DUSLTuIYpbYkSgy1F9ZmNG9S/lXvlUN6qMK0P0RlW+6eQmDUB4DgZ7HVvtXl4pvi4z5J2fv6Z3+9hg=="], |
| 5169 | 5189 | ||
| 5170 | "@lobehub/ui/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], | 5190 | "@lobehub/ui/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], |
| 5171 | 5191 | ||
| 5192 | "@lobehub/ui/es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="], | ||
| 5193 | |||
| 5172 | "@lobehub/ui/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="], | 5194 | "@lobehub/ui/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="], |
| 5173 | 5195 | ||
| 5174 | "@lobehub/ui/marked": ["marked@17.0.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA=="], | 5196 | "@lobehub/ui/marked": ["marked@17.0.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA=="], |
| @@ -5297,6 +5319,8 @@ · 122 unmodified lines | |||
| 5297 | 5319 | ||
| 5298 | "@react-grab/cli/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], | 5320 | "@react-grab/cli/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], |
| 5299 | 5321 | ||
| 5322 | "@react-grab/cli/ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], | ||
| 5323 | |||
| 5300 | "@reduxjs/toolkit/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="], | 5324 | "@reduxjs/toolkit/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="], |
| 5301 | 5325 | ||
| 5302 | "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], | 5326 | "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], |
| @@ -5471,6 +5495,8 @@ · 168 unmodified lines | |||
| 5471 | 5495 | ||
| 5472 | "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], | 5496 | "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], |
| 5473 | 5497 | ||
| 5498 | "ink/es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="], | ||
| 5499 | |||
| 5474 | "ink/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], | 5500 | "ink/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], |
| 5475 | 5501 | ||
| 5476 | "ink/type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="], | 5502 | "ink/type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="], |
| @@ -5483,8 +5509,6 @@ · 6 unmodified lines | |||
| 5483 | 5509 | ||
| 5484 | "libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], | 5510 | "libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], |
| 5485 | 5511 | ||
| 5486 | "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], | ||
| 5487 | |||
| 5488 | "matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], | 5512 | "matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], |
| 5489 | 5513 | ||
| 5490 | "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], | 5514 | "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], |
| @@ -5513,9 +5537,7 @@ · 22 unmodified lines | |||
| 5513 | 5537 | ||
| 5514 | "ora/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], | 5538 | "ora/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], |
| 5515 | 5539 | ||
| 5516 | "ora/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], | 5540 | "ora/cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="], |
| 5517 | |||
| 5518 | "ora/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], | ||
| 5519 | 5541 | ||
| 5520 | "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], | 5542 | "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], |
| 5521 | 5543 | ||
| @@ -5555,6 +5577,8 @@ · 33 unmodified lines | |||
| 5555 | 5577 | ||
| 5556 | "readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], | 5578 | "readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], |
| 5557 | 5579 | ||
| 5580 | "recharts/es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="], | ||
| 5581 | |||
| 5558 | "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], | 5582 | "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], |
| 5559 | 5583 | ||
| 5560 | "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], | 5584 | "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], |
| @@ -5773,6 +5797,40 @@ · 212 unmodified lines | |||
| 5773 | 5797 | ||
| 5774 | "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], | 5798 | "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], |
| 5775 | 5799 | ||
| 5800 | "@executor-js/mcporter/rolldown/@oxc-project/types": ["@oxc-project/types@0.130.0", "", {}, "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q=="], | ||
| 5801 | |||
| 5802 | "@executor-js/mcporter/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.1", "", { "os": "android", "cpu": "arm64" }, "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg=="], | ||
| 5803 | |||
| 5804 | "@executor-js/mcporter/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg=="], | ||
| 5805 | |||
| 5806 | "@executor-js/mcporter/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg=="], | ||
| 5807 | |||
| 5808 | "@executor-js/mcporter/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw=="], | ||
| 5809 | |||
| 5810 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ=="], | ||
| 5811 | |||
| 5812 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A=="], | ||
| 5813 | |||
| 5814 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg=="], | ||
| 5815 | |||
| 5816 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg=="], | ||
| 5817 | |||
| 5818 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ=="], | ||
| 5819 | |||
| 5820 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw=="], | ||
| 5821 | |||
| 5822 | "@executor-js/mcporter/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ=="], | ||
| 5823 | |||
| 5824 | "@executor-js/mcporter/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.1", "", { "os": "none", "cpu": "arm64" }, "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ=="], | ||
| 5825 | |||
| 5826 | "@executor-js/mcporter/rolldown/@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.1", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ=="], | ||
| 5827 | |||
| 5828 | "@executor-js/mcporter/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw=="], | ||
| 5829 | |||
| 5830 | "@executor-js/mcporter/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.1", "", { "os": "win32", "cpu": "x64" }, "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ=="], | ||
| 5831 | |||
| 5832 | "@executor-js/mcporter/rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], | ||
| 5833 | |||
| 5776 | "@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], | 5834 | "@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], |
| 5777 | 5835 | ||
| 5778 | "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], | 5836 | "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], |
| @@ -5809,6 +5867,16 @@ · 30 unmodified lines | |||
| 5809 | 5867 | ||
| 5810 | "@pierre/diffs/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], | 5868 | "@pierre/diffs/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], |
| 5811 | 5869 | ||
| 5870 | "@react-grab/cli/ora/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], | ||
| 5871 | |||
| 5872 | "@react-grab/cli/ora/log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], | ||
| 5873 | |||
| 5874 | "@react-grab/cli/ora/stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], | ||
| 5875 | |||
| 5876 | "@react-grab/cli/ora/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], | ||
| 5877 | |||
| 5878 | "@react-grab/cli/ora/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], | ||
| 5879 | |||
| 5812 | "@types/better-sqlite3/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], | 5880 | "@types/better-sqlite3/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], |
| 5813 | 5881 | ||
| 5814 | "@types/cacheable-request/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], | 5882 | "@types/cacheable-request/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], |
| @@ -6043,10 +6111,6 @@ · 228 unmodified lines | |||
| 6043 | 6111 | ||
| 6044 | "ora/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], | 6112 | "ora/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], |
| 6045 | 6113 | ||
| 6046 | "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], | ||
| 6047 | |||
| 6048 | "ora/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], | ||
| 6049 | |||
| 6050 | "posthog-js/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="], | 6114 | "posthog-js/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="], |
| 6051 | 6115 | ||
| 6052 | "posthog-js/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.208.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-transformer": "0.208.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA=="], | 6116 | "posthog-js/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.208.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-transformer": "0.208.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA=="], |
| @@ -6237,6 +6301,10 @@ · 184 unmodified lines | |||
| 6237 | 6301 | ||
| 6238 | "@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], | 6302 | "@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], |
| 6239 | 6303 | ||
| 6304 | "@executor-js/mcporter/rolldown/@rolldown/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], | ||
| 6305 | |||
| 6306 | "@executor-js/mcporter/rolldown/@rolldown/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], | ||
| 6307 | |||
| 6240 | "@inquirer/core/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], | 6308 | "@inquirer/core/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], |
| 6241 | 6309 | ||
| 6242 | "@libsql/kysely-libsql/@libsql/client/@libsql/hrana-client/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], | 6310 | "@libsql/kysely-libsql/@libsql/client/@libsql/hrana-client/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], |
| @@ -6257,6 +6325,14 @@ · 14 unmodified lines | |||
| 6257 | 6325 | ||
| 6258 | "@libsql/kysely-libsql/@libsql/client/libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], | 6326 | "@libsql/kysely-libsql/@libsql/client/libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], |
| 6259 | 6327 | ||
| 6328 | "@react-grab/cli/ora/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], | ||
| 6329 | |||
| 6330 | "@react-grab/cli/ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], | ||
| 6331 | |||
| 6332 | "@react-grab/cli/ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], | ||
| 6333 | |||
| 6334 | "@react-grab/cli/ora/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], | ||
| 6335 | |||
| 6260 | "agents/yargs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], | 6336 | "agents/yargs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], |
| 6261 | 6337 | ||
| 6262 | "agents/yargs/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], | 6338 | "agents/yargs/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], |
| @@ -6293,6 +6369,8 @@ · 30 unmodified lines | |||
| 6293 | 6369 | ||
| 6294 | "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], | 6370 | "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], |
| 6295 | 6371 | ||
| 6372 | "@react-grab/cli/ora/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], | ||
| 6373 | |||
| 6296 | "agents/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], | 6374 | "agents/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], |
| 6297 | 6375 | ||
| 6298 | "agents/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], | 6376 | "agents/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], |
| @@ -41,10 +41,14 @@ scenario( · 40 unmodified lines | |||
| 41 | 41 | ||
| 42 | const openCreateOrgModal = async (currentOrg: string) => { | 42 | const openCreateOrgModal = async (currentOrg: string) => { |
| 43 | await page.getByRole("button", { name: /Test User/ }).click(); | 43 | await page.getByRole("button", { name: /Test User/ }).click(); |
| 44 | // The org entry + "Create organization" are radix menu items; role | 44 | // The org entry is a radix submenu trigger; its content loads the |
| 45 | // locators keep us off the look-alike trigger button beneath. | 45 | // org list from the API, so wait for the sub-content to mount and |
| 46 | // click "Create organization" scoped INSIDE it — clicking during | ||
| 47 | // the loading re-render dismisses the whole menu. | ||
| 46 | await page.getByRole("menuitem", { name: currentOrg }).click(); | 48 | await page.getByRole("menuitem", { name: currentOrg }).click(); |
| 47 | await page.getByRole("menuitem", { name: "Create organization" }).click(); | 49 | const subContent = page.locator('[data-slot="dropdown-menu-sub-content"]'); |
| 50 | await subContent.waitFor({ state: "visible" }); | ||
| 51 | await subContent.getByText("Create organization", { exact: true }).click(); | ||
| 48 | await page.getByText("Add another organization").waitFor(); | 52 | await page.getByText("Add another organization").waitFor(); |
| 49 | }; | 53 | }; |
| 50 | 54 | ||
| @@ -45,7 +45,9 @@ scenario( · 44 unmodified lines | |||
| 45 | await step('Open the org switcher and choose "Create organization"', async () => { | 45 | await step('Open the org switcher and choose "Create organization"', async () => { |
| 46 | await page.getByRole("button", { name: /Test User/ }).click(); | 46 | await page.getByRole("button", { name: /Test User/ }).click(); |
| 47 | await page.getByRole("menuitem", { name: ORG_1 }).click(); | 47 | await page.getByRole("menuitem", { name: ORG_1 }).click(); |
| 48 | await page.getByRole("menuitem", { name: "Create organization" }).click(); | 48 | const subContent = page.locator('[data-slot="dropdown-menu-sub-content"]'); |
| 49 | await subContent.waitFor({ state: "visible" }); | ||
| 50 | await subContent.getByText("Create organization", { exact: true }).click(); | ||
| 49 | await page.getByText("Add another organization").waitFor(); | 51 | await page.getByText("Add another organization").waitFor(); |
| 50 | }); | 52 | }); |
| 51 | 53 | ||
| @@ -13,6 +13,8 @@ · 12 unmodified lines | |||
| 13 | }, | 13 | }, |
| 14 | "dependencies": { | 14 | "dependencies": { |
| 15 | "@executor-js/api": "workspace:*", | 15 | "@executor-js/api": "workspace:*", |
| 16 | "@executor-js/emulate": "^0.6.0", | ||
| 17 | "@executor-js/mcporter": "^0.11.4", | ||
| 16 | "@executor-js/plugin-graphql": "workspace:*", | 18 | "@executor-js/plugin-graphql": "workspace:*", |
| 17 | "@executor-js/plugin-mcp": "workspace:*", | 19 | "@executor-js/plugin-mcp": "workspace:*", |
| 18 | "@executor-js/plugin-openapi": "workspace:*", | 20 | "@executor-js/plugin-openapi": "workspace:*", |
| @@ -72,13 +72,18 @@ export const bootProcesses = ( · 71 unmodified lines | |||
| 72 | }; | 72 | }; |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | export const waitForHttp = async (url: string, timeoutMs = 90_000): Promise<void> => { | 75 | export const waitForHttp = async ( |
| 76 | const deadline = Date.now() + timeoutMs; | 76 | url: string, |
| 77 | options: { readonly timeoutMs?: number; readonly expectRedirect?: boolean } = {}, | ||
| 78 | ): Promise<void> => { | ||
| 79 | const deadline = Date.now() + (options.timeoutMs ?? 90_000); | ||
| 77 | let lastError: unknown; | 80 | let lastError: unknown; |
| 78 | while (Date.now() < deadline) { | 81 | while (Date.now() < deadline) { |
| 79 | try { | 82 | try { |
| 80 | const response = await fetch(url, { redirect: "manual" }); | 83 | const response = await fetch(url, { redirect: "manual" }); |
| 81 | if (response.status < 500) return; | 84 | // During a cold vite compile /api/* falls back to the SPA's 200 HTML — |
| 85 | // expectRedirect waits for the real handler (302) instead. | ||
| 86 | if (options.expectRedirect ? response.status === 302 : response.status < 500) return; | ||
| 82 | lastError = new Error(`status ${response.status}`); | 87 | lastError = new Error(`status ${response.status}`); |
| 83 | } catch (error) { | 88 | } catch (error) { |
| 84 | lastError = error; | 89 | lastError = error; |
| @@ -1,14 +1,25 @@ | |||
| 1 | // Boot the cloud target: the app's OWN dev stack (PGlite dev-db + vite dev) | 1 | // Boot the cloud target: WorkOS + Autumn EMULATORS (in this process, from the |
| 2 | // with EXECUTOR_E2E_STUB=1 — the one flag that makes `vite dev` a logged-in, | 2 | // vendored emulate fork) plus the app's own dev stack (PGlite dev-db + vite |
| 3 | // fully-stubbed instance (multi-user WorkOS stub, free-plan Autumn, no | 3 | // dev) pointed at them via WORKOS_API_URL / AUTUMN_API_URL. The app runs its |
| 4 | // network). Set E2E_CLOUD_URL to attach to an already-running instance | 4 | // REAL auth/billing code — real SDKs, real sealed-session crypto, real JWKS — |
| 5 | // instead (e.g. while iterating on a scenario). | 5 | // against emulated services. Set E2E_CLOUD_URL to attach to a running stack. |
| 6 | import { rmSync } from "node:fs"; | 6 | import { rmSync } from "node:fs"; |
| 7 | import { resolve } from "node:path"; | 7 | import { resolve } from "node:path"; |
| 8 | import { fileURLToPath } from "node:url"; | 8 | import { fileURLToPath } from "node:url"; |
| 9 | 9 | ||
| 10 | // Vendored fork import (same pattern as mcporter). | ||
| 11 | import { createEmulator } from "@executor-js/emulate"; | ||
| 12 | |||
| 10 | import { bootProcesses, waitForHttp } from "./boot"; | 13 | import { bootProcesses, waitForHttp } from "./boot"; |
| 11 | import { CLOUD_BASE_URL, CLOUD_DB_PORT, CLOUD_PORT } from "../targets/cloud"; | 14 | import { |
| 15 | CLOUD_BASE_URL, | ||
| 16 | CLOUD_DB_PORT, | ||
| 17 | CLOUD_PORT, | ||
| 18 | WORKOS_EMULATOR_PORT, | ||
| 19 | AUTUMN_EMULATOR_PORT, | ||
| 20 | E2E_WORKOS_CLIENT_ID, | ||
| 21 | E2E_COOKIE_PASSWORD, | ||
| 22 | } from "../targets/cloud"; | ||
| 12 | 23 | ||
| 13 | const cloudDir = fileURLToPath(new URL("../../apps/cloud/", import.meta.url)); | 24 | const cloudDir = fileURLToPath(new URL("../../apps/cloud/", import.meta.url)); |
| 14 | 25 | ||
| @@ -18,31 +29,36 @@ export default async function setup(): Promise<(() => Promise<void>) | void> { · 3 unmodified lines | |||
| 18 | return; | 29 | return; |
| 19 | } | 30 | } |
| 20 | 31 | ||
| 21 | // Fresh stub DB per suite run — hermetic, like the selfhost data dir. The | 32 | // Fresh dev DB per suite run — hermetic, like the selfhost data dir. The |
| 22 | // WorkOS stub mints org ids from a per-process counter, so a persisted DB | 33 | // WorkOS emulator mints org ids from a per-process counter, so a persisted |
| 23 | // from a previous invocation collides with the new boot's ids (identities | 34 | // DB from a previous invocation collides with the new boot's ids (identities |
| 24 | // land in polluted orgs / org creation 500s). | 35 | // land in polluted orgs / org creation 500s). |
| 25 | const dbPath = resolve(cloudDir, ".e2e-stub-db"); | 36 | const dbPath = resolve(cloudDir, ".e2e-stub-db"); |
| 26 | rmSync(dbPath, { recursive: true, force: true }); | 37 | rmSync(dbPath, { recursive: true, force: true }); |
| 27 | 38 | ||
| 39 | // MCP access tokens minted by the emulator's OAuth server must carry the | ||
| 40 | // app's client id as audience (what the resource server verifies). | ||
| 41 | process.env.EMULATE_WORKOS_AUDIENCE = E2E_WORKOS_CLIENT_ID; | ||
| 42 | const workos = await createEmulator({ service: "workos", port: WORKOS_EMULATOR_PORT }); | ||
| 43 | const autumn = await createEmulator({ service: "autumn", port: AUTUMN_EMULATOR_PORT }); | ||
| 44 | |||
| 28 | const env = { | 45 | const env = { |
| 29 | EXECUTOR_E2E_STUB: "1", | 46 | // Real client, emulated service. |
| 30 | // The harness boots loopback MCP/OAuth test servers and points the | 47 | WORKOS_API_URL: workos.url, |
| 31 | // instance at them; the hosted SSRF guard would otherwise block outbound | 48 | AUTUMN_API_URL: autumn.url, |
| 32 | // probes/dials to localhost. Hermetic stub instance only. | 49 | WORKOS_API_KEY: "sk_test_emulate", |
| 33 | ALLOW_LOCAL_NETWORK: "true", | 50 | WORKOS_CLIENT_ID: E2E_WORKOS_CLIENT_ID, |
| 34 | // Stub creds — never contacted; the stub layers replace the clients. | 51 | WORKOS_COOKIE_PASSWORD: E2E_COOKIE_PASSWORD, |
| 35 | WORKOS_API_KEY: "sk_e2e_stub", | 52 | AUTUMN_SECRET_KEY: "am_test_emulate", |
| 36 | WORKOS_CLIENT_ID: "client_e2e_stub", | ||
| 37 | WORKOS_COOKIE_PASSWORD: "e2e_cookie_password_0123456789abcdef0123456789abcdef", | ||
| 38 | AUTUMN_SECRET_KEY: "am_e2e_stub", | ||
| 39 | ENCRYPTION_KEY: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", | 53 | ENCRYPTION_KEY: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", |
| 40 | DATABASE_URL: `postgresql://postgres:postgres@127.0.0.1:${CLOUD_DB_PORT}/postgres`, | 54 | DATABASE_URL: `postgresql://postgres:postgres@127.0.0.1:${CLOUD_DB_PORT}/postgres`, |
| 41 | EXECUTOR_DIRECT_DATABASE_URL: "true", | 55 | EXECUTOR_DIRECT_DATABASE_URL: "true", |
| 42 | CLOUDFLARE_INCLUDE_PROCESS_ENV: "true", | 56 | CLOUDFLARE_INCLUDE_PROCESS_ENV: "true", |
| 43 | VITE_PUBLIC_SITE_URL: CLOUD_BASE_URL, | 57 | VITE_PUBLIC_SITE_URL: CLOUD_BASE_URL, |
| 44 | MCP_AUTHKIT_DOMAIN: "https://example.com", | 58 | // The AuthKit domain (MCP OAuth metadata + JWKS) is the emulator too. |
| 59 | MCP_AUTHKIT_DOMAIN: workos.url, | ||
| 45 | MCP_RESOURCE_ORIGIN: CLOUD_BASE_URL, | 60 | MCP_RESOURCE_ORIGIN: CLOUD_BASE_URL, |
| 61 | ALLOW_LOCAL_NETWORK: "true", | ||
| 46 | // Throwaway PGlite on its own port + dir so it never fights `bun dev`. | 62 | // Throwaway PGlite on its own port + dir so it never fights `bun dev`. |
| 47 | DEV_DB_PORT: String(CLOUD_DB_PORT), | 63 | DEV_DB_PORT: String(CLOUD_DB_PORT), |
| 48 | DEV_DB_PATH: dbPath, | 64 | DEV_DB_PATH: dbPath, |
| @@ -63,9 +79,17 @@ export default async function setup(): Promise<(() => Promise<void>) | void> { · 14 unmodified lines | |||
| 63 | 79 | ||
| 64 | try { | 80 | try { |
| 65 | await waitForHttp(CLOUD_BASE_URL); | 81 | await waitForHttp(CLOUD_BASE_URL); |
| 82 | // The API plane is ready when login actually redirects to AuthKit. | ||
| 83 | await waitForHttp(`${CLOUD_BASE_URL}/api/auth/login`, { expectRedirect: true }); | ||
| 66 | } catch (error) { | 84 | } catch (error) { |
| 67 | await procs.teardown(); | 85 | await procs.teardown(); |
| 86 | await workos.close(); | ||
| 87 | await autumn.close(); | ||
| 68 | throw error; | 88 | throw error; |
| 69 | } | 89 | } |
| 70 | return procs.teardown; | 90 | return async () => { |
| 91 | await procs.teardown(); | ||
| 92 | await workos.close(); | ||
| 93 | await autumn.close(); | ||
| 94 | }; | ||
| 71 | } | 95 | } |
| @@ -8,7 +8,7 @@ import { join } from "node:path"; · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | import { Effect } from "effect"; | 9 | import { Effect } from "effect"; |
| 10 | 10 | ||
| 11 | import { createRuntime, type Runtime } from "../../../vendor/mcporter/dist/index.js"; | 11 | import { createRuntime, type Runtime } from "@executor-js/mcporter"; |
| 12 | 12 | ||
| 13 | import type { Identity, Target } from "../target"; | 13 | import type { Identity, Target } from "../target"; |
| 14 | 14 | ||
| @@ -1,8 +1,9 @@ | |||
| 1 | // The cloud app as a target: the stubbed dev server (`vite dev` + | 1 | // The cloud app as a target: its real dev server with the real WorkOS and |
| 2 | // EXECUTOR_E2E_STUB=1) — real SSR, real routes, real PGlite-backed DB, WorkOS | 2 | // Autumn SDKs pointed at emulators (WORKOS_API_URL / AUTUMN_API_URL — see |
| 3 | // and Autumn stubbed in-memory. Isolation: the stub resolves the user FROM the | 3 | // setup/cloud.globalsetup.ts). Identities are minted through the REAL login |
| 4 | // wos-session cookie value, so every identity is a fresh user (and org) on the | 4 | // flow: /api/auth/login → emulator hosted AuthKit (headless via login_hint) → |
| 5 | // one shared instance — no resets. Boot lives in setup/cloud.globalsetup.ts. | 5 | // /api/auth/callback → genuine sealed-session cookie. Isolation: every |
| 6 | // identity is a fresh user (and org) — no resets. | ||
| 6 | import { randomUUID } from "node:crypto"; | 7 | import { randomUUID } from "node:crypto"; |
| 7 | 8 | ||
| 8 | import { Effect } from "effect"; | 9 | import { Effect } from "effect"; |
| @@ -12,46 +13,90 @@ import type { Identity, Target } from "../src/target"; · 3 unmodified lines | |||
| 12 | export const CLOUD_PORT = Number(process.env.E2E_CLOUD_PORT ?? 4798); | 13 | export const CLOUD_PORT = Number(process.env.E2E_CLOUD_PORT ?? 4798); |
| 13 | export const CLOUD_DB_PORT = Number(process.env.E2E_CLOUD_DB_PORT ?? 5436); | 14 | export const CLOUD_DB_PORT = Number(process.env.E2E_CLOUD_DB_PORT ?? 5436); |
| 14 | export const CLOUD_BASE_URL = process.env.E2E_CLOUD_URL ?? `http://127.0.0.1:${CLOUD_PORT}`; | 15 | export const CLOUD_BASE_URL = process.env.E2E_CLOUD_URL ?? `http://127.0.0.1:${CLOUD_PORT}`; |
| 16 | export const WORKOS_EMULATOR_PORT = Number(process.env.E2E_WORKOS_EMULATOR_PORT ?? 4914); | ||
| 17 | export const AUTUMN_EMULATOR_PORT = Number(process.env.E2E_AUTUMN_EMULATOR_PORT ?? 4915); | ||
| 18 | export const E2E_WORKOS_CLIENT_ID = "client_e2e_emulate"; | ||
| 19 | export const E2E_COOKIE_PASSWORD = "e2e_cookie_password_0123456789abcdef0123456789abcdef"; | ||
| 15 | 20 | ||
| 16 | const freshId = () => randomUUID().slice(0, 8); | 21 | const cookiePair = (response: Response, name: string): string | undefined => { |
| 22 | for (const header of response.headers.getSetCookie?.() ?? []) { | ||
| 23 | if (header.startsWith(`${name}=`)) return header.split(";")[0]; | ||
| 24 | } | ||
| 25 | return undefined; | ||
| 26 | }; | ||
| 27 | |||
| 28 | /** The real product login, headless: login → hosted AuthKit → callback. */ | ||
| 29 | const signIn = async (email: string): Promise<string> => { | ||
| 30 | const login = await fetch(new URL("/api/auth/login", CLOUD_BASE_URL), { redirect: "manual" }); | ||
| 31 | const stateCookie = cookiePair(login, "wos-login-state"); | ||
| 32 | const authorizeUrl = new URL(login.headers.get("location") ?? ""); | ||
| 33 | if (!stateCookie || !authorizeUrl.searchParams.get("state")) { | ||
| 34 | throw new Error(`cloud signIn: login did not redirect to AuthKit (${login.status})`); | ||
| 35 | } | ||
| 36 | // The emulator's hosted login signs in headlessly via login_hint (creating | ||
| 37 | // the user if new) and redirects back with a code. | ||
| 38 | authorizeUrl.searchParams.set("login_hint", email); | ||
| 39 | const consent = await fetch(authorizeUrl, { redirect: "manual" }); | ||
| 40 | const callbackUrl = consent.headers.get("location"); | ||
| 41 | if (consent.status !== 302 || !callbackUrl) { | ||
| 42 | throw new Error(`cloud signIn: AuthKit emulator did not redirect (${consent.status})`); | ||
| 43 | } | ||
| 44 | const callback = await fetch(callbackUrl, { | ||
| 45 | redirect: "manual", | ||
| 46 | headers: { cookie: stateCookie }, | ||
| 47 | }); | ||
| 48 | const session = cookiePair(callback, "wos-session"); | ||
| 49 | if (!session) throw new Error(`cloud signIn: callback set no session (${callback.status})`); | ||
| 50 | return session; // "wos-session=<sealed>" | ||
| 51 | }; | ||
| 17 | 52 | ||
| 18 | export const cloudTarget = (): Target => ({ | 53 | export const cloudTarget = (): Target => ({ |
| 19 | name: "cloud", | 54 | name: "cloud", |
| 20 | baseUrl: CLOUD_BASE_URL, | 55 | baseUrl: CLOUD_BASE_URL, |
| 21 | mcpUrl: `${CLOUD_BASE_URL}/mcp`, | 56 | mcpUrl: `${CLOUD_BASE_URL}/mcp`, |
| 22 | capabilities: new Set(["api", "browser", "billing"]), | 57 | capabilities: new Set(["api", "browser", "billing", "mcp-oauth"]), |
| 23 | newIdentity: ({ org = true } = {}) => | 58 | newIdentity: ({ org = true } = {}) => |
| 24 | Effect.promise(async (): Promise<Identity> => { | 59 | Effect.promise(async (): Promise<Identity> => { |
| 25 | const user = `user_${freshId()}`; | 60 | const label = `user-${randomUUID().slice(0, 8)}`; |
| 26 | // The stub WorkOS resolves the user FROM the cookie value; a bare value | 61 | const email = `${label}@e2e.test`; |
| 27 | // is a fresh signed-in user with no organization yet. | 62 | let session = await signIn(email); |
| 28 | let value = user; | ||
| 29 | if (org) { | 63 | if (org) { |
| 30 | // Go through the REAL product flow: create the org via the session | 64 | // The real create-organization flow; the refreshed sealed session in |
| 31 | // route and adopt the refreshed `<user>|org:<org>` cookie it sets — | 65 | // the response carries the new org. |
| 32 | // membership and session state come from the same path real users take. | ||
| 33 | const response = await fetch(new URL("/api/auth/create-organization", CLOUD_BASE_URL), { | 66 | const response = await fetch(new URL("/api/auth/create-organization", CLOUD_BASE_URL), { |
| 34 | method: "POST", | 67 | method: "POST", |
| 35 | headers: { | 68 | headers: { |
| 36 | "content-type": "application/json", | 69 | "content-type": "application/json", |
| 37 | origin: new URL(CLOUD_BASE_URL).origin, | 70 | origin: new URL(CLOUD_BASE_URL).origin, |
| 38 | cookie: `wos-session=${value}`, | 71 | cookie: session, |
| 39 | }, | 72 | }, |
| 40 | body: JSON.stringify({ name: `Org ${user}` }), | 73 | body: JSON.stringify({ name: `Org ${label}` }), |
| 41 | }); | 74 | }); |
| 42 | if (!response.ok) { | 75 | if (!response.ok) { |
| 43 | throw new Error(`cloud newIdentity: create-organization → ${response.status}`); | 76 | throw new Error(`cloud newIdentity: create-organization failed (${response.status})`); |
| 44 | } | 77 | } |
| 45 | const refreshed = (response.headers.getSetCookie?.() ?? []) | 78 | session = cookiePair(response, "wos-session") ?? session; |
| 46 | .map((cookie) => /^wos-session=([^;]+)/.exec(cookie)?.[1]) | ||
| 47 | .find(Boolean); | ||
| 48 | if (!refreshed) throw new Error("cloud newIdentity: no refreshed session cookie"); | ||
| 49 | value = decodeURIComponent(refreshed); | ||
| 50 | } | 79 | } |
| 80 | const [name, value] = session.split(/=(.*)/s); | ||
| 51 | return { | 81 | return { |
| 52 | label: user, | 82 | label: email, |
| 53 | headers: { cookie: `wos-session=${value}` }, | 83 | headers: { cookie: session }, |
| 54 | cookies: [{ name: "wos-session", value }], | 84 | cookies: [{ name: name!, value: value! }], |
| 85 | credentials: { email, password: "emulated" }, | ||
| 55 | }; | 86 | }; |
| 56 | }), | 87 | }), |
| 88 | // MCP OAuth against the emulator's authorization server: complete the | ||
| 89 | // hosted flow headlessly as this identity. | ||
| 90 | mcpConsent: (identity) => async (request) => { | ||
| 91 | const authorizeUrl = new URL(request.authorizationUrl); | ||
| 92 | authorizeUrl.searchParams.set("login_hint", identity.credentials?.email ?? "mcp@e2e.test"); | ||
| 93 | const response = await fetch(authorizeUrl, { redirect: "manual" }); | ||
| 94 | const location = response.headers.get("location"); | ||
| 95 | if (response.status !== 302 || !location) { | ||
| 96 | throw new Error(`cloud mcpConsent: authorize did not redirect (${response.status})`); | ||
| 97 | } | ||
| 98 | const code = new URL(location).searchParams.get("code"); | ||
| 99 | if (!code) throw new Error("cloud mcpConsent: no code in redirect"); | ||
| 100 | return { code }; | ||
| 101 | }, | ||
| 57 | }); | 102 | }); |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | // in setup/selfhost.globalsetup.ts. | 4 | // in setup/selfhost.globalsetup.ts. |
| 5 | import { Effect } from "effect"; | 5 | import { Effect } from "effect"; |
| 6 | 6 | ||
| 7 | import { cookieConsentStrategy } from "../../vendor/mcporter/dist/index.js"; | 7 | import { cookieConsentStrategy } from "@executor-js/mcporter"; |
| 8 | 8 | ||
| 9 | import type { Identity, Target } from "../src/target"; | 9 | import type { Identity, Target } from "../src/target"; |
| 10 | 10 | ||
| @@ -96,8 +96,22 @@ export interface WorkOSVaultPromiseApi { · 95 unmodified lines | |||
| 96 | export interface WorkOSVaultCredentials { | 96 | export interface WorkOSVaultCredentials { |
| 97 | readonly apiKey: string; | 97 | readonly apiKey: string; |
| 98 | readonly clientId: string; | 98 | readonly clientId: string; |
| 99 | /** Optional WorkOS API base-URL override (e.g. a WorkOS emulator in tests). */ | ||
| 100 | readonly apiUrl?: string; | ||
| 99 | } | 101 | } |
| 100 | 102 | ||
| 103 | const apiUrlOptions = ( | ||
| 104 | url: string | undefined, | ||
| 105 | ): { apiHostname?: string; port?: number; https?: boolean } => { | ||
| 106 | if (!url) return {}; | ||
| 107 | const parsed = new URL(url); | ||
| 108 | return { | ||
| 109 | apiHostname: parsed.hostname, | ||
| 110 | ...(parsed.port ? { port: Number(parsed.port) } : {}), | ||
| 111 | https: parsed.protocol === "https:", | ||
| 112 | }; | ||
| 113 | }; | ||
| 114 | |||
| 101 | interface WorkOSVaultUseOptions { | 115 | interface WorkOSVaultUseOptions { |
| 102 | readonly expectedErrorStatuses?: readonly number[]; | 116 | readonly expectedErrorStatuses?: readonly number[]; |
| 103 | readonly expectedErrorOutcome?: string; | 117 | readonly expectedErrorOutcome?: string; |
| @@ -205,6 +219,7 @@ export const makeConfiguredWorkOSVaultClient = ( · 101 unmodified lines | |||
| 205 | new WorkOSClient({ | 219 | new WorkOSClient({ |
| 206 | apiKey: credentials.apiKey, | 220 | apiKey: credentials.apiKey, |
| 207 | clientId: credentials.clientId, | 221 | clientId: credentials.clientId, |
| 222 | ...apiUrlOptions(credentials.apiUrl), | ||
| 208 | }), | 223 | }), |
| 209 | ), | 224 | ), |
| 210 | catch: (cause) => new WorkOSVaultClientInstantiationError({ cause }), | 225 | catch: (cause) => new WorkOSVaultClientInstantiationError({ cause }), |
| @@ -1 +1 @@ | |||
| 1 | Subproject commit a42fe29889c8a11aa752fc848af5ed71a76fa26e | 1 | Subproject commit 41f09e973c174d4d64c60b9f4ec271cf7ef9c2eb |