From 27f37ff5c93e7d5551ccf755fe911ba1b66eb827 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 18:37:16 +0000 Subject: [PATCH 1/5] Initial plan From bbc5cb870419f33dbf54801120a9f69fd0eb1245 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 18:43:31 +0000 Subject: [PATCH 2/5] Initial plan for Apex Trading connector Co-authored-by: georgevanderson <4805522+georgevanderson@users.noreply.github.com> --- Dockerfile | 160 ++++++++++++++++++++++++++++++++++++++++++++++ moose.config.toml | 55 ++++++++++++++++ project.toml | 55 ++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 Dockerfile create mode 100644 moose.config.toml create mode 100644 project.toml 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/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/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 From 9651b906e6955ae6eb7057cbca5cabded50e4ae2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 18:55:20 +0000 Subject: [PATCH 3/5] Add Apex Trading connector with core resources implementation Co-authored-by: georgevanderson <4805522+georgevanderson@users.noreply.github.com> --- .../apex-trading/_meta/README.md | 6 + .../apex-trading/_meta/connector.json | 9 ++ .../v1/514-labs/_meta/CHANGELOG.md | 7 ++ .../apex-trading/v1/514-labs/_meta/LICENSE | 18 +++ .../apex-trading/v1/514-labs/_meta/README.md | 10 ++ .../v1/514-labs/_meta/connector.json | 22 ++++ .../514-labs/typescript/_meta/connector.json | 8 ++ .../514-labs/typescript/default/.env.example | 10 ++ .../v1/514-labs/typescript/default/.gitignore | 3 + .../typescript/default/CONNECTOR_GUIDE.md | 83 ++++++++++++++ .../v1/514-labs/typescript/default/README.md | 87 ++++++++++++++ .../typescript/default/docs/configuration.md | 7 ++ .../default/docs/getting-started.md | 16 +++ .../typescript/default/docs/limits.md | 3 + .../typescript/default/docs/observability.md | 17 +++ .../typescript/default/docs/schema.md | 22 ++++ .../default/examples/basic-usage.ts | 85 ++++++++++++++ .../typescript/default/install.config.toml | 32 ++++++ .../typescript/default/jest.config.cjs | 4 + .../514-labs/typescript/default/package.json | 23 ++++ .../default/schemas/extracted/json/README.md | 15 +++ .../default/schemas/extracted/json/events.md | 3 + .../schemas/extracted/json/events.schema.json | 1 + .../schemas/extracted/relational/README.md | 3 + .../schemas/extracted/relational/tables.json | 1 + .../schemas/extracted/relational/tables.sql | 1 + .../typescript/default/schemas/index.json | 41 +++++++ .../default/schemas/raw/files/README.md | 18 +++ .../default/schemas/raw/json/README.md | 24 ++++ .../default/schemas/raw/json/events.md | 3 + .../schemas/raw/json/events.schema.json | 1 + .../default/schemas/raw/relational/README.md | 3 + .../schemas/raw/relational/tables.json | 1 + .../default/schemas/raw/relational/tables.sql | 1 + .../typescript/default/scripts/postinstall.sh | 26 +++++ .../default/src/client/connector.ts | 106 +++++++++++++++++ .../typescript/default/src/generated/.gitkeep | 0 .../514-labs/typescript/default/src/index.ts | 3 + .../default/src/lib/make-resource.ts | 55 +++++++++ .../typescript/default/src/lib/paginate.ts | 78 +++++++++++++ .../src/observability/logging-hooks.ts | 107 ++++++++++++++++++ .../src/observability/metrics-hooks.ts | 54 +++++++++ .../default/src/resources/accounts.ts | 50 ++++++++ .../typescript/default/src/resources/index.ts | 5 + .../default/src/resources/orders.ts | 87 ++++++++++++++ .../default/src/resources/products.ts | 106 +++++++++++++++++ .../default/src/resources/trades.ts | 58 ++++++++++ .../default/tests/observability.test.ts | 19 ++++ .../typescript/default/tests/resource.test.ts | 18 +++ .../514-labs/typescript/default/tsconfig.json | 18 +++ .../typescript/default/tsconfig.test.json | 14 +++ .../apex-trading/v1/_meta/version.json | 7 ++ pnpm-lock.yaml | 77 ++++++++----- 53 files changed, 1446 insertions(+), 30 deletions(-) create mode 100644 connector-registry/apex-trading/_meta/README.md create mode 100644 connector-registry/apex-trading/_meta/connector.json create mode 100644 connector-registry/apex-trading/v1/514-labs/_meta/CHANGELOG.md create mode 100644 connector-registry/apex-trading/v1/514-labs/_meta/LICENSE create mode 100644 connector-registry/apex-trading/v1/514-labs/_meta/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/_meta/connector.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/_meta/connector.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/.gitignore create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/CONNECTOR_GUIDE.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/docs/configuration.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/docs/getting-started.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/docs/limits.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/docs/observability.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/docs/schema.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/examples/basic-usage.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/install.config.toml create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/jest.config.cjs create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/package.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/json/events.schema.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/extracted/relational/tables.sql create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/index.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/files/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/events.schema.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/README.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/relational/tables.sql create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/scripts/postinstall.sh create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/client/connector.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/generated/.gitkeep create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/index.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/make-resource.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/paginate.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/logging-hooks.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/observability/metrics-hooks.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/index.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/orders.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/products.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/tests/observability.test.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/tests/resource.test.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/tsconfig.test.json create mode 100644 connector-registry/apex-trading/v1/_meta/version.json 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..a953a9fd --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example @@ -0,0 +1,10 @@ +# Apex Trading API credentials +APEX_API_KEY=your_api_key_here +APEX_API_SECRET=your_api_secret_here +APEX_API_PASSPHRASE=your_passphrase_here + +# Optional: Set environment (production or testnet) +# APEX_ENVIRONMENT=production + +# Optional: Custom base URL +# APEX_BASE_URL=https://omni.apex.exchange/api/v3 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..e3b884bb --- /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/accounts.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..1b042dac --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/README.md @@ -0,0 +1,87 @@ +# Apex Trading Connector + +TypeScript connector for the Apex Trading API. + +## 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!, + apiSecret: process.env.APEX_API_SECRET, + apiPassphrase: process.env.APEX_API_PASSPHRASE, + environment: 'production', // or 'testnet' + logging: { enabled: true, level: 'info' }, + metrics: { enabled: true }, +}) + +// List products +for await (const page of connector.products.list()) { + console.log('Products:', page) +} + +// Get account balance +const balance = await connector.accounts.getBalance() +console.log('Balance:', balance) + +// List orders +for await (const page of connector.orders.list({ symbol: 'BTC-USDT' })) { + console.log('Orders:', page) +} + +// Create an order +const order = await connector.orders.create({ + symbol: 'BTC-USDT', + side: 'BUY', + type: 'LIMIT', + quantity: '0.001', + price: '50000', + timeInForce: 'GTC', +}) +console.log('Order created:', order) +``` + +## Configuration + +### Required +- `apiKey`: Your Apex Trading API key + +### Optional +- `apiSecret`: Your API secret (required for some operations) +- `apiPassphrase`: Your API passphrase (required for some operations) +- `baseUrl`: Custom API base URL +- `environment`: 'production' or 'testnet' (default: 'production') +- `logging`: Logging configuration +- `metrics`: Metrics collection configuration + +## Available Resources + +- **accounts**: Account management and balance information +- **orders**: Order creation, listing, and management +- **trades**: Trade history and information +- **products**: Market products, tickers, and order book data + +## 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..e7ac97de --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/examples/basic-usage.ts @@ -0,0 +1,85 @@ +import { createConnector } from '../src' + +async function main() { + const connector = createConnector() + + // Initialize the connector with your API credentials + connector.initialize({ + apiKey: process.env.APEX_API_KEY!, + apiSecret: process.env.APEX_API_SECRET, + apiPassphrase: process.env.APEX_API_PASSPHRASE, + environment: 'production', // or 'testnet' + logging: { enabled: true, level: 'info' }, + metrics: { enabled: true }, + }) + + console.log('Apex Trading Connector - Basic Usage Examples\n') + + // Example 1: List products + console.log('1. Listing products...') + let count = 0 + for await (const page of connector.products.list({ pageSize: 10, maxItems: 10 })) { + console.log(` Found ${page.length} products:`) + page.forEach(product => { + console.log(` - ${product.symbol}: ${product.baseAsset}/${product.quoteAsset}`) + }) + count += page.length + } + console.log(` Total products listed: ${count}\n`) + + // Example 2: Get ticker for a specific symbol + console.log('2. Getting ticker for BTC-USDT...') + try { + const ticker = await connector.products.getTicker('BTC-USDT') + console.log(` Last Price: ${ticker.lastPrice}`) + console.log(` 24h Change: ${ticker.priceChangePercent}%`) + console.log(` 24h Volume: ${ticker.volume}\n`) + } catch (error) { + console.log(' Error getting ticker (may need valid symbol):', (error as Error).message, '\n') + } + + // Example 3: Get account balance + console.log('3. Getting account balance...') + try { + const balance = await connector.accounts.getBalance() + console.log(` Balance: ${balance.balance}`) + console.log(` Available: ${balance.availableBalance}`) + console.log(` Locked: ${balance.lockedBalance}\n`) + } catch (error) { + console.log(' Error getting balance (requires authentication):', (error as Error).message, '\n') + } + + // Example 4: List orders + console.log('4. Listing orders...') + try { + let orderCount = 0 + for await (const page of connector.orders.list({ pageSize: 10, maxItems: 10 })) { + console.log(` Found ${page.length} orders`) + page.forEach(order => { + console.log(` - ${order.symbol} ${order.side} ${order.type}: ${order.status}`) + }) + orderCount += page.length + } + console.log(` Total orders: ${orderCount}\n`) + } catch (error) { + console.log(' Error listing orders (requires authentication):', (error as Error).message, '\n') + } + + // Example 5: List trades + console.log('5. Listing recent trades...') + try { + let tradeCount = 0 + for await (const page of connector.trades.list({ pageSize: 10, maxItems: 10 })) { + console.log(` Found ${page.length} trades`) + tradeCount += page.length + } + console.log(` Total trades: ${tradeCount}\n`) + } catch (error) { + console.log(' Error listing trades (requires authentication):', (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..4933e68c --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/client/connector.ts @@ -0,0 +1,106 @@ +/** + * CONNECTOR IMPLEMENTATION GUIDE + * See CONNECTOR_GUIDE.md in the root of this connector for step-by-step instructions. + * + * Quick checklist: + * [ ] Phase 3: Configure authentication (update ConnectorConfig type & init method below) + * [ ] Phase 4: Implement pagination in src/lib/paginate.ts (offset/cursor/page) + * [ ] Phase 5: Implement resources in src/resources/ + * [ ] Phase 6: Add schemas to schemas/raw/json/ + * [ ] Phase 7: Update .env.example and README.md + * [ ] Phase 8: Write tests in tests/ + * [ ] Phase 9: Build and test (pnpm run build && pnpm test) + * + * Reference connectors: + * - Simple API key: connector-registry/socrata/ + * - OAuth2: connector-registry/meta-ads/ + */ + +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 createAccountsResource } from '../resources/accounts' +import { createResource as createOrdersResource } from '../resources/orders' +import { createResource as createTradesResource } from '../resources/trades' +import { createResource as createProductsResource } from '../resources/products' + +export type ApexTradingConfig = ConnectorConfig & { + apiKey?: string + apiSecret?: string + apiPassphrase?: string + environment?: 'production' | 'testnet' + 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 ?? + (userConfig.environment === 'testnet' + ? 'https://testnet.apex.exchange/api/v3' + : 'https://omni.apex.exchange/api/v3') + + const apiKey = userConfig.apiKey ?? userConfig.auth?.bearer?.token + + const config: ConnectorConfig = { + ...userConfig, + baseUrl, + userAgent: userConfig.userAgent ?? 'apex-trading-connector', + defaultHeaders: { + ...userConfig.defaultHeaders, + ...(apiKey ? { 'X-API-Key': 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 accounts() { return createAccountsResource(this.sendLite as any) } + get orders() { return createOrdersResource(this.sendLite as any) } + get trades() { return createTradesResource(this.sendLite as any) } + get products() { return createProductsResource(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..9280576a --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/paginate.ts @@ -0,0 +1,78 @@ +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> + +// Offset-based pagination for Apex Trading API +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 + } +} + +// Cursor-based pagination helper (if needed for some endpoints) +export async function* paginateCursor(params: { + send: SendFn; + path: string; + query?: Record; + pageSize?: number; + extractItems: (res: any) => T[]; + extractNextCursor: (res: any) => string | undefined; +}): AsyncGenerator> { + const { send, path, query = {}, pageSize, extractItems, extractNextCursor } = params + let cursor: string | undefined = undefined + + while (true) { + const response = await send({ + method: 'GET', + path, + query: { + ...query, + ...(cursor ? { cursor } : {}), + ...(pageSize ? { limit: pageSize } : {}), + }, + }) + + const items = extractItems(response.data) + if (items.length === 0) break + + yield items + + cursor = extractNextCursor(response.data) + if (!cursor) 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/accounts.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts new file mode 100644 index 00000000..c61c9392 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts @@ -0,0 +1,50 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Account { + id: string + userId: string + balance: string + availableBalance: string + lockedBalance: string + equity: string + totalMargin: string + freeMargin: string + unrealizedPnl: string + createdAt: string + updatedAt: string +} + +export interface ListAccountsParams { + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListAccountsParams) { + const { pageSize, maxItems } = params ?? {} + + yield* paginateOffset({ + send, + path: '/accounts', + pageSize, + maxItems, + }) + }, + + async get(id: string): Promise { + const response = await send({ + method: 'GET', + path: `/accounts/${id}`, + }) + return response.data + }, + + async getBalance(): Promise<{ balance: string; availableBalance: string; lockedBalance: string }> { + const response = await send({ + method: 'GET', + path: '/account/balance', + }) + 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..c4ab08c4 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/index.ts @@ -0,0 +1,5 @@ +export { createResource as createAccountsResource } from './accounts' +export { createResource as createOrdersResource } from './orders' +export { createResource as createTradesResource } from './trades' +export { createResource as createProductsResource } from './products' + 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..354d4842 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/orders.ts @@ -0,0 +1,87 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Order { + id: string + clientOrderId?: string + accountId: string + symbol: string + side: 'BUY' | 'SELL' + type: 'LIMIT' | 'MARKET' | 'STOP_LIMIT' | 'STOP_MARKET' + price?: string + quantity: string + filledQuantity: string + status: 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'REJECTED' | 'EXPIRED' + timeInForce?: 'GTC' | 'IOC' | 'FOK' + createdAt: string + updatedAt: string +} + +export interface ListOrdersParams { + symbol?: string + status?: 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'REJECTED' | 'EXPIRED' + side?: 'BUY' | 'SELL' + startTime?: string + endTime?: string + pageSize?: number + maxItems?: number +} + +export interface CreateOrderParams { + symbol: string + side: 'BUY' | 'SELL' + type: 'LIMIT' | 'MARKET' | 'STOP_LIMIT' | 'STOP_MARKET' + quantity: string + price?: string + stopPrice?: string + timeInForce?: 'GTC' | 'IOC' | 'FOK' + clientOrderId?: string +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListOrdersParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/orders', + query: filters, + pageSize, + maxItems, + }) + }, + + async get(orderId: string): Promise { + const response = await send({ + method: 'GET', + path: `/orders/${orderId}`, + }) + return response.data + }, + + async create(params: CreateOrderParams): Promise { + const response = await send({ + method: 'POST', + path: '/orders', + body: params, + }) + return response.data + }, + + async cancel(orderId: string): Promise { + const response = await send({ + method: 'DELETE', + path: `/orders/${orderId}`, + }) + return response.data + }, + + async cancelAll(symbol?: string): Promise<{ canceledCount: number }> { + const response = await send<{ canceledCount: number }>({ + method: 'DELETE', + path: '/orders', + query: symbol ? { symbol } : undefined, + }) + 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..776eedb0 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/products.ts @@ -0,0 +1,106 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Product { + id: string + symbol: string + baseAsset: string + quoteAsset: string + status: 'TRADING' | 'HALT' | 'BREAK' + baseAssetPrecision: number + quoteAssetPrecision: number + minPrice: string + maxPrice: string + tickSize: string + minQuantity: string + maxQuantity: string + stepSize: string + minNotional: string +} + +export interface ListProductsParams { + symbol?: string + status?: 'TRADING' | 'HALT' | 'BREAK' + pageSize?: number + maxItems?: number +} + +export interface Ticker { + symbol: string + lastPrice: string + priceChange: string + priceChangePercent: string + volume: string + quoteVolume: string + openPrice: string + highPrice: string + lowPrice: string + timestamp: string +} + +export interface OrderBook { + symbol: string + bids: Array<[string, string]> // [price, quantity] + asks: Array<[string, string]> // [price, quantity] + timestamp: string +} + +export interface PublicTrade { + id: string + price: string + quantity: string + timestamp: string + isBuyerMaker: boolean +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListProductsParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/products', + query: filters, + pageSize, + maxItems, + }) + }, + + async get(symbol: string): Promise { + const response = await send({ + method: 'GET', + path: `/products/${symbol}`, + }) + return response.data + }, + + async getTicker(symbol: string): Promise { + const response = await send({ + method: 'GET', + path: '/ticker', + query: { symbol }, + }) + return response.data + }, + + async getOrderBook(symbol: string, limit?: number): Promise { + const response = await send({ + method: 'GET', + path: '/depth', + query: { symbol, limit }, + }) + return response.data + }, + + async *getRecentTrades(symbol: string, limit?: number) { + const response = await send({ + method: 'GET', + path: '/trades', + query: { symbol, limit }, + }) + + const trades = Array.isArray(response.data) ? response.data : [] + yield trades + }, +}) + diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts new file mode 100644 index 00000000..18e7797a --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts @@ -0,0 +1,58 @@ +import { paginateOffset } from '../lib/paginate' +import type { SendFn } from '../lib/paginate' + +export interface Trade { + id: string + orderId: string + symbol: string + side: 'BUY' | 'SELL' + price: string + quantity: string + fee: string + feeAsset: string + isMaker: boolean + createdAt: string +} + +export interface ListTradesParams { + symbol?: string + orderId?: string + startTime?: string + endTime?: string + pageSize?: number + maxItems?: number +} + +export const createResource = (send: SendFn) => ({ + async *list(params?: ListTradesParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/trades', + query: filters, + pageSize, + maxItems, + }) + }, + + async get(tradeId: string): Promise { + const response = await send({ + method: 'GET', + path: `/trades/${tradeId}`, + }) + return response.data + }, + + async *history(params?: ListTradesParams) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/trades/history', + query: filters, + pageSize, + maxItems, + }) + }, +}) 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..0a51f21c --- /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('/accounts').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: '/accounts?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('/accounts?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..4902e337 --- /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('accounts.list yields chunks and respects maxItems', async () => { + const BASE = 'https://omni.apex.exchange' + nock(BASE).get('/api/v3/accounts').query({ limit: 2, offset: 0 }).reply(200, [{ id: '1' }, { id: '2' }]) + nock(BASE).get('/api/v3/accounts').query({ limit: 2, offset: 2 }).reply(200, [{ id: '3' }, { id: '4' }]) + nock(BASE).get('/api/v3/accounts').query({ limit: 0, offset: 4 }).reply(200, []) + + const conn = createConnector() + conn.initialize({ apiKey: 'test-key' }) + const pages: Array> = [] + for await (const page of conn.accounts.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/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) From 1d5466d260f61f14c7ded9df744c11645f2bf3f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 18:58:59 +0000 Subject: [PATCH 4/5] Add schemas and complete documentation for Apex Trading connector Co-authored-by: georgevanderson <4805522+georgevanderson@users.noreply.github.com> --- .../typescript/default/docs/configuration.md | 111 +++++++++++++++++- .../typescript/default/docs/limits.md | 73 +++++++++++- .../typescript/default/schemas/index.json | 42 +++---- .../default/schemas/raw/json/accounts.md | 37 ++++++ .../schemas/raw/json/accounts.schema.json | 55 +++++++++ .../default/schemas/raw/json/orders.md | 59 ++++++++++ .../schemas/raw/json/orders.schema.json | 67 +++++++++++ .../default/schemas/raw/json/products.md | 47 ++++++++ .../schemas/raw/json/products.schema.json | 66 +++++++++++ .../default/schemas/raw/json/trades.md | 47 ++++++++ .../schemas/raw/json/trades.schema.json | 51 ++++++++ 11 files changed, 624 insertions(+), 31 deletions(-) create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json 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 index 59237d7c..f4b03b05 100644 --- 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 @@ -1,7 +1,108 @@ # 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 +This document describes all configuration options for the Apex Trading connector. + +## Required Configuration + +### `apiKey` +- **Type**: `string` +- **Required**: Yes +- **Description**: Your Apex Trading API key. You can generate an API key from your Apex Trading account dashboard. + +## Optional Configuration + +### `apiSecret` +- **Type**: `string` +- **Required**: No +- **Description**: Your API secret. Required for certain authenticated operations that need request signing. + +### `apiPassphrase` +- **Type**: `string` +- **Required**: No +- **Description**: Your API passphrase. Required for certain authenticated operations. + +### `baseUrl` +- **Type**: `string` +- **Required**: No +- **Default**: `https://omni.apex.exchange/api/v3` +- **Description**: Custom API base URL. Useful for testing or if Apex changes their API endpoint. + +### `environment` +- **Type**: `'production' | 'testnet'` +- **Required**: No +- **Default**: `'production'` +- **Description**: Determines which API environment to use. When set to `'testnet'`, the base URL defaults to `https://testnet.apex.exchange/api/v3`. + +### `logging` +- **Type**: `object` +- **Required**: No +- **Description**: Logging configuration for debugging and monitoring. + +#### `logging.enabled` +- **Type**: `boolean` +- **Default**: `false` +- **Description**: Enable request/response logging. + +#### `logging.level` +- **Type**: `'debug' | 'info' | 'warn' | 'error'` +- **Default**: `'info'` +- **Description**: Minimum log level to output. + +#### `logging.includeQueryParams` +- **Type**: `boolean` +- **Default**: `false` +- **Description**: Include query parameters in logs. + +#### `logging.includeHeaders` +- **Type**: `boolean` +- **Default**: `false` +- **Description**: Include headers in logs (be careful with sensitive data). + +#### `logging.includeBody` +- **Type**: `boolean` +- **Default**: `false` +- **Description**: Include request/response bodies in logs. + +### `metrics` +- **Type**: `object` +- **Required**: No +- **Description**: Metrics collection configuration. + +#### `metrics.enabled` +- **Type**: `boolean` +- **Default**: `false` +- **Description**: Enable metrics collection for request/response statistics. + +## Advanced Configuration + +You can also pass any configuration from the base `ConnectorConfig` type: + +### `retry` +- **Type**: `object` +- **Description**: Retry configuration for failed requests (maxAttempts, initialDelayMs, maxDelayMs, backoffMultiplier, respectRetryAfter). + +### `rateLimit` +- **Type**: `object` +- **Description**: Rate limiting configuration (requestsPerSecond: 15, burstCapacity, adaptiveFromHeaders). + +### `hooks` +- **Type**: `object` +- **Description**: Arrays for beforeRequest/afterResponse/onError/onRetry lifecycle hooks. + +## Example Configuration + +```typescript +import { createConnector } from '@workspace/connector-apex-trading' + +const connector = createConnector() + +connector.initialize({ + apiKey: process.env.APEX_API_KEY!, + apiSecret: process.env.APEX_API_SECRET, + apiPassphrase: process.env.APEX_API_PASSPHRASE, + environment: 'production', // or 'testnet' + logging: { enabled: true, level: 'info' }, + metrics: { enabled: true }, +}) +``` + 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 index 447b11f1..fb99220d 100644 --- 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 @@ -1,3 +1,72 @@ -# Limits +# API Limits + +This document describes the rate limits and constraints of the Apex Trading API. + +## Rate Limits + +### Global Rate Limit +- **Limit**: 15 requests per second per API key +- **Enforcement**: Per API token/key +- **Headers**: The API returns rate limit information in response headers: + - `X-RateLimit-Limit`: Maximum requests per second (15) + - `X-RateLimit-Remaining`: Remaining requests in the current window + - `Retry-After`: Time in seconds to wait before retrying (when rate limited) + +### HTTP Status Codes +- **429 Too Many Requests**: Rate limit exceeded. The connector will automatically retry after the specified delay. + +## Connector Rate Limiting + +This connector automatically handles rate limiting to prevent you from exceeding API limits: + +- **Default Setting**: 15 requests per second (matching the API limit) +- **Automatic Retry**: When a 429 status is received, the connector respects the `Retry-After` header +- **Configuration**: You can customize rate limiting in the connector configuration: + +```typescript +connector.initialize({ + apiKey: 'your-api-key', + rateLimit: { + requestsPerSecond: 15, + burstCapacity: 30, // optional + adaptiveFromHeaders: true, // optional - adjust based on API response headers + }, +}) +``` + +## Best Practices + +1. **Use Pagination Wisely**: When listing large datasets, use appropriate page sizes to minimize requests +2. **Batch Operations**: Where possible, batch multiple operations into single requests +3. **Cache Data**: Cache frequently accessed reference data (products, etc.) to reduce API calls +4. **Monitor Rate Limits**: Enable metrics to track your API usage + +## Data Limits + +### Pagination +- **Maximum Page Size**: Varies by endpoint, typically 100-1000 items +- **Recommended Page Size**: 100 items for optimal performance +- **Offset/Limit**: Most endpoints use offset-based pagination + +## Error Handling + +When you exceed rate limits, the connector will: + +1. Receive a `429 Too Many Requests` response +2. Read the `Retry-After` header +3. Wait the specified time +4. Automatically retry the request (up to `maxAttempts`) + +You can configure retry behavior: + +```typescript +connector.initialize({ + apiKey: 'your-api-key', + retry: { + maxAttempts: 3, + retryableStatusCodes: [429, 500, 502, 503, 504], + respectRetryAfter: true, + }, +}) +``` -Describe API limits, quotas, and rate limiting behavior. 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 index 245115ca..0b72ed6d 100644 --- 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 @@ -3,39 +3,33 @@ "version": "0.1.0", "datasets": [ { - "name": "events", + "name": "accounts", "stage": "raw", "kind": "endpoints", - "path": "raw/endpoints/events.schema.json", - "doc": "raw/endpoints/events.md" + "path": "raw/json/accounts.schema.json", + "doc": "raw/json/accounts.md" }, { - "name": "events", - "stage": "extracted", + "name": "orders", + "stage": "raw", "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", + "path": "raw/json/orders.schema.json", + "doc": "raw/json/orders.md" + }, + { + "name": "trades", "stage": "raw", "kind": "endpoints", - "path": "raw/endpoints/endpoints/users/create.schema.json", - "doc": "raw/endpoints/endpoints/users/create.md", - "metadata": { - "category": "endpoint", - "apiMethod": "POST" - } + "path": "raw/json/trades.schema.json", + "doc": "raw/json/trades.md" }, - "nested_organization_example": { - "name": "reports.analytics", + { + "name": "products", "stage": "raw", "kind": "endpoints", - "path": "raw/endpoints/endpoints/reports/analytics.schema.json", - "doc": "raw/endpoints/endpoints/reports/analytics.md" + "path": "raw/json/products.schema.json", + "doc": "raw/json/products.md" } - } + ] } + diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md new file mode 100644 index 00000000..98e3ba6e --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md @@ -0,0 +1,37 @@ +# Accounts + +Account information from Apex Trading, including balances, equity, and margin details. + +## Common Queries + +Get all accounts: +``` +No filters needed +``` + +Get account balance: +``` +Use the getBalance() method for current balance information +``` + +## API Endpoints + +``` +GET /api/v3/accounts - List all accounts +GET /api/v3/accounts/{id} - Get specific account +GET /api/v3/account/balance - Get account balance +``` + +## Fields + +- **id**: Unique account identifier +- **userId**: User ID associated with the account +- **balance**: Total account balance +- **availableBalance**: Available balance for trading +- **lockedBalance**: Balance locked in open orders +- **equity**: Account equity +- **totalMargin**: Total margin used +- **freeMargin**: Free margin available +- **unrealizedPnl**: Unrealized profit and loss +- **createdAt**: Account creation timestamp +- **updatedAt**: Account last update timestamp diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json new file mode 100644 index 00000000..ef1b1e13 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json @@ -0,0 +1,55 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Account", + "description": "Apex Trading account information", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique account identifier" + }, + "userId": { + "type": "string", + "description": "User ID associated with the account" + }, + "balance": { + "type": "string", + "description": "Total account balance" + }, + "availableBalance": { + "type": "string", + "description": "Available balance for trading" + }, + "lockedBalance": { + "type": "string", + "description": "Balance locked in open orders" + }, + "equity": { + "type": "string", + "description": "Account equity" + }, + "totalMargin": { + "type": "string", + "description": "Total margin used" + }, + "freeMargin": { + "type": "string", + "description": "Free margin available" + }, + "unrealizedPnl": { + "type": "string", + "description": "Unrealized profit and loss" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Account creation timestamp" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Account last update timestamp" + } + }, + "required": ["id", "userId", "balance", "availableBalance", "lockedBalance"] +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md new file mode 100644 index 00000000..96c0cf28 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md @@ -0,0 +1,59 @@ +# Orders + +Order data from Apex Trading, including order details, status, and execution information. + +## Common Queries + +List all orders: +``` +No filters needed +``` + +Filter by symbol: +``` +symbol=BTC-USDT +``` + +Filter by status: +``` +status=NEW +status=FILLED +``` + +Filter by side: +``` +side=BUY +side=SELL +``` + +Filter by date range: +``` +startTime=2024-01-01T00:00:00Z +endTime=2024-01-31T23:59:59Z +``` + +## API Endpoints + +``` +GET /api/v3/orders - List orders +GET /api/v3/orders/{id} - Get specific order +POST /api/v3/orders - Create new order +DELETE /api/v3/orders/{id} - Cancel order +DELETE /api/v3/orders - Cancel all orders (optionally filtered by symbol) +``` + +## Fields + +- **id**: Unique order identifier +- **clientOrderId**: Client-specified order identifier +- **accountId**: Account ID +- **symbol**: Trading pair symbol (e.g., BTC-USDT) +- **side**: Order side (BUY or SELL) +- **type**: Order type (LIMIT, MARKET, STOP_LIMIT, STOP_MARKET) +- **price**: Order price (for limit orders) +- **quantity**: Order quantity +- **filledQuantity**: Quantity filled +- **status**: Order status (NEW, PARTIALLY_FILLED, FILLED, CANCELED, REJECTED, EXPIRED) +- **timeInForce**: Time in force (GTC, IOC, FOK) +- **createdAt**: Order creation timestamp +- **updatedAt**: Order last update timestamp diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json new file mode 100644 index 00000000..1efed7ad --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json @@ -0,0 +1,67 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Order", + "description": "Apex Trading order", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique order identifier" + }, + "clientOrderId": { + "type": "string", + "description": "Client-specified order identifier" + }, + "accountId": { + "type": "string", + "description": "Account ID" + }, + "symbol": { + "type": "string", + "description": "Trading pair symbol (e.g., BTC-USDT)" + }, + "side": { + "type": "string", + "enum": ["BUY", "SELL"], + "description": "Order side" + }, + "type": { + "type": "string", + "enum": ["LIMIT", "MARKET", "STOP_LIMIT", "STOP_MARKET"], + "description": "Order type" + }, + "price": { + "type": "string", + "description": "Order price (for limit orders)" + }, + "quantity": { + "type": "string", + "description": "Order quantity" + }, + "filledQuantity": { + "type": "string", + "description": "Quantity filled" + }, + "status": { + "type": "string", + "enum": ["NEW", "PARTIALLY_FILLED", "FILLED", "CANCELED", "REJECTED", "EXPIRED"], + "description": "Order status" + }, + "timeInForce": { + "type": "string", + "enum": ["GTC", "IOC", "FOK"], + "description": "Time in force" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Order creation timestamp" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Order last update timestamp" + } + }, + "required": ["id", "accountId", "symbol", "side", "type", "quantity", "filledQuantity", "status"] +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md new file mode 100644 index 00000000..e389925a --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md @@ -0,0 +1,47 @@ +# Products + +Product/trading pair information from Apex Trading, including trading rules, precision, and status. + +## Common Queries + +List all products: +``` +No filters needed +``` + +Filter by symbol: +``` +symbol=BTC-USDT +``` + +Filter by status: +``` +status=TRADING +``` + +## API Endpoints + +``` +GET /api/v3/products - List products +GET /api/v3/products/{symbol} - Get specific product +GET /api/v3/ticker?symbol={symbol} - Get ticker for product +GET /api/v3/depth?symbol={symbol} - Get order book for product +GET /api/v3/trades?symbol={symbol} - Get recent trades for product +``` + +## Fields + +- **id**: Unique product identifier +- **symbol**: Trading pair symbol (e.g., BTC-USDT) +- **baseAsset**: Base asset (e.g., BTC) +- **quoteAsset**: Quote asset (e.g., USDT) +- **status**: Product trading status (TRADING, HALT, BREAK) +- **baseAssetPrecision**: Base asset precision (decimal places) +- **quoteAssetPrecision**: Quote asset precision (decimal places) +- **minPrice**: Minimum allowed price +- **maxPrice**: Maximum allowed price +- **tickSize**: Price tick size +- **minQuantity**: Minimum order quantity +- **maxQuantity**: Maximum order quantity +- **stepSize**: Quantity step size +- **minNotional**: Minimum notional value (price * quantity) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json new file mode 100644 index 00000000..343437e5 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json @@ -0,0 +1,66 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Product", + "description": "Apex Trading product/trading pair information", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique product identifier" + }, + "symbol": { + "type": "string", + "description": "Trading pair symbol (e.g., BTC-USDT)" + }, + "baseAsset": { + "type": "string", + "description": "Base asset (e.g., BTC)" + }, + "quoteAsset": { + "type": "string", + "description": "Quote asset (e.g., USDT)" + }, + "status": { + "type": "string", + "enum": ["TRADING", "HALT", "BREAK"], + "description": "Product trading status" + }, + "baseAssetPrecision": { + "type": "integer", + "description": "Base asset precision (decimal places)" + }, + "quoteAssetPrecision": { + "type": "integer", + "description": "Quote asset precision (decimal places)" + }, + "minPrice": { + "type": "string", + "description": "Minimum allowed price" + }, + "maxPrice": { + "type": "string", + "description": "Maximum allowed price" + }, + "tickSize": { + "type": "string", + "description": "Price tick size" + }, + "minQuantity": { + "type": "string", + "description": "Minimum order quantity" + }, + "maxQuantity": { + "type": "string", + "description": "Maximum order quantity" + }, + "stepSize": { + "type": "string", + "description": "Quantity step size" + }, + "minNotional": { + "type": "string", + "description": "Minimum notional value (price * quantity)" + } + }, + "required": ["id", "symbol", "baseAsset", "quoteAsset", "status"] +} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md new file mode 100644 index 00000000..18599eb0 --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md @@ -0,0 +1,47 @@ +# Trades + +Trade execution data from Apex Trading, including price, quantity, fees, and maker/taker information. + +## Common Queries + +List all trades: +``` +No filters needed +``` + +Filter by symbol: +``` +symbol=BTC-USDT +``` + +Filter by order: +``` +orderId=12345 +``` + +Filter by date range: +``` +startTime=2024-01-01T00:00:00Z +endTime=2024-01-31T23:59:59Z +``` + +## API Endpoints + +``` +GET /api/v3/trades - List trades +GET /api/v3/trades/{id} - Get specific trade +GET /api/v3/trades/history - Get trade history +``` + +## Fields + +- **id**: Unique trade identifier +- **orderId**: Order ID associated with this trade +- **symbol**: Trading pair symbol (e.g., BTC-USDT) +- **side**: Trade side (BUY or SELL) +- **price**: Trade execution price +- **quantity**: Trade quantity +- **fee**: Trading fee +- **feeAsset**: Asset used for fee payment +- **isMaker**: Whether this trade was a maker trade +- **createdAt**: Trade execution timestamp diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json new file mode 100644 index 00000000..d8a5efda --- /dev/null +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json @@ -0,0 +1,51 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Trade", + "description": "Apex Trading trade execution", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique trade identifier" + }, + "orderId": { + "type": "string", + "description": "Order ID associated with this trade" + }, + "symbol": { + "type": "string", + "description": "Trading pair symbol (e.g., BTC-USDT)" + }, + "side": { + "type": "string", + "enum": ["BUY", "SELL"], + "description": "Trade side" + }, + "price": { + "type": "string", + "description": "Trade execution price" + }, + "quantity": { + "type": "string", + "description": "Trade quantity" + }, + "fee": { + "type": "string", + "description": "Trading fee" + }, + "feeAsset": { + "type": "string", + "description": "Asset used for fee payment" + }, + "isMaker": { + "type": "boolean", + "description": "Whether this trade was a maker trade" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Trade execution timestamp" + } + }, + "required": ["id", "orderId", "symbol", "side", "price", "quantity", "fee", "feeAsset", "isMaker"] +} From f62139db5a767e450199579acaa92fe52bb25238 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 20:54:20 +0000 Subject: [PATCH 5/5] Fix: Implement correct Apex Trading connector for wholesale cannabis platform Co-authored-by: georgevanderson <4805522+georgevanderson@users.noreply.github.com> --- .../514-labs/typescript/default/.env.example | 8 +- .../typescript/default/CONNECTOR_GUIDE.md | 2 +- .../v1/514-labs/typescript/default/README.md | 86 +++++++++----- .../typescript/default/docs/configuration.md | 111 +----------------- .../typescript/default/docs/limits.md | 73 +----------- .../default/examples/basic-usage.ts | 107 ++++++++++------- .../typescript/default/schemas/index.json | 42 ++++--- .../default/schemas/raw/json/accounts.md | 37 ------ .../schemas/raw/json/accounts.schema.json | 55 --------- .../default/schemas/raw/json/orders.md | 59 ---------- .../schemas/raw/json/orders.schema.json | 67 ----------- .../default/schemas/raw/json/products.md | 47 -------- .../schemas/raw/json/products.schema.json | 66 ----------- .../default/schemas/raw/json/trades.md | 47 -------- .../schemas/raw/json/trades.schema.json | 51 -------- .../default/src/client/connector.ts | 46 ++------ .../typescript/default/src/lib/paginate.ts | 46 +++++--- .../default/src/resources/accounts.ts | 50 -------- .../default/src/resources/batches.ts | 49 ++++++++ .../default/src/resources/buyers.ts | 45 +++++++ .../default/src/resources/companies.ts | 48 ++++++++ .../typescript/default/src/resources/index.ts | 7 +- .../default/src/resources/orders.ts | 103 ++++++++-------- .../default/src/resources/products.ts | 100 ++++------------ .../default/src/resources/trades.ts | 58 --------- .../default/tests/observability.test.ts | 6 +- .../typescript/default/tests/resource.test.ts | 12 +- 27 files changed, 422 insertions(+), 1006 deletions(-) delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/batches.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/buyers.ts create mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/companies.ts delete mode 100644 connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts 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 index a953a9fd..6e8d9f45 100644 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/.env.example @@ -1,10 +1,6 @@ # Apex Trading API credentials APEX_API_KEY=your_api_key_here -APEX_API_SECRET=your_api_secret_here -APEX_API_PASSPHRASE=your_passphrase_here - -# Optional: Set environment (production or testnet) -# APEX_ENVIRONMENT=production # Optional: Custom base URL -# APEX_BASE_URL=https://omni.apex.exchange/api/v3 +# APEX_BASE_URL=https://api-docs.apextrading.com + 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 index e3b884bb..8425b0b7 100644 --- 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 @@ -30,7 +30,7 @@ Or view online: [Connector Implementation Guide](../../../../../../_scaffold/CON - [ ] Test with API to verify it works ### Phase 5: Implement Resources -- [ ] Define resource types in `src/resources/accounts.ts` +- [ ] Define resource types in `src/resources/products.ts` - [ ] Implement list/get/create methods as needed - [ ] Add resource getters to connector class 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 index 1b042dac..0533cbd2 100644 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/README.md +++ b/connector-registry/apex-trading/v1/514-labs/typescript/default/README.md @@ -1,6 +1,10 @@ # Apex Trading Connector -TypeScript connector for the Apex Trading API. +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 @@ -17,37 +21,28 @@ const connector = createConnector() connector.initialize({ apiKey: process.env.APEX_API_KEY!, - apiSecret: process.env.APEX_API_SECRET, - apiPassphrase: process.env.APEX_API_PASSPHRASE, - environment: 'production', // or 'testnet' logging: { enabled: true, level: 'info' }, metrics: { enabled: true }, }) -// List products -for await (const page of connector.products.list()) { +// 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) } -// Get account balance -const balance = await connector.accounts.getBalance() -console.log('Balance:', balance) - -// List orders -for await (const page of connector.orders.list({ symbol: 'BTC-USDT' })) { +// List receiving orders +for await (const page of connector.orders.receiving({ + status: 'confirmed' +})) { console.log('Orders:', page) } -// Create an order -const order = await connector.orders.create({ - symbol: 'BTC-USDT', - side: 'BUY', - type: 'LIMIT', - quantity: '0.001', - price: '50000', - timeInForce: 'GTC', -}) -console.log('Order created:', order) +// Get company details +const company = await connector.companies.get('company-id') +console.log('Company:', company) ``` ## Configuration @@ -56,19 +51,50 @@ console.log('Order created:', order) - `apiKey`: Your Apex Trading API key ### Optional -- `apiSecret`: Your API secret (required for some operations) -- `apiPassphrase`: Your API passphrase (required for some operations) -- `baseUrl`: Custom API base URL -- `environment`: 'production' or 'testnet' (default: 'production') +- `baseUrl`: Custom API base URL (default: https://api-docs.apextrading.com) - `logging`: Logging configuration - `metrics`: Metrics collection configuration ## Available Resources -- **accounts**: Account management and balance information -- **orders**: Order creation, listing, and management -- **trades**: Trade history and information -- **products**: Market products, tickers, and order book data +- **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 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 index f4b03b05..59237d7c 100644 --- 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 @@ -1,108 +1,7 @@ # Configuration -This document describes all configuration options for the Apex Trading connector. - -## Required Configuration - -### `apiKey` -- **Type**: `string` -- **Required**: Yes -- **Description**: Your Apex Trading API key. You can generate an API key from your Apex Trading account dashboard. - -## Optional Configuration - -### `apiSecret` -- **Type**: `string` -- **Required**: No -- **Description**: Your API secret. Required for certain authenticated operations that need request signing. - -### `apiPassphrase` -- **Type**: `string` -- **Required**: No -- **Description**: Your API passphrase. Required for certain authenticated operations. - -### `baseUrl` -- **Type**: `string` -- **Required**: No -- **Default**: `https://omni.apex.exchange/api/v3` -- **Description**: Custom API base URL. Useful for testing or if Apex changes their API endpoint. - -### `environment` -- **Type**: `'production' | 'testnet'` -- **Required**: No -- **Default**: `'production'` -- **Description**: Determines which API environment to use. When set to `'testnet'`, the base URL defaults to `https://testnet.apex.exchange/api/v3`. - -### `logging` -- **Type**: `object` -- **Required**: No -- **Description**: Logging configuration for debugging and monitoring. - -#### `logging.enabled` -- **Type**: `boolean` -- **Default**: `false` -- **Description**: Enable request/response logging. - -#### `logging.level` -- **Type**: `'debug' | 'info' | 'warn' | 'error'` -- **Default**: `'info'` -- **Description**: Minimum log level to output. - -#### `logging.includeQueryParams` -- **Type**: `boolean` -- **Default**: `false` -- **Description**: Include query parameters in logs. - -#### `logging.includeHeaders` -- **Type**: `boolean` -- **Default**: `false` -- **Description**: Include headers in logs (be careful with sensitive data). - -#### `logging.includeBody` -- **Type**: `boolean` -- **Default**: `false` -- **Description**: Include request/response bodies in logs. - -### `metrics` -- **Type**: `object` -- **Required**: No -- **Description**: Metrics collection configuration. - -#### `metrics.enabled` -- **Type**: `boolean` -- **Default**: `false` -- **Description**: Enable metrics collection for request/response statistics. - -## Advanced Configuration - -You can also pass any configuration from the base `ConnectorConfig` type: - -### `retry` -- **Type**: `object` -- **Description**: Retry configuration for failed requests (maxAttempts, initialDelayMs, maxDelayMs, backoffMultiplier, respectRetryAfter). - -### `rateLimit` -- **Type**: `object` -- **Description**: Rate limiting configuration (requestsPerSecond: 15, burstCapacity, adaptiveFromHeaders). - -### `hooks` -- **Type**: `object` -- **Description**: Arrays for beforeRequest/afterResponse/onError/onRetry lifecycle hooks. - -## Example Configuration - -```typescript -import { createConnector } from '@workspace/connector-apex-trading' - -const connector = createConnector() - -connector.initialize({ - apiKey: process.env.APEX_API_KEY!, - apiSecret: process.env.APEX_API_SECRET, - apiPassphrase: process.env.APEX_API_PASSPHRASE, - environment: 'production', // or 'testnet' - logging: { enabled: true, level: 'info' }, - metrics: { enabled: true }, -}) -``` - +- 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/limits.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/docs/limits.md index fb99220d..447b11f1 100644 --- 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 @@ -1,72 +1,3 @@ -# API Limits - -This document describes the rate limits and constraints of the Apex Trading API. - -## Rate Limits - -### Global Rate Limit -- **Limit**: 15 requests per second per API key -- **Enforcement**: Per API token/key -- **Headers**: The API returns rate limit information in response headers: - - `X-RateLimit-Limit`: Maximum requests per second (15) - - `X-RateLimit-Remaining`: Remaining requests in the current window - - `Retry-After`: Time in seconds to wait before retrying (when rate limited) - -### HTTP Status Codes -- **429 Too Many Requests**: Rate limit exceeded. The connector will automatically retry after the specified delay. - -## Connector Rate Limiting - -This connector automatically handles rate limiting to prevent you from exceeding API limits: - -- **Default Setting**: 15 requests per second (matching the API limit) -- **Automatic Retry**: When a 429 status is received, the connector respects the `Retry-After` header -- **Configuration**: You can customize rate limiting in the connector configuration: - -```typescript -connector.initialize({ - apiKey: 'your-api-key', - rateLimit: { - requestsPerSecond: 15, - burstCapacity: 30, // optional - adaptiveFromHeaders: true, // optional - adjust based on API response headers - }, -}) -``` - -## Best Practices - -1. **Use Pagination Wisely**: When listing large datasets, use appropriate page sizes to minimize requests -2. **Batch Operations**: Where possible, batch multiple operations into single requests -3. **Cache Data**: Cache frequently accessed reference data (products, etc.) to reduce API calls -4. **Monitor Rate Limits**: Enable metrics to track your API usage - -## Data Limits - -### Pagination -- **Maximum Page Size**: Varies by endpoint, typically 100-1000 items -- **Recommended Page Size**: 100 items for optimal performance -- **Offset/Limit**: Most endpoints use offset-based pagination - -## Error Handling - -When you exceed rate limits, the connector will: - -1. Receive a `429 Too Many Requests` response -2. Read the `Retry-After` header -3. Wait the specified time -4. Automatically retry the request (up to `maxAttempts`) - -You can configure retry behavior: - -```typescript -connector.initialize({ - apiKey: 'your-api-key', - retry: { - maxAttempts: 3, - retryableStatusCodes: [429, 500, 502, 503, 504], - respectRetryAfter: true, - }, -}) -``` +# Limits +Describe API limits, quotas, and rate limiting behavior. 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 index e7ac97de..634ffbfa 100644 --- 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 @@ -3,79 +3,98 @@ import { createConnector } from '../src' async function main() { const connector = createConnector() - // Initialize the connector with your API credentials + // Initialize the connector with your API key connector.initialize({ apiKey: process.env.APEX_API_KEY!, - apiSecret: process.env.APEX_API_SECRET, - apiPassphrase: process.env.APEX_API_PASSPHRASE, - environment: 'production', // or 'testnet' logging: { enabled: true, level: 'info' }, metrics: { enabled: true }, }) - console.log('Apex Trading Connector - Basic Usage Examples\n') + console.log('Apex Trading Connector - Wholesale Cannabis Platform\n') - // Example 1: List products - console.log('1. Listing products...') - let count = 0 - for await (const page of connector.products.list({ pageSize: 10, maxItems: 10 })) { - console.log(` Found ${page.length} products:`) - page.forEach(product => { - console.log(` - ${product.symbol}: ${product.baseAsset}/${product.quoteAsset}`) - }) - count += page.length - } - console.log(` Total products listed: ${count}\n`) - - // Example 2: Get ticker for a specific symbol - console.log('2. Getting ticker for BTC-USDT...') + // Example 1: List products with incremental sync + console.log('1. Listing products (incremental sync)...') try { - const ticker = await connector.products.getTicker('BTC-USDT') - console.log(` Last Price: ${ticker.lastPrice}`) - console.log(` 24h Change: ${ticker.priceChangePercent}%`) - console.log(` 24h Volume: ${ticker.volume}\n`) + 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 getting ticker (may need valid symbol):', (error as Error).message, '\n') + console.log(' Error listing products:', (error as Error).message, '\n') } - // Example 3: Get account balance - console.log('3. Getting account balance...') + // Example 2: List batches + console.log('2. Listing batches...') try { - const balance = await connector.accounts.getBalance() - console.log(` Balance: ${balance.balance}`) - console.log(` Available: ${balance.availableBalance}`) - console.log(` Locked: ${balance.lockedBalance}\n`) + 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 getting balance (requires authentication):', (error as Error).message, '\n') + console.log(' Error listing batches:', (error as Error).message, '\n') } - // Example 4: List orders - console.log('4. Listing orders...') + // Example 3: List receiving orders + console.log('3. Listing receiving orders...') try { let orderCount = 0 - for await (const page of connector.orders.list({ pageSize: 10, maxItems: 10 })) { + 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.symbol} ${order.side} ${order.type}: ${order.status}`) + console.log(` - Order ${order.order_number}: ${order.status}`) }) orderCount += page.length } console.log(` Total orders: ${orderCount}\n`) } catch (error) { - console.log(' Error listing orders (requires authentication):', (error as Error).message, '\n') + 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 trades - console.log('5. Listing recent trades...') + // Example 5: List buyers + console.log('5. Listing buyers...') try { - let tradeCount = 0 - for await (const page of connector.trades.list({ pageSize: 10, maxItems: 10 })) { - console.log(` Found ${page.length} trades`) - tradeCount += page.length + 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 trades: ${tradeCount}\n`) + console.log(` Total buyers: ${buyerCount}\n`) } catch (error) { - console.log(' Error listing trades (requires authentication):', (error as Error).message, '\n') + console.log(' Error listing buyers:', (error as Error).message, '\n') } console.log('Done!') 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 index 0b72ed6d..245115ca 100644 --- 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 @@ -3,33 +3,39 @@ "version": "0.1.0", "datasets": [ { - "name": "accounts", + "name": "events", "stage": "raw", "kind": "endpoints", - "path": "raw/json/accounts.schema.json", - "doc": "raw/json/accounts.md" + "path": "raw/endpoints/events.schema.json", + "doc": "raw/endpoints/events.md" }, { - "name": "orders", - "stage": "raw", + "name": "events", + "stage": "extracted", "kind": "endpoints", - "path": "raw/json/orders.schema.json", - "doc": "raw/json/orders.md" - }, - { - "name": "trades", + "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/json/trades.schema.json", - "doc": "raw/json/trades.md" + "path": "raw/endpoints/endpoints/users/create.schema.json", + "doc": "raw/endpoints/endpoints/users/create.md", + "metadata": { + "category": "endpoint", + "apiMethod": "POST" + } }, - { - "name": "products", + "nested_organization_example": { + "name": "reports.analytics", "stage": "raw", "kind": "endpoints", - "path": "raw/json/products.schema.json", - "doc": "raw/json/products.md" + "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/json/accounts.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md deleted file mode 100644 index 98e3ba6e..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.md +++ /dev/null @@ -1,37 +0,0 @@ -# Accounts - -Account information from Apex Trading, including balances, equity, and margin details. - -## Common Queries - -Get all accounts: -``` -No filters needed -``` - -Get account balance: -``` -Use the getBalance() method for current balance information -``` - -## API Endpoints - -``` -GET /api/v3/accounts - List all accounts -GET /api/v3/accounts/{id} - Get specific account -GET /api/v3/account/balance - Get account balance -``` - -## Fields - -- **id**: Unique account identifier -- **userId**: User ID associated with the account -- **balance**: Total account balance -- **availableBalance**: Available balance for trading -- **lockedBalance**: Balance locked in open orders -- **equity**: Account equity -- **totalMargin**: Total margin used -- **freeMargin**: Free margin available -- **unrealizedPnl**: Unrealized profit and loss -- **createdAt**: Account creation timestamp -- **updatedAt**: Account last update timestamp diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json deleted file mode 100644 index ef1b1e13..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/accounts.schema.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Account", - "description": "Apex Trading account information", - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique account identifier" - }, - "userId": { - "type": "string", - "description": "User ID associated with the account" - }, - "balance": { - "type": "string", - "description": "Total account balance" - }, - "availableBalance": { - "type": "string", - "description": "Available balance for trading" - }, - "lockedBalance": { - "type": "string", - "description": "Balance locked in open orders" - }, - "equity": { - "type": "string", - "description": "Account equity" - }, - "totalMargin": { - "type": "string", - "description": "Total margin used" - }, - "freeMargin": { - "type": "string", - "description": "Free margin available" - }, - "unrealizedPnl": { - "type": "string", - "description": "Unrealized profit and loss" - }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "Account creation timestamp" - }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "Account last update timestamp" - } - }, - "required": ["id", "userId", "balance", "availableBalance", "lockedBalance"] -} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md deleted file mode 100644 index 96c0cf28..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.md +++ /dev/null @@ -1,59 +0,0 @@ -# Orders - -Order data from Apex Trading, including order details, status, and execution information. - -## Common Queries - -List all orders: -``` -No filters needed -``` - -Filter by symbol: -``` -symbol=BTC-USDT -``` - -Filter by status: -``` -status=NEW -status=FILLED -``` - -Filter by side: -``` -side=BUY -side=SELL -``` - -Filter by date range: -``` -startTime=2024-01-01T00:00:00Z -endTime=2024-01-31T23:59:59Z -``` - -## API Endpoints - -``` -GET /api/v3/orders - List orders -GET /api/v3/orders/{id} - Get specific order -POST /api/v3/orders - Create new order -DELETE /api/v3/orders/{id} - Cancel order -DELETE /api/v3/orders - Cancel all orders (optionally filtered by symbol) -``` - -## Fields - -- **id**: Unique order identifier -- **clientOrderId**: Client-specified order identifier -- **accountId**: Account ID -- **symbol**: Trading pair symbol (e.g., BTC-USDT) -- **side**: Order side (BUY or SELL) -- **type**: Order type (LIMIT, MARKET, STOP_LIMIT, STOP_MARKET) -- **price**: Order price (for limit orders) -- **quantity**: Order quantity -- **filledQuantity**: Quantity filled -- **status**: Order status (NEW, PARTIALLY_FILLED, FILLED, CANCELED, REJECTED, EXPIRED) -- **timeInForce**: Time in force (GTC, IOC, FOK) -- **createdAt**: Order creation timestamp -- **updatedAt**: Order last update timestamp diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json deleted file mode 100644 index 1efed7ad..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/orders.schema.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Order", - "description": "Apex Trading order", - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique order identifier" - }, - "clientOrderId": { - "type": "string", - "description": "Client-specified order identifier" - }, - "accountId": { - "type": "string", - "description": "Account ID" - }, - "symbol": { - "type": "string", - "description": "Trading pair symbol (e.g., BTC-USDT)" - }, - "side": { - "type": "string", - "enum": ["BUY", "SELL"], - "description": "Order side" - }, - "type": { - "type": "string", - "enum": ["LIMIT", "MARKET", "STOP_LIMIT", "STOP_MARKET"], - "description": "Order type" - }, - "price": { - "type": "string", - "description": "Order price (for limit orders)" - }, - "quantity": { - "type": "string", - "description": "Order quantity" - }, - "filledQuantity": { - "type": "string", - "description": "Quantity filled" - }, - "status": { - "type": "string", - "enum": ["NEW", "PARTIALLY_FILLED", "FILLED", "CANCELED", "REJECTED", "EXPIRED"], - "description": "Order status" - }, - "timeInForce": { - "type": "string", - "enum": ["GTC", "IOC", "FOK"], - "description": "Time in force" - }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "Order creation timestamp" - }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "Order last update timestamp" - } - }, - "required": ["id", "accountId", "symbol", "side", "type", "quantity", "filledQuantity", "status"] -} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md deleted file mode 100644 index e389925a..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.md +++ /dev/null @@ -1,47 +0,0 @@ -# Products - -Product/trading pair information from Apex Trading, including trading rules, precision, and status. - -## Common Queries - -List all products: -``` -No filters needed -``` - -Filter by symbol: -``` -symbol=BTC-USDT -``` - -Filter by status: -``` -status=TRADING -``` - -## API Endpoints - -``` -GET /api/v3/products - List products -GET /api/v3/products/{symbol} - Get specific product -GET /api/v3/ticker?symbol={symbol} - Get ticker for product -GET /api/v3/depth?symbol={symbol} - Get order book for product -GET /api/v3/trades?symbol={symbol} - Get recent trades for product -``` - -## Fields - -- **id**: Unique product identifier -- **symbol**: Trading pair symbol (e.g., BTC-USDT) -- **baseAsset**: Base asset (e.g., BTC) -- **quoteAsset**: Quote asset (e.g., USDT) -- **status**: Product trading status (TRADING, HALT, BREAK) -- **baseAssetPrecision**: Base asset precision (decimal places) -- **quoteAssetPrecision**: Quote asset precision (decimal places) -- **minPrice**: Minimum allowed price -- **maxPrice**: Maximum allowed price -- **tickSize**: Price tick size -- **minQuantity**: Minimum order quantity -- **maxQuantity**: Maximum order quantity -- **stepSize**: Quantity step size -- **minNotional**: Minimum notional value (price * quantity) diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json deleted file mode 100644 index 343437e5..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/products.schema.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Product", - "description": "Apex Trading product/trading pair information", - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique product identifier" - }, - "symbol": { - "type": "string", - "description": "Trading pair symbol (e.g., BTC-USDT)" - }, - "baseAsset": { - "type": "string", - "description": "Base asset (e.g., BTC)" - }, - "quoteAsset": { - "type": "string", - "description": "Quote asset (e.g., USDT)" - }, - "status": { - "type": "string", - "enum": ["TRADING", "HALT", "BREAK"], - "description": "Product trading status" - }, - "baseAssetPrecision": { - "type": "integer", - "description": "Base asset precision (decimal places)" - }, - "quoteAssetPrecision": { - "type": "integer", - "description": "Quote asset precision (decimal places)" - }, - "minPrice": { - "type": "string", - "description": "Minimum allowed price" - }, - "maxPrice": { - "type": "string", - "description": "Maximum allowed price" - }, - "tickSize": { - "type": "string", - "description": "Price tick size" - }, - "minQuantity": { - "type": "string", - "description": "Minimum order quantity" - }, - "maxQuantity": { - "type": "string", - "description": "Maximum order quantity" - }, - "stepSize": { - "type": "string", - "description": "Quantity step size" - }, - "minNotional": { - "type": "string", - "description": "Minimum notional value (price * quantity)" - } - }, - "required": ["id", "symbol", "baseAsset", "quoteAsset", "status"] -} diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md deleted file mode 100644 index 18599eb0..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.md +++ /dev/null @@ -1,47 +0,0 @@ -# Trades - -Trade execution data from Apex Trading, including price, quantity, fees, and maker/taker information. - -## Common Queries - -List all trades: -``` -No filters needed -``` - -Filter by symbol: -``` -symbol=BTC-USDT -``` - -Filter by order: -``` -orderId=12345 -``` - -Filter by date range: -``` -startTime=2024-01-01T00:00:00Z -endTime=2024-01-31T23:59:59Z -``` - -## API Endpoints - -``` -GET /api/v3/trades - List trades -GET /api/v3/trades/{id} - Get specific trade -GET /api/v3/trades/history - Get trade history -``` - -## Fields - -- **id**: Unique trade identifier -- **orderId**: Order ID associated with this trade -- **symbol**: Trading pair symbol (e.g., BTC-USDT) -- **side**: Trade side (BUY or SELL) -- **price**: Trade execution price -- **quantity**: Trade quantity -- **fee**: Trading fee -- **feeAsset**: Asset used for fee payment -- **isMaker**: Whether this trade was a maker trade -- **createdAt**: Trade execution timestamp diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json b/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json deleted file mode 100644 index d8a5efda..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/schemas/raw/json/trades.schema.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Trade", - "description": "Apex Trading trade execution", - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique trade identifier" - }, - "orderId": { - "type": "string", - "description": "Order ID associated with this trade" - }, - "symbol": { - "type": "string", - "description": "Trading pair symbol (e.g., BTC-USDT)" - }, - "side": { - "type": "string", - "enum": ["BUY", "SELL"], - "description": "Trade side" - }, - "price": { - "type": "string", - "description": "Trade execution price" - }, - "quantity": { - "type": "string", - "description": "Trade quantity" - }, - "fee": { - "type": "string", - "description": "Trading fee" - }, - "feeAsset": { - "type": "string", - "description": "Asset used for fee payment" - }, - "isMaker": { - "type": "boolean", - "description": "Whether this trade was a maker trade" - }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "Trade execution timestamp" - } - }, - "required": ["id", "orderId", "symbol", "side", "price", "quantity", "fee", "feeAsset", "isMaker"] -} 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 index 4933e68c..011e78de 100644 --- 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 @@ -1,46 +1,23 @@ -/** - * CONNECTOR IMPLEMENTATION GUIDE - * See CONNECTOR_GUIDE.md in the root of this connector for step-by-step instructions. - * - * Quick checklist: - * [ ] Phase 3: Configure authentication (update ConnectorConfig type & init method below) - * [ ] Phase 4: Implement pagination in src/lib/paginate.ts (offset/cursor/page) - * [ ] Phase 5: Implement resources in src/resources/ - * [ ] Phase 6: Add schemas to schemas/raw/json/ - * [ ] Phase 7: Update .env.example and README.md - * [ ] Phase 8: Write tests in tests/ - * [ ] Phase 9: Build and test (pnpm run build && pnpm test) - * - * Reference connectors: - * - Simple API key: connector-registry/socrata/ - * - OAuth2: connector-registry/meta-ads/ - */ - 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 createAccountsResource } from '../resources/accounts' -import { createResource as createOrdersResource } from '../resources/orders' -import { createResource as createTradesResource } from '../resources/trades' 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 - apiSecret?: string - apiPassphrase?: string - environment?: 'production' | 'testnet' + 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 ?? - (userConfig.environment === 'testnet' - ? 'https://testnet.apex.exchange/api/v3' - : 'https://omni.apex.exchange/api/v3') - + const baseUrl = userConfig.baseUrl ?? 'https://api-docs.apextrading.com' const apiKey = userConfig.apiKey ?? userConfig.auth?.bearer?.token const config: ConnectorConfig = { @@ -49,7 +26,7 @@ export class Connector extends ApiConnectorBase { userAgent: userConfig.userAgent ?? 'apex-trading-connector', defaultHeaders: { ...userConfig.defaultHeaders, - ...(apiKey ? { 'X-API-Key': apiKey } : {}), + ...(apiKey ? { 'Authorization': `****** ${apiKey}` } : {}), }, auth: userConfig.auth ?? { type: 'bearer', @@ -95,12 +72,11 @@ export class Connector extends ApiConnectorBase { private get sendLite() { return async (args: any) => (this as any).request(args) } - get accounts() { return createAccountsResource(this.sendLite as any) } - get orders() { return createOrdersResource(this.sendLite as any) } - get trades() { return createTradesResource(this.sendLite as any) } 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/lib/paginate.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/lib/paginate.ts index 9280576a..1c7b8b17 100644 --- 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 @@ -9,15 +9,16 @@ export type SendFn = (args: { operation?: string; }) => Promise> -// Offset-based pagination for Apex Trading API -export async function* paginateOffset(params: { +// 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 = {}, pageSize = 100, maxItems } = params + const { send, path, query = {}, updatedAtFrom, pageSize = 100, maxItems } = params let offset = 0 let totalFetched = 0 @@ -30,7 +31,12 @@ export async function* paginateOffset(params: { const response = await send({ method: 'GET', path, - query: { ...query, limit: currentLimit, offset }, + query: { + ...query, + limit: currentLimit, + offset, + ...(updatedAtFrom ? { updated_at_from: updatedAtFrom } : {}) + }, }) const items = Array.isArray(response.data) ? response.data : [] @@ -44,35 +50,37 @@ export async function* paginateOffset(params: { } } -// Cursor-based pagination helper (if needed for some endpoints) -export async function* paginateCursor(params: { +// Standard offset pagination +export async function* paginateOffset(params: { send: SendFn; path: string; query?: Record; pageSize?: number; - extractItems: (res: any) => T[]; - extractNextCursor: (res: any) => string | undefined; + maxItems?: number; }): AsyncGenerator> { - const { send, path, query = {}, pageSize, extractItems, extractNextCursor } = params - let cursor: string | undefined = undefined + const { send, path, query = {}, pageSize = 100, maxItems } = params + let offset = 0 + let totalFetched = 0 while (true) { - const response = await send({ + 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, - ...(cursor ? { cursor } : {}), - ...(pageSize ? { limit: pageSize } : {}), - }, + query: { ...query, limit: currentLimit, offset }, }) - const items = extractItems(response.data) + const items = Array.isArray(response.data) ? response.data : [] if (items.length === 0) break + totalFetched += items.length + offset += items.length yield items - cursor = extractNextCursor(response.data) - if (!cursor) break + if (items.length < currentLimit) break } } diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts deleted file mode 100644 index c61c9392..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/accounts.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { paginateOffset } from '../lib/paginate' -import type { SendFn } from '../lib/paginate' - -export interface Account { - id: string - userId: string - balance: string - availableBalance: string - lockedBalance: string - equity: string - totalMargin: string - freeMargin: string - unrealizedPnl: string - createdAt: string - updatedAt: string -} - -export interface ListAccountsParams { - pageSize?: number - maxItems?: number -} - -export const createResource = (send: SendFn) => ({ - async *list(params?: ListAccountsParams) { - const { pageSize, maxItems } = params ?? {} - - yield* paginateOffset({ - send, - path: '/accounts', - pageSize, - maxItems, - }) - }, - - async get(id: string): Promise { - const response = await send({ - method: 'GET', - path: `/accounts/${id}`, - }) - return response.data - }, - - async getBalance(): Promise<{ balance: string; availableBalance: string; lockedBalance: string }> { - const response = await send({ - method: 'GET', - path: '/account/balance', - }) - return response.data - }, -}) 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 index c4ab08c4..9be7fbe1 100644 --- 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 @@ -1,5 +1,6 @@ -export { createResource as createAccountsResource } from './accounts' -export { createResource as createOrdersResource } from './orders' -export { createResource as createTradesResource } from './trades' 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 index 354d4842..6ff64e5a 100644 --- 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 @@ -1,43 +1,38 @@ import { paginateOffset } from '../lib/paginate' import type { SendFn } from '../lib/paginate' +export type OrderType = 'receiving' | 'shipping' | 'transporter' + export interface Order { id: string - clientOrderId?: string - accountId: string - symbol: string - side: 'BUY' | 'SELL' - type: 'LIMIT' | 'MARKET' | 'STOP_LIMIT' | 'STOP_MARKET' - price?: string - quantity: string - filledQuantity: string - status: 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'REJECTED' | 'EXPIRED' - timeInForce?: 'GTC' | 'IOC' | 'FOK' - createdAt: string - updatedAt: 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 { - symbol?: string - status?: 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'REJECTED' | 'EXPIRED' - side?: 'BUY' | 'SELL' - startTime?: string - endTime?: string + type?: OrderType + status?: string + company_id?: string + buyer_id?: string + start_date?: string + end_date?: string pageSize?: number maxItems?: number } -export interface CreateOrderParams { - symbol: string - side: 'BUY' | 'SELL' - type: 'LIMIT' | 'MARKET' | 'STOP_LIMIT' | 'STOP_MARKET' - quantity: string - price?: string - stopPrice?: string - timeInForce?: 'GTC' | 'IOC' | 'FOK' - clientOrderId?: string -} - export const createResource = (send: SendFn) => ({ async *list(params?: ListOrdersParams) { const { pageSize, maxItems, ...filters } = params ?? {} @@ -51,36 +46,46 @@ export const createResource = (send: SendFn) => ({ }) }, - async get(orderId: string): Promise { - const response = await send({ - method: 'GET', - path: `/orders/${orderId}`, + async *receiving(params?: Omit) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/receiving-orders', + query: filters, + pageSize, + maxItems, }) - return response.data }, - async create(params: CreateOrderParams): Promise { - const response = await send({ - method: 'POST', - path: '/orders', - body: params, + async *shipping(params?: Omit) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/shipping-orders', + query: filters, + pageSize, + maxItems, }) - return response.data }, - async cancel(orderId: string): Promise { - const response = await send({ - method: 'DELETE', - path: `/orders/${orderId}`, + async *transporter(params?: Omit) { + const { pageSize, maxItems, ...filters } = params ?? {} + + yield* paginateOffset({ + send, + path: '/transporter-orders', + query: filters, + pageSize, + maxItems, }) - return response.data }, - async cancelAll(symbol?: string): Promise<{ canceledCount: number }> { - const response = await send<{ canceledCount: number }>({ - method: 'DELETE', - path: '/orders', - query: symbol ? { symbol } : undefined, + 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 index 776eedb0..cd618a8e 100644 --- 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 @@ -1,106 +1,50 @@ -import { paginateOffset } from '../lib/paginate' +import { paginateIncremental, paginateOffset } from '../lib/paginate' import type { SendFn } from '../lib/paginate' export interface Product { id: string - symbol: string - baseAsset: string - quoteAsset: string - status: 'TRADING' | 'HALT' | 'BREAK' - baseAssetPrecision: number - quoteAssetPrecision: number - minPrice: string - maxPrice: string - tickSize: string - minQuantity: string - maxQuantity: string - stepSize: string - minNotional: 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 { - symbol?: string - status?: 'TRADING' | 'HALT' | 'BREAK' + updated_at_from?: string // For incremental sync + category?: string + brand?: string + strain?: string pageSize?: number maxItems?: number } -export interface Ticker { - symbol: string - lastPrice: string - priceChange: string - priceChangePercent: string - volume: string - quoteVolume: string - openPrice: string - highPrice: string - lowPrice: string - timestamp: string -} - -export interface OrderBook { - symbol: string - bids: Array<[string, string]> // [price, quantity] - asks: Array<[string, string]> // [price, quantity] - timestamp: string -} - -export interface PublicTrade { - id: string - price: string - quantity: string - timestamp: string - isBuyerMaker: boolean -} - export const createResource = (send: SendFn) => ({ async *list(params?: ListProductsParams) { - const { pageSize, maxItems, ...filters } = params ?? {} + const { pageSize, maxItems, updated_at_from, ...filters } = params ?? {} - yield* paginateOffset({ + yield* paginateIncremental({ send, path: '/products', query: filters, + updatedAtFrom: updated_at_from, pageSize, maxItems, }) }, - async get(symbol: string): Promise { + async get(id: string): Promise { const response = await send({ method: 'GET', - path: `/products/${symbol}`, - }) - return response.data - }, - - async getTicker(symbol: string): Promise { - const response = await send({ - method: 'GET', - path: '/ticker', - query: { symbol }, - }) - return response.data - }, - - async getOrderBook(symbol: string, limit?: number): Promise { - const response = await send({ - method: 'GET', - path: '/depth', - query: { symbol, limit }, + path: `/products/${id}`, }) return response.data }, - - async *getRecentTrades(symbol: string, limit?: number) { - const response = await send({ - method: 'GET', - path: '/trades', - query: { symbol, limit }, - }) - - const trades = Array.isArray(response.data) ? response.data : [] - yield trades - }, }) - diff --git a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts b/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts deleted file mode 100644 index 18e7797a..00000000 --- a/connector-registry/apex-trading/v1/514-labs/typescript/default/src/resources/trades.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { paginateOffset } from '../lib/paginate' -import type { SendFn } from '../lib/paginate' - -export interface Trade { - id: string - orderId: string - symbol: string - side: 'BUY' | 'SELL' - price: string - quantity: string - fee: string - feeAsset: string - isMaker: boolean - createdAt: string -} - -export interface ListTradesParams { - symbol?: string - orderId?: string - startTime?: string - endTime?: string - pageSize?: number - maxItems?: number -} - -export const createResource = (send: SendFn) => ({ - async *list(params?: ListTradesParams) { - const { pageSize, maxItems, ...filters } = params ?? {} - - yield* paginateOffset({ - send, - path: '/trades', - query: filters, - pageSize, - maxItems, - }) - }, - - async get(tradeId: string): Promise { - const response = await send({ - method: 'GET', - path: `/trades/${tradeId}`, - }) - return response.data - }, - - async *history(params?: ListTradesParams) { - const { pageSize, maxItems, ...filters } = params ?? {} - - yield* paginateOffset({ - send, - path: '/trades/history', - query: filters, - pageSize, - maxItems, - }) - }, -}) 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 index 0a51f21c..87638e5f 100644 --- 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 @@ -5,14 +5,14 @@ import { createConnector } from '../src' it('logging includes url, headers, body when enabled', async () => { const BASE = 'https://api.example.com' - nock(BASE).get('/accounts').query({ x: '1' }).reply(200, [{ id: 1 }], { 'x-test-header': 'ok' }) + 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: '/accounts?x=1' }) + 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('/accounts?x=1') + 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 index 4902e337..960e7586 100644 --- 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 @@ -3,16 +3,16 @@ import nock from 'nock' import { createConnector } from '../src' -it('accounts.list yields chunks and respects maxItems', async () => { - const BASE = 'https://omni.apex.exchange' - nock(BASE).get('/api/v3/accounts').query({ limit: 2, offset: 0 }).reply(200, [{ id: '1' }, { id: '2' }]) - nock(BASE).get('/api/v3/accounts').query({ limit: 2, offset: 2 }).reply(200, [{ id: '3' }, { id: '4' }]) - nock(BASE).get('/api/v3/accounts').query({ limit: 0, offset: 4 }).reply(200, []) +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.accounts.list({ pageSize: 2, maxItems: 4 })) pages.push(page) + for await (const page of conn.products.list({ pageSize: 2, maxItems: 4 })) pages.push(page) expect(pages.map(p => p.length)).toEqual([2, 2]) })