diff --git a/.husky/pre-commit b/.husky/pre-commit index 81a0264c..0fbe73b0 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,4 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" + echo "๐Ÿ” Running pre-commit checks..." diff --git a/apps/api/package.json b/apps/api/package.json index 16042526..7bf6ed21 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -43,6 +43,7 @@ "@nexiom/dbmanager": "workspace:*", "@nexiom/engine": "workspace:*", "@nexiom/identity": "workspace:*", + "@nexiom/piece-framework": "workspace:*", "@nexiom/piece-quickbooks": "workspace:*", "@nexiom/piece-salesforce": "workspace:*", "@nexiom/queue": "workspace:*", diff --git a/apps/api/src/modules/connections/connections/callback.controller.spec.ts b/apps/api/src/modules/connections/connections/callback.controller.spec.ts index 3480b648..1210bfe9 100644 --- a/apps/api/src/modules/connections/connections/callback.controller.spec.ts +++ b/apps/api/src/modules/connections/connections/callback.controller.spec.ts @@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { OAuthCallbackController } from './callback.controller.js'; import { PieceRegistryService } from '@nexiom/engine'; -import type { Piece } from '@nexiom/connectors/framework'; +import type { Piece } from '@nexiom/piece-framework'; import type { Request, Response } from 'express'; import { vi, describe, it, expect, beforeEach } from 'vitest'; import type { Mocked } from 'vitest'; diff --git a/apps/api/src/modules/connections/connections/connectors.controller.spec.ts b/apps/api/src/modules/connections/connections/connectors.controller.spec.ts index 32298df3..022555c8 100644 --- a/apps/api/src/modules/connections/connections/connectors.controller.spec.ts +++ b/apps/api/src/modules/connections/connections/connectors.controller.spec.ts @@ -1,4 +1,4 @@ -import type { Piece } from '@nexiom/connectors/framework'; +import type { Piece } from '@nexiom/piece-framework'; /* eslint-disable @typescript-eslint/unbound-method */ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectorsController } from './connectors.controller.js'; diff --git a/apps/api/src/modules/connections/connections/connectors.controller.ts b/apps/api/src/modules/connections/connections/connectors.controller.ts index 22b857f4..d5a860ec 100644 --- a/apps/api/src/modules/connections/connections/connectors.controller.ts +++ b/apps/api/src/modules/connections/connections/connectors.controller.ts @@ -26,7 +26,7 @@ import type { Response } from 'express'; import { AuthContext, type RequestAuthContext, AuthGuard } from '@nexiom/auth'; import { getAdminRoleId, getOwnerRoleId } from '@nexiom/identity/constants'; import { EncryptionService, AppCredentialError } from '@nexiom/connectors'; -import type { AnyProperty } from '@nexiom/connectors'; +import type { AnyProperty } from '@nexiom/piece-framework'; import { ConnectorsService } from '../connectors.service.js'; import { OauthStateService } from '../oauth-state.service.js'; import { diff --git a/apps/api/src/modules/connections/connections/token-refresh.service.spec.ts b/apps/api/src/modules/connections/connections/token-refresh.service.spec.ts index 1d331ff7..678c9e58 100644 --- a/apps/api/src/modules/connections/connections/token-refresh.service.spec.ts +++ b/apps/api/src/modules/connections/connections/token-refresh.service.spec.ts @@ -1,7 +1,7 @@ import { DefaultOAuthRefreshClient } from './token-refresh.service.js'; import { EncryptionService, OAuthRefreshError } from '@nexiom/connectors'; import { PieceRegistryService } from '@nexiom/engine'; -import type { Piece } from '@nexiom/connectors/framework'; +import type { Piece } from '@nexiom/piece-framework'; import { describe, it, diff --git a/apps/api/src/modules/connections/connections/token-refresh.service.ts b/apps/api/src/modules/connections/connections/token-refresh.service.ts index e2226570..3d485838 100644 --- a/apps/api/src/modules/connections/connections/token-refresh.service.ts +++ b/apps/api/src/modules/connections/connections/token-refresh.service.ts @@ -4,7 +4,7 @@ import { OAuthRefreshError, EncryptionService, } from '@nexiom/connectors'; -import { PropertyType, resolveOAuth2Url } from '@nexiom/connectors/framework'; +import { PropertyType, resolveOAuth2Url } from '@nexiom/piece-framework'; import { appConnections, AppConnectionStatus, diff --git a/apps/api/src/modules/connections/connectors.service.spec.ts b/apps/api/src/modules/connections/connectors.service.spec.ts index d99ad1b0..54bd2869 100644 --- a/apps/api/src/modules/connections/connectors.service.spec.ts +++ b/apps/api/src/modules/connections/connectors.service.spec.ts @@ -4,7 +4,7 @@ import { ConfigService } from '@nestjs/config'; import { ConnectorsService } from './connectors.service.js'; import { EncryptionService, AppCredentialError } from '@nexiom/connectors'; import { PieceRegistryService } from '@nexiom/engine'; -import type { Piece } from '@nexiom/connectors/framework'; +import type { Piece } from '@nexiom/piece-framework'; import { DB_MANAGER } from '../dbmanager/dbmanager.module.js'; import { SchemaPlan } from '@nexiom/dbmanager'; import { diff --git a/apps/api/src/modules/connections/connectors.service.ts b/apps/api/src/modules/connections/connectors.service.ts index 20a902f2..24ce4d77 100644 --- a/apps/api/src/modules/connections/connectors.service.ts +++ b/apps/api/src/modules/connections/connectors.service.ts @@ -10,12 +10,10 @@ import { ConflictException, } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { - AppCredentialError, - resolveOAuth2Url, - PropertyType, -} from '@nexiom/connectors'; -import type { OAuth2Auth, OAuthCredentialBlob } from '@nexiom/connectors'; +import { AppCredentialError } from '@nexiom/connectors'; +import { resolveOAuth2Url, PropertyType } from '@nexiom/piece-framework'; +import type { OAuthCredentialBlob } from '@nexiom/connectors'; +import type { OAuth2Auth } from '@nexiom/piece-framework'; import { appConnections, AppConnectionStatus, diff --git a/apps/api/src/modules/scheduler/poll-sync-runner.ts b/apps/api/src/modules/scheduler/poll-sync-runner.ts index a1042f91..95dbe251 100644 --- a/apps/api/src/modules/scheduler/poll-sync-runner.ts +++ b/apps/api/src/modules/scheduler/poll-sync-runner.ts @@ -17,7 +17,8 @@ import { syncCursors, } from '@nexiom/database'; import { TokenManagerService } from '@nexiom/connectors'; -import type { Piece, OAuthCredentialBlob } from '@nexiom/connectors'; +import type { OAuthCredentialBlob } from '@nexiom/connectors'; +import type { Piece } from '@nexiom/piece-framework'; import { REDIS_CLIENT, type Redis } from '@nexiom/cache'; import { CursorManagerService, diff --git a/apps/api/src/modules/stitches/metadata-discovery.service.ts b/apps/api/src/modules/stitches/metadata-discovery.service.ts index 74bdb739..02683581 100644 --- a/apps/api/src/modules/stitches/metadata-discovery.service.ts +++ b/apps/api/src/modules/stitches/metadata-discovery.service.ts @@ -18,11 +18,11 @@ import { import { REDIS_CLIENT, type Redis } from '@nexiom/cache'; import { TokenManagerService } from '@nexiom/connectors'; import { PieceRegistryService } from '@nexiom/engine'; +import type { OAuthCredentialBlob } from '@nexiom/connectors'; import type { ObjectDescriptor, FieldDescriptor, - OAuthCredentialBlob, -} from '@nexiom/connectors'; +} from '@nexiom/piece-framework'; // Single source of truth for metadata cache TTL. const TTL_SECONDS = 5 * 60; // 5 minutes diff --git a/apps/api/src/modules/trigger/dlq-processor.service.spec.ts b/apps/api/src/modules/trigger/dlq-processor.service.spec.ts index ec4e1c73..36a04dac 100644 --- a/apps/api/src/modules/trigger/dlq-processor.service.spec.ts +++ b/apps/api/src/modules/trigger/dlq-processor.service.spec.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { DlqProcessorService } from './dlq-processor.service.js'; /* eslint-disable @typescript-eslint/unbound-method */ -import { TriggerStrategy } from '@nexiom/connectors'; +import { TriggerStrategy } from '@nexiom/piece-framework'; import type { TriggerExecutorService } from './trigger-executor.service.js'; import { PieceRegistryService } from '@nexiom/engine'; diff --git a/apps/api/src/modules/trigger/poller.service.spec.ts b/apps/api/src/modules/trigger/poller.service.spec.ts index 36abb5b1..3f7d7841 100644 --- a/apps/api/src/modules/trigger/poller.service.spec.ts +++ b/apps/api/src/modules/trigger/poller.service.spec.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { PollerService } from './poller.service.js'; /* eslint-disable @typescript-eslint/unbound-method */ -import { TriggerStrategy } from '@nexiom/connectors'; +import { TriggerStrategy } from '@nexiom/piece-framework'; import type { TriggerExecutorService } from './trigger-executor.service.js'; import { PieceRegistryService } from '@nexiom/engine'; diff --git a/apps/api/src/modules/trigger/redis-trigger-store.ts b/apps/api/src/modules/trigger/redis-trigger-store.ts index 637fefc4..2dbc7ffc 100644 --- a/apps/api/src/modules/trigger/redis-trigger-store.ts +++ b/apps/api/src/modules/trigger/redis-trigger-store.ts @@ -1,4 +1,4 @@ -import type { TriggerStore } from '@nexiom/connectors'; +import type { TriggerStore } from '@nexiom/piece-framework'; import type { Redis } from 'ioredis'; /** diff --git a/apps/api/src/modules/trigger/trigger-executor.service.spec.ts b/apps/api/src/modules/trigger/trigger-executor.service.spec.ts index 20e82e08..acae1d81 100644 --- a/apps/api/src/modules/trigger/trigger-executor.service.spec.ts +++ b/apps/api/src/modules/trigger/trigger-executor.service.spec.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { TriggerExecutorService } from './trigger-executor.service.js'; -import { TriggerStrategy } from '@nexiom/connectors'; -import type { Trigger } from '@nexiom/connectors'; +import { TriggerStrategy } from '@nexiom/piece-framework'; +import type { Trigger } from '@nexiom/piece-framework'; function makeMockDb() { return { diff --git a/apps/api/src/modules/trigger/trigger-executor.service.ts b/apps/api/src/modules/trigger/trigger-executor.service.ts index 4dd14409..7b2ad24a 100644 --- a/apps/api/src/modules/trigger/trigger-executor.service.ts +++ b/apps/api/src/modules/trigger/trigger-executor.service.ts @@ -1,5 +1,5 @@ import { Injectable, Inject, Logger } from '@nestjs/common'; -import type { Trigger, TriggerContext } from '@nexiom/connectors'; +import type { Trigger, TriggerContext } from '@nexiom/piece-framework'; import type { DrizzleDb } from '@nexiom/database'; import { DATABASE_CONNECTION } from '@nexiom/database'; import { SchemaPlan } from '@nexiom/dbmanager'; diff --git a/apps/api/src/modules/trigger/webhooks.controller.spec.ts b/apps/api/src/modules/trigger/webhooks.controller.spec.ts index 020e53db..d73227d4 100644 --- a/apps/api/src/modules/trigger/webhooks.controller.spec.ts +++ b/apps/api/src/modules/trigger/webhooks.controller.spec.ts @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest'; import { WebhooksController } from './webhooks.controller.js'; import { NotFoundException, UnauthorizedException } from '@nestjs/common'; -import { TriggerStrategy } from '@nexiom/connectors'; +import { TriggerStrategy } from '@nexiom/piece-framework'; import { PieceRegistryService } from '@nexiom/engine'; import type { TriggerExecutorService } from './trigger-executor.service.js'; diff --git a/apps/worker/package.json b/apps/worker/package.json index 4dfe0e07..07c8c0d1 100644 --- a/apps/worker/package.json +++ b/apps/worker/package.json @@ -43,6 +43,7 @@ "@nexiom/dbmanager": "workspace:*", "@nexiom/engine": "workspace:*", "@nexiom/identity": "workspace:*", + "@nexiom/piece-framework": "workspace:*", "@nexiom/piece-quickbooks": "workspace:*", "@nexiom/piece-salesforce": "workspace:*", "@nexiom/queue": "workspace:*", diff --git a/apps/worker/src/modules/pipeline/delivery.service.spec.ts b/apps/worker/src/modules/pipeline/delivery.service.spec.ts index 4fc787a4..36eb07f3 100644 --- a/apps/worker/src/modules/pipeline/delivery.service.spec.ts +++ b/apps/worker/src/modules/pipeline/delivery.service.spec.ts @@ -390,7 +390,7 @@ describe("DeliveryService", () => { }); it("should set RETRY status when piece throws RetryableException", async () => { - const { RetryableException } = await import("@nexiom/connectors"); + const { RetryableException } = await import("@nexiom/piece-framework"); pieceRegistry .getPiece() .executeAction.mockRejectedValueOnce( diff --git a/apps/worker/src/modules/pipeline/delivery.service.ts b/apps/worker/src/modules/pipeline/delivery.service.ts index ba9ffcd2..78a0be65 100644 --- a/apps/worker/src/modules/pipeline/delivery.service.ts +++ b/apps/worker/src/modules/pipeline/delivery.service.ts @@ -6,7 +6,7 @@ import { Optional, Logger, } from "@nestjs/common"; -import { eq } from "drizzle-orm"; +import { eq, sql } from "drizzle-orm"; import { QueueService, QueueName } from "@nexiom/queue"; import { DATABASE_CONNECTION, @@ -18,9 +18,8 @@ import { } from "@nexiom/database"; import type { DrizzleDb } from "@nexiom/database"; import { StorageResolverService, PieceRegistryService } from "@nexiom/engine"; -import { sql } from "drizzle-orm"; import { TokenManagerService } from "@nexiom/connectors"; -import { RetryableException } from "@nexiom/connectors"; +import { RetryableException } from "@nexiom/piece-framework"; import { sanitizeError, isValidPipelineMessage, diff --git a/apps/worker/src/modules/pipeline/fanout.service.spec.ts b/apps/worker/src/modules/pipeline/fanout.service.spec.ts index d21a876c..af2c6e92 100644 --- a/apps/worker/src/modules/pipeline/fanout.service.spec.ts +++ b/apps/worker/src/modules/pipeline/fanout.service.spec.ts @@ -32,7 +32,8 @@ describe("FanOutService", () => { }), onConflictDoNothing: vi.fn().mockResolvedValue(undefined), returning: vi.fn().mockResolvedValue([{ id: "outbound_1" }]), - then: (res: any) => Promise.resolve(undefined).then(res), + then: (onfulfilled?: ((value: any) => any) | null) => + Promise.resolve(undefined as any).then(onfulfilled), }), }); queueService = { consume: vi.fn(), send: vi.fn() }; diff --git a/apps/worker/src/modules/pipeline/normalization.service.spec.ts b/apps/worker/src/modules/pipeline/normalization.service.spec.ts index 4533c934..02cc7021 100644 --- a/apps/worker/src/modules/pipeline/normalization.service.spec.ts +++ b/apps/worker/src/modules/pipeline/normalization.service.spec.ts @@ -32,13 +32,15 @@ describe("NormalizationService", () => { values: vi.fn().mockReturnValue({ onConflictDoNothing: vi.fn().mockReturnValue({ // directly awaitable (for normalizedOutbox insert that has no .returning()) - then: (res: any) => Promise.resolve(undefined).then(res), + then: (onfulfilled?: ((value: any) => any) | null) => + Promise.resolve(undefined as any).then(onfulfilled), // also supports .returning() for chains that need it returning: vi.fn().mockResolvedValue(returnVal), }), returning: vi.fn().mockResolvedValue(returnVal), // plain insert().values() with no conflict resolution - then: (res: any) => Promise.resolve(undefined).then(res), + then: (onfulfilled?: ((value: any) => any) | null) => + Promise.resolve(undefined as any).then(onfulfilled), }), }); mockTxInsert.mockImplementation(() => makeInsertChain()); @@ -158,7 +160,8 @@ describe("NormalizationService", () => { onConflictDoNothing: vi.fn().mockReturnValue({ returning: vi.fn().mockResolvedValue([]), }), - then: (res: any) => Promise.resolve(undefined).then(res), + then: (onfulfilled?: ((value: any) => any) | null) => + Promise.resolve(undefined as any).then(onfulfilled), }), }), update: vi.fn().mockReturnThis(), diff --git a/apps/worker/src/modules/pipeline/replica.service.spec.ts b/apps/worker/src/modules/pipeline/replica.service.spec.ts index e9aacc16..83b46d7d 100644 --- a/apps/worker/src/modules/pipeline/replica.service.spec.ts +++ b/apps/worker/src/modules/pipeline/replica.service.spec.ts @@ -66,7 +66,8 @@ describe("ReplicaService", () => { returning: vi.fn().mockResolvedValue([{ id: "1" }]), }), onConflictDoNothing: vi.fn().mockResolvedValue(undefined), - then: (res: any) => Promise.resolve(undefined).then(res), + then: (onfulfilled?: ((value: any) => any) | null) => + Promise.resolve(undefined as any).then(onfulfilled), }; }), })); diff --git a/docs/architecture/master/tasks.md b/docs/architecture/master/tasks.md index fdd28d52..15a041fe 100644 --- a/docs/architecture/master/tasks.md +++ b/docs/architecture/master/tasks.md @@ -612,6 +612,25 @@ Each task is one commit (or one small PR). Checkboxes track completion. --- +## Phase 8 โ€” Fleet Sharding + +### T053 ยท engine: Custom Logic Extension Hook (`isolated-vm`) + +- [ ] Add `isolated-vm` dependency to `@nexiom/engine`. +- [ ] Implement `LogicResolverService` that checks the local shard directory for a tenant's custom script before falling back to generic pipeline logic. +- [ ] Run custom scripts within a secure `ivm.Isolate` context with strict memory buffers and timeouts (e.g., 128MB, 1s timeout) to prevent platform DoS. +- Files: `packages/engine/src/executor/logic-resolver.ts` +- Depends: T035 + +### T054 ยท worker: GitOps Shard Synchronization + +- [ ] Implement a worker cron service that pulls/fetches mapped Git Shard repositories (e.g. `fluxnex-shard-001`) onto the local disk every 5 minutes. +- [ ] Implement an in-memory or Redis-backed cache invalidation when a shard is updated so the `LogicResolverService` uses the latest custom logic from customers. +- Files: `apps/worker/src/modules/gitops/shard-sync.service.ts` +- Depends: T053 + +--- + ## Summary | Phase | Tasks | Completed | Key deliverable | @@ -626,8 +645,9 @@ Each task is one commit (or one small PR). Checkboxes track completion. | 5 โ€” AI Mapping | T040โ€“T042 | โฌœ All | Claude-powered field suggestions | | 6 โ€” Environments | T043โ€“T045 | โฌœ All | Sandbox/Production routing | | 7 โ€” Delivery Outbox | T051โ€“T052 | โœ… All | Delivery Outbox Resiliency | +| 8 โ€” Fleet Sharding | T053โ€“T054 | โฌœ All | Sandboxed execution of customer logic | -**Total: 52 tasks ยท Completed: ~38 ยท Remaining: ~14** +**Total: 54 tasks ยท Completed: ~38 ยท Remaining: ~16** --- diff --git a/packages/connectors/package.json b/packages/connectors/package.json index 6eab2c1f..c19ed9ef 100644 --- a/packages/connectors/package.json +++ b/packages/connectors/package.json @@ -11,11 +11,6 @@ "import": "./dist/index.js", "default": "./dist/index.js" }, - "./framework": { - "types": "./dist/framework/index.d.ts", - "import": "./dist/framework/index.js", - "default": "./dist/framework/index.js" - }, "./intelligence": { "types": "./dist/intelligence/index.d.ts", "import": "./dist/intelligence/index.js", @@ -30,6 +25,7 @@ }, "dependencies": { "@nexiom/database": "workspace:*", + "@nexiom/piece-framework": "workspace:*", "drizzle-orm": "^0.45.1", "ioredis": "^5.3.2" }, diff --git a/packages/connectors/src/framework/framework.spec.ts b/packages/connectors/src/http-client/host-http-client.spec.ts similarity index 63% rename from packages/connectors/src/framework/framework.spec.ts rename to packages/connectors/src/http-client/host-http-client.spec.ts index 7818fcdb..6cdf5e32 100644 --- a/packages/connectors/src/framework/framework.spec.ts +++ b/packages/connectors/src/http-client/host-http-client.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi, beforeEach } from 'vitest'; +import { describe, expect, it, vi, beforeAll, afterEach } from 'vitest'; import { createPiece, createAction, @@ -6,22 +6,26 @@ import { PieceAuth, httpClient, initializeHttpClient, - HostHttpClient, HttpMethod, -} from './index.js'; -import type { NormalizedRecord, VendorResponse } from './canonical/index.js'; +} from '@nexiom/piece-framework'; +import type { NormalizedRecord, VendorResponse } from '@nexiom/piece-framework'; +import { HostHttpClient } from './host-http-client.js'; import { TokenManagerService } from '../oauth/token-manager.service.js'; import { DrizzleDb } from '@nexiom/database'; import { Redis } from 'ioredis'; describe('Activepieces Framework Native Shim', () => { - beforeEach(() => { + beforeAll(() => { // Initialize the singleton to prevent the "accessed before platform initialization" throw - initializeHttpClient( + initializeHttpClient(new HostHttpClient( {} as TokenManagerService, { execute: vi.fn().mockResolvedValue([]) } as unknown as DrizzleDb, - { incr: vi.fn().mockResolvedValue(1), expire: vi.fn() } as unknown as Redis - ); + { eval: vi.fn().mockResolvedValue(1) } as unknown as Redis + )); + }); + + afterEach(() => { + vi.restoreAllMocks(); }); it('Should successfully type-check and instantiate a mocked Salesforce piece exactly like Activepieces', async () => { @@ -109,8 +113,6 @@ describe('Activepieces Framework Native Shim', () => { }); expect(result).toEqual({ success: true, id: '001A000001bcdefQAA' }); - - sendRequestSpy.mockRestore(); }); it('forwards normalize from CreatePieceParams to the Piece instance', async () => { @@ -178,4 +180,83 @@ describe('Activepieces Framework Native Shim', () => { } }); }); + + describe('HostHttpClient Response Parsing', () => { + let client: HostHttpClient; + + beforeAll(() => { + client = new HostHttpClient( + {} as TokenManagerService, + { execute: vi.fn().mockResolvedValue([]) } as unknown as DrizzleDb, + { eval: vi.fn().mockResolvedValue(1) } as unknown as Redis + ); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should deeply parse JSON by default', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + headers: new Headers({ 'Content-Type': 'application/json' }), + text: async () => '{"hello":"world"}', + } as any); + + const result = await client.sendRequest({ method: HttpMethod.GET, url: 'https://example.com' }); + expect(result.body).toEqual({ hello: 'world' }); + }); + + it('should correctly return non-ok responses without throwing', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue({ + ok: false, + status: 404, + headers: new Headers({ 'Content-Type': 'application/json' }), + text: async () => '{"error":"Not Found"}', + } as any); + + const result = await client.sendRequest({ method: HttpMethod.GET, url: 'https://example.com' }); + expect(result.status).toBe(404); + expect(result.body).toEqual({ error: 'Not Found' }); + }); + + it('should parse text when responseType is text', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + headers: new Headers({ 'Content-Type': 'text/plain' }), + text: async () => 'hello world', + } as any); + + const result = await client.sendRequest({ method: HttpMethod.GET, url: 'https://example.com', responseType: 'text' }); + expect(result.body).toBe('hello world'); + }); + + it('should return arrayBuffer when responseType is arraybuffer', async () => { + const buffer = new ArrayBuffer(8); + vi.spyOn(globalThis, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + headers: new Headers({ 'Content-Type': 'application/octet-stream' }), + arrayBuffer: async () => buffer, + } as any); + + const result = await client.sendRequest({ method: HttpMethod.GET, url: 'https://example.com', responseType: 'arraybuffer' }); + expect(result.body).toBe(buffer); + }); + + it('should return raw stream when responseType is stream', async () => { + const stream = 'fake_stream' as any; + vi.spyOn(globalThis, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + headers: new Headers({ 'Content-Type': 'application/octet-stream' }), + body: stream, + } as any); + + const result = await client.sendRequest({ method: HttpMethod.GET, url: 'https://example.com', responseType: 'stream' }); + expect(result.body).toBe(stream); + }); + }); }); diff --git a/packages/connectors/src/framework/http-client.ts b/packages/connectors/src/http-client/host-http-client.ts similarity index 90% rename from packages/connectors/src/framework/http-client.ts rename to packages/connectors/src/http-client/host-http-client.ts index 3bfbff2d..c351a1c9 100644 --- a/packages/connectors/src/framework/http-client.ts +++ b/packages/connectors/src/http-client/host-http-client.ts @@ -3,40 +3,15 @@ import { InternalServerErrorException, BadGatewayException, BadRequestException, + OnModuleInit, } from '@nestjs/common'; import { TokenManagerService } from '../oauth/token-manager.service.js'; import { DrizzleDb } from '@nexiom/database'; import { sql } from 'drizzle-orm'; import { Redis } from 'ioredis'; -export enum HttpMethod { - GET = 'GET', - POST = 'POST', - PUT = 'PUT', - PATCH = 'PATCH', - DELETE = 'DELETE', - HEAD = 'HEAD', -} - -export interface HttpRequest { - method: HttpMethod; - url: string; - headers?: Record; - body?: any; - queryParams?: Record; - responseType?: any; - authentication?: { - type: string; - token: string; - }; -} - -export interface HttpResponse { - status: number; - headers: Record; - body: T; -} - +import type { HttpClient, HttpRequest, HttpResponse } from '@nexiom/piece-framework'; +import { HttpMethod, initializeHttpClient } from '@nexiom/piece-framework'; /** How long a trace context is retained before it is treated as expired (5 minutes). */ const EXECUTION_STATE_TTL_MS = 5 * 60 * 1000; @@ -52,7 +27,7 @@ interface InternalExecutionState { * It is solely responsible for enterprise reliability: Distributed Rate Limiting, Retries, Audit Logs, and DLQ errors. */ @Injectable() -export class HostHttpClient { +export class HostHttpClient implements HttpClient, OnModuleInit { // A global AsyncLocalStorage map or static context to bind the current executing connectionId to generic fetch calls private static readonly executionState = new Map(); /** Single shared cleanup timer โ€” prevents one timer per bindExecutionCtx call. */ @@ -64,6 +39,17 @@ export class HostHttpClient { private readonly redis: Redis, ) { } + onModuleInit() { + try { + initializeHttpClient(this); + } catch (error) { + if (error instanceof Error && error.message === 'HttpClient already initialized') { + return; // Idempotent re-init is safe + } + throw error; // Rethrow real failures + } + } + /** * Called by the Sync Engine right before executing `action.run()`. * Tells the client which Connection is currently responsible for the outgoing HTTP requests. @@ -136,7 +122,7 @@ export class HostHttpClient { const duration = Date.now() - startTime; // Parse Body - const responseBody = await this.parseResponseBody(response); + const responseBody = await this.parseResponseBody(response, request.responseType); const payload: HttpResponse = { status: response.status, @@ -270,7 +256,18 @@ export class HostHttpClient { }; } - private async parseResponseBody(response: Response): Promise { + private async parseResponseBody(response: Response, responseType?: 'json' | 'text' | 'arraybuffer' | 'stream'): Promise { + if (responseType === 'arraybuffer') { + return response.arrayBuffer(); + } + if (responseType === 'stream') { + return response.body; + } + if (responseType === 'text') { + return response.text(); + } + + // Default to JSON strategy const text = await response.text(); try { return JSON.parse(text); @@ -418,30 +415,4 @@ export class HostHttpClient { } } -/** - * Global instance for Activepieces context execution. - * Throws an error if accessed before being fully initialized by the host platform to prevent null panics. - */ -let _httpClientInstance: HostHttpClient | null = null; - -export function initializeHttpClient( - tokenManager: TokenManagerService, - db: DrizzleDb, - redis: Redis -) { - _httpClientInstance ??= new HostHttpClient(tokenManager, db, redis); -} -export const httpClient = new Proxy({} as HostHttpClient, { - get: (_target, prop) => { - if (!_httpClientInstance) { - throw new InternalServerErrorException('HostHttpClient accessed before platform initialization'); - } - const value = (_httpClientInstance as any)[prop]; - // Bind methods to the instance to ensure `this` works inside sendRequest - if (typeof value === 'function') { - return value.bind(_httpClientInstance); - } - return value; - } -}); diff --git a/packages/connectors/src/index.ts b/packages/connectors/src/index.ts index c23256c8..56dc1851 100644 --- a/packages/connectors/src/index.ts +++ b/packages/connectors/src/index.ts @@ -3,7 +3,7 @@ * * Entrypoints: * - `@nexiom/connectors` โ€” runtime services (encryption, token manager) - * - `@nexiom/connectors/framework` โ€” piece/action/trigger/auth/property definitions + * - `@nexiom/piece-framework` โ€” piece/action/trigger/auth/property definitions */ // Crypto utilities @@ -13,8 +13,7 @@ export * from './crypto/encryption.service.js'; // Token management (OAuth refresh, credential storage) export * from './oauth/token-manager.service.js'; -// Framework โ€” Piece, Action, Trigger, Auth, Property definitions -export * from './framework/index.js'; + /** * @deprecated The ProviderRegistry and dynamic `OAuthProvider` architectures have been removed in favor of the `PieceRegistry` flow. @@ -27,3 +26,4 @@ export interface OAuthProvider { } // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class SalesforceConnector { } +export * from "./http-client/host-http-client.js"; diff --git a/packages/connectors/src/intelligence/interfaces.ts b/packages/connectors/src/intelligence/interfaces.ts index 2ccd0e74..37286ded 100644 --- a/packages/connectors/src/intelligence/interfaces.ts +++ b/packages/connectors/src/intelligence/interfaces.ts @@ -1,15 +1,7 @@ -import type { TriggerStore } from '../framework/index.js'; +import type { TriggerStore, FieldDescriptor } from '@nexiom/piece-framework'; import type { ObjectHint } from './optimization-registry.js'; -/** Describes a single field in an SaaS object. */ -export interface FieldDescriptor { - name: string; - type: string; // 'string' | 'datetime' | 'reference' | 'currency' | โ€ฆ - filterable: boolean; - sortable: boolean; - nillable: boolean; - referenceTo?: string[]; -} + /** Describes a relationship to child records. */ export interface ChildRelationshipDescriptor { diff --git a/packages/connectors/src/intelligence/universal-trigger-engine.spec.ts b/packages/connectors/src/intelligence/universal-trigger-engine.spec.ts index 2fa1a07c..4d9ae40e 100644 --- a/packages/connectors/src/intelligence/universal-trigger-engine.spec.ts +++ b/packages/connectors/src/intelligence/universal-trigger-engine.spec.ts @@ -8,7 +8,7 @@ import type { IBulkAdapter, ObjectSchema } from './interfaces.js'; -import type { TriggerStore } from '../framework/index.js'; +import type { TriggerStore } from '@nexiom/piece-framework'; // Mock dependencies vi.mock('./smart-cursor-selector.js', () => ({ diff --git a/packages/engine/package.json b/packages/engine/package.json index 073611c2..90d1db92 100644 --- a/packages/engine/package.json +++ b/packages/engine/package.json @@ -20,7 +20,8 @@ }, "dependencies": { "@nexiom/connectors": "workspace:*", - "@nexiom/database": "workspace:*" + "@nexiom/database": "workspace:*", + "@nexiom/piece-framework": "workspace:*" }, "devDependencies": { "@nestjs/common": "^11.0.1", diff --git a/packages/engine/src/pieces/piece-loader.service.ts b/packages/engine/src/pieces/piece-loader.service.ts index 52722fa9..00289069 100644 --- a/packages/engine/src/pieces/piece-loader.service.ts +++ b/packages/engine/src/pieces/piece-loader.service.ts @@ -1,6 +1,6 @@ import { Injectable, Logger, Inject, Optional } from '@nestjs/common'; import { eq } from 'drizzle-orm'; -import type { Piece } from '@nexiom/connectors'; +import type { Piece } from '@nexiom/piece-framework'; import { pieces, type DrizzleDb } from '@nexiom/database'; /** @@ -124,7 +124,11 @@ export class PieceLoaderService { typeof v['actions'] === 'object' && v['actions'] !== null && typeof v['triggers'] === 'object' && - v['triggers'] !== null + v['triggers'] !== null && + typeof v['auth'] === 'object' && + v['auth'] !== null && + Array.isArray(v['categories']) && + v['categories'].every(c => typeof c === 'string') ); } } diff --git a/packages/engine/src/pieces/piece-registry.service.spec.ts b/packages/engine/src/pieces/piece-registry.service.spec.ts index ace59fee..832e6515 100644 --- a/packages/engine/src/pieces/piece-registry.service.spec.ts +++ b/packages/engine/src/pieces/piece-registry.service.spec.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { PieceRegistryService } from '@nexiom/engine'; -import type { Piece } from '@nexiom/connectors'; +import type { Piece } from '@nexiom/piece-framework'; // A minimal mock piece โ€” this service is generic and has no knowledge of real integrations. const mockPiece: Piece = { diff --git a/packages/engine/src/pieces/piece-registry.service.ts b/packages/engine/src/pieces/piece-registry.service.ts index 471b2003..44d6ac0d 100644 --- a/packages/engine/src/pieces/piece-registry.service.ts +++ b/packages/engine/src/pieces/piece-registry.service.ts @@ -1,5 +1,5 @@ import { Injectable, Logger, Inject } from '@nestjs/common'; -import type { Piece, Trigger } from '@nexiom/connectors'; +import type { Piece, Trigger } from '@nexiom/piece-framework'; /** NestJS injection token for the list of registered Pieces. */ export const PIECES = 'PIECES'; diff --git a/packages/engine/src/pieces/pieces.module.ts b/packages/engine/src/pieces/pieces.module.ts index 957929e1..c0b4dfa7 100644 --- a/packages/engine/src/pieces/pieces.module.ts +++ b/packages/engine/src/pieces/pieces.module.ts @@ -6,7 +6,7 @@ import { import { PieceLoaderService, PIECE_LOADER_ANCHOR_URL } from './piece-loader.service.js'; import { DATABASE_CONNECTION } from '@nexiom/database'; import type { DrizzleDb } from '@nexiom/database'; -import type { Piece } from '@nexiom/connectors'; +import type { Piece } from '@nexiom/piece-framework'; const SHARED_PROVIDERS = [ PieceLoaderService, diff --git a/packages/engine/src/state/cursor-manager.service.spec.ts b/packages/engine/src/state/cursor-manager.service.spec.ts index d5525d2c..c89c1b3c 100644 --- a/packages/engine/src/state/cursor-manager.service.spec.ts +++ b/packages/engine/src/state/cursor-manager.service.spec.ts @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach } from 'vitest'; import type { ConfigService } from '@nestjs/config'; import { CursorManagerService, DEFAULT_CURSOR_CHECKPOINT_INTERVAL } from './cursor-manager.service.js'; import type { StreamBookmark } from './cursor-manager.types.js'; -import type { StreamDescriptor, PollRecord } from '@nexiom/connectors/framework'; +import type { StreamDescriptor, PollRecord } from '@nexiom/piece-framework'; // --------------------------------------------------------------------------- // Helpers diff --git a/packages/engine/src/state/cursor-manager.service.ts b/packages/engine/src/state/cursor-manager.service.ts index 866826d1..23369922 100644 --- a/packages/engine/src/state/cursor-manager.service.ts +++ b/packages/engine/src/state/cursor-manager.service.ts @@ -1,6 +1,6 @@ import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import type { ReplicationKeyType, StreamDescriptor, PollWindow, PollRecord } from '@nexiom/connectors/framework'; +import type { ReplicationKeyType, StreamDescriptor, PollWindow, PollRecord } from '@nexiom/piece-framework'; import type { StreamBookmark } from './cursor-manager.types.js'; /** diff --git a/packages/engine/src/state/cursor-manager.types.ts b/packages/engine/src/state/cursor-manager.types.ts index af6fcbca..60447e76 100644 --- a/packages/engine/src/state/cursor-manager.types.ts +++ b/packages/engine/src/state/cursor-manager.types.ts @@ -1,4 +1,4 @@ -import type { ReplicationKeyType } from '@nexiom/connectors/framework'; +import type { ReplicationKeyType } from '@nexiom/piece-framework'; /** * Re-export connector-framework types used by the cursor engine so consumers @@ -10,7 +10,7 @@ export type { PollWindow, PollRecord, PollPage, -} from '@nexiom/connectors/framework'; +} from '@nexiom/piece-framework'; // --------------------------------------------------------------------------- // Singer-style state document diff --git a/packages/piece-framework/package.json b/packages/piece-framework/package.json new file mode 100644 index 00000000..c4ce0f1d --- /dev/null +++ b/packages/piece-framework/package.json @@ -0,0 +1,27 @@ +{ + "name": "@nexiom/piece-framework", + "version": "1.0.0", + "type": "module", + "private": true, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + } + }, + "scripts": { + "build": "tsc", + "test": "vitest run", + "test:watch": "vitest", + "test:cov": "vitest run --coverage" + }, + "devDependencies": { + "@types/node": "^25.5.0", + "@vitest/coverage-v8": "^4.0.18", + "typescript": "^5.7.3", + "vitest": "^4.0.18" + } +} diff --git a/packages/connectors/src/framework/action.ts b/packages/piece-framework/src/action.ts similarity index 100% rename from packages/connectors/src/framework/action.ts rename to packages/piece-framework/src/action.ts diff --git a/packages/connectors/src/framework/auth.spec.ts b/packages/piece-framework/src/auth.spec.ts similarity index 100% rename from packages/connectors/src/framework/auth.spec.ts rename to packages/piece-framework/src/auth.spec.ts diff --git a/packages/connectors/src/framework/auth.ts b/packages/piece-framework/src/auth.ts similarity index 100% rename from packages/connectors/src/framework/auth.ts rename to packages/piece-framework/src/auth.ts diff --git a/packages/connectors/src/framework/canonical/index.ts b/packages/piece-framework/src/canonical/index.ts similarity index 100% rename from packages/connectors/src/framework/canonical/index.ts rename to packages/piece-framework/src/canonical/index.ts diff --git a/packages/piece-framework/src/http-client.ts b/packages/piece-framework/src/http-client.ts new file mode 100644 index 00000000..c3189230 --- /dev/null +++ b/packages/piece-framework/src/http-client.ts @@ -0,0 +1,53 @@ +export enum HttpMethod { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + PATCH = 'PATCH', + DELETE = 'DELETE', + HEAD = 'HEAD', +} + +export interface HttpRequest { + method: HttpMethod; + url: string; + headers?: Record; + body?: any; + queryParams?: Record; + responseType?: 'json' | 'text' | 'arraybuffer' | 'stream'; + authentication?: { + type: string; + token: string; + }; +} + +export interface HttpResponse { + status: number; + headers: Record; + body: T; +} + +export interface HttpClient { + sendRequest(request: HttpRequest): Promise>; +} + +let _httpClientInstance: HttpClient | null = null; + +export function initializeHttpClient(client: HttpClient) { + if (_httpClientInstance) { + throw new Error('HttpClient already initialized'); + } + _httpClientInstance = client; +} + +export const httpClient = new Proxy({} as HttpClient, { + get: (_target, prop) => { + if (!_httpClientInstance) { + throw new Error('HttpClient accessed before platform initialization'); + } + const value = (_httpClientInstance as any)[prop]; + if (typeof value === 'function') { + return value.bind(_httpClientInstance); + } + return value; + } +}); diff --git a/packages/connectors/src/framework/index.ts b/packages/piece-framework/src/index.ts similarity index 93% rename from packages/connectors/src/framework/index.ts rename to packages/piece-framework/src/index.ts index 7cbd861e..e175e42b 100644 --- a/packages/connectors/src/framework/index.ts +++ b/packages/piece-framework/src/index.ts @@ -8,9 +8,8 @@ export * from './retryable-exception.js'; export { httpClient, initializeHttpClient, - HostHttpClient, + HttpClient, HttpMethod, HttpRequest, HttpResponse, - } from './http-client.js'; diff --git a/packages/connectors/src/framework/piece.ts b/packages/piece-framework/src/piece.ts similarity index 94% rename from packages/connectors/src/framework/piece.ts rename to packages/piece-framework/src/piece.ts index 15a9abde..857ce8d0 100644 --- a/packages/connectors/src/framework/piece.ts +++ b/packages/piece-framework/src/piece.ts @@ -1,10 +1,15 @@ import { Action } from './action.js'; import { PieceAuthProperty } from './auth.js'; import { Trigger } from './trigger.js'; -import { InternalServerErrorException } from '@nestjs/common'; -import type { FieldDescriptor as BaseFieldDescriptor } from '../intelligence/interfaces.js'; import type { NormalizedRecord, VendorResponse } from './canonical/index.js'; +export class PieceInternalServerError extends Error { + constructor(message: string) { + super(message); + this.name = 'PieceInternalServerError'; + } +} + /** A SaaS object available for metadata discovery. */ export interface ObjectDescriptor { name: string; @@ -138,13 +143,14 @@ export type StreamDescriptor = keyProperties: [string, ...string[]]; }; -/** - * A single field within a SaaS object schema, as exposed by the Piece API. - * Extends the intelligence-layer BaseFieldDescriptor with `label` for UI display. - * `referenceTo` and all other base fields are inherited. - */ -export interface FieldDescriptor extends BaseFieldDescriptor { +export interface FieldDescriptor { + name: string; label: string; + type: string; + filterable: boolean; + sortable: boolean; + nillable: boolean; + referenceTo?: string[]; } /** @@ -297,13 +303,13 @@ export function createPiece(params: CreatePieceParams): Piece { // Convert Action array to a Record for O(1) invocation lookups const actionsMap = params.actions.reduce( (acc, action) => { - if (acc[action.name]) { - throw new InternalServerErrorException(`Duplicate action name: ${action.name}`); + if (Object.hasOwn(acc, action.name)) { + throw new PieceInternalServerError(`Duplicate action name: ${action.name}`); } acc[action.name] = action; return acc; }, - {} as Record, + Object.create(null) as Record, ); const triggersMap = (params.triggers || []).reduce( @@ -318,13 +324,13 @@ export function createPiece(params: CreatePieceParams): Piece { console.warn('[createPiece] Skipping invalid trigger entry โ€” missing or non-string name:', trigger); return acc; } - if (acc[trigger.name]) { - throw new InternalServerErrorException(`Duplicate trigger name: ${trigger.name}`); + if (Object.hasOwn(acc, trigger.name)) { + throw new PieceInternalServerError(`Duplicate trigger name: ${trigger.name}`); } acc[trigger.name] = trigger; return acc; }, - {} as Record, + Object.create(null) as Record, ); // Validate webhook config at construction time so misconfigured pieces @@ -341,7 +347,7 @@ export function createPiece(params: CreatePieceParams): Piece { params.webhook.signatureEncoding !== 'base64' && params.webhook.signatureEncoding !== 'hex') ) { - throw new InternalServerErrorException( + throw new PieceInternalServerError( `[createPiece] Invalid webhook config for piece "${params.name}": ` + `secretKeyEnv and signatureHeader must be non-empty strings, ` + `and signatureEncoding (when present) must be 'base64' or 'hex'.`, @@ -357,7 +363,7 @@ export function createPiece(params: CreatePieceParams): Piece { auth: params.auth, categories: (params.categories ?? []).map((cat) => { if (!Object.values(PieceCategory).includes(cat)) { - throw new InternalServerErrorException(`Invalid PieceCategory: ${String(cat)}`); + throw new PieceInternalServerError(`Invalid PieceCategory: ${String(cat)}`); } return cat; }), diff --git a/packages/connectors/src/framework/property.ts b/packages/piece-framework/src/property.ts similarity index 100% rename from packages/connectors/src/framework/property.ts rename to packages/piece-framework/src/property.ts diff --git a/packages/connectors/src/framework/retryable-exception.ts b/packages/piece-framework/src/retryable-exception.ts similarity index 100% rename from packages/connectors/src/framework/retryable-exception.ts rename to packages/piece-framework/src/retryable-exception.ts diff --git a/packages/connectors/src/framework/trigger.ts b/packages/piece-framework/src/trigger.ts similarity index 100% rename from packages/connectors/src/framework/trigger.ts rename to packages/piece-framework/src/trigger.ts diff --git a/packages/piece-framework/tsconfig.json b/packages/piece-framework/tsconfig.json new file mode 100644 index 00000000..c89b19e6 --- /dev/null +++ b/packages/piece-framework/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "types": [ + "node" + ] + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "src/**/*.spec.ts", + "src/**/*.test.ts" + ] +} \ No newline at end of file diff --git a/packages/piece-framework/tsconfig.spec.json b/packages/piece-framework/tsconfig.spec.json new file mode 100644 index 00000000..708367c4 --- /dev/null +++ b/packages/piece-framework/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./dist/tsconfig.spec.tsbuildinfo", + "types": [ + "vitest/globals", + "node" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.test.ts" + ] +} \ No newline at end of file diff --git a/packages/piece-framework/vitest.config.ts b/packages/piece-framework/vitest.config.ts new file mode 100644 index 00000000..2300f180 --- /dev/null +++ b/packages/piece-framework/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.spec.ts', 'src/**/*.test.ts'], + coverage: { + provider: 'v8', + }, + }, +}); diff --git a/packages/pieces/quickbooks/package.json b/packages/pieces/quickbooks/package.json index c9660282..f84d6a14 100644 --- a/packages/pieces/quickbooks/package.json +++ b/packages/pieces/quickbooks/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@nexiom/connectors": "workspace:*", + "@nexiom/piece-framework": "workspace:*", "dayjs": "^1.11.19" } } \ No newline at end of file diff --git a/packages/pieces/quickbooks/src/index.ts b/packages/pieces/quickbooks/src/index.ts index 0b0ea481..5c3d8c04 100644 --- a/packages/pieces/quickbooks/src/index.ts +++ b/packages/pieces/quickbooks/src/index.ts @@ -6,7 +6,7 @@ import { type FieldDescriptor, type NormalizedRecord, type VendorResponse, -} from '@nexiom/connectors/framework'; +} from '@nexiom/piece-framework'; import { quickbooksAuth } from './lib/auth.js'; import { quickbooksCommon, resolveEnvironment } from './lib/common.js'; import { quickbooksUniversalTrigger } from './triggers/universal-trigger.js'; diff --git a/packages/pieces/quickbooks/src/lib/auth.ts b/packages/pieces/quickbooks/src/lib/auth.ts index 8c6bf9a6..28895791 100644 --- a/packages/pieces/quickbooks/src/lib/auth.ts +++ b/packages/pieces/quickbooks/src/lib/auth.ts @@ -1,4 +1,4 @@ -import { PieceAuth, Property } from '@nexiom/connectors/framework'; +import { PieceAuth, Property } from '@nexiom/piece-framework'; export const quickbooksAuth = PieceAuth.OAuth2({ description: 'You can find Company ID under **settings->Additional Info**.', diff --git a/packages/pieces/quickbooks/src/triggers/quickbooks-polling.helper.ts b/packages/pieces/quickbooks/src/triggers/quickbooks-polling.helper.ts index e243d4a2..cc622954 100644 --- a/packages/pieces/quickbooks/src/triggers/quickbooks-polling.helper.ts +++ b/packages/pieces/quickbooks/src/triggers/quickbooks-polling.helper.ts @@ -1,4 +1,4 @@ -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; import { quickbooksCommon, resolveEnvironment, type QuickbooksEntityResponse } from '../lib/common.js'; import { type ObjectHint } from '@nexiom/connectors/intelligence'; import { QuickBooksQueryAdapter } from './quickbooks-query.adapter.js'; @@ -35,7 +35,6 @@ export async function runQuickBooksQuery( const { since, lastId } = parseCursorState(lastCursorParams); const sql = QuickBooksQueryAdapter.buildQBOQuery(entityType, { - objectName: entityType, cursorField: 'MetaData.LastUpdatedTime', cursorValue: since, cursorIdField: 'Id', diff --git a/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.spec.ts b/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.spec.ts index aef66594..9ef57e6d 100644 --- a/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.spec.ts +++ b/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.spec.ts @@ -7,7 +7,6 @@ describe('QuickBooksQueryAdapter', () => { it('should build a standard query with all parameters', () => { const result = QuickBooksQueryAdapter.buildQBOQuery('Invoice', { - objectName: 'Invoice', cursorField: 'MetaData.LastUpdatedTime', cursorValue: '2026-01-01T00:00:00.000Z', limit: 100 @@ -18,7 +17,6 @@ describe('QuickBooksQueryAdapter', () => { it('should build a query without MAXRESULTS if limit is 0', () => { const result = QuickBooksQueryAdapter.buildQBOQuery('Customer', { - objectName: 'Customer', cursorField: 'MetaData.CreateTime', cursorValue: '2025-12-31T23:59:59Z', limit: 0 @@ -29,7 +27,6 @@ describe('QuickBooksQueryAdapter', () => { it('should default to MAXRESULTS 100 if limit is undefined', () => { const result = QuickBooksQueryAdapter.buildQBOQuery('Account', { - objectName: 'Account', cursorField: 'Id', cursorValue: '100', limit: undefined @@ -41,7 +38,6 @@ describe('QuickBooksQueryAdapter', () => { it('should throw an error for invalid entityType formats to prevent SQL injection', () => { expect(() => { QuickBooksQueryAdapter.buildQBOQuery('Invoice; DROP TABLE Invoice', { - objectName: 'Invoice', cursorField: 'Id', cursorValue: '1', limit: 10 @@ -52,7 +48,6 @@ describe('QuickBooksQueryAdapter', () => { it('should throw an error for invalid cursor formats to prevent SQL injection', () => { expect(() => { QuickBooksQueryAdapter.buildQBOQuery('Invoice', { - objectName: 'Invoice', cursorField: 'Id', cursorValue: "1' OR '1'='1", limit: 10 @@ -63,7 +58,6 @@ describe('QuickBooksQueryAdapter', () => { it('should throw an error for invalid cursorField formats to prevent SQL injection', () => { expect(() => { QuickBooksQueryAdapter.buildQBOQuery('Invoice', { - objectName: 'Invoice', cursorField: 'Id; DROP TABLE Invoice', cursorValue: '1', limit: 10 @@ -74,7 +68,6 @@ describe('QuickBooksQueryAdapter', () => { it('should throw an error for invalid limit formats to prevent SQL injection', () => { expect(() => { QuickBooksQueryAdapter.buildQBOQuery('Invoice', { - objectName: 'Invoice', cursorField: 'Id', cursorValue: '1', limit: '10; DROP TABLE' as any @@ -83,7 +76,6 @@ describe('QuickBooksQueryAdapter', () => { expect(() => { QuickBooksQueryAdapter.buildQBOQuery('Invoice', { - objectName: 'Invoice', cursorField: 'Id', cursorValue: '1', limit: -5 diff --git a/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.ts b/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.ts index 01462114..801a68dc 100644 --- a/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.ts +++ b/packages/pieces/quickbooks/src/triggers/quickbooks-query.adapter.ts @@ -1,8 +1,9 @@ -import type { QuerySpec } from '@nexiom/connectors/intelligence'; - -export type QBOQuerySpec = Omit & { +export type QBOQuerySpec = { + cursorField: string; + cursorValue: string; cursorIdField?: string; cursorIdValue?: string; + limit?: number | string; }; export class QuickBooksQueryAdapter { @@ -55,6 +56,10 @@ export class QuickBooksQueryAdapter { if (limit === undefined) return 100; if (limit === 0) return 0; + if (typeof limit === 'string' && limit.trim() === '') { + return 100; + } + const parsed = Number(limit); if (Number.isNaN(parsed) || parsed < 0) { throw new Error(`Invalid limit: ${limit}`); diff --git a/packages/pieces/quickbooks/src/triggers/universal-trigger.ts b/packages/pieces/quickbooks/src/triggers/universal-trigger.ts index 4b378c4d..4c050919 100644 --- a/packages/pieces/quickbooks/src/triggers/universal-trigger.ts +++ b/packages/pieces/quickbooks/src/triggers/universal-trigger.ts @@ -1,4 +1,4 @@ -import { createTrigger, TriggerStrategy, type TriggerContext, Property } from '@nexiom/connectors/framework'; +import { createTrigger, TriggerStrategy, type TriggerContext, Property } from '@nexiom/piece-framework'; import { quickbooksAuth } from '../lib/auth.js'; import { QuickBooksAuth, runQuickBooksQuery } from './quickbooks-polling.helper.js'; import { optimizationService } from '@nexiom/connectors/intelligence'; diff --git a/packages/pieces/salesforce/package.json b/packages/pieces/salesforce/package.json index 40e9881f..ccb63363 100644 --- a/packages/pieces/salesforce/package.json +++ b/packages/pieces/salesforce/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@nexiom/connectors": "workspace:*", + "@nexiom/piece-framework": "workspace:*", "dayjs": "^1.11.19" } } \ No newline at end of file diff --git a/packages/pieces/salesforce/src/index.ts b/packages/pieces/salesforce/src/index.ts index 396118f7..42c1a007 100644 --- a/packages/pieces/salesforce/src/index.ts +++ b/packages/pieces/salesforce/src/index.ts @@ -6,7 +6,7 @@ import { type FieldDescriptor, type NormalizedRecord, type VendorResponse, -} from '@nexiom/connectors/framework'; +} from '@nexiom/piece-framework'; import { salesforceUniversalTrigger } from './lib/trigger/universal-trigger.js'; diff --git a/packages/pieces/salesforce/src/lib/auth.ts b/packages/pieces/salesforce/src/lib/auth.ts index ded74074..7d48fb79 100644 --- a/packages/pieces/salesforce/src/lib/auth.ts +++ b/packages/pieces/salesforce/src/lib/auth.ts @@ -1,4 +1,4 @@ -import { PieceAuth, Property } from '@nexiom/connectors/framework'; +import { PieceAuth, Property } from '@nexiom/piece-framework'; export const salesforceAuth = PieceAuth.OAuth2({ description: 'Connect your Salesforce account', diff --git a/packages/pieces/salesforce/src/lib/common/index.ts b/packages/pieces/salesforce/src/lib/common/index.ts index af5f0579..ec43dbed 100644 --- a/packages/pieces/salesforce/src/lib/common/index.ts +++ b/packages/pieces/salesforce/src/lib/common/index.ts @@ -3,8 +3,8 @@ import { HttpMethod, httpClient, Property -} from '@nexiom/connectors/framework'; -import type { HttpResponse } from '@nexiom/connectors/framework'; +} from '@nexiom/piece-framework'; +import type { HttpResponse } from '@nexiom/piece-framework'; import { salesforceAuth } from '../auth.js'; /** Salesforce REST API version โ€” must match the version in openapi.json. */ diff --git a/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.spec.ts b/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.spec.ts index db1142f5..8f22c8dd 100644 --- a/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.spec.ts +++ b/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.spec.ts @@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { SalesforceBulkAdapter } from './salesforce-bulk.adapter.js'; import { sfFetch } from '../sf-fetch.js'; import type { SalesforceAuth } from '../salesforce-types.js'; -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; vi.mock('@nexiom/connectors/intelligence', async (importOriginal) => { const mod = await importOriginal() as any; diff --git a/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.ts b/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.ts index 59f5b4d1..2d564b6a 100644 --- a/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.ts +++ b/packages/pieces/salesforce/src/lib/intelligence/salesforce-bulk.adapter.ts @@ -1,4 +1,4 @@ -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; import { type IBulkAdapter, IgtLogger diff --git a/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.spec.ts b/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.spec.ts index 196ac334..d9726864 100644 --- a/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.spec.ts +++ b/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.spec.ts @@ -3,7 +3,7 @@ import { SalesforceDiscoveryAdapter } from './salesforce-discovery.adapter.js'; import { sfFetch } from '../sf-fetch.js'; import { SF_API_VERSION } from '../common/index.js'; import type { SalesforceAuth } from '../salesforce-types.js'; -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; vi.mock('@nexiom/connectors/intelligence', async (importOriginal) => { const mod = await importOriginal() as any; diff --git a/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.ts b/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.ts index 3d504d38..e257ee44 100644 --- a/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.ts +++ b/packages/pieces/salesforce/src/lib/intelligence/salesforce-discovery.adapter.ts @@ -1,4 +1,4 @@ -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; import { type IDiscoveryAdapter, type ObjectSchema, diff --git a/packages/pieces/salesforce/src/lib/sf-fetch.ts b/packages/pieces/salesforce/src/lib/sf-fetch.ts index ec49e5c0..275c5215 100644 --- a/packages/pieces/salesforce/src/lib/sf-fetch.ts +++ b/packages/pieces/salesforce/src/lib/sf-fetch.ts @@ -1,4 +1,4 @@ -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; import { SF_API_VERSION } from './common/index.js'; /** Thrown when Salesforce returns 401. The caller must refresh / re-auth. */ diff --git a/packages/pieces/salesforce/src/lib/trigger/salesforce-polling.helper.ts b/packages/pieces/salesforce/src/lib/trigger/salesforce-polling.helper.ts index c126496c..f50e087c 100644 --- a/packages/pieces/salesforce/src/lib/trigger/salesforce-polling.helper.ts +++ b/packages/pieces/salesforce/src/lib/trigger/salesforce-polling.helper.ts @@ -1,4 +1,4 @@ -import type { TriggerStore } from '@nexiom/connectors/framework'; +import type { TriggerStore } from '@nexiom/piece-framework'; import { sfFetch } from '../sf-fetch.js'; import { SF_API_VERSION } from '../common/index.js'; diff --git a/packages/pieces/salesforce/src/lib/trigger/universal-trigger.ts b/packages/pieces/salesforce/src/lib/trigger/universal-trigger.ts index e3deb274..8da8407a 100644 --- a/packages/pieces/salesforce/src/lib/trigger/universal-trigger.ts +++ b/packages/pieces/salesforce/src/lib/trigger/universal-trigger.ts @@ -1,4 +1,4 @@ -import { createTrigger, TriggerStrategy, type TriggerContext, type TriggerStore } from '@nexiom/connectors/framework'; +import { createTrigger, TriggerStrategy, type TriggerContext, type TriggerStore } from '@nexiom/piece-framework'; import { salesforceAuth } from '../auth.js'; import { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0e1a548..6fc8c2df 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: '@nexiom/identity': specifier: workspace:* version: link:../../packages/identity + '@nexiom/piece-framework': + specifier: workspace:* + version: link:../../packages/piece-framework '@nexiom/piece-quickbooks': specifier: workspace:* version: link:../../packages/pieces/quickbooks @@ -95,7 +98,7 @@ importers: version: 3.0.3 better-auth: specifier: ^1.4.10 - version: 1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) + version: 1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) class-transformer: specifier: ^0.5.1 version: 0.5.1 @@ -340,7 +343,7 @@ importers: version: 1.13.2 better-auth: specifier: ^1.4.10 - version: 1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.28.5)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@24.10.4)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) + version: 1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@24.10.4)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) framer-motion: specifier: ^12.38.0 version: 12.38.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -507,6 +510,9 @@ importers: '@nexiom/identity': specifier: workspace:* version: link:../../packages/identity + '@nexiom/piece-framework': + specifier: workspace:* + version: link:../../packages/piece-framework '@nexiom/piece-quickbooks': specifier: workspace:* version: link:../../packages/pieces/quickbooks @@ -521,7 +527,7 @@ importers: version: 3.0.3 better-auth: specifier: ^1.4.10 - version: 1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) + version: 1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) class-transformer: specifier: ^0.5.1 version: 0.5.1 @@ -753,6 +759,9 @@ importers: '@nexiom/database': specifier: workspace:* version: link:../database + '@nexiom/piece-framework': + specifier: workspace:* + version: link:../piece-framework drizzle-orm: specifier: ^0.45.1 version: 0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3) @@ -765,13 +774,13 @@ importers: version: 11.1.11(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@vitest/coverage-v8': specifier: ^4.0.18 - version: 4.0.18(vitest@4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.18(vitest@4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^4.0.18 - version: 4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/database: dependencies: @@ -819,6 +828,9 @@ importers: '@nexiom/database': specifier: workspace:* version: link:../database + '@nexiom/piece-framework': + specifier: workspace:* + version: link:../piece-framework devDependencies: '@nestjs/common': specifier: ^11.0.1 @@ -828,13 +840,13 @@ importers: version: 4.0.2(@nestjs/common@11.1.11(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2) '@vitest/coverage-v8': specifier: ^2.1.9 - version: 2.1.9(vitest@2.1.9(@types/node@25.0.5)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) + version: 2.1.9(vitest@2.1.9(@types/node@25.5.0)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^2.1.9 - version: 2.1.9(@types/node@25.0.5)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + version: 2.1.9(@types/node@25.5.0)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) packages/eslint-config: dependencies: @@ -994,31 +1006,52 @@ importers: specifier: ^4.0.18 version: 4.0.18(@types/node@22.19.3)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + packages/piece-framework: + devDependencies: + '@types/node': + specifier: ^25.5.0 + version: 25.5.0 + '@vitest/coverage-v8': + specifier: ^4.0.18 + version: 4.0.18(vitest@4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + typescript: + specifier: ^5.7.3 + version: 5.9.3 + vitest: + specifier: ^4.0.18 + version: 4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + packages/pieces/quickbooks: dependencies: '@nexiom/connectors': specifier: workspace:* version: link:../../connectors + '@nexiom/piece-framework': + specifier: workspace:* + version: link:../../piece-framework dayjs: specifier: ^1.11.19 version: 1.11.20 devDependencies: vitest: specifier: ^4.0.18 - version: 4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/pieces/salesforce: dependencies: '@nexiom/connectors': specifier: workspace:* version: link:../../connectors + '@nexiom/piece-framework': + specifier: workspace:* + version: link:../../piece-framework dayjs: specifier: ^1.11.19 version: 1.11.20 devDependencies: vitest: specifier: ^4.0.18 - version: 4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/queue: dependencies: @@ -4512,6 +4545,9 @@ packages: '@types/node@25.0.5': resolution: {integrity: sha512-FuLxeLuSVOqHPxSN1fkcD8DLU21gAP7nCKqGRJ/FglbCUBs0NYN6TpHcdmyLeh8C0KwGIaZQJSv+OYG+KZz+Gw==} + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} + '@types/nodemailer@7.0.4': resolution: {integrity: sha512-ee8fxWqOchH+Hv6MDDNNy028kwvVnLplrStm4Zf/3uHWw5zzo8FoYYeffpJtGs2wWysEumMH0ZIdMGMY1eMAow==} @@ -9185,6 +9221,9 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} @@ -11719,6 +11758,14 @@ snapshots: '@types/node': 25.0.5 optional: true + '@inquirer/confirm@5.1.21(@types/node@25.5.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@25.5.0) + '@inquirer/type': 3.0.10(@types/node@25.5.0) + optionalDependencies: + '@types/node': 25.5.0 + optional: true + '@inquirer/core@10.3.2(@types/node@22.19.3)': dependencies: '@inquirer/ansi': 1.0.2 @@ -11759,6 +11806,20 @@ snapshots: '@types/node': 25.0.5 optional: true + '@inquirer/core@10.3.2(@types/node@25.5.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@25.5.0) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 25.5.0 + optional: true + '@inquirer/editor@4.2.23(@types/node@22.19.3)': dependencies: '@inquirer/core': 10.3.2(@types/node@22.19.3) @@ -11876,6 +11937,11 @@ snapshots: '@types/node': 25.0.5 optional: true + '@inquirer/type@3.0.10(@types/node@25.5.0)': + optionalDependencies: + '@types/node': 25.5.0 + optional: true + '@ioredis/commands@1.5.1': {} '@isaacs/balanced-match@4.0.1': {} @@ -14067,6 +14133,10 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + '@types/nodemailer@7.0.4': dependencies: '@aws-sdk/client-sesv2': 3.965.0 @@ -14329,6 +14399,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@25.5.0)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magic-string: 0.30.21 + magicast: 0.3.5 + std-env: 3.10.0 + test-exclude: 7.0.2 + tinyrainbow: 1.2.0 + vitest: 2.1.9(@types/node@25.5.0)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + transitivePeerDependencies: + - supports-color + '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@types/node@22.19.3)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -14343,7 +14431,7 @@ snapshots: tinyrainbow: 3.0.3 vitest: 4.0.18(@types/node@22.19.3)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.18 @@ -14355,7 +14443,7 @@ snapshots: obug: 2.1.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitest: 4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/expect@2.1.9': dependencies: @@ -14373,14 +14461,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@2.1.9(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(vite@5.4.21(@types/node@25.0.5)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1))': + '@vitest/mocker@2.1.9(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(vite@5.4.21(@types/node@22.19.3)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1))': dependencies: '@vitest/spy': 2.1.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.10(@types/node@22.19.3)(typescript@5.9.3) - vite: 5.4.21(@types/node@25.0.5)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + vite: 5.4.21(@types/node@22.19.3)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) '@vitest/mocker@2.1.9(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(vite@5.4.21(@types/node@24.10.4)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1))': dependencies: @@ -14400,6 +14488,15 @@ snapshots: msw: 2.12.10(@types/node@25.0.5)(typescript@5.9.3) vite: 5.4.21(@types/node@25.0.5)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + '@vitest/mocker@2.1.9(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.12.10(@types/node@25.5.0)(typescript@5.9.3) + vite: 5.4.21(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + '@vitest/mocker@4.0.18(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(vite@7.3.1(@types/node@22.19.3)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.18 @@ -14409,14 +14506,14 @@ snapshots: msw: 2.12.10(@types/node@22.19.3)(typescript@5.9.3) vite: 7.3.1(@types/node@22.19.3)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@4.0.18(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(vite@7.3.1(@types/node@25.0.5)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@4.0.18(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - msw: 2.12.10(@types/node@25.0.5)(typescript@5.9.3) - vite: 7.3.1(@types/node@25.0.5)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + msw: 2.12.10(@types/node@25.5.0)(typescript@5.9.3) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@2.1.9': dependencies: @@ -14924,30 +15021,7 @@ snapshots: bcryptjs@3.0.3: {} - better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.28.5)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@24.10.4)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)): - dependencies: - '@better-auth/core': 1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0) - '@better-auth/telemetry': 1.4.10(@better-auth/core@1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)) - '@better-auth/utils': 0.3.0 - '@better-fetch/fetch': 1.1.21 - '@noble/ciphers': 2.1.1 - '@noble/hashes': 2.0.1 - better-call: 1.1.7(zod@4.3.5) - defu: 6.1.4 - jose: 6.1.3 - kysely: 0.28.9 - nanostores: 1.1.0 - zod: 4.3.5 - optionalDependencies: - drizzle-kit: 0.31.8 - drizzle-orm: 0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3) - next: 16.1.1(@babel/core@7.28.5)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3) - pg: 8.16.3 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - vitest: 2.1.9(@types/node@24.10.4)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) - - better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)): + better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@24.10.4)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)): dependencies: '@better-auth/core': 1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0) '@better-auth/telemetry': 1.4.10(@better-auth/core@1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)) @@ -14968,7 +15042,7 @@ snapshots: pg: 8.16.3 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - vitest: 2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + vitest: 2.1.9(@types/node@24.10.4)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)): dependencies: @@ -14987,7 +15061,7 @@ snapshots: optionalDependencies: drizzle-kit: 0.31.8 drizzle-orm: 0.45.1(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3) - next: 16.1.1(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3) + next: 16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3) pg: 8.16.3 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) @@ -17187,6 +17261,32 @@ snapshots: - '@types/node' optional: true + msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.21(@types/node@25.5.0) + '@mswjs/interceptors': 0.41.3 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.1.1 + graphql: 16.12.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.10.1 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.0 + type-fest: 5.4.4 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + optional: true + multer@2.0.2: dependencies: append-field: 1.0.0 @@ -17246,33 +17346,6 @@ snapshots: rxjs: 7.8.2 zod: 4.3.5 - next@16.1.1(@babel/core@7.28.5)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3): - dependencies: - '@next/env': 16.1.1 - '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001780 - postcss: 8.4.31 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3) - optionalDependencies: - '@next/swc-darwin-arm64': 16.1.1 - '@next/swc-darwin-x64': 16.1.1 - '@next/swc-linux-arm64-gnu': 16.1.1 - '@next/swc-linux-arm64-musl': 16.1.1 - '@next/swc-linux-x64-gnu': 16.1.1 - '@next/swc-linux-x64-musl': 16.1.1 - '@next/swc-win32-arm64-msvc': 16.1.1 - '@next/swc-win32-x64-msvc': 16.1.1 - '@playwright/test': 1.58.2 - sass: 1.97.3 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - optional: true - next@16.1.1(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3): dependencies: '@next/env': 16.1.1 @@ -17300,33 +17373,6 @@ snapshots: - babel-plugin-macros optional: true - next@16.1.1(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.3): - dependencies: - '@next/env': 16.1.1 - '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001780 - postcss: 8.4.31 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - styled-jsx: 5.1.6(react@19.2.3) - optionalDependencies: - '@next/swc-darwin-arm64': 16.1.1 - '@next/swc-darwin-x64': 16.1.1 - '@next/swc-linux-arm64-gnu': 16.1.1 - '@next/swc-linux-arm64-musl': 16.1.1 - '@next/swc-linux-x64-gnu': 16.1.1 - '@next/swc-linux-x64-musl': 16.1.1 - '@next/swc-win32-arm64-msvc': 16.1.1 - '@next/swc-win32-x64-msvc': 16.1.1 - '@playwright/test': 1.58.2 - sass: 1.97.3 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - optional: true - node-abort-controller@3.1.1: {} node-addon-api@7.1.1: @@ -18793,14 +18839,6 @@ snapshots: dependencies: webpack: 5.103.0(@swc/core@1.15.11) - styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.3): - dependencies: - client-only: 0.0.1 - react: 19.2.3 - optionalDependencies: - '@babel/core': 7.28.5 - optional: true - styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.3): dependencies: client-only: 0.0.1 @@ -18809,12 +18847,6 @@ snapshots: '@babel/core': 7.29.0 optional: true - styled-jsx@5.1.6(react@19.2.3): - dependencies: - client-only: 0.0.1 - react: 19.2.3 - optional: true - stylehacks@6.1.1(postcss@8.5.6): dependencies: browserslist: 4.28.1 @@ -19222,6 +19254,8 @@ snapshots: undici-types@7.16.0: {} + undici-types@7.18.2: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: @@ -19358,6 +19392,24 @@ snapshots: - supports-color - terser + vite-node@2.1.9(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-plugin-checker@0.12.0(eslint@9.39.2(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.4)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)): dependencies: '@babel/code-frame': 7.29.0 @@ -19416,6 +19468,20 @@ snapshots: sass-embedded: 1.97.3 terser: 5.44.1 + vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1): + dependencies: + esbuild: 0.25.12 + postcss: 8.5.6 + rollup: 4.55.1 + optionalDependencies: + '@types/node': 25.5.0 + fsevents: 2.3.3 + less: 4.5.1 + lightningcss: 1.30.2 + sass: 1.97.3 + sass-embedded: 1.97.3 + terser: 5.44.1 + vite@7.3.1(@types/node@22.19.3)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12 @@ -19436,7 +19502,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vite@7.3.1(@types/node@25.0.5)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -19445,7 +19511,7 @@ snapshots: rollup: 4.55.1 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.0.5 + '@types/node': 25.5.0 fsevents: 2.3.3 jiti: 2.6.1 less: 4.5.1 @@ -19459,7 +19525,7 @@ snapshots: vitest@2.1.9(@types/node@22.19.3)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1): dependencies: '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(vite@5.4.21(@types/node@25.0.5)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) + '@vitest/mocker': 2.1.9(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(vite@5.4.21(@types/node@22.19.3)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) '@vitest/pretty-format': 2.1.9 '@vitest/runner': 2.1.9 '@vitest/snapshot': 2.1.9 @@ -19567,6 +19633,43 @@ snapshots: - supports-color - terser + vitest@2.1.9(@types/node@25.5.0)(happy-dom@20.1.0)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + vite-node: 2.1.9(@types/node@25.5.0)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.5.0 + happy-dom: 20.1.0 + jsdom: 27.4.0(@noble/hashes@2.0.1) + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vitest@4.0.18(@types/node@22.19.3)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.3)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 @@ -19606,10 +19709,10 @@ snapshots: - tsx - yaml - vitest@4.0.18(@types/node@25.0.5)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.0.18(@types/node@25.5.0)(happy-dom@20.1.0)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@2.0.1))(less@4.5.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(msw@2.12.10(@types/node@25.0.5)(typescript@5.9.3))(vite@7.3.1(@types/node@25.0.5)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 4.0.18(msw@2.12.10(@types/node@25.5.0)(typescript@5.9.3))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -19626,10 +19729,10 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.0.5)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.0.5 + '@types/node': 25.5.0 happy-dom: 20.1.0 jsdom: 27.4.0(@noble/hashes@2.0.1) transitivePeerDependencies: