diff --git a/.eslintignore b/.eslintignore index d2b87fc6a..fe35f6e1c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,5 +2,3 @@ dist /docs examples node_modules -types -types/demo diff --git a/.prettierignore b/.prettierignore index 34b7584b3..07356dd88 100644 --- a/.prettierignore +++ b/.prettierignore @@ -11,6 +11,5 @@ examples official/fixtures/ package-lock.json style_guides/ -types/ vendor/ venv/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 58659b396..d37c1a496 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ - Breaking: `makeApiCall` now accepts `delete` (the `del` alias was removed) - `requestMiddleware` compatibility preserved using a fetch-era compatibility request object - Default `User-Agent` retains structured runtime metadata fields (`Nodejs/`, `OS/`, `OSVersion/`, `OSArch/`) via runtime-safe detection +- TypeScript declarations are now generated from source and published from `dist/types`. +- Internal root `types/` declaration sources and demo fixtures were removed from the repository. ## v8.9.0 (2026-06-25) diff --git a/README.md b/README.md index 6967e8c58..afac0398e 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,9 @@ just update-examples-submodule Starting with `v5.3.0`, this project has Typescript definitions included. +Current definitions are generated from source and published with the package at `dist/types`. +No consumer configuration changes are required when importing `@easypost/api` from the package root. + #### Typescript Exclusions - We do not provide a DefinitelyTyped version of these definitions at this time diff --git a/UPGRADE_GUIDE.md b/UPGRADE_GUIDE.md index 3c8b9755c..1f94c7705 100644 --- a/UPGRADE_GUIDE.md +++ b/UPGRADE_GUIDE.md @@ -16,6 +16,10 @@ Use the following guide to assist in the upgrade process of the `easypost-node` - [Response Objects Are Now Plain JSON Objects](#90-response-objects-are-now-plain-json-objects) - [HTTP Transport Migrated to Fetch](#90-http-transport-migrated-to-fetch) +### 9.0 Low Impact Changes + +- [Type Declarations Are Source-Generated](#90-type-declarations-are-source-generated) + ### 9.0 Response Objects Are Now Plain JSON Objects Likelihood of Impact: **High** @@ -67,6 +71,13 @@ const client = new EasyPostClient('api_key', { await client.makeApiCall('delete', '/trackers/trk_123'); ``` +### 9.0 Type Declarations Are Source-Generated + +Likelihood of Impact: **Low** + +Type declarations are generated from source and published from `dist/types`. +Package-root imports are unchanged. If you were importing internal files from the old root `types/` folder, migrate to package-root imports. + ## Upgrading from 7.x to 8.0 ### 8.0 High Impact Changes diff --git a/dev-docs/TS_MIGRATION_EXECUTION_BOARD.md b/dev-docs/TS_MIGRATION_EXECUTION_BOARD.md deleted file mode 100644 index 9ec8ca0eb..000000000 --- a/dev-docs/TS_MIGRATION_EXECUTION_BOARD.md +++ /dev/null @@ -1,381 +0,0 @@ -# EasyPost Node TS Migration Execution Board - -## Goal - -Execute the JS-to-TS migration as one native GitHub stack of dependent pull requests: - -- No integration branch -- No manual merge choreography outside stack semantics -- Each PR targets the branch below it -- Backwards compatible runtime behavior -- Permissive type behavior for SDK consumers - -This board is the operational companion to `TS_MIGRATION_PLAN.md`. - -## GitHub Stacks Reference Model - -Based on GitHub stacked pull requests docs: - -- Bottom PR targets trunk (`master`). -- Every next PR targets the branch below. -- Stack-aware CI/rules apply across layers. -- Rebase and retargeting are handled by stack workflows. -- To land all migration layers together, merge from the top PR (or stack-merge up to top). - -Notes: - -- If only a lower PR is merged, upper PRs remain open and are re-targeted/rebased. -- We will not use a temporary integration branch. - -## Operating Model - -### Tooling - -- GitHub CLI 2.90.0+ and Git 2.20+ -- `gh extension install github/gh-stack` - -Primary commands: - -- `gh stack init` -- `gh stack add` -- `gh stack submit` -- `gh stack sync` -- `gh stack view` - -Draft-first PR command behavior: - -- Use `gh stack submit --auto` to create new stack PRs as drafts by default. -- Use `gh stack submit --open` only when a layer (or the whole stack) is ready for review. - -### Stack Initialization - -1. Start from clean `master`. -2. Initialize migration stack: - - `gh stack init ts-migrate/00-baseline-safety-net` -3. Add each next branch at top with: - - `gh stack add ts-migrate/` -4. Commit layer-specific changes on each branch. -5. Submit/update full stack with: - - `gh stack submit --auto` -6. Keep stack current with: - - `gh stack sync` - -### Merge Policy - -- We will not run merges directly from this execution process. -- Review/approval happens per layer. -- When repository maintainers are ready to land everything, they merge the top migration PR (or equivalent stack merge operation to top). -- New PRs should remain draft until a layer passes its required checks. - -### PR Size Targets - -- Preferred: 150-500 changed lines per PR. -- Hard cap: 800 changed lines unless it is mechanical rename-only work. -- If a PR exceeds cap, split by module boundary into an additional stack layer. - -### Definition of Safe for Every PR - -- Runtime behavior unchanged unless explicitly approved. -- Existing tests pass. -- Node compatibility is not regressed. -- Public API shape remains unchanged. - -## Type-Integration Policy (When We Move Beyond Rename-Only) - -Rename-only conversion is an allowed bootstrap for early foundation layers, not the end-state. - -Policy by phase: - -- TSM-00 through TSM-05: - - mechanical JS->TS conversion is allowed to unblock stack progress - - temporary `@ts-nocheck` is allowed only on files first entering TS -- TSM-06 through TSM-10 (services): - - begin real type integration in every touched file - - no new `@ts-nocheck` allowed - - remove `@ts-nocheck` from files touched in the PR unless explicitly listed as deferred -- TSM-11 through TSM-15 (models): - - continue type integration and remove remaining `@ts-nocheck` in converted model/service files - - treat internal helper/model boundaries as typed seams (prefer `unknown` + narrowing over `any`) -- TSM-90 through TSM-91: - - zero `@ts-nocheck` under `src/` - - migration exceptions removed or justified with explicit follow-up - -Minimum typed-code requirements for TSM-06+ PRs: - -- exported class methods have explicit parameter and return types -- newly introduced `any` is disallowed unless justified inline -- API response boundaries should default to `unknown` and be narrowed where used - -Deferred typing (if needed in a layer) must be explicit: - -- add a short "Deferred Typing" section in the PR body -- list exact file/symbol and why it is deferred -- include the planned catch-up layer (same branch family if possible) - -## Single Stack Topology - -All branches are in one stack and must remain in this order. - -1. `ts-migrate/00-baseline-safety-net` -2. `ts-migrate/01-ts-build-scaffolding` -3. `ts-migrate/02-package-export-readiness` -4. `ts-migrate/03-type-strategy-guardrails` -5. `ts-migrate/04-core-entry-shared-infra` -6. `ts-migrate/05-base-service-hydration` -7. `ts-migrate/06-services-group-a` -8. `ts-migrate/07-services-group-b` -9. `ts-migrate/08-services-group-c` -10. `ts-migrate/09-services-group-d` -11. `ts-migrate/10-services-group-e` -12. `ts-migrate/11-models-group-a` -13. `ts-migrate/12-models-group-b` -14. `ts-migrate/13-models-group-c` -15. `ts-migrate/14-models-group-d` -16. `ts-migrate/15-models-group-e` -17. `ts-migrate/90-cutover-generated-types` -18. `ts-migrate/91-cleanup-calibration` - -## Detailed PR Board - -| PR ID | Branch | Base Branch | Scope | Est. Effort | Required Checks | -| ------ | ---------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------ | ----------- | ------------------------------------------- | -| TSM-00 | `ts-migrate/00-baseline-safety-net` | `master` | baseline scripts, API surface snapshot, migration checklist wiring | S | build, test, lint, types, node-compat smoke | -| TSM-01 | `ts-migrate/01-ts-build-scaffolding` | `ts-migrate/00-baseline-safety-net` | tsconfig split, mixed JS/TS compile setup, lint parser readiness | M | build, test, lint, types | -| TSM-02 | `ts-migrate/02-package-export-readiness` | `ts-migrate/01-ts-build-scaffolding` | package metadata prep, consumer import compatibility tests | S | build, test, package smoke | -| TSM-03 | `ts-migrate/03-type-strategy-guardrails` | `ts-migrate/02-package-export-readiness` | permissive TS policy doc + type tests for compatibility | S | types, test | -| TSM-04 | `ts-migrate/04-core-entry-shared-infra` | `ts-migrate/03-type-strategy-guardrails` | convert core entry/shared files to TS with behavior parity | M | build, test, lint, types | -| TSM-05 | `ts-migrate/05-base-service-hydration` | `ts-migrate/04-core-entry-shared-infra` | convert base service + dynamic hydration layer | M | build, test, types, targeted service tests | -| TSM-06 | `ts-migrate/06-services-group-a` | `ts-migrate/05-base-service-hydration` | convert Group A services + immediate deps | M | group tests, build, types | -| TSM-07 | `ts-migrate/07-services-group-b` | `ts-migrate/06-services-group-a` | convert Group B services + immediate deps | M | group tests, build, types | -| TSM-08 | `ts-migrate/08-services-group-c` | `ts-migrate/07-services-group-b` | convert Group C services + immediate deps | M | group tests, build, types | -| TSM-09 | `ts-migrate/09-services-group-d` | `ts-migrate/08-services-group-c` | convert Group D services + immediate deps | M | group tests, build, types | -| TSM-10 | `ts-migrate/10-services-group-e` | `ts-migrate/09-services-group-d` | convert Group E services + immediate deps | M | group tests, build, types | -| TSM-11 | `ts-migrate/11-models-group-a` | `ts-migrate/10-services-group-e` | convert remaining Group A models | S-M | group tests, build, types | -| TSM-12 | `ts-migrate/12-models-group-b` | `ts-migrate/11-models-group-a` | convert remaining Group B models | S-M | group tests, build, types | -| TSM-13 | `ts-migrate/13-models-group-c` | `ts-migrate/12-models-group-b` | convert remaining Group C models | S-M | group tests, build, types | -| TSM-14 | `ts-migrate/14-models-group-d` | `ts-migrate/13-models-group-c` | convert remaining Group D models | S-M | group tests, build, types | -| TSM-15 | `ts-migrate/15-models-group-e` | `ts-migrate/14-models-group-d` | convert remaining Group E models | S-M | group tests, build, types | -| TSM-90 | `ts-migrate/90-cutover-generated-types` | `ts-migrate/15-models-group-e` | generated declarations from src, remove `types/`, metadata switch | M-L | full CI, package smoke, TS demo compile | -| TSM-91 | `ts-migrate/91-cleanup-calibration` | `ts-migrate/90-cutover-generated-types` | remove migration-only exceptions, docs cleanup, final polish | S-M | full CI | - -## Scope Group Definitions - -Group A: - -- Address, Parcel, Customs, Shipment - -Group B: - -- Batch, Order, Pickup, Rate, SmartRate, ScanForm, Refund - -Group C: - -- CarrierAccount, CarrierType, CarrierMetadata, Billing - -Group D: - -- Tracker, Event, Webhook, Insurance, Claim - -Group E: - -- User, ApiKey, Referral/CustomerPortal, EndShipper, Embeddable, Luma, FedExRegistration - -## File Ownership Boundaries Per Layer - -Each layer must only edit files in its declared scope plus minimal shared typing/config glue needed to compile. - -Foundation layers (TSM-00 through TSM-05) can edit: - -- `package.json` -- `tsconfig*.json` -- `.eslintrc` -- `.github/workflows/ci.yml` -- core runtime files (`src/easypost.*`, `src/constants.*`, base utilities, base service/model primitives) - -Service/model layers (TSM-06 through TSM-15): - -- only module-group service/model files -- related tests for those modules -- minimal local imports/types required by those modules - -Cutover layers (TSM-90 through TSM-91): - -- `types/` deletion and declaration wiring -- docs updates -- removal of migration scaffolding - -## Agent Collaboration Model (Parallel Research, Serial Landing) - -Multiple agents are still useful with a single stack: - -- Stack Maintainer: - - owns branch creation, stack submit/sync, and final PR descriptions -- Worker Agents: - - prepare patch proposals for upcoming layers - - run focused verification on their slice - - hand off patch sets to stack maintainer - -Landing policy: - -- Exactly one active landing branch at a time (current top of stack). -- Accepted worker patches are applied in stack order. -- No separate integration branch. - -## Required Validation Matrix by Stage - -### Foundation Layers - -Run: - -- `npm run build` -- `npm run test` -- `npm run lint` -- `npm run typescript` - -### Service/Model Layers - -Run: - -- `npm run build` -- `npm run test` (targeted subset allowed for per-layer iteration) -- `npm run typescript` - -Additional hardening checks for TSM-06 through TSM-15: - -- `rg "@ts-nocheck" src` must trend downward each layer and never increase -- `rg "\bany\b" src/` results reviewed in PR notes when non-zero - -### Cutover Layers - -Run: - -- `npm run clean && npm run build` -- `npm run test` -- `npm run lint` -- `npm run typescript` -- package smoke install/consume tests for CJS, ESM, TS demo - -## Stack Coordination Playbook - -1. Initialize stack and create TSM-00 branch. -2. Create each next branch with `gh stack add` in strict order. -3. Commit one logical unit per branch layer. -4. Submit/update PR chain with `gh stack submit --auto` (draft by default). -5. Keep stack rebased and synchronized with `gh stack sync`. -6. Review each layer in GitHub stack map. -7. Land entire migration by merging top PR when approved. - -## Post-Migration Cleanup (Expected) - -After TSM-91 and a stabilization period, clean up migration-only scaffolding. - -Likely cleanup candidates: - -- Consolidate migration-specific TypeScript scripts in `package.json`. -- Collapse temporary multi-tsconfig setup if fewer files can represent the final workflow. -- Remove temporary lint overrides that were only needed during mixed JS/TS transition. -- Archive or remove migration process docs that are no longer active runbooks. -- Keep only durable compatibility tests; remove one-off transition tests. - -Cleanup acceptance criteria: - -- No loss of runtime behavior coverage. -- No loss of CJS/ESM import compatibility checks. -- No loss of permissive public type-surface regression coverage. - -## Typing Hardening Schedule for Completed Work - -The first five layers are already landed/active as mostly mechanical conversion. Tightening starts now, not after step 16. - -Planned catch-up timing: - -- During TSM-06 through TSM-08: - - opportunistically remove `@ts-nocheck` in already-converted foundation files when those files are touched for service wiring - - prioritize `src/services/base_service.ts` and `src/easypost.ts` first because they influence many downstream modules -- During TSM-09 through TSM-11: - - complete remaining foundation-file `@ts-nocheck` removals - - add explicit method signatures and key object-shape aliases for hydration paths -- Before opening TSM-90: - - all foundation files converted in TSM-04/05 must be `@ts-nocheck` free - - any remaining permissive typing must be intentional and documented - -Required tracking in each TSM-06+ PR summary: - -- `@ts-nocheck` count in `src/` before/after -- deferred typing items carried forward (if any) -- quick note on where permissive typing remains intentional for SDK compatibility - -## Labeling - -Recommended labels: - -- `ts-migration` -- `stacked-pr` -- `compatibility-critical` -- `permissive-types` -- `tsm-00` ... `tsm-91` - -## PR Summary Standards - -Do not leave the pull request template text in place. - -For each stacked PR, replace the template with a concise, PR-specific summary: - -- 1 short paragraph describing what changed in this layer. -- 3-6 bullets listing concrete file/scope changes. -- a short testing section with exact commands run. - -Keep PR summaries brief and communicative: - -- avoid long narrative prose. -- avoid repeating migration context from other docs. -- link to stack PR numbers only when needed for dependency context. - -Suggested title pattern: - -- `TSM-XX: ` - -Suggested body shape: - -- `Summary` -- `Changes in this PR` -- `Testing` -- `Stack Context` (optional, one line) - -## Risk Register - -| Risk | Likelihood | Impact | Mitigation | -| ------------------------------------------------ | ---------- | ------ | ----------------------------------------------------- | -| Hidden runtime behavior drift during conversion | Medium | High | no-refactor rule, baseline snapshots, test parity | -| Type tightening causes consumer compile failures | Medium | High | permissive guardrails, type tests, widen by default | -| Branch drift within stack | Medium | High | frequent `gh stack sync`, single maintainer ownership | -| Declaration output path mistakes at cutover | Medium | High | package smoke tests + TS demo compile | -| CI duration growth slows review loop | Medium | Medium | targeted checks per layer + full checks at cutover | - -## Cutover Gate Checklist (Must Be Green Before TSM-90 Merge) - -- [ ] Layers TSM-00 through TSM-15 are complete and green -- [ ] No remaining `.js` source in `src/` -- [ ] Declarations generated from TS source successfully -- [ ] `types/` no longer required by any script/workflow -- [ ] package consume tests pass for CJS/ESM/TS users - -## Release Readiness Checklist (Before Landing Top PR) - -- [ ] Changelog entry drafted for migration internals and no expected runtime break -- [ ] README updated to reflect TS-source-generated declarations -- [ ] UPGRADE_GUIDE updated if any type-level behavior requires note -- [ ] Post-merge monitoring owner assigned - -## Suggested Execution Cadence - -- Foundation phase: one layer per day -- Conversion phase: one to two layers per day depending on churn -- Cutover phase: one focused layer per day -- Rebase/sync window: at least twice daily - -## Optional Automation Helpers - -- Script to verify layer ownership boundaries by glob before CI. -- Script to compare exported key lists against baseline snapshots. -- Script to ensure no `types/` imports remain after cutover. diff --git a/dev-docs/TS_MIGRATION_PLAN.md b/dev-docs/TS_MIGRATION_PLAN.md deleted file mode 100644 index 0fc96d7f5..000000000 --- a/dev-docs/TS_MIGRATION_PLAN.md +++ /dev/null @@ -1,457 +0,0 @@ -# EasyPost Node JS->TS Migration Plan - -## Purpose - -Migrate the codebase from JavaScript source + separate declaration files to TypeScript source while: - -- Preserving runtime behavior and public API compatibility. -- Preserving permissive typing philosophy for SDK consumers. -- Removing the standalone `types/` source-of-truth by the end of migration. -- Delivering work as small, reviewable native GitHub stacked pull requests. - -Execution details for branch naming, stack workflow, and PR ordering are documented in `TS_MIGRATION_EXECUTION_BOARD.md`. - -## Current State Summary - -- Runtime source is JavaScript under `src/`. -- Types are maintained separately under `types/` and published via package exports. -- Build is Vite-based and emits both CJS and ESM artifacts. -- CI includes build, node compatibility, tests, lint, coverage, and a TypeScript check for declaration files. - -Implication: the repo currently has dual maintenance burden (runtime JS + parallel type declarations). - -## GitHub Stacks Adoption Model - -This migration uses GitHub native stacked pull requests (public preview) and the `gh stack` CLI extension. - -- Bottom PR targets trunk (`master`). -- Every higher PR targets the branch directly below it. -- No integration branch is used. -- The stack is managed as one dependency chain. -- Rebase/sync is handled with stack-aware workflows (`gh stack sync` / `gh stack rebase`). - -Merge behavior alignment: - -- If the goal is to land the entire migration stack in one action, merge from the top PR (or use stack merge up to top). -- Pull requests still merge bottom-up logically as part of the stack operation. -- If only a lower PR is merged, higher PRs stay open and are automatically re-targeted/rebased by stack mechanics. - -## Migration Principles - -### Backwards Compatibility - -- Keep package name, import paths, exports, and runtime object/service behavior unchanged. -- Keep CJS + ESM outputs and file names (`dist/easypost.js` and `dist/easypost.mjs`). -- Avoid introducing runtime validation that rejects currently accepted input unless explicitly approved as breaking. -- Preserve support matrix for Node versions currently validated in CI. -- Keep public method names, parameter ordering, and return semantics stable. -- Keep all test assertions and code the same, they serve as the source of truth the migration worked properly. - -### Permissive Type Philosophy - -- Maintain broad input and extension points where API payloads are variable. -- Prefer `unknown` over `any` by default at boundaries, but allow targeted `any` escape hatches where required for compatibility/extensibility. -- Use optional fields and index signatures for dynamic API object shapes. -- Strongly type stable contracts (service names, IDs, known envelopes) while leaving long-tail API fields permissive. -- Minimize consumer breakage from stricter typing; widen instead of narrowing when in doubt. - -### Delivery and Risk - -- Use one stacked PR chain with small, independent review scope per layer. -- Keep each PR behavior-preserving and green in CI. -- Defer broad refactors until after full TS compilation parity is established. -- Avoid side branches that bypass stack ordering. -- Open stack PRs as drafts by default and mark ready only after layer checks pass. -- Replace PR template boilerplate with concise PR-specific summaries for each layer. - -## Target End State - -- `src/` fully migrated to `.ts` (and `.mts`/`.cts` only if needed). -- Type declarations generated from TypeScript source during build (`dist/*.d.ts` and maps as needed). -- `types/` directory removed from source control. -- `package.json` `types`/`exports.types` point to generated declaration output in `dist`. -- CI validates TS source compilation and type generation directly from runtime source. - -## Non-Goals - -- No intentional API redesign. -- No large behavioral refactors bundled with migration. -- No strict domain modeling of every API field if that harms permissiveness or compatibility. - -## High-Level Workstreams - -1. Tooling + build pipeline modernization for TS source support. -2. Type strategy + compatibility policy implementation. -3. Incremental source conversion (`src/` modules). -4. Test and CI adaptation. -5. Packaging/export transition from `types/` to generated declarations. -6. Cleanup and stabilization. - -## Stacked PR Plan (Small Chunks) - -The following plan is implemented as one ordered GitHub stack. Each PR is a layer in the same chain. - -Operational note: use `gh stack submit --auto` during creation/updates so new stack PRs open as drafts by default. - -### PR 0 - Baseline Safety Net and Telemetry - -Scope: - -- Add migration tracking doc/checklist references. -- Capture baseline behavior snapshots: - - test pass status - - node compatibility pass status - - package surface snapshot (`exports`, `main`, `module`, `types`) -- Add lightweight API-surface verification script (public entry shape smoke check). - -Acceptance criteria: - -- Existing CI remains green. -- Baseline artifacts/scripts available and documented. - -### PR 1 - TS Build Scaffolding (No Source Conversion Yet) - -Scope: - -- Introduce migration `tsconfig` layout for source compilation: - - `tsconfig.base.json` - - `tsconfig.build.json` - - `tsconfig.test.json` (if needed) -- Configure compiler options for permissive migration: - - `allowJs: true` (initially) - - `checkJs: false` (initially) - - `declaration: true` - - `emitDeclarationOnly: false` (or split with declaration emit config) - - conservative strictness profile with targeted opt-outs where needed -- Update lint/parser setup to handle mixed JS/TS source during transition. -- Keep current outputs intact. - -Acceptance criteria: - -- Build succeeds with mixed JS/TS inputs. -- No runtime output changes. -- CI still green. - -### PR 2 - Package/Export Readiness for Generated Types - -Scope: - -- Prepare package metadata for eventual generated declarations in `dist`. -- Keep current `types/` wiring active until cutover PR. -- Add compatibility tests for CJS and ESM import paths. - -Acceptance criteria: - -- No consumer-visible export change yet. -- Compatibility tests pass. - -### PR 3 - Type Philosophy and Guardrails - -Scope: - -- Add `TYPE_STRATEGY.md` (or section in this plan) codifying permissive TS rules: - - when to use `unknown` vs `any` - - allowable index signatures - - widening rules for public API params - - how to represent dynamic API payloads -- Add type tests for representative consumer usage: - - permissive request payloads - - hook middleware flexibility - - common JS-like TS usage patterns - -Acceptance criteria: - -- Type tests pass. -- Rules documented and enforced in review checklist. - -### PR 4 - Convert Core Entry and Shared Infrastructure - -Scope: - -- Convert entrypoint and shared core files first: - - `src/easypost.js` - - `src/constants.js` - - shared utility modules - - core error handler plumbing -- Preserve dynamic behavior in conversion (no logic rewrite). -- Add minimal internal types/interfaces for request/response hooks. - -Acceptance criteria: - -- Runtime tests unchanged and passing. -- Generated declarations for converted modules are correct. -- No public API breaks. - -### PR 5 - Convert Base Service + Dynamic Hydration Layer - -Scope: - -- Convert `src/services/base_service.js` and closely related model base files. -- Model dynamic object hydration using permissive patterns: - - discriminated known keys where stable - - fallback index signatures for unknown object members -- Keep ID-prefix and object-name mapping behavior identical. - -Acceptance criteria: - -- Existing service tests pass unchanged. -- Type signatures remain permissive for dynamic payloads. - -### PR 6-10 - Service Group Conversion Layers - -Scope: - -- Split service conversion into five sequential stack layers: - - PR6 Group A: Address, Parcel, Customs, Shipment - - PR7 Group B: Batch, Order, Pickup, Rate, SmartRate, ScanForm, Refund - - PR8 Group C: CarrierAccount, CarrierType, CarrierMetadata, Billing - - PR9 Group D: Tracker, Event, Webhook, Insurance, Claim - - PR10 Group E: User, ApiKey, Referral/CustomerPortal, EndShipper, Embeddable, Luma, FedExRegistration -- Convert service files and immediate model dependencies only. -- Keep method signatures and behavior stable. - -Acceptance criteria per layer: - -- Layer-level tests pass. -- No regressions in API behavior. -- Declaration output generated from TS for converted modules. - -### PR 11-15 - Model Group Conversion Layers - -Scope: - -- Convert remaining model classes in five sequential layers aligned to Groups A-E. -- Preserve open object shapes and helper methods. -- Keep serialization/deserialization semantics unchanged. - -Acceptance criteria per layer: - -- Model tests and service integration tests pass. -- No runtime shape regressions. - -### PR 90 - Remove Standalone `types/` Source - -Scope: - -- Replace `types/` declaration source with generated declarations from `src/`. -- Remove `types/` from repo. -- Update package metadata: - - `types` path -> `dist/...d.ts` - - `exports["."].types` -> generated path -- Update CI to compile/check generated declarations from source. - -Acceptance criteria: - -- Consumer TS demo/tests pass against generated declarations. -- `types/` directory no longer required. -- Package pack/install smoke tests pass. - -### PR 91 - Strictness Calibration + Cleanup - -Scope: - -- Remove migration-only tsconfig/lint exceptions no longer needed. -- Keep intentional permissive points documented. -- Clean dead code, stale comments, and temporary migration scripts. - -Acceptance criteria: - -- CI fully green. -- Migration checklist complete. - -## Suggested Stack Graph - -```mermaid -graph TD - PR0[PR0 Baseline Safety Net] - PR1[PR1 TS Build Scaffolding] - PR2[PR2 Package Export Readiness] - PR3[PR3 Type Philosophy Guardrails] - PR4[PR4 Core Entry and Shared Infra] - PR5[PR5 Base Service Dynamic Hydration] - PR6[PR6 Services Group A] - PR7[PR7 Services Group B] - PR8[PR8 Services Group C] - PR9[PR9 Services Group D] - PR10[PR10 Services Group E] - PR11[PR11 Models Group A] - PR12[PR12 Models Group B] - PR13[PR13 Models Group C] - PR14[PR14 Models Group D] - PR15[PR15 Models Group E] - PR90[PR90 Remove types dir] - PR91[PR91 Cleanup] - - PR0 --> PR1 --> PR2 --> PR3 --> PR4 --> PR5 --> PR6 --> PR7 --> PR8 --> PR9 --> PR10 --> PR11 --> PR12 --> PR13 --> PR14 --> PR15 --> PR90 --> PR91 -``` - -## Detailed Change Inventory - -### 1) Source File Extension Changes - -- Rename `src/**/*.js` -> `src/**/*.ts` in batches. -- Update all relative imports to extensionless or TS-compatible resolution strategy consistent with build. -- Ensure generated `dist` file names remain unchanged. - -### 2) Build and Compiler - -- Introduce source-compilation tsconfig for `src/`. -- Generate declarations from source into `dist` (or intermediate + copy to dist). -- Keep Vite bundling behavior for CJS/ESM output parity. -- Add/adjust source map configuration parity. - -### 3) Lint and Formatting - -- Ensure ESLint parser/plugin config supports mixed mode then TS-only mode. -- Add rules to avoid accidental over-tightening of public API types. - -### 4) Package Metadata - -- Update `types` and `exports.types` paths to generated declarations. -- Ensure `files`/publish inclusion includes declaration outputs and excludes old `types/` source. - -### 5) CI Workflows - -- Replace declaration-only check with TS source compile + type generation checks. -- Keep node compatibility matrix unchanged. -- Add package smoke test for CJS/ESM/TS consumer install. - -### 6) Tests - -- Keep runtime unit/integration tests unchanged where possible. -- Add type-level consumer tests: - - permissive object payload acceptance - - middleware hook typing flexibility - - common endpoint return value usage - -### 7) Documentation - -- Update README and upgrade guide sections to reflect: - - types are generated from TS source - - permissive type guarantees - - any known typing caveats -- Add migration note for contributors (how to author permissive TS in this repo). - -### 8) Repo Cleanup - -- Remove `types/` directory after cutover. -- Remove obsolete scripts/config specific to old declaration maintenance. -- Verify docs generation still works with `.ts` inputs or update docs tooling config. - -## Compatibility Contract Checklist (Must Pass Before Final Cutover) - -- Public exports unchanged (`import`/`require` behavior). -- Public class/service names unchanged. -- Public method signatures behavior-compatible. -- Runtime response object behavior unchanged (including dynamic fields). -- Node compatibility matrix green. -- Existing tests green. -- TS consumer demo compiles using generated declarations. -- No mandatory code changes for existing JS consumers. - -## Permissive Typing Rules (Concrete) - -Use these defaults unless there is strong evidence a narrower type is needed: - -- Request payload inputs: - - `Record` for open payloads. - - Optional known fields plus index signature for endpoint-specific extras. -- API response objects: - - Known top-level fields typed. - - Additional dynamic properties via `[key: string]: unknown`. -- Middleware/hooks: - - Flexible request/response object interfaces with extensible fields. -- IDs and enums: - - Keep stable ID prefixes and known literal unions where non-breaking. - - Prefer `string` over narrow unions when providers may introduce new values. -- Escape hatches: - - Allow local `any` with comments for compatibility-critical dynamic points. - -## Multi-Agent Execution Plan - -Multiple agents can still help, but stack landing is serialized by design. - -Recommended model: - -1. One stack maintainer agent/person owns branch creation, `gh stack submit`, and `gh stack sync`. -2. Contributor agents prepare patches for upcoming layers against the current top branch tip. -3. Maintainer applies accepted patches in order, one stack layer per PR. -4. Reviewers approve each layer independently in GitHub stack UI. - -Coordination rules: - -- Each PR must include: - - scope statement - - compatibility checklist results - - test evidence - - risk notes -- No integration branch. -- No out-of-order branch creation. - -## PR Template Additions (Recommended) - -For each stacked PR, require: - -- What changed (module list) -- Why safe (compatibility notes) -- Type permissiveness notes (what remained intentionally broad) -- Test evidence (runtime + type) -- Follow-up tasks left for next stack layer - -## Rollback Strategy - -- Because PRs are small and stacked, rollback by reverting from the highest merged layer downward as needed. -- Keep behavior snapshots from PR0 for quick diff-based validation. -- If type breakage appears in consumers, widen types in the nearest layer without runtime changes. - -## Definition of Done - -Migration is complete when: - -- All runtime source under `src/` is TypeScript. -- Declarations are generated from source and published from `dist`. -- `types/` directory is removed. -- Compatibility checklist is fully green. -- Documentation and contributor guidance are updated. -- Stack is fully merged with no unresolved compatibility regressions. - -## Post-Migration Cleanup (Expected) - -Once the migration is complete and stable, evaluate and remove transitional scaffolding that is no longer needed. - -Likely cleanup candidates: - -- Consolidate TypeScript scripts in `package.json` if split commands are no longer necessary. -- Consolidate `tsconfig` files if build/test/type-checking can be expressed with fewer configs. -- Remove temporary migration-only lint exceptions once TypeScript source is the default. -- Re-evaluate migration-only compatibility tests and keep only long-term contract tests. -- Remove migration planning boilerplate from active contributor workflows after rollout. - -Keep long-term: - -- Runtime CJS/ESM compatibility tests. -- Type compatibility tests that protect permissive public SDK behavior. -- Any config explicitly required for dual-module packaging stability. - -## Execution Checklist - -- [ ] PR0 baseline and API surface snapshot -- [ ] PR1 TS scaffolding for mixed-mode build -- [ ] PR2 package/export readiness -- [ ] PR3 permissive typing policy and type tests -- [ ] PR4 core entry + shared infra conversion -- [ ] PR5 base service + hydration conversion -- [ ] PR6 services group A conversion -- [ ] PR7 services group B conversion -- [ ] PR8 services group C conversion -- [ ] PR9 services group D conversion -- [ ] PR10 services group E conversion -- [ ] PR11 models group A conversion -- [ ] PR12 models group B conversion -- [ ] PR13 models group C conversion -- [ ] PR14 models group D conversion -- [ ] PR15 models group E conversion -- [ ] PR90 remove `types/`, switch to generated declarations -- [ ] PR91 cleanup and strictness calibration -- [ ] README/UPGRADE docs updated -- [ ] final package smoke tests for CJS/ESM/TS consumers diff --git a/dev-docs/TYPE_STRATEGY.md b/dev-docs/TYPE_STRATEGY.md deleted file mode 100644 index abd81db98..000000000 --- a/dev-docs/TYPE_STRATEGY.md +++ /dev/null @@ -1,56 +0,0 @@ -# Type Strategy (Permissive-First) - -## Goal - -As the source migrates from JavaScript to TypeScript, keep the SDK permissive and backwards-compatible for consumers while improving maintainability for contributors. - -## Core Rules - -1. Prefer permissive API boundaries. - -- Request payloads should allow extension fields. -- Response objects should model known fields and allow unknown extras. - -1. Prefer `unknown` over `any` by default. - -- Use `unknown` for data that must be narrowed before use. -- Use `any` only at compatibility-critical dynamic seams (middleware adapters, opaque third-party objects), with a short justification comment. - -1. Widen rather than narrow when uncertain. - -- If a strict type risks breaking existing consumers, choose the wider compatible type in migration PRs. -- Track stricter candidates as follow-up work, not migration blockers. - -1. Keep runtime behavior unchanged. - -- No new runtime schema enforcement during migration. -- Typing changes must not alter accepted payloads or returned object shapes. - -## Recommended Patterns - -1. Input payloads - -- Use known optional fields plus an index signature for open-ended payloads. -- Use `Record` for opaque payload passthroughs. - -1. Output payloads - -- Type stable fields explicitly. -- Add `[key: string]: unknown` for provider-specific or future fields. - -1. Middleware and hooks - -- Keep callback inputs broad enough for current and future adapters. -- Preserve pass-through support for wrapper libraries. - -1. Enums and literals - -- Avoid over-constraining values that may expand server-side. -- Prefer `string` where provider values are not contractually closed. - -## Review Checklist - -- Does this type change preserve existing consumer call patterns? -- Does it avoid rejecting currently valid payloads? -- Is any `any` usage localized and justified? -- Are dynamic fields still representable without unsafe casts at call sites?