diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..53ac2f5e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,160 @@ + +# Stage 1: Full monorepo context for dependency resolution +FROM node:20-bookworm-slim AS monorepo-base + +# This is to remove the notice to update NPM that will break the output from STDOUT +RUN npm config set update-notifier false + +# Install alternative package managers globally +RUN npm install -g pnpm@latest + +# Set working directory to monorepo root +WORKDIR /monorepo + +# Copy workspace configuration files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY .npmrc ./ +COPY pnpm-lock.yaml ./ + +# Copy workspace package directories (will be replaced with actual patterns) +COPY apps ./apps +COPY packages ./packages +COPY examples ./examples +COPY packages/cli ./packages/cli + +# Install all dependencies from monorepo root +RUN pnpm install --frozen-lockfile + +# Stage 2: Production image +FROM node:20-bookworm-slim + +# This is to remove the notice to update NPM that will break the output from STDOUT +RUN npm config set update-notifier false + +# Install alternative package managers globally +RUN npm install -g pnpm@latest + +ARG DEBIAN_FRONTEND=noninteractive + +# Update the package lists for upgrades for security purposes +RUN apt-get update && apt-get upgrade -y + +# Install ca-certificates, tail and locales package +RUN apt-get install -y ca-certificates locales coreutils curl && update-ca-certificates + +# moose depends on libc 2.40+, not available in stable +# This uses unstable, but unpinned because they delete older versions +RUN echo "deb http://deb.debian.org/debian/ unstable main" >> /etc/apt/sources.list \ + && apt-get update \ + && apt-get install -y libc6 \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Generate locale files +RUN locale-gen en_US.UTF-8 +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 +ENV TZ=UTC +ENV DOCKER_IMAGE=true + +# Install Moose +ARG FRAMEWORK_VERSION="0.0.0" +ARG DOWNLOAD_URL +RUN echo "DOWNLOAD_URL: ${DOWNLOAD_URL}" +RUN ldd --version +RUN curl -Lo /usr/local/bin/moose ${DOWNLOAD_URL} +RUN chmod +x /usr/local/bin/moose + +RUN moose --version + +# Setup healthcheck +HEALTHCHECK --interval=30s --timeout=3s \ + CMD curl -f http://localhost:4000/health || exit 1 + +# Sets up non-root user using 1001 because node creates a user with 1000 +RUN groupadd --gid 1001 moose \ + && useradd --uid 1001 --gid moose --shell /bin/bash --create-home moose + +# Set the working directory inside the container +WORKDIR /application + +# Ensure application directory is owned by moose user +RUN chown -R moose:moose /application + +# Placeholder for the language specific copy package file copy + +# Copy application files from monorepo stage +COPY --from=monorepo-base --chown=moose:moose /monorepo/pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api/app ./app +COPY --from=monorepo-base --chown=moose:moose /monorepo/pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api/package.json ./package.json +COPY --from=monorepo-base --chown=moose:moose /monorepo/pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api/tsconfig.json ./tsconfig.json + +# Use pnpm deploy from workspace context to create clean production dependencies +USER root:root +WORKDIR /temp-monorepo +COPY --from=monorepo-base /monorepo/pnpm-workspace.yaml ./ +COPY --from=monorepo-base /monorepo/pnpm-lock.yaml ./ +COPY --from=monorepo-base /monorepo/pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api ./pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api +# Copy all workspace directories that exist +COPY --from=monorepo-base /monorepo/apps ./apps +COPY --from=monorepo-base /monorepo/packages ./packages +COPY --from=monorepo-base /monorepo/examples ./examples +COPY --from=monorepo-base /monorepo/packages/cli ./packages/cli +# Use package manager to install only production dependencies + +# Use package manager to install only production dependencies +RUN pnpm --filter "./pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api" deploy /temp-deploy --legacy + +# Fix: pnpm deploy --legacy doesn't copy native bindings, so rebuild them from source +# Generic solution: Find and rebuild all packages with native bindings (those with binding.gyp) +RUN echo "=== Rebuilding native modules ===" && \ + cd /temp-deploy && \ + found_native=0 && \ + for dir in $(find node_modules -name "binding.gyp" -type f 2>/dev/null | xargs -r dirname); do \ + found_native=1; \ + package_name=$(basename $(dirname "$dir")); \ + echo "Found native module: $package_name in $dir"; \ + if (cd "$dir" && npm rebuild 2>&1); then \ + echo "โœ“ Successfully rebuilt $package_name"; \ + else \ + echo "โš  Warning: Failed to rebuild $package_name (may be optional)"; \ + fi; \ + done && \ + if [ $found_native -eq 0 ]; then \ + echo "No native modules found (this is normal if your deps don't have native bindings)"; \ + fi && \ + echo "=== Native modules rebuild complete ===" +RUN cp -r /temp-deploy/node_modules /application/node_modules +RUN chown -R moose:moose /application/node_modules + +# No TypeScript path transformations needed +USER root:root +# Clean up temporary directories +RUN rm -rf /temp-deploy /temp-monorepo + +RUN if [ -d "/application/node_modules/@514labs/moose-lib/dist/" ]; then ls -la /application/node_modules/@514labs/moose-lib/dist/; fi +USER moose:moose +WORKDIR /application + +# https://stackoverflow.com/questions/70096208/dockerfile-copy-folder-if-it-exists-conditional-copy/70096420#70096420 +COPY --chown=moose:moose pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api/project.tom[l] ./project.toml +COPY --chown=moose:moose pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api/moose.config.tom[l] ./moose.config.toml +COPY --chown=moose:moose pipeline-registry/dutchie-to-clickhouse/v001/514-labs/typescript/open-api/.moose/packager/versions .moose/versions + + +# Placeholder for the language specific install command +# Dependencies copied from monorepo build stage + + +# all commands from here on will be run as the moose user +USER moose:moose + +# Checks that the project is valid +RUN which moose +RUN moose check --write-infra-map || (echo "Error running moose check" && exit 1) + +# Expose the ports on which the application will listen +EXPOSE 4000 + +# Set the command to run the application +CMD ["moose", "prod"] diff --git a/connector-registry/apex-trading/_meta/README.md b/connector-registry/apex-trading/_meta/README.md new file mode 100644 index 00000000..cd78ab3f --- /dev/null +++ b/connector-registry/apex-trading/_meta/README.md @@ -0,0 +1,6 @@ +# apex-trading (Registry) + +This is the top-level registry entry for `apex-trading`. + +- Versions live under `apex-trading/v1` +- See author implementations under `apex-trading/v1/514-labs` diff --git a/connector-registry/apex-trading/_meta/connector.json b/connector-registry/apex-trading/_meta/connector.json new file mode 100644 index 00000000..81d1d253 --- /dev/null +++ b/connector-registry/apex-trading/_meta/connector.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schemas.connector-factory.dev/connector-root.schema.json", + "identifier": "apex-trading", + "name": "apex-trading", + "category": "api", + "tags": [], + "description": "", + "homepage": "" +} \ No newline at end of file diff --git a/connector-registry/apex-trading/v1/514-labs/_meta/CHANGELOG.md b/connector-registry/apex-trading/v1/514-labs/_meta/CHANGELOG.md new file mode 100644 index 00000000..22497eec --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/_meta/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to this connector will be documented in this file. + +## 0.1.0 - Scaffold created + +- Initial scaffold for `apex-trading` (TypeScript) added. diff --git a/connector-registry/apex-trading/v1/514-labs/_meta/LICENSE b/connector-registry/apex-trading/v1/514-labs/_meta/LICENSE new file mode 100644 index 00000000..c872170b --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/_meta/LICENSE @@ -0,0 +1,18 @@ +MIT License + +Copyright (c) 514-labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/connector-registry/apex-trading/v1/514-labs/_meta/README.md b/connector-registry/apex-trading/v1/514-labs/_meta/README.md new file mode 100644 index 00000000..cef0a4ef --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/_meta/README.md @@ -0,0 +1,10 @@ +# apex-trading Connector (by 514-labs) + +This directory contains language-agnostic metadata and documentation for the `apex-trading` connector. + +- Name: `apex-trading` +- Author: `514-labs` +- Category: `api` +- Languages: `typescript` + +See `_meta/connector.json` for connector metadata and implementation folders for language-specific code. diff --git a/connector-registry/apex-trading/v1/514-labs/_meta/connector.json b/connector-registry/apex-trading/v1/514-labs/_meta/connector.json new file mode 100644 index 00000000..32236d64 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/_meta/connector.json @@ -0,0 +1,22 @@ +{ + "name": "apex-trading", + "author": "514-labs", + "version": "v1", + "languages": [ + "typescript" + ], + "category": "api", + "capabilities": { + "extract": true, + "transform": false, + "load": false + }, + "source": { + "type": "api", + "spec": "", + "homepage": "" + }, + "tags": [], + "maintainers": [], + "issues": { "typescript": { "default": "" } } +} \ No newline at end of file diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/_meta/connector.json b/connector-registry/apex-trading/v1/514-labs/typescript/_meta/connector.json new file mode 100644 index 00000000..7574c821 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/_meta/connector.json @@ -0,0 +1,8 @@ +{ + "identifier": "apex-trading", + "name": "apex-trading", + "author": "514-labs", + "version": "v1", + "language": "typescript", + "implementations": ["default"] +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example b/connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example new file mode 100644 index 00000000..6e8d9f45 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example @@ -0,0 +1,6 @@ +# Apex Trading API credentials +APEX_API_KEY=your_api_key_here + +# Optional: Custom base URL +# APEX_BASE_URL=https://api-docs.apextrading.com + diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/.gitignore b/connector-registry/apex-trading/v1/514-labs/typescript/default/.gitignore new file mode 100644 index 00000000..deed335b --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +.env diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/CONNECTOR_GUIDE.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/CONNECTOR_GUIDE.md new file mode 100644 index 00000000..8425b0b7 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/CONNECTOR_GUIDE.md @@ -0,0 +1,83 @@ +# Connector Implementation Guide + +This guide walks you through implementing your `apex-trading` connector from scaffold to production. + +**๐Ÿ“– For detailed step-by-step instructions, see:** +`connector-registry/_scaffold/CONNECTOR_IMPLEMENTATION_GUIDE.md` + +Or view online: [Connector Implementation Guide](../../../../../../_scaffold/CONNECTOR_IMPLEMENTATION_GUIDE.md) + +## Quick Checklist + +### Phase 1: Understand Your API โœ“ +- [ ] Read the `apex-trading` API documentation +- [ ] Identify authentication method +- [ ] Understand pagination pattern +- [ ] Note rate limits +- [ ] Identify key endpoints + +### Phase 2: Scaffold โœ“ +- [x] Connector scaffolded + +### Phase 3: Configure Authentication +- [ ] Update `ConnectorConfig` type in `src/client/connector.ts` +- [ ] Implement `init()` method to set up auth +- [ ] Update `.env.example` with required credentials + +### Phase 4: Implement Pagination +- [ ] Choose pagination pattern (offset/cursor/page) +- [ ] Implement in `src/lib/paginate.ts` +- [ ] Test with API to verify it works + +### Phase 5: Implement Resources +- [ ] Define resource types in `src/resources/products.ts` +- [ ] Implement list/get/create methods as needed +- [ ] Add resource getters to connector class + +### Phase 6: Add Schemas +- [ ] Create JSON schemas in `schemas/raw/json/` +- [ ] Add documentation `.md` files +- [ ] Register in `schemas/index.json` + +### Phase 7: Update Documentation +- [ ] Update `README.md` with examples +- [ ] Document config in `docs/configuration.md` +- [ ] Update `.env.example` + +### Phase 8: Write Tests +- [ ] Update `tests/resource.test.ts` +- [ ] Add observability tests if using logging/metrics +- [ ] Test pagination edge cases + +### Phase 9: Build & Test +- [ ] Run `pnpm run build` - should complete without errors +- [ ] Run `pnpm test` - all tests should pass +- [ ] Try `examples/basic-usage.ts` with real API + +### Phase 10: Real-World Testing +- [ ] Test with real credentials +- [ ] Verify pagination with large datasets +- [ ] Test error handling +- [ ] Test rate limiting (if applicable) + +## Common Patterns + +See the detailed guide for code examples of: +- Simple API key authentication +- Bearer token authentication +- OAuth2 authentication +- Offset-based pagination +- Cursor-based pagination +- Page number pagination + +## Reference Connectors + +Look at these for examples: +- **Socrata** (`connector-registry/socrata/`): Simple API with offset pagination +- **Meta Ads** (`connector-registry/meta-ads/`): OAuth2 with cursor pagination +- **Google Analytics** (`connector-registry/google-analytics/`): Service account auth + +## Need Help? + +Refer to the full implementation guide at: +`connector-registry/_scaffold/CONNECTOR_IMPLEMENTATION_GUIDE.md` diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/README.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/README.md new file mode 100644 index 00000000..0533cbd2 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/README.md @@ -0,0 +1,113 @@ +# Apex Trading Connector + +TypeScript connector for the Apex Trading wholesale cannabis platform API. + +## Overview + +Apex Trading is a wholesale cannabis trading platform. This connector provides access to products, batches, orders, companies, and buyers data. + +## Installation + +```bash +pnpm add @workspace/connector-apex-trading +``` + +## Quick Start + +```typescript +import { createConnector } from '@workspace/connector-apex-trading' + +const connector = createConnector() + +connector.initialize({ + apiKey: process.env.APEX_API_KEY!, + logging: { enabled: true, level: 'info' }, + metrics: { enabled: true }, +}) + +// List products with incremental sync +for await (const page of connector.products.list({ + updated_at_from: '2024-01-01T00:00:00Z', + pageSize: 100 +})) { + console.log('Products:', page) +} + +// List receiving orders +for await (const page of connector.orders.receiving({ + status: 'confirmed' +})) { + console.log('Orders:', page) +} + +// Get company details +const company = await connector.companies.get('company-id') +console.log('Company:', company) +``` + +## Configuration + +### Required +- `apiKey`: Your Apex Trading API key + +### Optional +- `baseUrl`: Custom API base URL (default: https://api-docs.apextrading.com) +- `logging`: Logging configuration +- `metrics`: Metrics collection configuration + +## Available Resources + +- **products**: Product catalog with cannabis products +- **batches**: Product batches with tracking and test results +- **orders**: Orders (receiving, shipping, transporter) +- **companies**: Trading companies (distributors, retailers, etc.) +- **buyers**: Buyer information and purchase history + +## API Features + +### Incremental Sync + +Products and batches support incremental sync using `updated_at_from`: + +```typescript +// Get products updated since last sync +for await (const page of connector.products.list({ + updated_at_from: lastSyncTime +})) { + // Process updated products +} +``` + +### Order Types + +Access different order types: + +```typescript +// Receiving orders +for await (const page of connector.orders.receiving()) { } + +// Shipping orders +for await (const page of connector.orders.shipping()) { } + +// Transporter orders +for await (const page of connector.orders.transporter()) { } + +// All orders +for await (const page of connector.orders.list()) { } +``` + +## API Rate Limits + +The Apex Trading API has a rate limit of 15 requests per second. This connector automatically handles rate limiting. + +## Documentation + +- [Getting Started](./docs/getting-started.md) +- [Configuration](./docs/configuration.md) +- [Schemas](./docs/schema.md) +- [API Limits](./docs/limits.md) +- [Observability](./docs/observability.md) + +## License + +See [LICENSE](../../_meta/LICENSE) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/configuration.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/configuration.md new file mode 100644 index 00000000..59237d7c --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/configuration.md @@ -0,0 +1,7 @@ +# Configuration + +- baseUrl, timeoutMs, userAgent +- auth: api key, basic, bearer, oauth2 (per core) +- retry: maxAttempts, initialDelayMs, maxDelayMs, backoffMultiplier, respectRetryAfter +- rateLimit: requestsPerSecond, burstCapacity, adaptiveFromHeaders +- hooks: arrays for beforeRequest/afterResponse/onError/onRetry diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/getting-started.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/getting-started.md new file mode 100644 index 00000000..ae23d7b8 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/getting-started.md @@ -0,0 +1,16 @@ +# Getting started + +```ts +import { createConnector } from './src' + +const conn = createConnector() +conn.initialize({ + baseUrl: 'https://api.example.com', + auth: { type: 'bearer', bearer: { token: process.env.API_TOKEN! } }, + logging: { enabled: true, level: 'info' }, +}) + +for await (const page of conn.myResource.getAll({ pageSize: 100, maxItems: 500 })) { + console.log(page.length) +} +``` diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/limits.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/limits.md new file mode 100644 index 00000000..447b11f1 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/limits.md @@ -0,0 +1,3 @@ +# Limits + +Describe API limits, quotas, and rate limiting behavior. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/observability.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/observability.md new file mode 100644 index 00000000..684a6ef4 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/observability.md @@ -0,0 +1,17 @@ +# Observability + +## Logging +```ts +conn.initialize({ + logging: { enabled: true, level: 'info', includeQueryParams: true, includeHeaders: true, includeBody: false } +}) +``` +Emits http_request and http_response with optional fields. + +## Metrics +```ts +import { createMetricsHooks, InMemoryMetricsSink } from '../src/observability/metrics-hooks' +const sink = new InMemoryMetricsSink() +conn.initialize({ hooks: createMetricsHooks(sink) }) +``` +Inspect sink.events for telemetry. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/schema.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/schema.md new file mode 100644 index 00000000..fd596dce --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/schema.md @@ -0,0 +1,22 @@ +# Schema + +Refer to `schemas/index.json` and related files. + +## Organization + +Schemas support nested folder structures for better organization: + +- **raw/** - Raw API schemas + - `endpoints/` - API endpoint request/response schemas + - `types/` - Shared type definitions for endpoints (not shown as Files) + - `events/` - Event payloads +- **extracted/** - Normalized schemas + - `entities/` - Business entities + - `metrics/` - Aggregated data +- **files/** - File-based schemas (CSV/JSON/Parquet/Avro/NDJSON). Only items under `schemas/files` appear in the Files tab. + +## Adding Schemas + +1. Create schema files in appropriate nested folders +2. Update `schemas/index.json` with correct paths for endpoints and tables +3. Place file schemas under `schemas/files` (no index entries needed) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/examples/basic-usage.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/examples/basic-usage.ts new file mode 100644 index 00000000..634ffbfa --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/examples/basic-usage.ts @@ -0,0 +1,104 @@ +import { createConnector } from '../src' + +async function main() { + const connector = createConnector() + + // Initialize the connector with your API key + connector.initialize({ + apiKey: process.env.APEX_API_KEY!, + logging: { enabled: true, level: 'info' }, + metrics: { enabled: true }, + }) + + console.log('Apex Trading Connector - Wholesale Cannabis Platform\n') + + // Example 1: List products with incremental sync + console.log('1. Listing products (incremental sync)...') + try { + let count = 0 + for await (const page of connector.products.list({ + pageSize: 10, + maxItems: 10, + updated_at_from: '2024-01-01T00:00:00Z' // Get products updated since this date + })) { + console.log(` Found ${page.length} products:`) + page.forEach(product => { + console.log(` - ${product.name} (${product.category || 'No category'})`) + }) + count += page.length + } + console.log(` Total products listed: ${count}\n`) + } catch (error) { + console.log(' Error listing products:', (error as Error).message, '\n') + } + + // Example 2: List batches + console.log('2. Listing batches...') + try { + let batchCount = 0 + for await (const page of connector.batches.list({ pageSize: 10, maxItems: 10 })) { + console.log(` Found ${page.length} batches`) + page.forEach(batch => { + console.log(` - Batch ${batch.batch_number}: ${batch.quantity} units`) + }) + batchCount += page.length + } + console.log(` Total batches: ${batchCount}\n`) + } catch (error) { + console.log(' Error listing batches:', (error as Error).message, '\n') + } + + // Example 3: List receiving orders + console.log('3. Listing receiving orders...') + try { + let orderCount = 0 + for await (const page of connector.orders.receiving({ + pageSize: 10, + maxItems: 10, + status: 'confirmed' + })) { + console.log(` Found ${page.length} orders`) + page.forEach(order => { + console.log(` - Order ${order.order_number}: ${order.status}`) + }) + orderCount += page.length + } + console.log(` Total orders: ${orderCount}\n`) + } catch (error) { + console.log(' Error listing orders:', (error as Error).message, '\n') + } + + // Example 4: List companies + console.log('4. Listing companies...') + try { + let companyCount = 0 + for await (const page of connector.companies.list({ pageSize: 10, maxItems: 10 })) { + console.log(` Found ${page.length} companies`) + page.forEach(company => { + console.log(` - ${company.name} (${company.type})`) + }) + companyCount += page.length + } + console.log(` Total companies: ${companyCount}\n`) + } catch (error) { + console.log(' Error listing companies:', (error as Error).message, '\n') + } + + // Example 5: List buyers + console.log('5. Listing buyers...') + try { + let buyerCount = 0 + for await (const page of connector.buyers.list({ pageSize: 10, maxItems: 10 })) { + console.log(` Found ${page.length} buyers`) + buyerCount += page.length + } + console.log(` Total buyers: ${buyerCount}\n`) + } catch (error) { + console.log(' Error listing buyers:', (error as Error).message, '\n') + } + + console.log('Done!') +} + +main().catch(console.error) + diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/install.config.toml b/connector-registry/apex-trading/v1/514-labs/typescript/default/install.config.toml new file mode 100644 index 00000000..845da362 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/install.config.toml @@ -0,0 +1,32 @@ +language = "typescript" +description = "TypeScript connector for apex-trading" +post_install_print = """ +๐Ÿš€ Next steps to get your apex-trading connector running: + +๐Ÿ“– IMPORTANT: Read the implementation guide first! + $ cat CONNECTOR_GUIDE.md + Or open: connector-registry/_scaffold/CONNECTOR_IMPLEMENTATION_GUIDE.md + +๐Ÿ“‚ Go to your connector directory: + $ cd + +๐Ÿ“ฆ Install dependencies: + $ npm install + +๐Ÿ”ง Build the connector: + $ npm run build + +๐Ÿงช Run tests: + $ npm test + +๐Ÿ“‹ Follow the checklist in CONNECTOR_GUIDE.md: + Phase 3: Configure authentication in src/client/connector.ts + Phase 4: Implement pagination in src/lib/paginate.ts + Phase 5: Implement resources in src/resources/ + Phase 6-10: Add schemas, docs, tests + +๐Ÿ’ก Reference connectors for examples: + โ€ข connector-registry/socrata/ (simple API key + offset pagination) + โ€ข connector-registry/meta-ads/ (OAuth2 + cursor pagination) + โ€ข connector-registry/google-analytics/ (service account auth) +""" diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/jest.config.cjs b/connector-registry/apex-trading/v1/514-labs/typescript/default/jest.config.cjs new file mode 100644 index 00000000..9755da07 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/jest.config.cjs @@ -0,0 +1,4 @@ +module.exports = { + testEnvironment: 'node', + transform: { '^.+\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }] }, +}; diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/package.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/package.json new file mode 100644 index 00000000..64c8faff --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/package.json @@ -0,0 +1,23 @@ +{ + "name": "@workspace/connector-apex-trading", + "version": "0.0.0", + "private": true, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "test": "jest --runInBand" + }, + "engines": {"node": ">=20"}, + "dependencies": { + "@connector-factory/core": "^0.1.0" + }, + "devDependencies": { + "typescript": "^5.4.0", + "jest": "^29.7.0", + "ts-jest": "^29.1.2", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.30", + "nock": "^13.5.0" + } +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/README.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/README.md new file mode 100644 index 00000000..d7c9a8c9 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/README.md @@ -0,0 +1,15 @@ +# Extracted JSON Schemas + +This directory contains normalized/transformed JSON schemas. + +## Organization + +Like raw schemas, extracted schemas can be organized in nested folders: +- `entities/` - Normalized business entities +- `metrics/` - Calculated metrics or aggregations +- `reports/` - Structured report schemas +- Or any logical grouping for your transformed data + +## Naming Convention + +Use the same folder structure as in `raw/endpoints/` when there's a 1:1 mapping, or create new logical groupings for transformed data. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.md new file mode 100644 index 00000000..e8764b29 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.md @@ -0,0 +1,3 @@ +# Extracted events (JSON) + +Describe the normalized event shape. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.schema.json new file mode 100644 index 00000000..587ffc88 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.schema.json @@ -0,0 +1 @@ +{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"title\": \"Extracted Event\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {}\n}\n \ No newline at end of file diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/README.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/README.md new file mode 100644 index 00000000..7cfaa6c8 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/README.md @@ -0,0 +1,3 @@ +# Extracted relational schema + +Describe normalized tables and relationships. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.json new file mode 100644 index 00000000..a0300447 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.json @@ -0,0 +1 @@ +{\n \"tables\": []\n}\n \ No newline at end of file diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.sql b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.sql new file mode 100644 index 00000000..7e04bb7b --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.sql @@ -0,0 +1 @@ +-- DDL placeholders for extracted tables diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/index.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/index.json new file mode 100644 index 00000000..245115ca --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/index.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://schemas.connector-factory.dev/schema-index.schema.json", + "version": "0.1.0", + "datasets": [ + { + "name": "events", + "stage": "raw", + "kind": "endpoints", + "path": "raw/endpoints/events.schema.json", + "doc": "raw/endpoints/events.md" + }, + { + "name": "events", + "stage": "extracted", + "kind": "endpoints", + "path": "extracted/endpoints/events.schema.json", + "doc": "extracted/endpoints/events.md" + } + ], + "_examples": { + "_comment": "Below are examples of how to use nested folders. Copy and modify these patterns:", + "endpoint_example": { + "name": "users.create", + "stage": "raw", + "kind": "endpoints", + "path": "raw/endpoints/endpoints/users/create.schema.json", + "doc": "raw/endpoints/endpoints/users/create.md", + "metadata": { + "category": "endpoint", + "apiMethod": "POST" + } + }, + "nested_organization_example": { + "name": "reports.analytics", + "stage": "raw", + "kind": "endpoints", + "path": "raw/endpoints/endpoints/reports/analytics.schema.json", + "doc": "raw/endpoints/endpoints/reports/analytics.md" + } + } +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/files/README.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/files/README.md new file mode 100644 index 00000000..44529fa5 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/files/README.md @@ -0,0 +1,18 @@ +# File schemas + +Place file-based schemas here (CSV/JSON/Parquet/Avro/NDJSON). Files in this folder are shown in the Files tab. + +Examples: +- `events.csv` +- `events.schema.json` (with title/description) + +## OpenAPI type generation + +If you have an OpenAPI spec, you can generate TypeScript types and then re-export them from your resource model. + +### Recommended: hey-api +```bash +pnpm dlx @hey-api/openapi-ts -i schemas/raw/files/openapi.json -o src/generated +``` + +After generation, use the generated types by importing them directly (for example, from `src/resources/`). diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/README.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/README.md new file mode 100644 index 00000000..ee99c545 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/README.md @@ -0,0 +1,24 @@ +# Raw JSON Schemas + +This directory contains raw JSON schemas from the source API. + +## Organization + +Schemas can be organized in nested folders for better structure: +- `endpoints/` - API endpoint request/response schemas +- `types/` - Shared type definitions +- `events/` - Event or webhook payloads +- Or any logical grouping that makes sense for your connector + +## Example Structure + +``` +json/ +โ”œโ”€โ”€ endpoints/ +โ”‚ โ”œโ”€โ”€ users.schema.json +โ”‚ โ””โ”€โ”€ users.md +โ”œโ”€โ”€ types/ +โ”‚ โ”œโ”€โ”€ User.schema.json +โ”‚ โ””โ”€โ”€ User.md +โ””โ”€โ”€ events.schema.json +``` diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.md new file mode 100644 index 00000000..e5284e4f --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.md @@ -0,0 +1,3 @@ +# Raw events (JSON) + +Describe the upstream event payload. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.schema.json new file mode 100644 index 00000000..da422d28 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.schema.json @@ -0,0 +1 @@ +{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"title\": \"Raw Event\",\n \"type\": \"object\",\n \"additionalProperties\": true\n}\n \ No newline at end of file diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/README.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/README.md new file mode 100644 index 00000000..48f4d13b --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/README.md @@ -0,0 +1,3 @@ +# Raw relational schema + +Describe tables and relationships. diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.json new file mode 100644 index 00000000..a0300447 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.json @@ -0,0 +1 @@ +{\n \"tables\": []\n}\n \ No newline at end of file diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.sql b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.sql new file mode 100644 index 00000000..6c1336f9 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.sql @@ -0,0 +1 @@ +-- DDL placeholders for raw tables diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/scripts/postinstall.sh b/connector-registry/apex-trading/v1/514-labs/typescript/default/scripts/postinstall.sh new file mode 100644 index 00000000..076b92d2 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/scripts/postinstall.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -euo pipefail + +# This script runs after your package is installed (pnpm/npm postinstall lifecycle). +# It is intentionally minimal and documented so you can customize it for your distribution needs. +# +# Common use cases: +# - Copy shared core sources into this package for single-file distribution +# - Prune dev-only files from the published artifact +# - Flatten directories for easier consumption +# +# By default, this script does nothing. Uncomment and adapt as needed. + +main() { + echo "postinstall: no-op (customize scripts/postinstall.sh as needed)" + + # Example: flatten src into the package root + # if [ -d src ]; then + # shopt -s dotglob + # mv src/* . || true + # shopt -u dotglob + # rm -rf src + # fi +} + +main "$@" diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/client/connector.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/client/connector.ts new file mode 100644 index 00000000..011e78de --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/client/connector.ts @@ -0,0 +1,82 @@ +import { ApiConnectorBase } from '@connector-factory/core' +import type { ConnectorConfig, Hook } from '@connector-factory/core' +import { createLoggingHooks } from '../observability/logging-hooks' +import { createMetricsHooks, InMemoryMetricsSink } from '../observability/metrics-hooks' +import { createResource as createProductsResource } from '../resources/products' +import { createResource as createBatchesResource } from '../resources/batches' +import { createResource as createOrdersResource } from '../resources/orders' +import { createResource as createCompaniesResource } from '../resources/companies' +import { createResource as createBuyersResource } from '../resources/buyers' + +export type ApexTradingConfig = ConnectorConfig & { + apiKey?: string + baseUrl?: string + logging?: { enabled?: boolean; level?: 'debug'|'info'|'warn'|'error'; includeQueryParams?: boolean; includeHeaders?: boolean; includeBody?: boolean; logger?: (level: string, event: Record) => void } + metrics?: { enabled?: boolean } +} + +export class Connector extends ApiConnectorBase { + initialize(userConfig: ApexTradingConfig) { + const baseUrl = userConfig.baseUrl ?? 'https://api-docs.apextrading.com' + const apiKey = userConfig.apiKey ?? userConfig.auth?.bearer?.token + + const config: ConnectorConfig = { + ...userConfig, + baseUrl, + userAgent: userConfig.userAgent ?? 'apex-trading-connector', + defaultHeaders: { + ...userConfig.defaultHeaders, + ...(apiKey ? { 'Authorization': `****** ${apiKey}` } : {}), + }, + auth: userConfig.auth ?? { + type: 'bearer', + bearer: { token: apiKey ?? '' } + }, + retry: userConfig.retry ?? { + maxAttempts: 3, + retryableStatusCodes: [429, 500, 502, 503, 504], + }, + rateLimit: userConfig.rateLimit ?? { + requestsPerSecond: 15, // API limit is 15 req/sec + }, + } + + super.initialize(config, (cfg) => cfg) + + const cfg = (this as any).config as ConnectorConfig + const existing = cfg.hooks ?? {} + + if (userConfig.logging?.enabled) { + const logging = createLoggingHooks({ level: userConfig.logging.level, includeQueryParams: userConfig.logging.includeQueryParams, includeHeaders: userConfig.logging.includeHeaders, includeBody: userConfig.logging.includeBody, logger: userConfig.logging.logger as any }) + cfg.hooks = { + beforeRequest: [...(existing.beforeRequest ?? []), ...(logging.beforeRequest ?? [])], + afterResponse: [...(existing.afterResponse ?? []), ...(logging.afterResponse ?? [])], + onError: [...(existing.onError ?? []), ...(logging.onError ?? [])], + onRetry: [...(existing.onRetry ?? []), ...(logging.onRetry ?? [])], + } + } + + if (userConfig.metrics?.enabled) { + const sink = new InMemoryMetricsSink() + const metrics = createMetricsHooks(sink) + const curr = cfg.hooks ?? {} + cfg.hooks = { + beforeRequest: [...(curr.beforeRequest ?? []), ...(metrics.beforeRequest ?? [])], + afterResponse: [...(curr.afterResponse ?? []), ...(metrics.afterResponse ?? [])], + onError: [...(curr.onError ?? []), ...(metrics.onError ?? [])], + onRetry: [...(curr.onRetry ?? []), ...(metrics.onRetry ?? [])], + } + ;(this as any)._metricsSink = sink + } + } + + private get sendLite() { return async (args: any) => (this as any).request(args) } + + get products() { return createProductsResource(this.sendLite as any) } + get batches() { return createBatchesResource(this.sendLite as any) } + get orders() { return createOrdersResource(this.sendLite as any) } + get companies() { return createCompaniesResource(this.sendLite as any) } + get buyers() { return createBuyersResource(this.sendLite as any) } +} + +export function createConnector() { return new Connector() } diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/generated/.gitkeep b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/generated/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/index.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/index.ts new file mode 100644 index 00000000..cda885bb --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/index.ts @@ -0,0 +1,3 @@ +export { createConnector, Connector } from './client/connector' +export type { ApexTradingConfig } from './client/connector' +export * from './resources' diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/make-resource.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/make-resource.ts new file mode 100644 index 00000000..65fc86d2 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/make-resource.ts @@ -0,0 +1,55 @@ +import type { SendFn } from './paginate' + +/** + * Create a simple resource API at the given path. + * + * Exposes a single getAll async generator that fetches once and yields client-side chunks. + * This default suits APIs that don't expose server-side pagination. + * + * For real pagination, add a paginate helper and layer getAll on top. + */ +export function makeCrudResource< + Item, + ListParams extends Record | undefined = undefined +>( + objectPath: string, + send: SendFn, + options?: { + buildListQuery?: (params?: ListParams) => Record + } +) { + return { + async *getAll( + params?: (ListParams extends undefined + ? { pageSize?: number; maxItems?: number } + : ListParams & { pageSize?: number; maxItems?: number }) + ): AsyncGenerator> { + const listQuery = options?.buildListQuery?.(params as any) ?? {} + const res = await send({ method: 'GET', path: objectPath, query: listQuery, operation: 'getAll' }) + const data = Array.isArray(res.data) ? res.data : [] + + const pageSize = (params as any)?.pageSize as number | undefined + const maxItems = (params as any)?.maxItems as number | undefined + + let start = 0 + let remaining = typeof maxItems === 'number' ? Math.max(0, maxItems) : undefined + + if (!pageSize || pageSize <= 0) { + yield remaining !== undefined ? data.slice(0, remaining) : data + return + } + + while (start < data.length) { + const end = Math.min(data.length, start + pageSize) + let chunk = data.slice(start, end) + if (remaining !== undefined) { + if (remaining <= 0) break + if (chunk.length > remaining) chunk = chunk.slice(0, remaining) + remaining -= chunk.length + } + yield chunk + start = end + } + }, + } +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/paginate.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/paginate.ts new file mode 100644 index 00000000..1c7b8b17 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/paginate.ts @@ -0,0 +1,86 @@ +export type HttpResponseEnvelope = { data: T } + +export type SendFn = (args: { + method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + path: string; + query?: Record; + headers?: Record; + body?: unknown; + operation?: string; +}) => Promise> + +// Incremental sync pagination using updated_at_from parameter +export async function* paginateIncremental(params: { + send: SendFn; + path: string; + query?: Record; + updatedAtFrom?: string; + pageSize?: number; + maxItems?: number; +}): AsyncGenerator> { + const { send, path, query = {}, updatedAtFrom, pageSize = 100, maxItems } = params + let offset = 0 + let totalFetched = 0 + + while (true) { + const remaining = maxItems !== undefined ? maxItems - totalFetched : undefined + const currentLimit = remaining !== undefined ? Math.min(pageSize, remaining) : pageSize + + if (remaining !== undefined && remaining <= 0) break + + const response = await send({ + method: 'GET', + path, + query: { + ...query, + limit: currentLimit, + offset, + ...(updatedAtFrom ? { updated_at_from: updatedAtFrom } : {}) + }, + }) + + const items = Array.isArray(response.data) ? response.data : [] + if (items.length === 0) break + + totalFetched += items.length + offset += items.length + yield items + + if (items.length < currentLimit) break + } +} + +// Standard offset pagination +export async function* paginateOffset(params: { + send: SendFn; + path: string; + query?: Record; + pageSize?: number; + maxItems?: number; +}): AsyncGenerator> { + const { send, path, query = {}, pageSize = 100, maxItems } = params + let offset = 0 + let totalFetched = 0 + + while (true) { + const remaining = maxItems !== undefined ? maxItems - totalFetched : undefined + const currentLimit = remaining !== undefined ? Math.min(pageSize, remaining) : pageSize + + if (remaining !== undefined && remaining <= 0) break + + const response = await send({ + method: 'GET', + path, + query: { ...query, limit: currentLimit, offset }, + }) + + const items = Array.isArray(response.data) ? response.data : [] + if (items.length === 0) break + + totalFetched += items.length + offset += items.length + yield items + + if (items.length < currentLimit) break + } +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/logging-hooks.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/logging-hooks.ts new file mode 100644 index 00000000..cd7a9315 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/logging-hooks.ts @@ -0,0 +1,107 @@ +import type { Hook, HookContext } from '@connector-factory/core' + +export type LogLevel = 'debug' | 'info' | 'warn' | 'error' +export type LoggingOptions = { + level?: LogLevel + logger?: (level: LogLevel, event: Record) => void + includeQueryParams?: boolean + includeHeaders?: boolean + includeBody?: boolean +} + +const levelOrder: Record = { debug: 10, info: 20, warn: 30, error: 40 } +const shouldLog = (cfg: LoggingOptions, level: LogLevel) => + levelOrder[level] >= levelOrder[cfg.level ?? 'info'] + +function safeUrl(raw?: string, includeQuery = false): { url?: string; query?: Record } { + if (!raw) return {} + try { + const isPathOnly = raw.startsWith('/') + const u = new URL(isPathOnly ? `https://dummy$` : raw) + if (!includeQuery) { + return { url: isPathOnly ? u.pathname : u.toString() } + } + const query: Record = {} + u.searchParams.forEach((v, k) => { + query[k] = v + }) + return { url: isPathOnly ? `${u.pathname}${u.search}` : u.toString(), query } + } catch { + return { url: raw } + } +} + +export function createLoggingHooks( + opts: LoggingOptions = {} +): Partial<{ beforeRequest: Hook[]; afterResponse: Hook[]; onError: Hook[]; onRetry: Hook[] }> { + const logger = + opts.logger ?? ((level: LogLevel, event: Record) => { console.log(level, event) }) + + const beforeRequest: Hook = { + name: 'logging:beforeRequest', + execute: (ctx: HookContext) => { + if (ctx.type !== 'beforeRequest' || !shouldLog(opts, 'info')) return + const rawUrl = ctx.request.url || ctx.request.path + const { url, query } = safeUrl(rawUrl, !!opts.includeQueryParams) + const evt: Record = { + event: 'http_request', + operation: ctx.operation ?? ctx.request.operation, + method: ctx.request.method, + url, + } + if (opts.includeQueryParams && query) evt.query = query + if (opts.includeHeaders) evt.headers = ctx.request.headers + if (opts.includeBody && ctx.request.body !== undefined) evt.body = ctx.request.body + logger('info', evt) + }, + } + + const afterResponse: Hook = { + name: 'logging:afterResponse', + execute: (ctx: HookContext) => { + if (ctx.type !== 'afterResponse' || !shouldLog(opts, 'info')) return + const rawUrl = ctx.request.url || ctx.request.path + const { url } = safeUrl(rawUrl, !!opts.includeQueryParams) + const evt: Record = { + event: 'http_response', + operation: ctx.operation ?? ctx.request.operation, + method: ctx.request.method, + url, + status: ctx.response.status, + durationMs: ctx.response.meta?.durationMs, + retryCount: ctx.response.meta?.retryCount, + } + if (opts.includeHeaders) (evt as any).headers = (ctx.response as any).headers + if (opts.includeBody) (evt as any).body = ctx.response.data + logger('info', evt) + }, + } + + const onError: Hook = { + name: 'logging:onError', + execute: (ctx: HookContext) => { + if (ctx.type !== 'onError' || !shouldLog(opts, 'error')) return + logger('error', { + event: 'http_error', + operation: ctx.operation, + message: (ctx.error as any)?.message, + code: (ctx.error as any)?.code, + statusCode: (ctx.error as any)?.statusCode, + }) + }, + } + + const onRetry: Hook = { + name: 'logging:onRetry', + execute: (ctx: HookContext) => { + if (ctx.type !== 'onRetry' || !shouldLog(opts, 'debug')) return + logger('debug', { + event: 'http_retry', + operation: ctx.metadata.operation ?? ctx.operation, + attempt: ctx.metadata.attempt, + }) + }, + } + + return { beforeRequest: [beforeRequest], afterResponse: [afterResponse], onError: [onError], onRetry: [onRetry] } +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/metrics-hooks.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/metrics-hooks.ts new file mode 100644 index 00000000..d8200c65 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/metrics-hooks.ts @@ -0,0 +1,54 @@ +import type { Hook, HookContext } from '@connector-factory/core' + +export type MetricsEvent = + | { type: 'request'; operation?: string } + | { type: 'response'; operation?: string; status?: number; durationMs?: number } + | { type: 'error'; operation?: string; code?: string } + | { type: 'retry'; operation?: string; attempt?: number } + +export interface MetricsSink { record: (event: MetricsEvent) => void } +export class InMemoryMetricsSink implements MetricsSink { + public events: MetricsEvent[] = [] + record(e: MetricsEvent) { this.events.push(e) } +} + +export function createMetricsHooks(sink: MetricsSink) { + const beforeRequest: Hook = { + name: 'metrics:beforeRequest', + execute: (ctx: HookContext) => { + if (ctx.type !== 'beforeRequest') return + sink.record({ type: 'request', operation: ctx.operation ?? ctx.request?.operation }) + }, + } + + const afterResponse: Hook = { + name: 'metrics:afterResponse', + execute: (ctx: HookContext) => { + if (ctx.type !== 'afterResponse') return + sink.record({ + type: 'response', + operation: ctx.operation ?? ctx.request?.operation, + status: ctx.response?.status, + durationMs: ctx.response?.meta?.durationMs, + }) + }, + } + + const onError: Hook = { + name: 'metrics:onError', + execute: (ctx: HookContext) => { + if (ctx.type !== 'onError') return + sink.record({ type: 'error', operation: ctx.operation, code: (ctx.error as any)?.code }) + }, + } + + const onRetry: Hook = { + name: 'metrics:onRetry', + execute: (ctx: HookContext) => { + if (ctx.type !== 'onRetry') return + sink.record({ type: 'retry', operation: ctx.metadata?.operation ?? ctx.operation, attempt: ctx.metadata?.attempt }) + }, + } + + return { beforeRequest: [beforeRequest], afterResponse: [afterResponse], onError: [onError], onRetry: [onRetry] } +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/batches.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/batches.ts new file mode 100644 index 00000000..1e246451 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/batches.ts @@ -0,0 +1,49 @@ +import { paginateIncremental } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Batch { + id: string + product_id: string + batch_number: string + quantity: number + expiration_date?: string + test_results?: { + thc?: number + cbd?: number + tested_at?: string + lab?: string + } + created_at: string + updated_at: string +} + +export interface ListBatchesParams { + updated_at_from?: string // For incremental sync + product_id?: string + batch_number?: string + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListBatchesParams) { + const { pageSize, maxItems, updated_at_from, ...filters } = params ?? {} + + yield* paginateIncremental({ + send, + path: '/batches', + query: filters, + updatedAtFrom: updated_at_from, + pageSize, + maxItems, + }) + }, + + async get(id: string): Promise { + const response = await send({ + method: 'GET', + path: `/batches/${id}`, + }) + return response.data + }, +}) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/buyers.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/buyers.ts new file mode 100644 index 00000000..5f63c322 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/buyers.ts @@ -0,0 +1,45 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Buyer { + id: string + company_id: string + name: string + email?: string + phone?: string + purchase_history?: { + total_orders: number + total_spent: number + last_purchase_date?: string + } + created_at: string + updated_at: string +} + +export interface ListBuyersParams { + company_id?: string + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListBuyersParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/buyers', + query: filters, + pageSize, + maxItems, + }) + }, + + async get(id: string): Promise { + const response = await send({ + method: 'GET', + path: `/buyers/${id}`, + }) + return response.data + }, +}) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/companies.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/companies.ts new file mode 100644 index 00000000..97c0d606 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/companies.ts @@ -0,0 +1,48 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Company { + id: string + name: string + type: 'distributor' | 'retailer' | 'manufacturer' | 'cultivator' + license_number?: string + contact_email?: string + contact_phone?: string + address?: { + street?: string + city?: string + state?: string + zip_code?: string + } + created_at: string + updated_at: string +} + +export interface ListCompaniesParams { + type?: string + state?: string + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListCompaniesParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/companies', + query: filters, + pageSize, + maxItems, + }) + }, + + async get(id: string): Promise { + const response = await send({ + method: 'GET', + path: `/companies/${id}`, + }) + return response.data + }, +}) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/index.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/index.ts new file mode 100644 index 00000000..9be7fbe1 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/index.ts @@ -0,0 +1,6 @@ +export { createResource as createProductsResource } from './products' +export { createResource as createBatchesResource } from './batches' +export { createResource as createOrdersResource } from './orders' +export { createResource as createCompaniesResource } from './companies' +export { createResource as createBuyersResource } from './buyers' + diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/orders.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/orders.ts new file mode 100644 index 00000000..6ff64e5a --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/orders.ts @@ -0,0 +1,92 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export type OrderType = 'receiving' | 'shipping' | 'transporter' + +export interface Order { + id: string + type: OrderType + order_number: string + company_id: string + buyer_id?: string + status: 'pending' | 'confirmed' | 'in_transit' | 'delivered' | 'cancelled' + items: Array<{ + product_id: string + batch_id?: string + quantity: number + unit_price: number + }> + total_amount: number + created_at: string + updated_at: string + delivery_date?: string +} + +export interface ListOrdersParams { + type?: OrderType + status?: string + company_id?: string + buyer_id?: string + start_date?: string + end_date?: string + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListOrdersParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/orders', + query: filters, + pageSize, + maxItems, + }) + }, + + async *receiving(params?: Omit) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/receiving-orders', + query: filters, + pageSize, + maxItems, + }) + }, + + async *shipping(params?: Omit) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/shipping-orders', + query: filters, + pageSize, + maxItems, + }) + }, + + async *transporter(params?: Omit) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/transporter-orders', + query: filters, + pageSize, + maxItems, + }) + }, + + async get(id: string): Promise { + const response = await send({ + method: 'GET', + path: `/orders/${id}`, + }) + return response.data + }, +}) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/products.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/products.ts new file mode 100644 index 00000000..cd618a8e --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/products.ts @@ -0,0 +1,50 @@ +import { paginateIncremental, paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Product { + id: string + name: string + description?: string + category?: string + brand?: string + strain?: string + thc_content?: number + cbd_content?: number + unit_price?: number + unit_of_measure?: string + available_quantity?: number + created_at: string + updated_at: string +} + +export interface ListProductsParams { + updated_at_from?: string // For incremental sync + category?: string + brand?: string + strain?: string + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListProductsParams) { + const { pageSize, maxItems, updated_at_from, ...filters } = params ?? {} + + yield* paginateIncremental({ + send, + path: '/products', + query: filters, + updatedAtFrom: updated_at_from, + pageSize, + maxItems, + }) + }, + + async get(id: string): Promise { + const response = await send({ + method: 'GET', + path: `/products/${id}`, + }) + return response.data + }, +}) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/tests/observability.test.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/tests/observability.test.ts new file mode 100644 index 00000000..87638e5f --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/tests/observability.test.ts @@ -0,0 +1,19 @@ +/* eslint-env jest */ +// @ts-nocheck +import nock from 'nock' +import { createConnector } from '../src' + +it('logging includes url, headers, body when enabled', async () => { + const BASE = 'https://api.example.com' + nock(BASE).get('/products').query({ x: '1' }).reply(200, [{ id: 1 }], { 'x-test-header': 'ok' }) + const events: Array<{ level: string; event: Record }> = [] + const conn = createConnector() + conn.initialize({ baseUrl: BASE, auth: { type: 'bearer', bearer: { token: 't' } }, logging: { enabled: true, level: 'info', includeQueryParams: true, includeHeaders: true, includeBody: true, logger: (level, event) => events.push({ level, event }) } }) + await (conn as any).request({ method: 'GET', path: '/products?x=1' }) + const reqEvt = events.find(e => (e.event as any)?.event === 'http_request')?.event as any + const respEvt = events.find(e => (e.event as any)?.event === 'http_response')?.event as any + expect(String(respEvt.url)).toContain('/products?x=1') + expect(typeof reqEvt.headers).toBe('object') + expect((respEvt.headers ?? {})['x-test-header']).toBe('ok') + expect(respEvt.body).toEqual([{ id: 1 }]) +}) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/tests/resource.test.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/tests/resource.test.ts new file mode 100644 index 00000000..960e7586 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/tests/resource.test.ts @@ -0,0 +1,18 @@ +/* eslint-env jest */ +// @ts-nocheck +import nock from 'nock' +import { createConnector } from '../src' + +it('products.list yields chunks and respects maxItems', async () => { + const BASE = 'https://api-docs.apextrading.com' + nock(BASE).get('/products').query({ limit: 2, offset: 0 }).reply(200, [{ id: '1', name: 'Product 1' }, { id: '2', name: 'Product 2' }]) + nock(BASE).get('/products').query({ limit: 2, offset: 2 }).reply(200, [{ id: '3', name: 'Product 3' }, { id: '4', name: 'Product 4' }]) + nock(BASE).get('/products').query({ limit: 0, offset: 4 }).reply(200, []) + + const conn = createConnector() + conn.initialize({ apiKey: 'test-key' }) + const pages: Array> = [] + for await (const page of conn.products.list({ pageSize: 2, maxItems: 4 })) pages.push(page) + expect(pages.map(p => p.length)).toEqual([2, 2]) +}) + diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.json new file mode 100644 index 00000000..920e22a7 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "moduleResolution": "Node", + "declaration": true, + "outDir": "dist", + "rootDir": ".", + "strict": true, + "skipLibCheck": true, + "types": ["node", "jest"], + "resolveJsonModule": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "include": ["src/**/*"], + "exclude": ["dist", "node_modules", "examples", "tests"] +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.test.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.test.json new file mode 100644 index 00000000..2c9aa02f --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.test.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": ".temp-test", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src", + "tests" + ] +} diff --git a/connector-registry/apex-trading/v1/_meta/version.json b/connector-registry/apex-trading/v1/_meta/version.json new file mode 100644 index 00000000..3d4b6bde --- /dev/null +++ b/connector-registry/apex-trading/v1/_meta/version.json @@ -0,0 +1,7 @@ +{ + "name": "apex-trading", + "version": "v1", + "status": "beta", + "releasedAt": "", + "notes": "apex-trading v1 version" +} \ No newline at end of file diff --git a/moose.config.toml b/moose.config.toml new file mode 100644 index 00000000..45bfb4ec --- /dev/null +++ b/moose.config.toml @@ -0,0 +1,55 @@ +language = "Typescript" + +[typescript_config] +# Package manager to use for installing dependencies +# Options: "npm" (default), "pnpm", "yarn" +package_manager = "npm" + +[redpanda_config] +broker = "localhost:19092" +message_timeout_ms = 1000 +retention_ms = 30000 +replication_factor = 1 + +[clickhouse_config] +db_name = "local" +user = "panda" +password = "pandapass" +use_ssl = false +host = "localhost" +host_port = 18123 +native_port = 9000 + +[http_server_config] +host = "localhost" +port = 4000 +management_port = 5001 + +[redis_config] +url = "redis://127.0.0.1:6379" +key_prefix = "MS" + +[git_config] +main_branch_name = "main" + +[temporal_config] +db_user = "temporal" +db_password = "temporal" +db_port = 5432 +temporal_port = 7233 +# Uncomment and set to "http" or "https" to force a specific scheme +# temporal_scheme = "https" +temporal_version = "1.22.3" +admin_tools_version = "1.22.3" +ui_version = "2.21.3" +ui_port = 8080 +ui_cors_origins = "http://localhost:3000" +config_path = "config/dynamicconfig/development-sql.yaml" +postgresql_version = "13" + +[supported_old_versions] + +[features] +streaming_engine = true +workflows = true +data_model_v2 = true diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e983559..64ad1382 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -160,6 +160,31 @@ importers: specifier: ^5 version: 5.8.3 + connector-registry/apex-trading/v1/514-labs/typescript/default: + dependencies: + '@connector-factory/core': + specifier: workspace:* + version: link:../../../../../../packages/core + devDependencies: + '@types/jest': + specifier: ^29.5.12 + version: 29.5.14 + '@types/node': + specifier: ^20.11.30 + version: 20.16.13 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.16.13)(ts-node@10.9.2(@swc/core@1.10.15(@swc/helpers@0.5.15))(@types/node@20.16.13)(typescript@5.8.3)) + nock: + specifier: ^13.5.0 + version: 13.5.6 + ts-jest: + specifier: ^29.1.2 + version: 29.4.4(@babel/core@7.24.5)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.16.13)(ts-node@10.9.2(@swc/core@1.10.15(@swc/helpers@0.5.15))(@types/node@20.16.13)(typescript@5.8.3)))(typescript@5.8.3) + typescript: + specifier: ^5.4.0 + version: 5.8.3 + connector-registry/dutchie/v001/514-labs/typescript/open-api: dependencies: '@connector-factory/core': @@ -6240,10 +6265,6 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - minimatch@10.0.1: - resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} - engines: {node: 20 || >=22} - minimatch@10.0.3: resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} engines: {node: 20 || >=22} @@ -8410,7 +8431,7 @@ snapshots: '@babel/traverse': 7.24.5 '@babel/types': 7.24.5 convert-source-map: 2.0.0 - debug: 4.3.7 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -8428,7 +8449,7 @@ snapshots: dependencies: '@babel/compat-data': 7.24.4 '@babel/helper-validator-option': 7.23.5 - browserslist: 4.24.0 + browserslist: 4.26.3 lru-cache: 5.1.1 semver: 6.3.1 @@ -8581,7 +8602,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.5 '@babel/parser': 7.24.5 '@babel/types': 7.24.5 - debug: 4.3.7 + debug: 4.4.3 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -10928,7 +10949,7 @@ snapshots: '@types/minimatch@6.0.0': dependencies: - minimatch: 10.0.1 + minimatch: 10.0.3 '@types/ms@0.7.34': {} @@ -11032,7 +11053,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.8.3) '@typescript-eslint/types': 8.45.0 - debug: 4.3.7 + debug: 4.4.3 typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -11041,7 +11062,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) '@typescript-eslint/types': 8.45.0 - debug: 4.3.7 + debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -11064,7 +11085,7 @@ snapshots: '@typescript-eslint/types': 8.45.0 '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.8.3) '@typescript-eslint/utils': 8.45.0(eslint@8.57.1)(typescript@5.8.3) - debug: 4.3.7 + debug: 4.4.3 eslint: 8.57.1 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 @@ -11076,7 +11097,7 @@ snapshots: '@typescript-eslint/types': 8.45.0 '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) '@typescript-eslint/utils': 8.45.0(eslint@9.19.0(jiti@2.6.1))(typescript@5.9.3) - debug: 4.3.7 + debug: 4.4.3 eslint: 9.19.0(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 @@ -11091,11 +11112,11 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.8.3) '@typescript-eslint/types': 8.45.0 '@typescript-eslint/visitor-keys': 8.45.0 - debug: 4.3.7 + debug: 4.4.3 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.7.0 + semver: 7.7.2 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: @@ -11107,11 +11128,11 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) '@typescript-eslint/types': 8.45.0 '@typescript-eslint/visitor-keys': 8.45.0 - debug: 4.3.7 + debug: 4.4.3 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.7.0 + semver: 7.7.2 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -13118,7 +13139,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.3.7 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -13395,7 +13416,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 - debug: 4.3.7 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -13409,7 +13430,7 @@ snapshots: https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.3.7 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -13772,7 +13793,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.7 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -14848,7 +14869,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.7 + debug: 4.4.3 decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -14882,10 +14903,6 @@ snapshots: mimic-fn@4.0.0: {} - minimatch@10.0.1: - dependencies: - brace-expansion: 2.0.1 - minimatch@10.0.3: dependencies: '@isaacs/brace-expansion': 5.0.0 @@ -15003,7 +15020,7 @@ snapshots: nock@13.5.6: dependencies: - debug: 4.3.7 + debug: 4.4.3 json-stringify-safe: 5.0.1 propagate: 2.0.1 transitivePeerDependencies: @@ -15224,7 +15241,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.4 - debug: 4.3.7 + debug: 4.4.3 get-uri: 6.0.5 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -15431,7 +15448,7 @@ snapshots: proxy-agent@6.5.0: dependencies: agent-base: 7.1.4 - debug: 4.3.7 + debug: 4.4.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 @@ -16002,7 +16019,7 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 - debug: 4.3.7 + debug: 4.4.3 socks: 2.8.7 transitivePeerDependencies: - supports-color @@ -16895,7 +16912,7 @@ snapshots: vite-node@1.6.1(@types/node@22.18.8)(lightningcss@1.30.1)(terser@5.36.0): dependencies: cac: 6.7.14 - debug: 4.3.7 + debug: 4.4.3 pathe: 1.1.2 picocolors: 1.1.1 vite: 5.4.20(@types/node@22.18.8)(lightningcss@1.30.1)(terser@5.36.0) diff --git a/project.toml b/project.toml new file mode 100644 index 00000000..45bfb4ec --- /dev/null +++ b/project.toml @@ -0,0 +1,55 @@ +language = "Typescript" + +[typescript_config] +# Package manager to use for installing dependencies +# Options: "npm" (default), "pnpm", "yarn" +package_manager = "npm" + +[redpanda_config] +broker = "localhost:19092" +message_timeout_ms = 1000 +retention_ms = 30000 +replication_factor = 1 + +[clickhouse_config] +db_name = "local" +user = "panda" +password = "pandapass" +use_ssl = false +host = "localhost" +host_port = 18123 +native_port = 9000 + +[http_server_config] +host = "localhost" +port = 4000 +management_port = 5001 + +[redis_config] +url = "redis://127.0.0.1:6379" +key_prefix = "MS" + +[git_config] +main_branch_name = "main" + +[temporal_config] +db_user = "temporal" +db_password = "temporal" +db_port = 5432 +temporal_port = 7233 +# Uncomment and set to "http" or "https" to force a specific scheme +# temporal_scheme = "https" +temporal_version = "1.22.3" +admin_tools_version = "1.22.3" +ui_version = "2.21.3" +ui_port = 8080 +ui_cors_origins = "http://localhost:3000" +config_path = "config/dynamicconfig/development-sql.yaml" +postgresql_version = "13" + +[supported_old_versions] + +[features] +streaming_engine = true +workflows = true +data_model_v2 = true