Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
db3fe9f
feat(sdk): add the pristine store behind custom code
asadali214 Oct 20, 2026
185e066
feat(sdk): merge regenerated SDKs through the system git
asadali214 Oct 20, 2026
4d5b9cc
feat(sdk): keep your edits when regenerating an SDK
asadali214 Oct 20, 2026
8745391
feat(sdk): mark conflicts in git's index and explain a missing snapshot
asadali214 Oct 20, 2026
d857ea4
docs(sdk): record the custom-code design and how edits are kept
asadali214 Oct 20, 2026
fc026fb
docs(sdk): correct the undo command for the previous snapshot
asadali214 Oct 20, 2026
6ef3540
feat(sdk): name the customized files after a regeneration
asadali214 Oct 20, 2026
971195b
refactor(sdk): carry merge paths as RelativeFilePath
asadali214 Oct 20, 2026
a11166f
refactor(sdk): fold the merge service into the pristine store
asadali214 Oct 21, 2026
d39ea50
refactor(sdk): make the repository a context
asadali214 Oct 21, 2026
8e9e9bf
refactor(sdk): fold the merge layer into types and the git service
asadali214 Oct 21, 2026
8217ac5
feat(sdk): share snapshots through the remote
asadali214 Oct 21, 2026
270f6e8
refactor(sdk): keep the prompts to wording
asadali214 Oct 21, 2026
3596340
refactor(sdk): move the git types to src/types/git
asadali214 Oct 21, 2026
0fa08d3
refactor(sdk): keep the closing text with the prompts
asadali214 Oct 21, 2026
c2dd9f2
fix(sdk): keep the custom-code messages short and free of internals
asadali214 Oct 21, 2026
e1dd8d6
feat(sdk)!: remove --zip from sdk generate
asadali214 Oct 21, 2026
7c181df
feat(sdk): share snapshots with a pre-push hook instead of pushing fr…
asadali214 Oct 22, 2026
07c03c1
feat(sdk): ask what to do when a regeneration conflicts
asadali214 Oct 22, 2026
5679d46
docs(plan): record phase 9's commit
asadali214 Oct 22, 2026
9547c4e
refactor(sdk): fold the generate run into one action, with a silent core
asadali214 Oct 22, 2026
7774f85
test(sdk): make the clone and path tests pass on every runner
asadali214 Oct 23, 2026
f202faf
fix(sdk): find unresolved conflicts in git's index, not in marker text
asadali214 Oct 23, 2026
7ad6d3b
refactor(sdk): hand the prompts to the steps as delegates
asadali214 Oct 23, 2026
f955046
refactor(sdk): move the download into its own step, and let the actio…
asadali214 Oct 23, 2026
43ce5ab
fix(sdk): share the snapshot of an SDK at the repository root
asadali214 Oct 23, 2026
603567b
feat(sdk): resolve conflicts with your own changes, and drop the undo
asadali214 Oct 23, 2026
0ac2d07
fix(sdk): generate into --destination itself, so a clone of the SDK i…
asadali214 Oct 23, 2026
2d8d470
fix(sdk): merge the generation record as binary, so a pull never writ…
asadali214 Oct 23, 2026
f7b52fc
fix(sdk): remove before writing, and put the directory back when a wr…
asadali214 Oct 27, 2026
f174ea0
fix(sdk): keep your files when a conflict is settled for the generator
asadali214 Oct 27, 2026
e38b20b
fix(sdk): read every label git writes on a marker, and leave a half-r…
asadali214 Oct 27, 2026
697b628
fix(sdk): record any SDK path, keep every byte of a blob, and write f…
asadali214 Oct 27, 2026
19c50b6
feat(sdk)!: drop --api-version, and build every SDK from the project …
asadali214 Oct 27, 2026
68b933d
fix(sdk): refuse to write over an unmerged file, a merge in progress,…
asadali214 Oct 27, 2026
5cd5e1b
fix(sdk): settle a chosen side without merge-tree -X, and respect the…
asadali214 Oct 27, 2026
4d95a2f
fix(sdk): upload only the files git would commit, and preview the rea…
asadali214 Oct 27, 2026
3b310dd
docs(plan): bring the custom-code plan up to date with the review fol…
asadali214 Oct 27, 2026
98274ac
fix(sdk): say what --force, a merged file, a lost record, a mismatch …
asadali214 Oct 27, 2026
7c98380
feat(sdk): ask before git init, refuse --force over a recorded SDK, s…
asadali214 Oct 27, 2026
1faabcd
refactor(sdk): make GitService answer with Results, and compose them …
asadali214 Oct 27, 2026
30c0ca1
refactor(sdk): split the repository context by concept, type the SDK …
asadali214 Oct 27, 2026
df0a848
refactor(sdk): make the action's phases private methods that speak th…
asadali214 Oct 27, 2026
c13edf0
refactor(sdk): drop dead code and duplicates, trim comments, place th…
asadali214 Oct 28, 2026
76555c1
refactor(sdk): answer with Promise<Result> everywhere, as the rest of…
asadali214 Oct 28, 2026
88aa107
refactor(sdk): speak every prompt from execute, and narrow the contex…
asadali214 Oct 28, 2026
a904c21
Merge remote-tracking branch 'origin/dev' into asadali214/custom-code…
asadali214 Oct 28, 2026
ec80468
fix(sdk): merge dev's build staging into the project context the bran…
asadali214 Oct 28, 2026
7fc46e6
refactor(sdk): zip the SDK by walking it and leaving out what git ign…
asadali214 Oct 28, 2026
c332ef4
refactor(sdk): keep src/types/sdk pure, and move the stores and git t…
asadali214 Oct 28, 2026
57cba38
refactor(sdk): one problem shape, per-method error unions, and no fro…
asadali214 Oct 28, 2026
b92bc2e
refactor(sdk): type the ids, remotes, refs and relative paths git han…
asadali214 Oct 28, 2026
ed2817d
refactor(sdk): read the repository's facts first, then decide them in…
asadali214 Oct 28, 2026
481b8c7
refactor(sdk)!: decide the run's write mode once, and refuse where a …
asadali214 Oct 28, 2026
8ff5ce6
refactor(sdk): let the core say what a record, a hook and a conflict …
asadali214 Oct 28, 2026
dd89d80
refactor(sdk): pure write rules, one merge parser, named git methods,…
asadali214 Oct 28, 2026
0ce7f8a
docs: regenerate the README for the SDK commands' --force help
asadali214 Oct 28, 2026
fe156eb
test(sdk): stub the archive through zipWithout, which the SDK upload …
asadali214 Oct 29, 2026
ed36c8c
refactor(sdk): camelCase the zip file local and drop the redundant is…
Shield-Jaguar Oct 29, 2026
4049ec2
feat(sdk): apply the product review of custom code
asadali214 Oct 29, 2026
999dd93
refactor: remove the functions nothing in src calls
asadali214 Oct 29, 2026
bf508e6
Merge remote-tracking branch 'origin/asadali214/custom-code-injection…
asadali214 Oct 29, 2026
60429e0
feat(sdk): let --force replace a recorded SDK it cannot merge into, w…
asadali214 Oct 29, 2026
4bafe2b
fix(sdk): ask before a save removes hidden files from the SDK directory
asadali214 Oct 29, 2026
230aa82
feat(sdk): end a run that leaves files to resolve as Conflicted
asadali214 Oct 29, 2026
b42a721
feat(sdk): end a run without a repository with the steps that keep edits
asadali214 Oct 29, 2026
93d2f39
feat(sdk): word the next steps without assuming the SDK will be edited
asadali214 Oct 30, 2026
f0db7b2
feat(sdk): name the yellow end state Action required
asadali214 Oct 30, 2026
5ea4e40
feat(sdk): look for git only when the SDK directory has a repository …
asadali214 Oct 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .ai/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Supporting: **Types** (`src/types/`) for value objects, context objects, and dom
- **No raw string paths** — use `DirectoryPath`, `FilePath`, `FileName`, `UrlPath` value objects from `src/types/file/`
- **No `console.log`** — all output through `@clack/prompts` via Prompts classes only
- **Error handling**: Services return `Result<T, ServiceError>` (neverthrow); Actions return `ActionResult<T>` (success/failed/cancelled). No uncaught throws above infrastructure.
- **Async `Result`s are `Promise<Result<T, E>>`** — an `async` method body that `await`s each step and returns early on `isErr()`. `ResultAsync`, `safeTry`, `okAsync` and `errAsync` are not used: a signature never names `ResultAsync`, and a caller `await`s a `Result` rather than chaining `andThen` on a promise. A throwing promise becomes a `Result` through `try`/`catch` around the `await`.
- **Prompts delegation** — Actions never call `log.*` directly; every message goes through `this.prompts.*`
- **Temp directories** — always use `withDirPath()` wrapper, never `tmp-promise` directly
- **`authKey` typed as `string | null = null`**, not `undefined`
Expand Down
622 changes: 622 additions & 0 deletions .ai/plans/custom-code.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .ai/skills/action.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Actions live at `src/actions/` and are the single use-case orchestrators for eac

