first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
# `schemas/options` — plugin options schema
## Purpose
Declares the Zod schema for the options accepted by
`createImportPlugin`. Parsing options at the factory boundary
guarantees the resolved config (`ImportPluginConfig`) carries no
optional fields — every downstream consumer (`onInit`, `onReady`,
routes, service) reads from a fully-resolved object without `?? default`
fallbacks scattered across the call sites.
Defaults are documented inside the schema (`.default(...)`) so the Zod
parse output is the authoritative source of plugin defaults. Renaming a
field is a breaking change.
## Features
- Six options with sensible production defaults: `routePrefix`,
`maxFileSizeBytes`, `maxRows`, `maxErrorsBeforeAbort`, `previewRows`,
`defaultBatchSize`.
- Two TypeScript shapes — `ImportPluginOptionsInput` for caller-supplied
partials, `ImportPluginConfig` for the resolved config.
- Strict positive-integer / non-empty-string constraints surface bad
config as `IMPORT.INVALID_OPTIONS` with the `ZodError` as `cause`.
## Usage: Basic Example
```ts
import { ImportPluginOptionsSchema } from "@suaveplan/api-plugin-import";
const parsed = ImportPluginOptionsSchema.parse({});
// parsed.routePrefix === "/imports"
// parsed.maxFileSizeBytes === 52_428_800
```
## Usage: Advanced Example
```ts
import { ImportPluginOptionsSchema, type ImportPluginConfig } from "@suaveplan/api-plugin-import";
function configureImport(overrides: Partial<ImportPluginConfig>): ImportPluginConfig {
return ImportPluginOptionsSchema.parse({
routePrefix: "/v2/imports",
maxRows: 10_000,
...overrides,
});
}
```
## API Reference
- `ImportPluginOptionsSchema: z.ZodObject<…>` — Zod schema with
defaults for every field.
- `type ImportPluginOptionsInput` — caller-supplied partial input.
- `type ImportPluginConfig` — resolved options (every field
non-optional).
## Implementation Notes
- All numeric bounds are `int().positive()` because the consuming
fields are counts; the schema rejects zero with the standard Zod
error message.
- `previewRows` is capped at 1 000 to prevent a malicious client from
triggering a multi-megabyte preview render.
- `routePrefix` is non-empty; an empty prefix collapses the mount and
causes Hono route shadowing — the Zod gate prevents this footgun at
factory time.

View File

@@ -0,0 +1,81 @@
# `schemas/schemas` — public Zod request/response surface
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Carries the full public Zod surface used by the route handlers and any
external client (CLI tool, integration test, browser app) that wants to
validate or generate import requests / responses without depending on
the route module itself. Every body, query, and response shape that
crosses the HTTP boundary is declared here so the OpenAPI document and
the runtime validators stay in lockstep.
Keeping these schemas in their own module means consumers can import
them without pulling in the Hono/OpenAPI route builder, which is
important for browser clients and shared validation libraries.
## Features
- `ImportFormatSchema` / `ImportStatusSchema` — Zod enums mirroring the
cross-module type unions.
- `ColumnMappingSchema` — wire-form of a column mapping (functions
intentionally omitted; transforms are server-side only).
- `PreviewRequestSchema` / `PreviewResponseSchema` — `POST /preview`.
- `CreateImportJobSchema` — `POST /` body.
- `ImportJobResponseSchema` — every job-shape response.
- `ImportJobListQuerySchema` — `GET /` querystring with `z.coerce`
for the numeric fields so query strings parse without hand-rolling.
## Usage: Basic Example
```ts
import { CreateImportJobSchema } from "@suaveplan/api-plugin-import";
const result = CreateImportJobSchema.safeParse({
format: "csv",
data: "name\nAda",
mappings: [{ sourceColumn: "name", targetField: "displayName" }],
});
if (!result.success) throw new Error(result.error.message);
```
## Usage: Advanced Example
```ts
import { ImportJobResponseSchema, type ImportJobResponseShape } from "@suaveplan/api-plugin-import";
async function fetchJob(id: string): Promise<ImportJobResponseShape> {
const res = await fetch(`/imports/${id}`);
const json = await res.json();
return ImportJobResponseSchema.parse(json);
}
```
## API Reference
- `ImportFormatSchema`, `type ImportFormatInput`
- `ImportStatusSchema`, `type ImportStatusInput`
- `ColumnMappingSchema`, `type ColumnMappingInput`
- `PreviewRequestSchema`, `type PreviewRequestInput`
- `PreviewResponseSchema`, `type PreviewResponseShape`
- `CreateImportJobSchema`, `type CreateImportJobInput`
- `ImportJobResponseSchema`, `type ImportJobResponseShape`
- `ImportJobListQuerySchema`, `type ImportJobListQueryInput`
- `RowErrorSchema`
## Implementation Notes
- `ColumnMappingSchema` omits the `transform` callback — transforms are
authored in TypeScript on the server, not over the wire. Wire-form
mappings are pure renames + required flags.
- `PreviewResponseSchema.sampleRows` uses `z.record(z.string(),
z.unknown())` so heterogeneous row shapes survive validation.
- `ImportJobListQuerySchema` uses `z.coerce.number()` because Hono
delivers query parameters as strings — the coerce ensures `?limit=20`
parses to a number without manual `parseInt`.
- `CreateImportJobSchema.mappings` requires `min(1)` because zero
mappings is the service-layer `IMPORT.VALIDATION` failure; rejecting
it at the Zod boundary saves a service round-trip.