- **DO** use named export: `export class {PascalName}Action`.
- **DO** use `public readonly execute = async (...): Promise<ActionResult> =>` (arrow function property).
- **DO** `await` each `Result` a context or service answers with and return early on `isErr()` — never chain `andThen` or `asyncAndThen` on a promise, and never import `ResultAsync`.
- **DO** initialize prompts as a field: `private readonly prompts = new {Name}Prompts()`.
- **DO** initialize services as `private readonly` fields (inline with `new`) when the service takes no constructor args. If a service needs `configDir`, declare without initializer and assign in the constructor body after `this.configDir` is set.
- **DO** use the full constructor pattern when the action calls an API: `constructor(configDir: DirectoryPath, commandMetadata: CommandMetadata, authKey: string | null = null)`.
Expand Down
1 change: 1 addition & 0 deletions .ai/skills/command.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ These three layers are always created together and mirror each other in path str
- **DO** use typed path objects (`DirectoryPath`, `FilePath`, `FileName`, `UrlPath`) instead of raw strings.
- **DO** use `ActionResult.success(value?)`, `ActionResult.failed(message?)`, or `ActionResult.cancelled()` as return values.
- **DO** use neverthrow `Result<T, E>` for service returns — check with `.isErr()` / `.isOk()`.
- **DO** type an async `Result` as `Promise<Result<T, E>>` and `await` it before checking — never `ResultAsync`, `safeTry`, `okAsync` or `errAsync`.

### General — DON'T

Expand Down
5 changes: 3 additions & 2 deletions .ai/skills/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Context objects live at `src/types/` and encapsulate path derivation, validation
- **DON'T** expose derived file names — methods like `getScriptFileName()` leak internal naming logic.
- **DON'T** add public properties for internal state — constructor parameters are `private readonly`, not exposed.
- **DON'T** use `console.log` or any prompt output — contexts are silent.
- **DON'T** use `Result<T, E>` for a plain file operation — return `boolean`, `undefined` or the value. A context returns a `Result` only when it does network I/O (rare) or reports a structured problem the prompts switch on, as `PortalSourceContext.resolve()` does with `PortalSourceProblem`.
- **DON'T** use `Result<T, E>` for a plain file operation — return `boolean`, `undefined` or the value. A context returns a `Result` only when it does network I/O (rare) or reports a structured problem the prompts switch on, as `PortalSourceContext.resolve()` does with `PortalSourceProblem`. An async one is `Promise<Result<T, E>>`, written with `await` and early returns — never `ResultAsync` or `safeTry`.
- **DON'T** use raw string paths — always wrap in `DirectoryPath`, `FilePath`, `FileName`.
- **DON'T** add methods that only use infrastructure services (`fileService`, `zipService`) without touching domain-specific private fields — these are stateless utilities, not context behavior. Every public method must use at least one constructor-derived private field (e.g., `sdkDirectory`, `language`). If a method takes all its inputs as parameters and never reads context state, it belongs in a service or a different context.
- **DON'T** embed the context's own domain subject in method names — if the class is `SdkContext`, a method named `cleanUpSdkDirectory()` is redundant. Prefer concise behavioral verbs: `cleanUp()`, `getChanges()`, `save()`.
Expand Down Expand Up @@ -69,6 +69,7 @@ Context objects live at `src/types/` and encapsulate path derivation, validation
- [ ] `directory.join("subdir")` for subdirectory derivation
- [ ] No `console.log`, no prompt output — contexts are silent
- [ ] `Result` only for network I/O or for a structured problem type the prompts switch on
- [ ] Async `Result`s are `Promise<Result<T, E>>` with `await` and early returns on `isErr()` — no `ResultAsync`, `safeTry`, `okAsync` or `errAsync`
- [ ] Every public method uses at least one domain-specific private field — methods using only infrastructure services don't belong here
- [ ] No public properties that expose constructor parameters
- [ ] Method names do not embed the context's own domain subject — names are concise behavioral verbs (`cleanUp()` not `cleanUpSdkReviewDirectory()`)
Expand All @@ -83,7 +84,7 @@ Context objects live at `src/types/` and encapsulate path derivation, validation
| Input context (validate + file ops) | `src/types/spec-context.ts` | Good — zip detection internal |
| Temp context (zip + save stream) | `src/types/temp-context.ts` | Good — UUID naming internal |
| Temp context (download + resolve) | `src/types/resource-context.ts` | Good — URL/file decision internal |
| Composite (delegates to other contexts) | `src/types/project-context.ts` | Good — hands back `PortalSourceContext`, `PluginConfigContext` and `SdkContext`; knows the layout so no caller joins `src` |
| Composite (delegates to other contexts) | `src/types/project-context.ts` | Good — hands back `PortalSourceContext` and `PluginConfigContext`, and derives the SDK directory; knows the layout so no caller joins `src` |
| Output context (leaky — avoid pattern) | `src/types/sdk-context.ts` | Avoid — exposes `sdkLanguageDirectory`, has methods that only use infrastructure services without touching domain state |
| Input context (validate + typed result) | `src/types/portal-source-context.ts` | Good — reports problems, exposes no paths |

Expand Down
3 changes: 3 additions & 0 deletions .ai/skills/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Services live at `src/infrastructure/services/` and are the only layer that make

- **DO** use named export: `export class {PascalName}Service`.
- **DO** return `Promise<Result<T, ServiceError>>` from all public methods — use `ok()` and `err()` from neverthrow.
- **DO** write the body as `async`/`await`: wrap the call in `try`/`catch`, `await` each step, and return `err(...)` early when a step `isErr()`.
- **DO** catch `ProblemDetailsError` first (for 400/403 with structured error messages), then fall back to `handleServiceError(error)`.
- **DO** close file streams in `finally` blocks when using `FileWrapper` or `getStream()`.
- **DO** resolve auth as: `getAuthInfo(configDir.toString())` → `createAuthorizationHeader()` → `apiClientFactory.createApiClient()`.
Expand All @@ -23,6 +24,7 @@ Services live at `src/infrastructure/services/` and are the only layer that make
### DON'T

- **DON'T** throw — always return `err(...)` wrapped in `ServiceError`.
- **DON'T** return or chain `ResultAsync` — no `ResultAsync`, `safeTry`, `okAsync` or `errAsync`; the return type is `Promise<Result<T, E>>` and a step is checked with `isErr()`, not composed with `andThen`.
- **DON'T** use `console.log` — services are silent; errors communicated via `Result`.
- **DON'T** use raw string paths — use `DirectoryPath`, `FilePath`, `UrlPath`, `FileName`.
- **DON'T** use `axios.create()` as a class field — create a fresh instance per call in `axiosInstance()` method.
Expand Down Expand Up @@ -58,6 +60,7 @@ Services live at `src/infrastructure/services/` and are the only layer that make
- [ ] File placed at `src/infrastructure/services/{name}-service.ts`
- [ ] Named export (not default): `export class {PascalName}Service`
- [ ] All public methods return `Promise<Result<T, ServiceError>>` using neverthrow
- [ ] No `ResultAsync`, `safeTry`, `okAsync` or `errAsync` — bodies `await` and return early on `isErr()`
- [ ] Uses `ok()` and `err()` from neverthrow — never throws
- [ ] Catch blocks use `handleServiceError(error)` as fallback
- [ ] Auth uses `getAuthInfo(configDir.toString())` — note `.toString()` on DirectoryPath
Expand Down
1 change: 1 addition & 0 deletions .ai/skills/value-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Value objects live at `src/types/file/` and wrap a single primitive (`string`, `
- **DO** have methods that produce derived values return rich types — a method extracting a leaf name returns `FileName`, not `string`.
- **DO** compose rich types through each other — `FilePath` holds `DirectoryPath` and `FileName` as objects; both are passed as objects in constructors and methods.
- **DO** use `static create()` returning `T | undefined` for construction from user input or external data that can fail validation.
- **DO** use `static fromGit()` returning `T | undefined` for a value git printed (an id, a path, a ref): it validates as `create()` does, and the service turns `undefined` into an `err`, never a throw.
- **DO** use `static createInput()` for the flag-value-to-rich-type pattern when a sensible fallback exists (e.g. `DirectoryPath.default`).
- **DO** use `static readonly` for well-known singleton instances (e.g., `DirectoryPath.default`).
- **DO** access the private field directly inside methods — write `this.directoryPath` not `this.toString()`.
Expand Down
18 changes: 18 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,21 @@ _Avoid_: Example name, variant
**Unplaced sample**:
A code sample whose endpoint no spec in the source directory declares.
_Avoid_: Orphan sample, missing operation

### SDK regeneration

**SDK directory**:
The directory `sdk generate` writes an SDK into, and reads back on every later run: the `--destination` itself when one is named, else `<input>/sdk/<language>`.
_Avoid_: Destination, output directory, language directory

**Pristine snapshot**:
One generation's output exactly as the server returned it, stored as a commit under the hidden ref `refs/apimatic/pristine` of the SDK directory's own repository, never on a branch; the base of the next merge.
_Avoid_: Generated snapshot, baseline, original

**Generation record**:
`<sdk>/.apimatic/generation.json`, committed with the SDK, naming the pristine snapshot the directory was last written from. Written with `.apimatic/.gitattributes` beside it, so git merges it as binary and GitHub collapses it in pull requests.
_Avoid_: Lock file, manifest, metadata file

**Custom code**:
Whatever differs between the SDK directory on disk and its pristine snapshot: the developer's edits, additions, deletions and moves, kept by merging the next generation over them.
_Avoid_: Customizations (in code), user changes, overrides
36 changes: 23 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ The official CLI for APIMatic.
Node.js 24 or newer, for every command. npm only warns when your Node is older, so the
install succeeds and the CLI then refuses to run, naming the version it found.

Git 2.38 or newer on your `PATH`, for `sdk generate` to keep your changes to a generated SDK
across regenerations.
Without it the command still generates, and warns that your customizations will not persist.

# Getting Started

To get started with APIMatic's CLI using a step by step wizard, run the following command:
Expand Down Expand Up @@ -407,37 +411,39 @@ Generate an SDK for your API

```
USAGE
$ apimatic sdk generate -l csharp|java|php|python|ruby|typescript|go [-d <value>] [--api-version <value>]
[--zip] [--codegen-version v4] [--stability stable|beta] [-i <value>] [-f] [-k <value>]
$ apimatic sdk generate -l csharp|java|php|python|ruby|typescript|go [-d <value>] [--codegen-version v4]
[--stability stable|beta] [--git-init] [-i <value>] [-f] [-k <value>]

FLAGS
-d, --destination=<value> [default: <input>/sdk/<language> | <input>/sdk/<api-version>/<language>] path where
the SDK will be generated
-f, --force overwrite changes without asking for user consent.
-d, --destination=<value> [default: <input>/sdk/<language>] directory the SDK is generated into
-f, --force never ask: conflicts are resolved using the generator's changes, and an SDK that
cannot be merged is replaced, with a warning.
-i, --input=<value> [default: ./] path to the parent directory containing the 'src' directory, which
includes API specifications and configuration files.
-k, --auth-key=<value> override current authentication state with an authentication key.
-l, --language=<option> (required) Programming language for SDK generation
<options: csharp|java|php|python|ruby|typescript|go>
--api-version=<value> Version of the API to use for SDK generation (if multiple versions exist)
--codegen-version=<option> [default: v4] Version of the code generator to use
<options: v4>
--git-init make the SDK directory a git repository when it is not one of its own, so your edits
to the SDK are kept when you regenerate it
--stability=<option> Stability level of the generated SDK. Defaults to the level the language offers.
<options: stable|beta>
--zip Download the generated SDK as a .zip archive

DESCRIPTION
Generate an SDK for your API

Generate a Software Development Kit (SDK) from an API specification.
C#, TypeScript and Python are available; Java, Ruby, Go and PHP are coming soon.
With git 2.38 or newer installed and the SDK directory a git repository of its own (--git-init makes it one), your
edits to the generated SDK are kept when you regenerate it.

EXAMPLES
apimatic sdk generate --language=typescript

apimatic sdk generate --language=csharp --input=./

apimatic sdk generate --language=python --destination=./sdk --zip
apimatic sdk generate --language=python --destination=./my-python-sdk
```

_See code: [src/commands/sdk/generate.ts](https://github.com/apimatic/apimatic-cli/blob/dev/src/commands/sdk/generate.ts)_
Expand All @@ -450,11 +456,12 @@ Generate and publish an SDK to a package registry and/or source repository
USAGE
$ apimatic sdk publish [-p <value>] [-v <value>] [-d <value>] [-l csharp|java|php|python|ruby|typescript|go]
[-f] [-i <value>] [--publish-type package|sourcecode...] [--dry-run] [--codegen-version v4] [--stability
stable|beta]
stable|beta] [--git-init]

FLAGS
-d, --destination=<value> [default: <input>/sdk] path where the sdk will be generated.
-f, --force overwrite changes without asking for user consent.
-d, --destination=<value> [default: <input>/sdk/<language>] path where the sdk will be generated.
-f, --force never ask: conflicts are resolved using the generator's changes, and an SDK that
cannot be merged is replaced, with a warning.
-i, --input=<value> [default: ./] path to the parent directory containing the 'src' directory, which
includes API specifications and configuration files.
-l, --language=<option> Language of the SDK to generate and publish.
Expand All @@ -464,6 +471,9 @@ FLAGS
--codegen-version=<option> [default: v4] Version of the code generator to use
<options: v4>
--dry-run Generate the SDK locally for review without publishing.
--git-init In the step-by-step experience, make the SDK directory a git repository when it is not
one of its own, so your edits to the SDK are kept when you regenerate it. A run with
the other flags always does.
--publish-type=<option>... One or more publishing targets: 'package' for a package registry, 'sourcecode' for a
git repository.
<options: package|sourcecode>
Expand All @@ -474,8 +484,8 @@ DESCRIPTION
Generate and publish an SDK to a package registry and/or source repository

Generate and publish an SDK using a publishing profile configured in the APIMatic App. Requires an input directory
containing the API specification. Run without flags for a step-by-step interactive experience, or pass all required
flags for CI/CD automation.
containing the API specification. Run without flags, or with --git-init alone, for a step-by-step interactive
experience, or pass all required flags for CI/CD automation.

EXAMPLES
apimatic sdk publish
Expand Down
28 changes: 28 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@ export default [
...tseslint.configs.recommended.rules
}
},
{
// The functional core of the SDK work: data and pure functions only. Anything that reaches
// a process or the disk belongs in a context or in infrastructure.
files: ['src/types/sdk/**/*.ts'],
rules: {
'no-restricted-imports': [
'error',
{
paths: [
'fs',
'node:fs',
'fs/promises',
'node:fs/promises',
'fs-extra',
'child_process',
'node:child_process',
'execa'
].map((name) => ({ name, message: 'src/types/sdk/ is pure: no file or process access.' })),
patterns: [
{
group: ['**/infrastructure/**', '**/sdk-repository/**'],
message: 'src/types/sdk/ is pure: it does not import infrastructure or the effectful stores.'
}
]
}
]
}
},
{
// Test files use Mocha's global TDD/BDD functions and chai assertion
// expressions (e.g. `expect(x).to.be.true`), which the base config would
Expand Down
Loading
Loading