@homeflare/alchemy 0.27.4 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/caddy/admin-address.d.ts +27 -0
- package/dist/caddy/admin-address.d.ts.map +1 -0
- package/dist/caddy/admin-calls.d.ts +25 -28
- package/dist/caddy/admin-calls.d.ts.map +1 -1
- package/dist/caddy/admin.d.ts +28 -38
- package/dist/caddy/admin.d.ts.map +1 -1
- package/dist/caddy/caddy-http-client.d.ts +25 -0
- package/dist/caddy/caddy-http-client.d.ts.map +1 -0
- package/dist/caddy/config-errors.d.ts +24 -0
- package/dist/caddy/config-errors.d.ts.map +1 -0
- package/dist/caddy/config-lifecycle.d.ts +20 -49
- package/dist/caddy/config-lifecycle.d.ts.map +1 -1
- package/dist/caddy/config-reconcile.d.ts +45 -0
- package/dist/caddy/config-reconcile.d.ts.map +1 -0
- package/dist/caddy/config.d.ts +4 -3
- package/dist/caddy/config.d.ts.map +1 -1
- package/dist/caddy/fake-caddy.d.ts +10 -2
- package/dist/caddy/fake-caddy.d.ts.map +1 -1
- package/dist/caddy/index.d.ts +3 -3
- package/dist/caddy/index.d.ts.map +1 -1
- package/dist/caddy/index.js +487 -444
- package/dist/caddy/index.js.map +16 -12
- package/dist/caddy/local-admin.d.ts +20 -34
- package/dist/caddy/local-admin.d.ts.map +1 -1
- package/dist/caddy/providers.d.ts +19 -3
- package/dist/caddy/providers.d.ts.map +1 -1
- package/dist/cloudflare/mesh-node-token.d.ts +1 -1
- package/dist/cloudflare/mesh-node-token.d.ts.map +1 -1
- package/dist/forgejo/branch-protection.d.ts +4 -4
- package/dist/forgejo/org-actions-secrets.d.ts +4 -4
- package/dist/forgejo/org-label.d.ts +4 -4
- package/dist/forgejo/org-team.d.ts +4 -4
- package/dist/forgejo/repo-webhook.d.ts +4 -4
- package/dist/forgejo/repository.d.ts +4 -4
- package/dist/forgejo/team-member.d.ts +4 -4
- package/dist/github/declare-repo-baseline.d.ts +1 -1
- package/dist/github/declare-repo-baseline.d.ts.map +1 -1
- package/dist/github/index.d.ts +9 -5
- package/dist/github/index.d.ts.map +1 -1
- package/dist/github/index.js +161 -25
- package/dist/github/index.js.map +15 -13
- package/dist/github/repo-baseline-data.d.ts +10 -1
- package/dist/github/repo-baseline-data.d.ts.map +1 -1
- package/dist/github/repo-policy.d.ts +1 -1
- package/dist/github/repo-policy.d.ts.map +1 -1
- package/dist/github/repository-ruleset-errors.d.ts +37 -3
- package/dist/github/repository-ruleset-errors.d.ts.map +1 -1
- package/dist/github/repository-ruleset-form.d.ts.map +1 -1
- package/dist/github/repository-ruleset-guards.d.ts +15 -2
- package/dist/github/repository-ruleset-guards.d.ts.map +1 -1
- package/dist/github/repository-ruleset-narrowing-guards.d.ts +39 -0
- package/dist/github/repository-ruleset-narrowing-guards.d.ts.map +1 -0
- package/dist/github/repository-ruleset-octokit.d.ts +49 -0
- package/dist/github/repository-ruleset-octokit.d.ts.map +1 -1
- package/dist/github/repository-ruleset-probe.d.ts +2 -1
- package/dist/github/repository-ruleset-probe.d.ts.map +1 -1
- package/dist/github/repository-ruleset-props.d.ts +91 -0
- package/dist/github/repository-ruleset-props.d.ts.map +1 -0
- package/dist/github/repository-ruleset-providers.d.ts +42 -0
- package/dist/github/repository-ruleset-providers.d.ts.map +1 -0
- package/dist/github/repository-ruleset-reconcile.d.ts.map +1 -1
- package/dist/github/repository-ruleset.d.ts +28 -34
- package/dist/github/repository-ruleset.d.ts.map +1 -1
- package/dist/litellm/fake-litellm.d.ts +27 -16
- package/dist/litellm/fake-litellm.d.ts.map +1 -1
- package/dist/litellm/fake-stack.d.ts +9 -4
- package/dist/litellm/fake-stack.d.ts.map +1 -1
- package/dist/litellm/index.d.ts +7 -5
- package/dist/litellm/index.d.ts.map +1 -1
- package/dist/litellm/index.js +53 -123
- package/dist/litellm/index.js.map +8 -8
- package/dist/litellm/operations.d.ts +60 -0
- package/dist/litellm/operations.d.ts.map +1 -0
- package/dist/litellm/pass-through-endpoint.d.ts +10 -28
- package/dist/litellm/pass-through-endpoint.d.ts.map +1 -1
- package/dist/litellm/pass-through-errors.d.ts +37 -0
- package/dist/litellm/pass-through-errors.d.ts.map +1 -0
- package/dist/litellm/pass-through-form.d.ts +11 -4
- package/dist/litellm/pass-through-form.d.ts.map +1 -1
- package/dist/litellm/providers.d.ts +7 -5
- package/dist/litellm/providers.d.ts.map +1 -1
- package/dist/netbox/prefix.d.ts +4 -4
- package/dist/paperless/custom-field.d.ts +21 -21
- package/dist/paperless/custom-field.d.ts.map +1 -1
- package/dist/paperless/document-type.d.ts +34 -4
- package/dist/paperless/document-type.d.ts.map +1 -1
- package/dist/paperless/fake-paperless.d.ts +36 -19
- package/dist/paperless/fake-paperless.d.ts.map +1 -1
- package/dist/paperless/index.d.ts +7 -2
- package/dist/paperless/index.d.ts.map +1 -1
- package/dist/paperless/index.js +164 -228
- package/dist/paperless/index.js.map +10 -13
- package/dist/paperless/matching-locate.d.ts +42 -20
- package/dist/paperless/matching-locate.d.ts.map +1 -1
- package/dist/paperless/matching-types.d.ts +47 -18
- package/dist/paperless/matching-types.d.ts.map +1 -1
- package/dist/paperless/matching.d.ts +30 -27
- package/dist/paperless/matching.d.ts.map +1 -1
- package/dist/paperless/providers.d.ts +13 -7
- package/dist/paperless/providers.d.ts.map +1 -1
- package/dist/paperless/storage-path.d.ts +34 -4
- package/dist/paperless/storage-path.d.ts.map +1 -1
- package/dist/paperless/tag.d.ts +43 -8
- package/dist/paperless/tag.d.ts.map +1 -1
- package/dist/proxmox/acl.d.ts +30 -23
- package/dist/proxmox/acl.d.ts.map +1 -1
- package/dist/proxmox/distilled-pve.d.ts +89 -0
- package/dist/proxmox/distilled-pve.d.ts.map +1 -0
- package/dist/proxmox/index.js +663 -609
- package/dist/proxmox/index.js.map +12 -11
- package/dist/proxmox/members.d.ts +29 -10
- package/dist/proxmox/members.d.ts.map +1 -1
- package/docs/caddy-admin.md +1 -1
- package/docs/caddy.md +3 -2
- package/docs/credentials.md +16 -0
- package/docs/litellm.md +21 -13
- package/docs/paperless.md +12 -0
- package/docs/peers.md +5 -0
- package/docs/repo-policy.md +16 -1
- package/docs/repository-ruleset.md +53 -13
- package/docs/upstream-conformance.md +126 -10
- package/package.json +9 -2
- package/src/caddy/admin-address.ts +71 -0
- package/src/caddy/admin-calls.ts +48 -100
- package/src/caddy/admin.ts +37 -41
- package/src/caddy/adopt-scope.test.ts +1 -1
- package/src/caddy/caddy-http-client.ts +229 -0
- package/src/caddy/config-adopt-provider.test.ts +139 -0
- package/src/caddy/config-adopt.test.ts +60 -126
- package/src/caddy/config-errors.ts +47 -0
- package/src/caddy/config-lifecycle.test.ts +55 -42
- package/src/caddy/config-lifecycle.ts +72 -162
- package/src/caddy/config-reconcile.ts +138 -0
- package/src/caddy/config.ts +36 -42
- package/src/caddy/fake-caddy.ts +20 -2
- package/src/caddy/index.ts +3 -8
- package/src/caddy/local-admin.test.ts +35 -21
- package/src/caddy/local-admin.ts +60 -167
- package/src/caddy/providers.test.ts +14 -6
- package/src/caddy/providers.ts +20 -4
- package/src/github/declare-repo-baseline.ts +6 -6
- package/src/github/index.ts +10 -4
- package/src/github/repo-baseline-data.test.ts +13 -0
- package/src/github/repo-baseline-data.ts +11 -2
- package/src/github/repo-policy-stack.test.ts +59 -0
- package/src/github/repo-policy.ts +3 -2
- package/src/github/repository-ruleset-errors.ts +51 -4
- package/src/github/repository-ruleset-exact-adopt-k1.test.ts +109 -0
- package/src/github/repository-ruleset-exact-adopt.test.ts +184 -0
- package/src/github/repository-ruleset-form.ts +7 -3
- package/src/github/repository-ruleset-guards.ts +11 -4
- package/src/github/repository-ruleset-narrowing-guards.ts +141 -0
- package/src/github/repository-ruleset-narrowing.test.ts +210 -0
- package/src/github/repository-ruleset-octokit.test.ts +141 -0
- package/src/github/repository-ruleset-octokit.ts +121 -30
- package/src/github/repository-ruleset-probe.ts +2 -1
- package/src/github/repository-ruleset-props.ts +95 -0
- package/src/github/repository-ruleset-providers.ts +46 -0
- package/src/github/repository-ruleset-reconcile.ts +35 -0
- package/src/github/repository-ruleset-wire.test.ts +38 -27
- package/src/github/repository-ruleset-write-refusals.test.ts +6 -26
- package/src/github/repository-ruleset.ts +53 -43
- package/src/litellm/fake-litellm.ts +83 -78
- package/src/litellm/fake-stack.ts +13 -5
- package/src/litellm/index.ts +7 -21
- package/src/litellm/operations.ts +149 -0
- package/src/litellm/pass-through-endpoint-delete-swallow.test.ts +17 -20
- package/src/litellm/pass-through-endpoint-replace.test.ts +3 -4
- package/src/litellm/pass-through-endpoint.test.ts +8 -8
- package/src/litellm/pass-through-endpoint.ts +21 -31
- package/src/litellm/pass-through-errors.ts +37 -0
- package/src/litellm/pass-through-form.ts +20 -10
- package/src/litellm/providers.ts +8 -7
- package/src/paperless/custom-field.test.ts +49 -40
- package/src/paperless/custom-field.ts +57 -33
- package/src/paperless/document-type.test.ts +48 -0
- package/src/paperless/document-type.ts +51 -22
- package/src/paperless/fake-paperless.ts +63 -72
- package/src/paperless/index.ts +7 -13
- package/src/paperless/matching-locate.test.ts +102 -0
- package/src/paperless/matching-locate.ts +80 -86
- package/src/paperless/matching-types.ts +49 -16
- package/src/paperless/matching.ts +77 -90
- package/src/paperless/providers.ts +14 -10
- package/src/paperless/storage-path.test.ts +56 -0
- package/src/paperless/storage-path.ts +53 -24
- package/src/paperless/tag-identity.test.ts +127 -0
- package/src/paperless/tag.test.ts +100 -0
- package/src/paperless/tag.ts +62 -32
- package/src/proxmox/acl.test.ts +145 -0
- package/src/proxmox/acl.ts +128 -150
- package/src/proxmox/distilled-pve.test.ts +231 -0
- package/src/proxmox/distilled-pve.ts +147 -0
- package/src/proxmox/members-timeout.test.ts +161 -0
- package/src/proxmox/members.test.ts +9 -0
- package/src/proxmox/members.ts +36 -2
- package/dist/litellm/client.d.ts +0 -76
- package/dist/litellm/client.d.ts.map +0 -1
- package/dist/litellm/credentials.d.ts +0 -48
- package/dist/litellm/credentials.d.ts.map +0 -1
- package/dist/litellm/generated/pass-through.d.ts +0 -71
- package/dist/litellm/generated/pass-through.d.ts.map +0 -1
- package/dist/paperless/client.d.ts +0 -37
- package/dist/paperless/client.d.ts.map +0 -1
- package/dist/paperless/credentials.d.ts +0 -40
- package/dist/paperless/credentials.d.ts.map +0 -1
- package/dist/paperless/errors.d.ts +0 -49
- package/dist/paperless/errors.d.ts.map +0 -1
- package/src/litellm/client.ts +0 -195
- package/src/litellm/credentials.ts +0 -73
- package/src/litellm/generated/pass-through.ts +0 -73
- package/src/paperless/client.ts +0 -88
- package/src/paperless/credentials.ts +0 -69
- package/src/paperless/errors.ts +0 -62
- package/src/paperless/matching-identity.test.ts +0 -194
- package/src/paperless/matching.test.ts +0 -128
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/paperless/
|
|
3
|
+
"sources": ["../src/paperless/constraint-guard.ts", "../src/paperless/constraints.ts", "../src/paperless/generated/constraints/paperless-custom_fields.ts", "../src/paperless/generated/constraints/paperless-document_types.ts", "../src/paperless/generated/constraints/paperless-storage_paths.ts", "../src/paperless/generated/constraints/paperless-tags.ts", "../src/paperless/generated/constraints/index.ts", "../src/paperless/tag.ts", "../src/paperless/matching.ts", "../src/paperless/matching-locate.ts", "../src/paperless/document-type.ts", "../src/paperless/storage-path.ts", "../src/paperless/custom-field.ts", "../src/paperless/providers.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Where the Paperless URL and token come from — S24's shape (alchemy-provider-standard): a lazy\n * `Context.Service` whose VALUE is itself an `Effect`, resolved inside each operation with\n * `yield* yield* PaperlessCredentials`. Resolving twice, not once at layer build, is what keeps a\n * token out of any state the engine might persist and lets a consumer swap the source (an env var\n * today, an OpenBao mint tomorrow) without touching a resource file.\n *\n * ⛔ NO DEFAULT HOST, AND NO DEFAULT TOKEN. A published package that fell back to a loopback\n * address would let a consumer who forgot the variable watch every call fail against a machine\n * that is not theirs, instead of being told which variable is missing.\n * ⛔ THE TOKEN IS NEVER A PROP, NEVER AN ATTRIBUTE. Alchemy persists attributes unencrypted\n * (S25); nothing this family returns from `read`/`reconcile` may carry it.\n */\nimport * as Context from 'effect/Context';\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nexport class PaperlessCredentialsError extends Data.TaggedError('PaperlessCredentialsError')<{\n readonly message: string;\n}> {}\n\nexport interface PaperlessCredentialValue {\n /** Trailing slash stripped, e.g. `https://paperless.example.com`. */\n readonly url: string;\n readonly token: string;\n}\n\n/**\n * ★ `readEnvironment` NAMES EVERY VARIABLE IT CONSUMES (S24) — `PAPERLESS_URL`, `PAPERLESS_TOKEN`\n * — so a consumer's `alchemy provider check-env` (or an equivalent preflight) can list them.\n */\nconst readEnvironment: Effect.Effect<PaperlessCredentialValue, PaperlessCredentialsError> =\n Effect.suspend(() => {\n const url = process.env['PAPERLESS_URL'];\n const token = process.env['PAPERLESS_TOKEN'];\n if (url === undefined || url.trim() === '') {\n return Effect.fail(\n new PaperlessCredentialsError({\n message: 'PAPERLESS_URL is not set. Point it at your Paperless-ngx instance.',\n }),\n );\n }\n if (token === undefined || token.trim() === '') {\n return Effect.fail(\n new PaperlessCredentialsError({\n message:\n 'PAPERLESS_TOKEN is not set. Mint a scoped token and export it — never store it in Alchemy props.',\n }),\n );\n }\n return Effect.succeed({ token: token.trim(), url: url.trim().replace(/\\/$/, '') });\n });\n\n/**\n * The lazy service. ⚠️ `Layer.succeed` registers the EFFECT, not its result — `readEnvironment`\n * runs once per `yield* yield*`, so a call after the variables are exported sees them even if\n * the layer itself was built before that (true in `fake-paperless.test.ts`, which sets the env\n * vars right before each call).\n */\nexport class PaperlessCredentials extends Context.Service<\n PaperlessCredentials,\n Effect.Effect<PaperlessCredentialValue, PaperlessCredentialsError>\n>()('PaperlessCredentials') {}\n\nexport const environmentLayer: Layer.Layer<PaperlessCredentials> = Layer.succeed(\n PaperlessCredentials,\n readEnvironment,\n);\n",
|
|
6
|
-
"/**\n * Paperless-ngx's HTTP status codes, mapped to tagged errors exactly once — here, and never\n * again by a status check inside a resource (S21, alchemy-provider-standard).\n *\n * ⛔ A SINGLE `PaperlessError` CLASS WITH A `.status` FIELD WOULD WORK, AND IS WHAT `netbox/\n * client.ts` DOES. This family does it the S21 way instead: one tag per distinct MEANING, so a\n * caller writes `Effect.catchTag('PaperlessNotFound', …)` rather than `if (e.status === 404)`.\n * `matching.ts`'s \"a 403 is never read as absent\" rule is exactly what a shared tag buys —\n * `catchTag('PaperlessNotFound', …)` cannot accidentally also catch `PaperlessUnauthorized`.\n */\nimport * as Data from 'effect/Data';\n\n/** No object at that path. The only tag `matching.ts` folds to \"absent\". */\nexport class PaperlessNotFound extends Data.TaggedError('PaperlessNotFound')<{\n readonly method: string;\n readonly path: string;\n}> {}\n\n/** 401 (no/bad token) or 403 (token valid, forbidden) — NEVER read as \"the object is absent\". */\nexport class PaperlessUnauthorized extends Data.TaggedError('PaperlessUnauthorized')<{\n readonly status: 401 | 403;\n readonly method: string;\n readonly path: string;\n}> {}\n\n/** 400 — the vendor rejected the body. Carries it, so the message quotes Paperless's own words. */\nexport class PaperlessValidation extends Data.TaggedError('PaperlessValidation')<{\n readonly method: string;\n readonly path: string;\n readonly body: string;\n}> {}\n\n/** 5xx, or a status this family's endpoints do not otherwise document. */\nexport class PaperlessUnavailable extends Data.TaggedError('PaperlessUnavailable')<{\n readonly status: number;\n readonly method: string;\n readonly path: string;\n readonly detail: string;\n}> {}\n\nexport type PaperlessError =\n | PaperlessNotFound\n | PaperlessUnauthorized\n | PaperlessValidation\n | PaperlessUnavailable;\n\n/**\n * The one place a status code is read. ⚠️ Anything outside {400,401,403,404,5xx} — 405, 409, 429\n * — is not documented for these four endpoints, so it falls to `PaperlessValidation` rather than\n * inventing a fifth tag for a case that was never measured.\n */\nexport const statusToError = (\n status: number,\n method: string,\n path: string,\n body: string,\n): PaperlessError => {\n if (status === 404) return new PaperlessNotFound({ method, path });\n if (status === 401 || status === 403) return new PaperlessUnauthorized({ method, path, status });\n if (status >= 500) return new PaperlessUnavailable({ detail: body, method, path, status });\n return new PaperlessValidation({ body, method, path });\n};\n",
|
|
7
5
|
"/**\n * The generated tables, looked up by endpoint, and the refusal that stops a plan.\n *\n * ⛔ AN UNKNOWN KEY IS A DEFECT, NOT A REASON TO SKIP THE CHECK — the generator resolves every key\n * in its source scan against the vendor document, so a key absent here means the tables were\n * not regenerated, which the message says. Same posture as `../netbox/constraint-guard.ts`.\n */\nimport * as Effect from 'effect/Effect';\nimport {\n type EndpointConstraints,\n type EndpointKey,\n type PaperlessBody,\n refusal,\n violations,\n} from './constraints.ts';\nimport { PAPERLESS_CONSTRAINTS } from './generated/constraints/index.ts';\n\nexport { PAPERLESS_CONSTRAINTS };\n\nexport const constraintsFor = (key: EndpointKey): EndpointConstraints => {\n const table = PAPERLESS_CONSTRAINTS[key];\n if (table === undefined) {\n throw new Error(\n `no vendor constraint table for '${key}'. It is named in this package but not generated: ` +\n 'run `bun codegen/paperless.ts` (see codegen/README.md).',\n );\n }\n return table;\n};\n\nexport const bodyViolations = (\n key: EndpointKey,\n body: PaperlessBody,\n presence: boolean,\n): readonly string[] => violations(constraintsFor(key), body, { presence });\n\n/**\n * ⛔ `Effect.die`, NOT `Effect.fail`. A declaration the vendor would reject is a DEFECT in the\n * stack file, not a recoverable condition.\n */\nexport const guardBody = (\n key: EndpointKey | undefined,\n body: PaperlessBody,\n presence: boolean,\n): Effect.Effect<void> =>\n Effect.suspend(() => {\n if (key === undefined) return Effect.void;\n const found = bodyViolations(key, body, presence);\n return found.length === 0 ? Effect.void : Effect.die(new Error(refusal(key, found)));\n });\n",
|
|
8
6
|
"/**\n * Paperless-ngx's own rules, checked here, before the request is built.\n *\n * ★ THE SAME READER SHAPE AS `../netbox/constraints.ts`, AND FOR THE SAME REASON: both vendors\n * send a JSON body where a number stays a number and a boolean stays a boolean, so `String(v)`\n * at the door would be the exact mangling that incident (codegen/README.md) exists to prevent.\n * The table itself is generated by `bun codegen/paperless.ts` from the vendor's own OpenAPI\n * document — nothing here is hand-typed.\n *\n * ⚠️ WHAT THIS DELIBERATELY DOES NOT ENFORCE: a `format` name (a DRF validator run server-side); a\n * pattern the generator could not carry faithfully (codegen/py-pattern.ts), recorded verbatim as\n * `patternSource`; the `(name, owner)` uniqueness constraint (models.py) — that is `matching.ts`'s\n * job, not a per-field rule; and `CustomField.select_options`, which is not in the schema at all\n * (groundTruth: the serializer's own rule is unverified at 3.1.1 and this table cannot state a\n * rule the vendor document does not carry).\n */\n\nexport interface ParamConstraint {\n readonly type?: string;\n /** From the schema's `required` array. ⚠️ Checked on CREATE only. */\n readonly required?: boolean;\n readonly maxLength?: number;\n readonly minLength?: number;\n readonly minimum?: number;\n readonly maximum?: number;\n /** ⚠️ `(string | number)[]` — `matching_algorithm`'s enum is numeric (`DataTypeEnum`'s is not). */\n readonly enum?: readonly (string | number)[];\n readonly pattern?: string;\n readonly patternSource?: string;\n readonly format?: string;\n readonly default?: string;\n}\n\nexport type EndpointConstraints = Readonly<Record<string, ParamConstraint>>;\n\n/** `paperless:POST /api/tags/` — exactly how the generated tables key an endpoint. */\nexport type EndpointKey = string;\n\nexport type PaperlessBody = Record<string, unknown>;\n\nexport interface ViolationOptions {\n /** ⛔ CREATE ONLY. A PATCH is deliberately partial, so presence there refuses every ordinary edit. */\n readonly presence?: boolean;\n}\n\n/** ⚠️ `[...value].length`, NOT `value.length` — Django counts characters, JavaScript UTF-16 units. */\nconst lengthOf = (value: string): number => [...value].length;\n\nconst checkString = (name: string, value: string, rule: ParamConstraint): string[] => {\n const out: string[] = [];\n if (rule.maxLength !== undefined && lengthOf(value) > rule.maxLength) {\n out.push(`${name}: at most ${String(rule.maxLength)} characters`);\n }\n if (rule.minLength !== undefined && lengthOf(value) < rule.minLength) {\n out.push(`${name}: at least ${String(rule.minLength)} characters`);\n }\n if (rule.enum !== undefined && !rule.enum.includes(value)) {\n out.push(`${name}: must be one of ${rule.enum.join(', ')}`);\n }\n if (rule.pattern !== undefined && !new RegExp(rule.pattern).test(value)) {\n out.push(`${name}: must match ${rule.patternSource ?? rule.pattern}`);\n }\n return out;\n};\n\nconst checkNumber = (name: string, value: number, rule: ParamConstraint): string[] => {\n const out: string[] = [];\n if (!Number.isFinite(value)) return out;\n if (rule.minimum !== undefined && value < rule.minimum)\n out.push(`${name}: at least ${String(rule.minimum)}`);\n if (rule.maximum !== undefined && value > rule.maximum)\n out.push(`${name}: at most ${String(rule.maximum)}`);\n return out;\n};\n\nconst checkValue = (name: string, value: unknown, rule: ParamConstraint): readonly string[] => {\n if (typeof value === 'string') return checkString(name, value, rule);\n if (typeof value === 'number') return checkNumber(name, value, rule);\n return [];\n};\n\n/**\n * Every vendor rule this body breaks. Pure — no network, no clock, no environment.\n *\n * ⚠️ `null` IS A VALUE, NOT AN ABSENCE — Paperless uses explicit `null` to clear a nullable\n * foreign key (`owner`, `parent`), so it must not trip the presence check, and no string/number\n * rule applies to it.\n */\nexport const violations = (\n table: EndpointConstraints,\n body: PaperlessBody,\n options: ViolationOptions = {},\n): readonly string[] => {\n const out: string[] = [];\n for (const [name, rule] of Object.entries(table)) {\n if (!Object.hasOwn(body, name)) {\n if (options.presence === true && rule.required === true) out.push(`${name}: required`);\n continue;\n }\n const value = body[name];\n for (const item of Array.isArray(value) ? value : [value])\n out.push(...checkValue(name, item, rule));\n }\n return out;\n};\n\n/** The message a plan dies with. */\nexport const refusal = (endpoint: EndpointKey, found: readonly string[]): string =>\n `${endpoint} would be rejected by the vendor:\\n - ${found.join('\\n - ')}\\n` +\n \"These are Paperless-ngx's own limits, read from its served OpenAPI document \" +\n '(packages/alchemy/src/paperless/generated/constraints). Fix the declaration.';\n",
|
|
9
7
|
"/**\n * Generated Paperless-ngx REST API (OpenAPI 3.0.3) request-body constraints for `/api/custom_fields/` — DO NOT EDIT BY HAND.\n *\n * Run: bun codegen/paperless.ts\n * Manifest entry: `paperless-openapi` — Paperless-ngx REST API (OpenAPI 3.0.3) 3.1.1\n * sha256 d0fe550d2135e37b, Paperless-ngx web service, loopback\n * /api/schema/?format=json\n *\n * 8 of this product's 100 POST/PUT/PATCH/DELETE endpoints are tabled across all\n * areas: the ones this package writes to, named in its own source. Every other vendor write\n * endpoint is UNTABLED and therefore unchecked at plan time.\n *\n * ⚠️ A `patternSource` with no `pattern` beside it could NOT be carried into a JavaScript\n * RegExp faithfully — Django/DRF's `\\w` is Unicode and JavaScript's is ASCII\n * (codegen/py-pattern.ts). It is recorded and NOT enforced.\n * ⚠️ `data_type` on a custom field is CREATE-ONLY: enforced here as a value rule, never as a\n * reason to allow a PATCH — the refusal on change lives in the provider (custom-field.ts).\n */\nimport type { EndpointConstraints } from '../../constraints.ts';\n\nexport const PAPERLESS_CUSTOM_FIELDS_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>> = {\n \"paperless:PATCH /api/custom_fields/{id}/\": {\n \"name\": {\"maxLength\":128,\"minLength\":1,\"type\":\"string\"},\n },\n \"paperless:POST /api/custom_fields/\": {\n \"data_type\": {\"required\":true},\n \"name\": {\"maxLength\":128,\"minLength\":1,\"required\":true,\"type\":\"string\"},\n },\n};\n",
|
|
@@ -11,16 +9,15 @@
|
|
|
11
9
|
"/**\n * Generated Paperless-ngx REST API (OpenAPI 3.0.3) request-body constraints for `/api/storage_paths/` — DO NOT EDIT BY HAND.\n *\n * Run: bun codegen/paperless.ts\n * Manifest entry: `paperless-openapi` — Paperless-ngx REST API (OpenAPI 3.0.3) 3.1.1\n * sha256 d0fe550d2135e37b, Paperless-ngx web service, loopback\n * /api/schema/?format=json\n *\n * 8 of this product's 100 POST/PUT/PATCH/DELETE endpoints are tabled across all\n * areas: the ones this package writes to, named in its own source. Every other vendor write\n * endpoint is UNTABLED and therefore unchecked at plan time.\n *\n * ⚠️ A `patternSource` with no `pattern` beside it could NOT be carried into a JavaScript\n * RegExp faithfully — Django/DRF's `\\w` is Unicode and JavaScript's is ASCII\n * (codegen/py-pattern.ts). It is recorded and NOT enforced.\n * ⚠️ `data_type` on a custom field is CREATE-ONLY: enforced here as a value rule, never as a\n * reason to allow a PATCH — the refusal on change lives in the provider (custom-field.ts).\n */\nimport type { EndpointConstraints } from '../../constraints.ts';\n\nexport const PAPERLESS_STORAGE_PATHS_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>> = {\n \"paperless:PATCH /api/storage_paths/{id}/\": {\n \"match\": {\"maxLength\":256,\"type\":\"string\"},\n \"matching_algorithm\": {\"enum\":[0,1,2,3,4,5,6],\"type\":\"integer\"},\n \"name\": {\"maxLength\":128,\"minLength\":1,\"type\":\"string\"},\n \"path\": {\"minLength\":1,\"type\":\"string\"},\n },\n \"paperless:POST /api/storage_paths/\": {\n \"match\": {\"maxLength\":256,\"type\":\"string\"},\n \"matching_algorithm\": {\"enum\":[0,1,2,3,4,5,6],\"type\":\"integer\"},\n \"name\": {\"maxLength\":128,\"minLength\":1,\"required\":true,\"type\":\"string\"},\n \"path\": {\"minLength\":1,\"required\":true,\"type\":\"string\"},\n },\n};\n",
|
|
12
10
|
"/**\n * Generated Paperless-ngx REST API (OpenAPI 3.0.3) request-body constraints for `/api/tags/` — DO NOT EDIT BY HAND.\n *\n * Run: bun codegen/paperless.ts\n * Manifest entry: `paperless-openapi` — Paperless-ngx REST API (OpenAPI 3.0.3) 3.1.1\n * sha256 d0fe550d2135e37b, Paperless-ngx web service, loopback\n * /api/schema/?format=json\n *\n * 8 of this product's 100 POST/PUT/PATCH/DELETE endpoints are tabled across all\n * areas: the ones this package writes to, named in its own source. Every other vendor write\n * endpoint is UNTABLED and therefore unchecked at plan time.\n *\n * ⚠️ A `patternSource` with no `pattern` beside it could NOT be carried into a JavaScript\n * RegExp faithfully — Django/DRF's `\\w` is Unicode and JavaScript's is ASCII\n * (codegen/py-pattern.ts). It is recorded and NOT enforced.\n * ⚠️ `data_type` on a custom field is CREATE-ONLY: enforced here as a value rule, never as a\n * reason to allow a PATCH — the refusal on change lives in the provider (custom-field.ts).\n */\nimport type { EndpointConstraints } from '../../constraints.ts';\n\nexport const PAPERLESS_TAGS_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>> = {\n \"paperless:PATCH /api/tags/{id}/\": {\n \"color\": {\"maxLength\":7,\"minLength\":1,\"type\":\"string\"},\n \"match\": {\"maxLength\":256,\"type\":\"string\"},\n \"matching_algorithm\": {\"enum\":[0,1,2,3,4,5,6],\"type\":\"integer\"},\n \"name\": {\"maxLength\":128,\"minLength\":1,\"type\":\"string\"},\n },\n \"paperless:POST /api/tags/\": {\n \"color\": {\"maxLength\":7,\"minLength\":1,\"type\":\"string\"},\n \"match\": {\"maxLength\":256,\"type\":\"string\"},\n \"matching_algorithm\": {\"enum\":[0,1,2,3,4,5,6],\"type\":\"integer\"},\n \"name\": {\"maxLength\":128,\"minLength\":1,\"required\":true,\"type\":\"string\"},\n },\n};\n",
|
|
13
11
|
"/**\n * Every generated Paperless constraint table, merged — DO NOT EDIT BY HAND.\n *\n * Run: bun codegen/paperless.ts\n *\n * ⚠️ EVERY KEY IS PREFIXED `paperless:`, so one estate running several vendors' readers cannot\n * collide on an unprefixed `POST /api/…`.\n */\nimport type { EndpointConstraints } from '../../constraints.ts';\nimport { PAPERLESS_CUSTOM_FIELDS_CONSTRAINTS } from './paperless-custom_fields.ts';\nimport { PAPERLESS_DOCUMENT_TYPES_CONSTRAINTS } from './paperless-document_types.ts';\nimport { PAPERLESS_STORAGE_PATHS_CONSTRAINTS } from './paperless-storage_paths.ts';\nimport { PAPERLESS_TAGS_CONSTRAINTS } from './paperless-tags.ts';\n\nexport const PAPERLESS_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>> = {\n ...PAPERLESS_CUSTOM_FIELDS_CONSTRAINTS,\n ...PAPERLESS_DOCUMENT_TYPES_CONSTRAINTS,\n ...PAPERLESS_STORAGE_PATHS_CONSTRAINTS,\n ...PAPERLESS_TAGS_CONSTRAINTS,\n};\n\n/** sha256 of the merged table, truncated — a digest of the DATA, not the file text. */\nexport const PAPERLESS_CONSTRAINTS_DIGEST = '66e61dce8c099d7d';\n",
|
|
14
|
-
"/**\n * `Paperless.Tag` — a Paperless-ngx tag, create-or-update and never deleted by default.\n *\n * ★ `matchingAlgorithm` AND THE OTHER ENUM-SHAPED FIELDS ARE INDEXED OFF THE GENERATED REQUEST\n * TYPE (`PaperlessTagRequest['matching_algorithm']`), NEVER RETYPED
|
|
15
|
-
"/**\n * One shape for every Paperless taxonomy object (Tag, DocumentType, StoragePath, CustomField):\n * locate by `name__iexact` only while there is no prior state, identify the exact (name, owner),\n * create-or-update, never delete by default. Modelled on `../netbox/resource.ts`'s\n * `netboxOperations`, with the differences this unit's spec calls for.\n *\n * ⛔ THE CREATE BODY ALWAYS CARRIES `owner`, NULL WHEN UNDECLARED. `OwnedObjectSerializer.create`\n * sets the owner to the TOKEN USER when the field is absent from the body (Paperless-ngx\n * `documents/serialisers.py:495-502` at v3.1.1) — omitting it the way NetBox's `prefix-form.ts`\n * omits an undeclared foreign key would silently create an object owned by whichever credential\n * ran the deploy, invisible to every other user and a second row beside the estate's `owner:\n * null` one on the next apply. Sending `owner: null` explicitly is what keeps a create\n * idempotent under this vendor's default.\n *\n * ★ READ ANSWERS `Unowned(attrs)` ON EVERY MATCH (H1, alchemy-provider-standard). Paperless has no\n * ownership marker this package could check — `owner` here is the estate's OWN prop, not proof\n * of who created the row — so, per the house's 2026-09-21 decision, identical is not ours: a\n * live match never adopts silently. `--adopt` (or `adopt(true)`) resolves it, same as any other\n * marker-less API (upstream's `Snippet.ts#read`).\n *\n * ⛔ IDENTITY IS THE STORED `id`, NOT `name`/`owner`, ONCE A RESOURCE HAS STATE (PR 163, red-team\n * HIGH finding). `diff` and `reconcile` used to re-derive identity from `news` alone on EVERY\n * call — `fetchLive` located a live row by `(name, owner)` even when `output` (the engine's\n * record of what this declaration last wrote, `Provider.ts#reconcile`'s `output` parameter) was\n * right there holding the object's real id. Editing `name` (or `owner`, for the three owned\n * families) on an already-deployed resource is the single most ordinary edit anyone would make\n * — and it made `fetchLive(news)` miss the row it previously wrote, fall into the create branch,\n * POST a SECOND object under the new name/owner, and leave the original permanently orphaned\n * (`list()` always answers `[]` by design, so `nuke` can never find it either). `diff` reported\n * a plain `{action:'update'}` — nothing told the operator this was about to duplicate and\n * abandon an object.\n *\n * The fix: once `output` is defined, `fetchLive` locates by `output.id` (a direct\n * `GET {collection}/{id}/`), never by name — a changed `name`/`owner` becomes an ordinary PATCH\n * of that same id (Paperless allows PATCHing both on all four types; documents keep their\n * tag/type/path because the id never changes). `patchBody`/`matches` now compare `name` and\n * (when `spec.owned !== false`) `owner` against the live row too, so the rename/re-own actually\n * reaches the PATCH body — locating the right row was necessary but not sufficient. The\n * name/owner-based `fetchByName` locate survives ONLY for the no-state path: a genuine first\n * create, or the engine's own adoption probe (`provider.read`, called with `output: undefined`\n * per `Plan.ts`'s adopt block) — `read` is unchanged and still locates by name for exactly that\n * reason. If `output.id` no longer exists live (deleted out of band — by hand, or by another\n * tool), `fetchLive` refuses loudly (`Effect.die`) rather than silently falling through to a\n * create: a plan that would otherwise read as \"ordinary update\" instead names the id and tells\n * the operator to adopt or clean up state, the same posture `immutable` already uses below for\n * `CustomField.dataType`.\n */\nimport { Unowned } from 'alchemy/AdoptPolicy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Effect from 'effect/Effect';\nimport type { PaperlessRow } from './client.ts';\nimport { paperless } from './client.ts';\nimport { guardBody } from './constraint-guard.ts';\nimport type { PaperlessBody } from './constraints.ts';\nimport { absentOn404, matchingLocate, ownerOf } from './matching-locate.ts';\nimport type { MatchingProps, MatchingSpec } from './matching-types.ts';\n\n/** Re-exported so `tag.ts`/`document-type.ts`/`storage-path.ts`/`custom-field.ts` keep importing the contract from `./matching.ts` — only the shape itself lives in `matching-types.ts`, split out to hold the file-size cap. */\nexport type {\n FieldSpec,\n MatchingError,\n MatchingProps,\n MatchingRequirements,\n MatchingSpec,\n} from './matching-types.ts';\n\n/** Object equality good enough for this family's scalars, nullable ints and `extra_data` JSON. */\nconst sameValue = (a: unknown, b: unknown): boolean =>\n typeof a === 'object' && a !== null ? JSON.stringify(a) === JSON.stringify(b) : Object.is(a, b);\n\nexport const matchingOperations = <\n Props extends MatchingProps,\n Attributes extends { readonly id: number },\n>(\n spec: MatchingSpec<Props, Attributes>,\n) => {\n // ★ IDENTITY RESOLUTION LIVES IN `matching-locate.ts` (file-size cap) — `fetchByName` for the\n // no-state path, `fetchLive` for the `output.id`-first switch this file's header describes.\n const { fetchByName, fetchById, fetchLive, objectPath } = matchingLocate<Props>(spec);\n\n /** ⚠️ ALWAYS NAME-BASED — this is `read`'s own contract (S7): find the object from props alone, with no `output` to consult. Unaffected by the identity switch above. */\n const read = (props: Props) =>\n fetchByName(props).pipe(\n Effect.map((live) => (live === undefined ? undefined : spec.attributes(live, props))),\n );\n\n const readById = (props: Props, id: number) =>\n fetchById(id).pipe(\n Effect.map((live) => (live === undefined ? undefined : spec.attributes(live, props))),\n );\n\n const createBody = (props: Props): PaperlessBody => {\n const out: PaperlessBody =\n spec.owned === false\n ? { name: props.name }\n : { name: props.name, owner: props.owner ?? null };\n for (const field of [...spec.fields, ...(spec.createOnly ?? [])]) {\n const value = field.prop(props);\n if (value !== undefined) out[field.key] = value;\n }\n return out;\n };\n\n /**\n * ⚠️ Only fields that DIFFER from the live row — a PATCH that repeats an unchanged value is\n * still a write the audit log carries for nothing.\n * ⛔ `name` AND (WHEN OWNED) `owner` ARE COMPARED TOO, NOT JUST `spec.fields`. Locating the\n * right row by `id` fixed WHERE the write lands; without this, a rename/re-own would still\n * locate correctly and then send an empty-for-those-keys PATCH, so the live object's name or\n * owner would silently never change (PR 163).\n */\n const patchBody = (props: Props, live: PaperlessRow): PaperlessBody => {\n const out: PaperlessBody = {};\n if (props.name !== live['name']) out['name'] = props.name;\n if (spec.owned !== false && ownerOf(live) !== (props.owner ?? undefined)) {\n out['owner'] = props.owner ?? null;\n }\n for (const field of spec.fields) {\n const value = field.prop(props);\n if (value !== undefined && !sameValue(value, field.live(live))) out[field.key] = value;\n }\n return out;\n };\n\n const matches = (props: Props, live: PaperlessRow): boolean => {\n if (props.name !== live['name']) return false;\n if (spec.owned !== false && ownerOf(live) !== (props.owner ?? undefined)) return false;\n return spec.fields.every((field) => {\n const value = field.prop(props);\n return value === undefined || sameValue(value, field.live(live));\n });\n };\n\n return {\n read,\n\n diff: (news: Input<Props>, output: Attributes | undefined) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* fetchLive(news, output);\n if (live === undefined) return { action: 'update' } as const;\n const refusal = spec.immutable?.(live, news);\n if (refusal !== undefined) return yield* Effect.die(new Error(refusal));\n if (matches(news, live)) return { action: 'noop' } as const;\n return spec.endpoint.update === undefined\n ? ({ action: 'replace' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: (news: Props, output: Attributes | undefined) =>\n Effect.gen(function* () {\n const before = yield* fetchLive(news, output);\n let id: number | undefined;\n if (before === undefined) {\n const body = createBody(news);\n yield* guardBody(spec.endpoint.create, body, true);\n yield* paperless('POST', `${spec.collection}/`, body);\n } else {\n id = typeof before['id'] === 'number' ? before['id'] : undefined;\n // ⚠️ RE-CHECKED HERE, NOT ONLY IN `diff` — an adoption's first reconcile can run with\n // no prior `diff` at all, and `immutable` guards a write that would destroy data.\n const refusal = spec.immutable?.(before, news);\n if (refusal !== undefined) return yield* Effect.die(new Error(refusal));\n if (spec.endpoint.update !== undefined) {\n const body = patchBody(news, before);\n if (Object.keys(body).length > 0) {\n yield* guardBody(spec.endpoint.update, body, false);\n yield* paperless('PATCH', `${objectPath(before)}/`, body);\n }\n }\n }\n // ★ READ BACK BY id WHEN WE HAVE ONE — a just-PATCHed row is read back by the id we\n // wrote to, not by (possibly just-changed) name, so a rename's own read-back cannot\n // fail the way the write it follows no longer can either. A fresh create has no id yet\n // to read back by, so that branch still reads back by the name it just created.\n const after = yield* id === undefined ? read(news) : readById(news, id);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n `${spec.describe(news)}: the write returned no error but the object is still absent.`,\n ),\n );\n }\n return after;\n }),\n\n /**\n * ⛔ `output.id` FIRST, SAME SWITCH AS `fetchLive` (PR 163 re-review). The engine always\n * passes `output` here too (`Apply.ts`'s delete call sites all carry `output: attr`) —\n * `olds` is only the PROPS as last persisted, which drifts from the live object exactly\n * the way `news` did pre-fix: rename it out of band (by hand, or by another tool) after\n * the last successful reconcile, and a name-only locate silently finds nothing, `destroy`\n * returns as if there were nothing to delete, and the engine drops the state row anyway —\n * reporting \"deleted\" while the live object survives, permanently orphaned (the same\n * consequence `matching.ts`'s header describes for the original bug, on the delete path\n * the original fix didn't touch). A 404 on the `output.id` itself is NOT an error here,\n * unlike `fetchLive`'s die — it means the object is already gone, which is exactly the\n * idempotent success `delete` is supposed to report (S11, alchemy-provider-standard).\n */\n destroy: (olds: Props, output: Attributes | undefined) =>\n Effect.gen(function* () {\n const live = output === undefined ? yield* fetchByName(olds) : yield* fetchById(output.id);\n if (live === undefined) return;\n yield* absentOn404(paperless('DELETE', `${objectPath(live)}/`));\n }),\n };\n};\n\n/** The five provider handlers for a spec'd Paperless taxonomy object, wired once. */\nexport const matchingHandlers = <\n Props extends MatchingProps,\n Attributes extends { readonly id: number },\n>(\n spec: MatchingSpec<Props, Attributes>,\n) => {\n const ops = matchingOperations(spec);\n return {\n /** ⚠️ `[]` — Paperless index endpoints return the whole estate; adoption stays explicit. */\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: Props }) =>\n ops\n .read(olds)\n .pipe(Effect.map((attrs) => (attrs === undefined ? undefined : Unowned(attrs)))),\n diff: ({ news, output }: { news: Input<Props>; output: Attributes | undefined }) =>\n ops.diff(news, output),\n // ⛔ `output` IS WHAT MAKES THE IDENTITY FIX WORK (PR 163) — the engine always passes it\n // (`Provider.ts#reconcile`), so it is optional here only so a test can still call\n // `reconcile({ news })` for a from-nothing create without spelling out `output: undefined`.\n // ⚠️ `| undefined` on the optional type itself, not just `?` — `exactOptionalPropertyTypes`\n // otherwise refuses the engine's own `output: Attributes | undefined` at the call site.\n reconcile: ({ news, output }: { news: Props; output?: Attributes | undefined }) =>\n ops.reconcile(news, output),\n // ⚠️ `output` PASSED THROUGH, NOT DROPPED — see `destroy`'s own header above (PR 163\n // re-review). Same `| undefined` reasoning as `reconcile` just above.\n delete: ({ olds, output }: { olds: Props; output?: Attributes | undefined }) =>\n ops.destroy(olds, output),\n };\n};\n",
|
|
16
|
-
"/**\n *
|
|
17
|
-
"/**\n *
|
|
18
|
-
"/**\n * `Paperless.
|
|
19
|
-
"/**\n * `Paperless.
|
|
20
|
-
"/**\n *
|
|
21
|
-
"/**\n * All four Paperless taxonomy providers, one credentials layer shared between them.\n *\n * Layer.mergeAll(paperlessProviders(), …the stack's other providers)\n *\n * ⚠️ `HttpClient.HttpClient` IS NOT BUNDLED HERE, and that follows `../netbox/index.ts` and\n * `../forgejo/client.ts`'s own precedent (its header: \"the idiom Alchemy's own providers\n * follow — `Hetzner/Providers.ts` builds on `FetchHttpClient.layer`\") rather than diverging\n * from it: the transport is the consuming STACK's choice (`FetchHttpClient.layer` in\n * production, a fake `HttpClient` in a test), not a house default a provider file should pin.\n */\nimport * as Layer from 'effect/Layer';\nimport { CustomFieldProvider } from './custom-field.ts';\nimport { DocumentTypeProvider } from './document-type.ts';\nimport { type PaperlessCredentials, environmentLayer } from './credentials.ts';\nimport { StoragePathProvider } from './storage-path.ts';\nimport { TagProvider } from './tag.ts';\n\nexport const paperlessProviders = (\n credentials: Layer.Layer<PaperlessCredentials> = environmentLayer,\n) =>\n Layer.mergeAll(\n TagProvider(),\n DocumentTypeProvider(),\n StoragePathProvider(),\n CustomFieldProvider(),\n ).pipe(Layer.provide(credentials));\n"
|
|
12
|
+
"/**\n * `Paperless.Tag` — a Paperless-ngx tag, create-or-update and never deleted by default.\n *\n * ★ `matchingAlgorithm` AND THE OTHER ENUM-SHAPED FIELDS ARE INDEXED OFF THE GENERATED REQUEST\n * TYPE (`PaperlessTagRequest['matching_algorithm']`), NEVER RETYPED — see this family's header\n * in `docs/paperless.md`. Unchanged by the 2026-09-24 transport migration below: that generated\n * table is `codegen/paperless.ts`'s own concern, not `@distilled.cloud/paperless-ngx`'s.\n *\n * ⛔ NO CREDENTIAL IS A PROP. `PAPERLESS_URL`/`PAPERLESS_TOKEN` come from\n * `@distilled.cloud/paperless-ngx`'s `CredentialsFromEnv` (matching.ts), the same two variable\n * names the retired hand-rolled `credentials.ts` read.\n * ⛔ `defaultRemovalPolicy: 'retain'` — the reconciler this replaces never deletes taxonomy, and\n * a tag's id is referenced by every document it is attached to.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as tags from '@distilled.cloud/paperless-ngx/tags';\nimport * as Effect from 'effect/Effect';\nimport type { PaperlessTagRequest } from './generated/types/tags.ts';\nimport {\n LOCATE_PAGE,\n type MatchingRequirements,\n type MatchingSpec,\n matchingHandlers,\n} from './matching.ts';\n\nexport interface TagProps {\n /** ⚠️ maxLength 128 (generated constraint table). The locate key — see matching.ts's header. */\n name: string;\n owner?: number;\n /** ⚠️ minLength 1, maxLength 7 (a CSS hex color, generated table doesn't enforce the `#`). */\n color?: string;\n /** ⚠️ maxLength 256. The text or pattern documents are matched against. */\n match?: string;\n matchingAlgorithm?: PaperlessTagRequest['matching_algorithm'];\n isInsensitive?: boolean;\n /** Marks this tag as an inbox tag: newly consumed documents are tagged with it. */\n isInboxTag?: boolean;\n /** Another `Paperless.Tag`'s id — Paperless allows one level of tag nesting. */\n parent?: number;\n}\n\nexport interface TagAttributes {\n id: number;\n name: string;\n color: string;\n match: string;\n matchingAlgorithm: number;\n isInsensitive: boolean;\n isInboxTag: boolean;\n owner: number | undefined;\n parent: number | undefined;\n}\n\nexport interface Tag extends Resource<\n 'Paperless.Tag',\n TagProps,\n TagAttributes,\n never,\n MatchingRequirements\n> {}\n\nexport const Tag = Resource<Tag>('Paperless.Tag', { defaultRemovalPolicy: 'retain' });\n\n/**\n * ★ EXPORTED, NOT JUST PASSED INLINE — so a test can call `matchingOperations(spec)` directly\n * (tag.test.ts does), against an explicit fake `Credentials` layer, without touching\n * `matchingHandlers`'s baked-in `CredentialsFromEnv` — the same seam `../forgejo/repository.ts`\n * and `../netbox/prefix.ts` use.\n */\nexport const spec: MatchingSpec<\n TagProps,\n tags.Tag,\n TagAttributes,\n | tags.CreateTagError\n | tags.GetTagError\n | tags.ListTagsError\n | tags.UpdateTagsPartialError\n | tags.TagsDestroyError\n> = {\n attributes: (live, props) => ({\n color: live.color ?? '',\n id: live.id,\n isInboxTag: live.is_inbox_tag === true,\n isInsensitive: live.is_insensitive === true,\n match: live.match ?? '',\n matchingAlgorithm: live.matching_algorithm ?? 0,\n name: live.name,\n owner: live.owner ?? undefined,\n parent: live.parent ?? undefined,\n }),\n create: (body) => tags.createTag(body as unknown as tags.CreateTagRequest),\n describe: (props) => `tags ${props.name}`,\n destroy: (id) => tags.tagsDestroy({ id }),\n endpoint: { create: 'paperless:POST /api/tags/', update: 'paperless:PATCH /api/tags/{id}/' },\n fields: [\n { key: 'color', live: (r) => r.color, prop: (p) => p.color },\n { key: 'match', live: (r) => r.match, prop: (p) => p.match },\n {\n key: 'matching_algorithm',\n live: (r) => r.matching_algorithm,\n prop: (p) => p.matchingAlgorithm,\n },\n { key: 'is_insensitive', live: (r) => r.is_insensitive, prop: (p) => p.isInsensitive },\n { key: 'is_inbox_tag', live: (r) => r.is_inbox_tag, prop: (p) => p.isInboxTag },\n { key: 'parent', live: (r) => r.parent, prop: (p) => p.parent },\n ],\n getById: (id) =>\n tags.getTag({ id }).pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n list: (props) => tags.listTags({ name__iexact: props.name, page_size: LOCATE_PAGE }),\n ownerOf: (live) => live.owner ?? undefined,\n update: (id, body) =>\n tags.updateTagsPartial({\n ...(body as unknown as Omit<tags.UpdateTagsPartialRequest, 'id'>),\n id,\n }),\n};\n\nexport const handlers = matchingHandlers(spec);\n\nexport const TagProvider = () => Provider.effect(Tag, Effect.succeed(Tag.Provider.of(handlers)));\n",
|
|
13
|
+
"/**\n * One shape for every Paperless taxonomy object (Tag, DocumentType, StoragePath, CustomField):\n * locate by `name__iexact` only while there is no prior state, identify the exact (name, owner),\n * create-or-update, never delete by default. Modelled on `../netbox/resource.ts`'s\n * `netboxOperations` and `../forgejo/resource.ts`'s `forgejoOperations`.\n *\n * 🔴 WHY THIS REPLACED `client.ts`'s HAND-ROLLED `HttpClient` CALLS (2026-09-24, decision 43).\n * Measured against Tim's distilled research page 2026-09-23: upstream Alchemy only accepts\n * providers that call `@distilled.cloud/<vendor>` operations and `catchTag` their typed errors\n * — not a raw `fetch`/`HttpClient` client over a hand-maintained path table.\n * `@distilled.cloud/paperless-ngx` (aliased onto `@homeflare/distilled-paperless-ngx@0.3.0` —\n * docs/distilled-interim.md) covers every operation this family calls; its 404/400 shapes were\n * already live-measured (kit PR 194) before this migration touched a resource file.\n *\n * ⛔ THE CREATE BODY ALWAYS CARRIES `owner`, NULL WHEN UNDECLARED. `OwnedObjectSerializer.create`\n * sets the owner to the TOKEN USER when the field is absent from the body (Paperless-ngx\n * `documents/serialisers.py:495-502` at v3.1.1) — omitting it the way NetBox's `prefix-form.ts`\n * omits an undeclared foreign key would silently create an object owned by whichever credential\n * ran the deploy, invisible to every other user and a second row beside the estate's `owner:\n * null` one on the next apply. Sending `owner: null` explicitly is what keeps a create\n * idempotent under this vendor's default. Unchanged by the transport swap.\n *\n * ★ READ ANSWERS `Unowned(attrs)` ON EVERY MATCH (H1, alchemy-provider-standard). Paperless has no\n * ownership marker this package could check — `owner` here is the estate's OWN prop, not proof\n * of who created the row — so, per the house's 2026-09-21 decision, identical is not ours: a\n * live match never adopts silently.\n *\n * ⛔ IDENTITY IS THE STORED `id`, NOT `name`/`owner`, ONCE A RESOURCE HAS STATE (PR 163, red-team\n * HIGH finding — see `matching-locate.ts`'s `fetchLive` for the fix and the full history). This\n * migration keeps that fix byte-for-byte: only the wire call under `fetchByName`/`fetchById`\n * changed, not the switch itself.\n */\nimport { Unowned } from 'alchemy/AdoptPolicy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport { CredentialsFromEnv } from '@distilled.cloud/paperless-ngx/Credentials';\nimport type { PaperlessNgxOpContext } from '@distilled.cloud/paperless-ngx/Protocol';\nimport * as Effect from 'effect/Effect';\nimport { guardBody } from './constraint-guard.ts';\nimport type { PaperlessBody } from './constraints.ts';\nimport { fetchLive as identitySwitch, locateOne } from './matching-locate.ts';\nimport type { MatchingProps, MatchingSpec } from './matching-types.ts';\n\n/** Re-exported so `tag.ts`/`document-type.ts`/`storage-path.ts`/`custom-field.ts` keep importing the contract from `./matching.ts` — only the shape itself lives in `matching-types.ts`, split out to hold the file-size cap. */\nexport type {\n FieldSpec,\n MatchingPage,\n MatchingProps,\n MatchingRequirements,\n MatchingSpec,\n} from './matching-types.ts';\nexport { LOCATE_PAGE, soleMatch } from './matching-locate.ts';\n\n/** Object equality good enough for this family's scalars, nullable ints and `extra_data` JSON. */\nconst sameValue = (a: unknown, b: unknown): boolean =>\n typeof a === 'object' && a !== null ? JSON.stringify(a) === JSON.stringify(b) : Object.is(a, b);\n\nexport const matchingOperations = <\n Props extends MatchingProps,\n Live extends { readonly id: number; readonly name: string },\n Attributes extends { readonly id: number },\n E,\n>(\n spec: MatchingSpec<Props, Live, Attributes, E>,\n) => {\n const ownerOf = (live: Live): number | undefined =>\n spec.owned === false || spec.ownerOf === undefined ? undefined : spec.ownerOf(live);\n\n const ownerMatches = (live: Live, props: Props): boolean =>\n spec.owned === false || spec.ownerOf === undefined\n ? true\n : spec.ownerOf(live) === (props.owner ?? undefined);\n\n /** ★ THE NO-STATE LOCATE — see matching-locate.ts's `locateOne` and this file's own header. */\n const fetchByName = (props: Props) =>\n locateOne(\n spec.list(props),\n spec.describe(props),\n (row) => row.name === props.name && ownerMatches(row, props),\n );\n\n /** Already folds a 404 — each resource file's own `.pipe(Effect.catchTag('NotFound', …))`. */\n const fetchById = spec.getById;\n\n const fetchLive = (props: Props, output: Attributes | undefined) =>\n identitySwitch(props, output, fetchByName, fetchById, spec.describe);\n\n /** ⚠️ ALWAYS NAME-BASED — this is `read`'s own contract (S7): find the object from props alone, with no `output` to consult. */\n const read = (props: Props) =>\n fetchByName(props).pipe(\n Effect.map((live) => (live === undefined ? undefined : spec.attributes(live, props))),\n );\n\n const readById = (props: Props, id: number) =>\n fetchById(id).pipe(\n Effect.map((live) => (live === undefined ? undefined : spec.attributes(live, props))),\n );\n\n const createBody = (props: Props): PaperlessBody => {\n const out: PaperlessBody =\n spec.owned === false\n ? { name: props.name }\n : { name: props.name, owner: props.owner ?? null };\n for (const field of [...spec.fields, ...(spec.createOnly ?? [])]) {\n const value = field.prop(props);\n if (value !== undefined) out[field.key] = value;\n }\n return out;\n };\n\n /** ⚠️ Only fields that DIFFER from the live row. `name`/`owner` are compared too (PR 163). */\n const patchBody = (props: Props, live: Live): PaperlessBody => {\n const out: PaperlessBody = {};\n if (props.name !== live.name) out['name'] = props.name;\n if (spec.owned !== false && ownerOf(live) !== (props.owner ?? undefined)) {\n out['owner'] = props.owner ?? null;\n }\n for (const field of spec.fields) {\n const value = field.prop(props);\n if (value !== undefined && !sameValue(value, field.live(live))) out[field.key] = value;\n }\n return out;\n };\n\n const matches = (props: Props, live: Live): boolean => {\n if (props.name !== live.name) return false;\n if (spec.owned !== false && ownerOf(live) !== (props.owner ?? undefined)) return false;\n return spec.fields.every((field) => {\n const value = field.prop(props);\n return value === undefined || sameValue(value, field.live(live));\n });\n };\n\n return {\n read,\n\n diff: (news: Input<Props>, output: Attributes | undefined) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* fetchLive(news, output);\n if (live === undefined) return { action: 'update' } as const;\n const refusal = spec.immutable?.(live, news);\n if (refusal !== undefined) return yield* Effect.die(new Error(refusal));\n if (matches(news, live)) return { action: 'noop' } as const;\n return spec.update === undefined\n ? ({ action: 'replace' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: (news: Props, output: Attributes | undefined) =>\n Effect.gen(function* () {\n const before = yield* fetchLive(news, output);\n let id: number | undefined;\n if (before === undefined) {\n const body = createBody(news);\n yield* guardBody(spec.endpoint.create, body, true);\n yield* spec.create(body);\n } else {\n id = before.id;\n const refusal = spec.immutable?.(before, news);\n if (refusal !== undefined) return yield* Effect.die(new Error(refusal));\n if (spec.update !== undefined) {\n const body = patchBody(news, before);\n if (Object.keys(body).length > 0) {\n yield* guardBody(spec.endpoint.update, body, false);\n yield* spec.update(id, body);\n }\n }\n }\n const after = yield* id === undefined ? read(news) : readById(news, id);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n `${spec.describe(news)}: the write returned no error but the object is still absent.`,\n ),\n );\n }\n return after;\n }),\n\n /** ⛔ `output.id` FIRST, SAME SWITCH AS `fetchLive` (PR 163 re-review). A 404 on `output.id` is idempotent success, not an error, unlike `fetchLive`'s die. */\n destroy: (olds: Props, output: Attributes | undefined) =>\n Effect.gen(function* () {\n const live = output === undefined ? yield* fetchByName(olds) : yield* fetchById(output.id);\n if (live === undefined) return;\n yield* spec.destroy(live.id);\n }),\n };\n};\n\n/**\n * The five provider handlers for a spec'd Paperless taxonomy object, wired once.\n *\n * ★ CREDENTIALS ARE PROVIDED HERE, ONCE, NOT BY EVERY CALLER — the same shape\n * `netboxHandlers`/`forgejoHandlers` use. `CredentialsFromEnv` resolves `PAPERLESS_URL` /\n * `PAPERLESS_TOKEN` on the calling fiber per request, so this closure keeps that laziness —\n * nothing is captured at module load. ⛔ THE TOKEN IS NEVER A PROP.\n */\nexport const matchingHandlers = <\n Props extends MatchingProps,\n Live extends { readonly id: number; readonly name: string },\n Attributes extends { readonly id: number },\n E,\n>(\n spec: MatchingSpec<Props, Live, Attributes, E>,\n) => {\n const ops = matchingOperations(spec);\n const withCredentials = <A>(effect: Effect.Effect<A, E, PaperlessNgxOpContext>) =>\n Effect.provide(effect, CredentialsFromEnv);\n return {\n /** ⚠️ `[]` — Paperless index endpoints return the whole estate; adoption stays explicit. */\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: Props }) =>\n withCredentials(\n ops\n .read(olds)\n .pipe(Effect.map((attrs) => (attrs === undefined ? undefined : Unowned(attrs)))),\n ),\n diff: ({ news, output }: { news: Input<Props>; output: Attributes | undefined }) =>\n withCredentials(ops.diff(news, output)),\n reconcile: ({ news, output }: { news: Props; output?: Attributes | undefined }) =>\n withCredentials(ops.reconcile(news, output)),\n delete: ({ olds, output }: { olds: Props; output?: Attributes | undefined }) =>\n withCredentials(ops.destroy(olds, output)),\n };\n};\n",
|
|
14
|
+
"/**\n * The identity-resolution slice of `matching.ts`'s lifecycle, split into its own file so\n * `matching.ts` stays under the house's 250-line-per-file cap. Owns exactly one question — which\n * live Paperless row IS this declaration — by name while there is no state, by the stored\n * `output.id` once there is one. See `matching.ts`'s header for the PR 163 red-team HIGH finding\n * this identity switch fixes.\n *\n * ★ EVERY EXPORT HERE IS GENERIC OVER `R`, NOT TIED TO `PaperlessNgxOpContext` — mirroring\n * `../netbox/resource.ts`'s standalone `locateOne`. `matching.ts` wires these against a real\n * spec's `PaperlessNgxOpContext`-typed operations; `matching-locate.test.ts` wires them against\n * plain `Effect.succeed` fixtures (`R = never`) — the same function, no fake HTTP needed to\n * prove the pure rule.\n *\n * ⚠️ `NotFound` IS FOLDED TO \"ABSENT\" INSIDE EACH RESOURCE FILE'S OWN `spec.getById`, NOT HERE —\n * the direct successor to the old, centralized `absentOn404`, and the same split\n * `../netbox/resource.ts` and `../forgejo/resource.ts` use. `Effect.catchTag`'s tag-literal\n * inference needs a concrete error union to resolve `\"NotFound\"` against; a spec's `E` is only\n * concrete at each resource file's own call site (`GetTagError`, `GetDocumentTypeError`, …). A\n * LIST call is never folded here either — an empty `results` page is a normal 200, not a 404\n * (measured live, kit PR 194).\n */\nimport * as Effect from 'effect/Effect';\n\n/**\n * ★ Wide enough to see every case-variant candidate `name__iexact` returns; a natural key past it\n * is not one. Unchanged from the pre-migration `client.ts`'s own value.\n */\nexport const LOCATE_PAGE = 20;\n\n/**\n * The single row a filtered list returns, or `undefined`.\n *\n * ⛔ MORE THAN ONE MATCH IS A DEFECT, NOT A REASON TO TAKE THE FIRST. If an ambiguous match took\n * the first row, adopt would bind to it, the next plan would bind to the other, and every plan\n * after that would report drift that is not there — while \"fixing\" it PATCHed one object with\n * the other's declaration. Failing loudly is the only outcome an operator can act on.\n */\nexport const soleMatch = <T>(rows: readonly T[], describe: string): T | undefined => {\n if (rows.length > 1) {\n throw new Error(\n `${describe} matched ${String(rows.length)} Paperless objects with the same (name, owner).`,\n );\n }\n return rows[0];\n};\n\n/**\n * List, then narrow to at most one candidate. Any Paperless resource whose locate is \"filter\n * server-side, then disambiguate in this process\" reaches this once rather than reimplementing\n * the page-width assertion and the ambiguity defect per resource.\n */\nexport const locateOne = <Live, E, R>(\n list: Effect.Effect<{ readonly count: number; readonly results: readonly Live[] }, E, R>,\n describe: string,\n identifies?: (row: Live) => boolean,\n): Effect.Effect<Live | undefined, E, R> =>\n list.pipe(\n Effect.map((page) => {\n if (page.count > LOCATE_PAGE) {\n throw new Error(\n `${describe}: name__iexact matched ${String(page.count)} rows, more than the ` +\n `${String(LOCATE_PAGE)}-row page this reads. Narrow the name rather than paging.`,\n );\n }\n const rows = identifies === undefined ? page.results : page.results.filter(identifies);\n return soleMatch(rows, describe);\n }),\n );\n\n/**\n * ⛔ THE IDENTITY SWITCH (PR 163, red-team HIGH finding — see `matching.ts`'s header). `output`\n * defined means this declaration has already written something: identity is `output.id`, full\n * stop, and a changed `name`/`owner` in the caller's props is drift to PATCH, never a reason to\n * relocate. `output` undefined means there is nothing to be wrong about yet — locate by name.\n */\nexport const fetchLive = <Props, Live, Attributes extends { readonly id: number }, E, R>(\n props: Props,\n output: Attributes | undefined,\n fetchByName: (props: Props) => Effect.Effect<Live | undefined, E, R>,\n fetchById: (id: number) => Effect.Effect<Live | undefined, E, R>,\n describe: (props: Props) => string,\n): Effect.Effect<Live | undefined, E, R> =>\n output === undefined\n ? fetchByName(props)\n : fetchById(output.id).pipe(\n Effect.flatMap((live) =>\n live === undefined\n ? Effect.die(\n new Error(\n `${describe(props)}: id ${String(output.id)} is recorded in state but no ` +\n 'longer exists live (deleted out of band). Refusing to create a replacement ' +\n '— adopt the live object back under this declaration, or remove it from ' +\n 'state, before deploying again.',\n ),\n )\n : Effect.succeed(live),\n ),\n );\n",
|
|
15
|
+
"/**\n * `Paperless.DocumentType` — a Paperless-ngx document type, create-or-update and never deleted.\n * Same shape as `tag.ts` minus `color`/`isInboxTag`/`parent` — see that file's header for why\n * `matchingAlgorithm`'s type comes off the generated request type rather than being retyped, and\n * for the 2026-09-24 transport migration this file follows exactly.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as documentTypes from '@distilled.cloud/paperless-ngx/document_types';\nimport * as Effect from 'effect/Effect';\nimport type { PaperlessDocumentTypeRequest } from './generated/types/document-types.ts';\nimport {\n LOCATE_PAGE,\n type MatchingRequirements,\n type MatchingSpec,\n matchingHandlers,\n} from './matching.ts';\n\nexport interface DocumentTypeProps {\n /** ⚠️ maxLength 128 (generated constraint table). The locate key. */\n name: string;\n owner?: number;\n /** ⚠️ maxLength 256. */\n match?: string;\n matchingAlgorithm?: PaperlessDocumentTypeRequest['matching_algorithm'];\n isInsensitive?: boolean;\n}\n\nexport interface DocumentTypeAttributes {\n id: number;\n name: string;\n match: string;\n matchingAlgorithm: number;\n isInsensitive: boolean;\n owner: number | undefined;\n}\n\nexport interface DocumentType extends Resource<\n 'Paperless.DocumentType',\n DocumentTypeProps,\n DocumentTypeAttributes,\n never,\n MatchingRequirements\n> {}\n\nexport const DocumentType = Resource<DocumentType>('Paperless.DocumentType', {\n defaultRemovalPolicy: 'retain',\n});\n\n/** ★ Exported for direct testing — see tag.ts's own note on this seam. */\nexport const spec: MatchingSpec<\n DocumentTypeProps,\n documentTypes.DocumentType,\n DocumentTypeAttributes,\n | documentTypes.CreateDocumentTypeError\n | documentTypes.GetDocumentTypeError\n | documentTypes.ListDocumentTypesError\n | documentTypes.UpdateDocumentTypesPartialError\n | documentTypes.DocumentTypesDestroyError\n> = {\n attributes: (live, props) => ({\n id: live.id,\n isInsensitive: live.is_insensitive === true,\n match: live.match ?? '',\n matchingAlgorithm: live.matching_algorithm ?? 0,\n name: live.name,\n owner: live.owner ?? undefined,\n }),\n create: (body) =>\n documentTypes.createDocumentType(body as unknown as documentTypes.CreateDocumentTypeRequest),\n describe: (props) => `document_types ${props.name}`,\n destroy: (id) => documentTypes.documentTypesDestroy({ id }),\n endpoint: {\n create: 'paperless:POST /api/document_types/',\n update: 'paperless:PATCH /api/document_types/{id}/',\n },\n fields: [\n { key: 'match', live: (r) => r.match, prop: (p) => p.match },\n {\n key: 'matching_algorithm',\n live: (r) => r.matching_algorithm,\n prop: (p) => p.matchingAlgorithm,\n },\n { key: 'is_insensitive', live: (r) => r.is_insensitive, prop: (p) => p.isInsensitive },\n ],\n getById: (id) =>\n documentTypes\n .getDocumentType({ id })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n list: (props) =>\n documentTypes.listDocumentTypes({ name__iexact: props.name, page_size: LOCATE_PAGE }),\n ownerOf: (live) => live.owner ?? undefined,\n update: (id, body) =>\n documentTypes.updateDocumentTypesPartial({\n ...(body as unknown as Omit<documentTypes.UpdateDocumentTypesPartialRequest, 'id'>),\n id,\n }),\n};\n\nexport const handlers = matchingHandlers(spec);\n\nexport const DocumentTypeProvider = () =>\n Provider.effect(DocumentType, Effect.succeed(DocumentType.Provider.of(handlers)));\n",
|
|
16
|
+
"/**\n * `Paperless.StoragePath` — a Paperless-ngx storage path template, create-or-update and never\n * deleted. Same shape as `document-type.ts` plus the vendor-required `path` template string; see\n * `tag.ts`'s header for the 2026-09-24 transport migration this file follows exactly.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as storagePaths from '@distilled.cloud/paperless-ngx/storage_paths';\nimport * as Effect from 'effect/Effect';\nimport type { PaperlessStoragePathRequest } from './generated/types/storage-paths.ts';\nimport {\n LOCATE_PAGE,\n type MatchingRequirements,\n type MatchingSpec,\n matchingHandlers,\n} from './matching.ts';\n\nexport interface StoragePathProps {\n /** ⚠️ maxLength 128 (generated constraint table). The locate key. */\n name: string;\n owner?: number;\n /** ⚠️ minLength 1 (generated table). Paperless's storage-path template syntax, e.g. `{correspondent}/{title}`. */\n path: string;\n /** ⚠️ maxLength 256. */\n match?: string;\n matchingAlgorithm?: PaperlessStoragePathRequest['matching_algorithm'];\n isInsensitive?: boolean;\n}\n\nexport interface StoragePathAttributes {\n id: number;\n name: string;\n path: string;\n match: string;\n matchingAlgorithm: number;\n isInsensitive: boolean;\n owner: number | undefined;\n}\n\nexport interface StoragePath extends Resource<\n 'Paperless.StoragePath',\n StoragePathProps,\n StoragePathAttributes,\n never,\n MatchingRequirements\n> {}\n\nexport const StoragePath = Resource<StoragePath>('Paperless.StoragePath', {\n defaultRemovalPolicy: 'retain',\n});\n\n/** ★ Exported for direct testing — see tag.ts's own note on this seam. */\nexport const spec: MatchingSpec<\n StoragePathProps,\n storagePaths.StoragePath,\n StoragePathAttributes,\n | storagePaths.CreateStoragePathError\n | storagePaths.GetStoragePathError\n | storagePaths.ListStoragePathsError\n | storagePaths.UpdateStoragePathsPartialError\n | storagePaths.StoragePathsDestroyError\n> = {\n attributes: (live, props) => ({\n id: live.id,\n isInsensitive: live.is_insensitive === true,\n match: live.match ?? '',\n matchingAlgorithm: live.matching_algorithm ?? 0,\n name: live.name,\n owner: live.owner ?? undefined,\n path: live.path,\n }),\n create: (body) =>\n storagePaths.createStoragePath(body as unknown as storagePaths.CreateStoragePathRequest),\n describe: (props) => `storage_paths ${props.name}`,\n destroy: (id) => storagePaths.storagePathsDestroy({ id }),\n endpoint: {\n create: 'paperless:POST /api/storage_paths/',\n update: 'paperless:PATCH /api/storage_paths/{id}/',\n },\n fields: [\n { key: 'path', live: (r) => r.path, prop: (p) => p.path },\n { key: 'match', live: (r) => r.match, prop: (p) => p.match },\n {\n key: 'matching_algorithm',\n live: (r) => r.matching_algorithm,\n prop: (p) => p.matchingAlgorithm,\n },\n { key: 'is_insensitive', live: (r) => r.is_insensitive, prop: (p) => p.isInsensitive },\n ],\n getById: (id) =>\n storagePaths\n .getStoragePath({ id })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n list: (props) =>\n storagePaths.listStoragePaths({ name__iexact: props.name, page_size: LOCATE_PAGE }),\n ownerOf: (live) => live.owner ?? undefined,\n update: (id, body) =>\n storagePaths.updateStoragePathsPartial({\n ...(body as unknown as Omit<storagePaths.UpdateStoragePathsPartialRequest, 'id'>),\n id,\n }),\n};\n\nexport const handlers = matchingHandlers(spec);\n\nexport const StoragePathProvider = () =>\n Provider.effect(StoragePath, Effect.succeed(StoragePath.Provider.of(handlers)));\n",
|
|
17
|
+
"/**\n * `Paperless.CustomField` — a Paperless-ngx custom field, create-or-update and never deleted.\n *\n * ⛔ `dataType` IS CREATE-ONLY, ENFORCED AT PLAN TIME, NEVER A PATCH AND NEVER A REPLACE. A\n * replace would delete this id and create a new one — and Paperless deletes the field's VALUE\n * on every document when its custom field is deleted. `matching.ts`'s `immutable` hook carries\n * this refusal generically; `dataType` is simply never listed in `fields`, so nothing in\n * `matching.ts` ever builds a PATCH body that includes it.\n *\n * ⛔ NO `owner` FIELD, AND NO `ownerOf` SPEC ENTRY. Unlike `Tag`/`DocumentType`/`StoragePath`,\n * `CustomField` does not extend Paperless-ngx's `OwnedObjectSerializer` — its wire body is\n * exactly `{name, data_type, extra_data}` (measured against the v3.1.1 schema, and confirmed\n * again in `@distilled.cloud/paperless-ngx`'s generated `custom_fields.ts`, which has no\n * `owner` field either). `owned: false` stops `matching.ts` sending or comparing one.\n *\n * ⚠️ `CustomField.select_options` (the vendor's own rule for a `select` field's option list) is\n * not in the served schema at all, so it is recorded here and NOT enforced (groundTruth). See\n * `tag.ts`'s header for the 2026-09-24 transport migration this file follows.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as customFields from '@distilled.cloud/paperless-ngx/custom_fields';\nimport * as Effect from 'effect/Effect';\nimport type { PaperlessCustomFieldRequest } from './generated/types/custom-fields.ts';\nimport {\n LOCATE_PAGE,\n type MatchingRequirements,\n type MatchingSpec,\n matchingHandlers,\n} from './matching.ts';\n\nexport interface CustomFieldProps {\n /** ⚠️ maxLength 128 (generated constraint table). CustomField's name is globally unique (models.py:1169), with no owner to further scope it. */\n name: string;\n /** ⛔ CREATE-ONLY — see this file's header. `select`'s own option list (`select_options`) is not in the vendor schema and is unenforced here. */\n dataType: PaperlessCustomFieldRequest['data_type'];\n /** Arbitrary JSON the vendor attaches no schema to (e.g. a `select` field's option list). */\n extraData?: unknown;\n}\n\nexport interface CustomFieldAttributes {\n id: number;\n name: string;\n dataType: string;\n extraData: unknown;\n}\n\nexport interface CustomField extends Resource<\n 'Paperless.CustomField',\n CustomFieldProps,\n CustomFieldAttributes,\n never,\n MatchingRequirements\n> {}\n\nexport const CustomField = Resource<CustomField>('Paperless.CustomField', {\n defaultRemovalPolicy: 'retain',\n});\n\n/**\n * ⛔ EXTRACTED SO IT CAN BE TESTED WITHOUT A SERVER (custom-field.test.ts). `Pick<…, 'data_type'>`\n * rather than the full `CustomField`, so a test fixture need not spell out `name`/`document_count`.\n */\nexport const dataTypeImmutable = (\n live: Pick<customFields.CustomField, 'data_type'>,\n props: CustomFieldProps,\n): string | undefined =>\n live.data_type !== props.dataType\n ? `Paperless.CustomField \"${props.name}\": data_type is create-only (live: ${live.data_type}, ` +\n `declared: ${props.dataType}). Changing it would delete this field's value on every ` +\n 'document. Create a new custom field instead, and retire this one by hand.'\n : undefined;\n\n/** ★ Exported for direct testing — see tag.ts's own note on this seam. */\nexport const spec: MatchingSpec<\n CustomFieldProps,\n customFields.CustomField,\n CustomFieldAttributes,\n | customFields.CreateCustomFieldError\n | customFields.GetCustomFieldError\n | customFields.ListCustomFieldsError\n | customFields.UpdateCustomFieldsPartialError\n | customFields.CustomFieldsDestroyError\n> = {\n attributes: (live, props) => ({\n dataType: live.data_type ?? props.dataType,\n extraData: live.extra_data,\n id: live.id,\n name: live.name,\n }),\n create: (body) =>\n customFields.createCustomField(body as unknown as customFields.CreateCustomFieldRequest),\n createOnly: [{ key: 'data_type', live: (r) => r.data_type, prop: (p) => p.dataType }],\n describe: (props) => `custom_fields ${props.name}`,\n destroy: (id) => customFields.customFieldsDestroy({ id }),\n endpoint: {\n create: 'paperless:POST /api/custom_fields/',\n update: 'paperless:PATCH /api/custom_fields/{id}/',\n },\n fields: [{ key: 'extra_data', live: (r) => r.extra_data, prop: (p) => p.extraData }],\n getById: (id) =>\n customFields\n .getCustomField({ id })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n immutable: dataTypeImmutable,\n list: (props) =>\n customFields.listCustomFields({ name__iexact: props.name, page_size: LOCATE_PAGE }),\n owned: false,\n update: (id, body) =>\n customFields.updateCustomFieldsPartial({\n ...(body as unknown as Omit<customFields.UpdateCustomFieldsPartialRequest, 'id'>),\n id,\n }),\n};\n\nexport const customFieldHandlers = matchingHandlers(spec);\n\nexport const CustomFieldProvider = () =>\n Provider.effect(CustomField, Effect.succeed(CustomField.Provider.of(customFieldHandlers)));\n",
|
|
18
|
+
"/**\n * All four Paperless taxonomy providers.\n *\n * Layer.mergeAll(paperlessProviders(), …the stack's other providers)\n *\n * ⚠️ `HttpClient.HttpClient` IS NOT BUNDLED HERE, and that follows `../netbox/index.ts` and\n * `../forgejo/client.ts`'s own precedent: the transport is the consuming STACK's choice\n * (`FetchHttpClient.layer` in production, a fake `HttpClient` in a test), not a house default a\n * provider file should pin.\n *\n * 🔴 NO `credentials` PARAMETER ANY MORE (2026-09-24, the `@distilled.cloud/paperless-ngx`\n * migration — see `matching.ts`'s header). Each of the four `xxxProvider()`s now bakes in\n * `CredentialsFromEnv` itself, the same way `netboxHandlers`/`forgejoHandlers` do — there is no\n * longer a layer for this file to merge in or accept an override for. Nothing in this estate\n * called `paperlessProviders(customLayer)` (measured 2026-09-24: no tray repo declares a\n * Paperless resource at all — grep across `homeflare-landscape`'s tray repos' `origin/main`),\n * so this is an uneventful simplification, not a behaviour change for anything live.\n */\nimport * as Layer from 'effect/Layer';\nimport { CustomFieldProvider } from './custom-field.ts';\nimport { DocumentTypeProvider } from './document-type.ts';\nimport { StoragePathProvider } from './storage-path.ts';\nimport { TagProvider } from './tag.ts';\n\nexport const paperlessProviders = () =>\n Layer.mergeAll(\n TagProvider(),\n DocumentTypeProvider(),\n StoragePathProvider(),\n CustomFieldProvider(),\n );\n"
|
|
22
19
|
],
|
|
23
|
-
"mappings": "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",
|
|
24
|
-
"debugId": "
|
|
20
|
+
"mappings": "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",
|
|
21
|
+
"debugId": "9FA700BA2BD9F67464756E2164756E21",
|
|
25
22
|
"names": []
|
|
26
23
|
}
|
|
@@ -4,30 +4,52 @@
|
|
|
4
4
|
* live Paperless row IS this declaration — by name while there is no state, by the stored
|
|
5
5
|
* `output.id` once there is one. See `matching.ts`'s header for the PR 163 red-team HIGH finding
|
|
6
6
|
* this identity switch fixes.
|
|
7
|
+
*
|
|
8
|
+
* ★ EVERY EXPORT HERE IS GENERIC OVER `R`, NOT TIED TO `PaperlessNgxOpContext` — mirroring
|
|
9
|
+
* `../netbox/resource.ts`'s standalone `locateOne`. `matching.ts` wires these against a real
|
|
10
|
+
* spec's `PaperlessNgxOpContext`-typed operations; `matching-locate.test.ts` wires them against
|
|
11
|
+
* plain `Effect.succeed` fixtures (`R = never`) — the same function, no fake HTTP needed to
|
|
12
|
+
* prove the pure rule.
|
|
13
|
+
*
|
|
14
|
+
* ⚠️ `NotFound` IS FOLDED TO "ABSENT" INSIDE EACH RESOURCE FILE'S OWN `spec.getById`, NOT HERE —
|
|
15
|
+
* the direct successor to the old, centralized `absentOn404`, and the same split
|
|
16
|
+
* `../netbox/resource.ts` and `../forgejo/resource.ts` use. `Effect.catchTag`'s tag-literal
|
|
17
|
+
* inference needs a concrete error union to resolve `"NotFound"` against; a spec's `E` is only
|
|
18
|
+
* concrete at each resource file's own call site (`GetTagError`, `GetDocumentTypeError`, …). A
|
|
19
|
+
* LIST call is never folded here either — an empty `results` page is a normal 200, not a 404
|
|
20
|
+
* (measured live, kit PR 194).
|
|
7
21
|
*/
|
|
8
22
|
import * as Effect from 'effect/Effect';
|
|
9
|
-
import { type PaperlessRow } from './client.ts';
|
|
10
|
-
import type { MatchingError, MatchingProps, MatchingRequirements } from './matching-types.ts';
|
|
11
23
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
24
|
+
* ★ Wide enough to see every case-variant candidate `name__iexact` returns; a natural key past it
|
|
25
|
+
* is not one. Unchanged from the pre-migration `client.ts`'s own value.
|
|
14
26
|
*/
|
|
15
|
-
export declare const
|
|
16
|
-
/** ⚠️ Exported — `matching.ts`'s `patchBody`/`matches` compare the live `owner` too (PR 163). */
|
|
17
|
-
export declare const ownerOf: (row: PaperlessRow) => number | undefined;
|
|
27
|
+
export declare const LOCATE_PAGE = 20;
|
|
18
28
|
/**
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
29
|
+
* The single row a filtered list returns, or `undefined`.
|
|
30
|
+
*
|
|
31
|
+
* ⛔ MORE THAN ONE MATCH IS A DEFECT, NOT A REASON TO TAKE THE FIRST. If an ambiguous match took
|
|
32
|
+
* the first row, adopt would bind to it, the next plan would bind to the other, and every plan
|
|
33
|
+
* after that would report drift that is not there — while "fixing" it PATCHed one object with
|
|
34
|
+
* the other's declaration. Failing loudly is the only outcome an operator can act on.
|
|
21
35
|
*/
|
|
22
|
-
export declare const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
export declare const soleMatch: <T>(rows: readonly T[], describe: string) => T | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* List, then narrow to at most one candidate. Any Paperless resource whose locate is "filter
|
|
39
|
+
* server-side, then disambiguate in this process" reaches this once rather than reimplementing
|
|
40
|
+
* the page-width assertion and the ambiguity defect per resource.
|
|
41
|
+
*/
|
|
42
|
+
export declare const locateOne: <Live, E, R>(list: Effect.Effect<{
|
|
43
|
+
readonly count: number;
|
|
44
|
+
readonly results: readonly Live[];
|
|
45
|
+
}, E, R>, describe: string, identifies?: (row: Live) => boolean) => Effect.Effect<Live | undefined, E, R>;
|
|
46
|
+
/**
|
|
47
|
+
* ⛔ THE IDENTITY SWITCH (PR 163, red-team HIGH finding — see `matching.ts`'s header). `output`
|
|
48
|
+
* defined means this declaration has already written something: identity is `output.id`, full
|
|
49
|
+
* stop, and a changed `name`/`owner` in the caller's props is drift to PATCH, never a reason to
|
|
50
|
+
* relocate. `output` undefined means there is nothing to be wrong about yet — locate by name.
|
|
51
|
+
*/
|
|
52
|
+
export declare const fetchLive: <Props, Live, Attributes extends {
|
|
53
|
+
readonly id: number;
|
|
54
|
+
}, E, R>(props: Props, output: Attributes | undefined, fetchByName: (props: Props) => Effect.Effect<Live | undefined, E, R>, fetchById: (id: number) => Effect.Effect<Live | undefined, E, R>, describe: (props: Props) => string) => Effect.Effect<Live | undefined, E, R>;
|
|
33
55
|
//# sourceMappingURL=matching-locate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matching-locate.d.ts","sourceRoot":"","sources":["../../src/paperless/matching-locate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"matching-locate.d.ts","sourceRoot":"","sources":["../../src/paperless/matching-locate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,QAAQ,SAAS,CAAC,EAAE,YAAY,MAAM,KAAG,CAAC,GAAG,SAOvE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,IAAI,EAAE,CAAC,EAAE,CAAC,QAC5B,MAAM,CAAC,MAAM,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE,CAAA;CAAE,EAAE,CAAC,EAAE,CAAC,CAAC,YAC9E,MAAM,eACH,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,KAClC,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,CAYpC,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,EAAE,IAAI,EAAE,UAAU,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,EAAE,CAAC,SAC9E,KAAK,UACJ,UAAU,GAAG,SAAS,eACjB,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,aACzD,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,YACtD,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,KACjC,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,CAgBhC,CAAC"}
|
|
@@ -4,50 +4,71 @@
|
|
|
4
4
|
* itself (the identity/locate/create/patch logic the PR 163 red-team HIGH finding is about) stays
|
|
5
5
|
* under the house's 250-line-per-file cap. See `matching.ts`'s header for the identity design
|
|
6
6
|
* (`output.id` once a resource has state) this `MatchingSpec` shape supports.
|
|
7
|
+
*
|
|
8
|
+
* 🔴 MOVED ONTO `@distilled.cloud/paperless-ngx` (2026-09-24, decision 43) — `Live` is now
|
|
9
|
+
* whatever a distilled operation decodes (a `tags.Tag`, a `documentTypes.DocumentType`, …), no
|
|
10
|
+
* more untyped `PaperlessRow`. `E` is left to each resource file to declare (the union of the
|
|
11
|
+
* distilled operations it actually calls), so a call site's precise per-operation error union
|
|
12
|
+
* flows straight through instead of being widened by hand here — the same split
|
|
13
|
+
* `../netbox/resource.ts` and `../forgejo/resource.ts` use.
|
|
7
14
|
*/
|
|
8
|
-
import type {
|
|
9
|
-
import type
|
|
10
|
-
import type
|
|
11
|
-
import type { EndpointKey } from './constraints.ts';
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
import type { PaperlessNgxOpContext } from '@distilled.cloud/paperless-ngx/Protocol';
|
|
16
|
+
import type * as Effect from 'effect/Effect';
|
|
17
|
+
import type * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
18
|
+
import type { EndpointKey, PaperlessBody } from './constraints.ts';
|
|
19
|
+
/**
|
|
20
|
+
* What a CONSUMING STACK must provide. `matchingHandlers` (matching.ts) bakes in
|
|
21
|
+
* `CredentialsFromEnv` itself, the same way `netboxHandlers`/`forgejoHandlers` do, so only the
|
|
22
|
+
* transport is left — see matching.ts's own note on `withCredentials`.
|
|
23
|
+
*/
|
|
24
|
+
export type MatchingRequirements = HttpClient.HttpClient;
|
|
15
25
|
/** A wire field beyond `name`/`owner`: how to read it from props, and how to read it back. */
|
|
16
|
-
export interface FieldSpec<Props> {
|
|
26
|
+
export interface FieldSpec<Props, Live> {
|
|
17
27
|
readonly key: string;
|
|
18
28
|
readonly prop: (props: Props) => unknown;
|
|
19
|
-
readonly live: (row:
|
|
29
|
+
readonly live: (row: Live) => unknown;
|
|
20
30
|
}
|
|
21
31
|
export interface MatchingProps {
|
|
22
32
|
readonly name: string;
|
|
23
33
|
/** `undefined` means undeclared — the create body still sends `owner: null` (see matching.ts's header). */
|
|
24
34
|
readonly owner?: number;
|
|
25
35
|
}
|
|
26
|
-
|
|
36
|
+
/** The shape every `list*` distilled operation this family calls answers. */
|
|
37
|
+
export interface MatchingPage<Live> {
|
|
38
|
+
readonly count: number;
|
|
39
|
+
readonly results: readonly Live[];
|
|
40
|
+
}
|
|
41
|
+
export interface MatchingSpec<Props extends MatchingProps, Live extends {
|
|
42
|
+
readonly id: number;
|
|
43
|
+
readonly name: string;
|
|
44
|
+
}, Attributes extends {
|
|
27
45
|
readonly id: number;
|
|
28
|
-
}> {
|
|
29
|
-
/** `tags`, `document_types`, `storage_paths`, `custom_fields`. */
|
|
30
|
-
readonly collection: string;
|
|
46
|
+
}, E> {
|
|
31
47
|
/**
|
|
32
48
|
* ⚠️ DEFAULT `true`. `Tag`, `DocumentType` and `StoragePath` extend Paperless-ngx's
|
|
33
49
|
* `OwnedObjectSerializer`; `CustomField` does not — its wire body has no `owner` key at all
|
|
34
50
|
* (measured against the v3.1.1 schema: `CustomFieldRequest` is `{name, data_type,
|
|
35
|
-
* extra_data}`). `false` stops `createBody` sending a field the vendor would silently ignore
|
|
51
|
+
* extra_data}`). `false` stops `createBody` sending a field the vendor would silently ignore,
|
|
52
|
+
* and `ownerOf` need not be declared.
|
|
36
53
|
*/
|
|
37
54
|
readonly owned?: boolean;
|
|
38
55
|
/** Compared, PATCHed when they differ, and sent on create. */
|
|
39
|
-
readonly fields: readonly FieldSpec<Props>[];
|
|
56
|
+
readonly fields: readonly FieldSpec<Props, Live>[];
|
|
40
57
|
/**
|
|
41
58
|
* Sent on CREATE only — never compared, never PATCHed. `CustomField.dataType` (custom-field.ts)
|
|
42
59
|
* is the one user: it must reach the create body, but `immutable` is what refuses a later
|
|
43
60
|
* change, and `matches`/`patchBody` must never see it as ordinary drift.
|
|
44
61
|
*/
|
|
45
|
-
readonly createOnly?: readonly FieldSpec<Props>[];
|
|
46
|
-
readonly attributes: (live:
|
|
62
|
+
readonly createOnly?: readonly FieldSpec<Props, Live>[];
|
|
63
|
+
readonly attributes: (live: Live, props: Props) => Attributes | undefined;
|
|
64
|
+
/** Reads the live row's owner. Required unless `owned === false` (CustomField). */
|
|
65
|
+
readonly ownerOf?: (live: Live) => number | undefined;
|
|
66
|
+
/** The generated constraint table to check each body against, by endpoint key. */
|
|
47
67
|
readonly endpoint: {
|
|
48
68
|
readonly create: EndpointKey;
|
|
49
69
|
readonly update?: EndpointKey;
|
|
50
70
|
};
|
|
71
|
+
/** For `soleMatch`'s message and for read-back failures. */
|
|
51
72
|
readonly describe: (props: Props) => string;
|
|
52
73
|
/**
|
|
53
74
|
* A field this object refuses to change once set — `CustomField.dataType` (custom-field.ts):
|
|
@@ -55,6 +76,14 @@ export interface MatchingSpec<Props extends MatchingProps, Attributes extends {
|
|
|
55
76
|
* replace is acceptable. Return the refusal message, or `undefined` when unchanged. Checked in
|
|
56
77
|
* `diff` (plan time) and again in `reconcile` (an adoption `diff` never saw).
|
|
57
78
|
*/
|
|
58
|
-
readonly immutable?: (live:
|
|
79
|
+
readonly immutable?: (live: Live, props: Props) => string | undefined;
|
|
80
|
+
/** `name__iexact` + `page_size` — wired per resource file (`listTags`, `listDocumentTypes`, …). */
|
|
81
|
+
readonly list: (props: Props) => Effect.Effect<MatchingPage<Live>, E, PaperlessNgxOpContext>;
|
|
82
|
+
/** Already folds the SDK's `NotFound` to `undefined` — each resource file's own `.pipe(Effect.catchTag('NotFound', …))`. */
|
|
83
|
+
readonly getById: (id: number) => Effect.Effect<Live | undefined, E, PaperlessNgxOpContext>;
|
|
84
|
+
readonly create: (body: PaperlessBody) => Effect.Effect<Live, E, PaperlessNgxOpContext>;
|
|
85
|
+
/** Absent would mean create-only-and-never-updated; every family here declares one. */
|
|
86
|
+
readonly update?: (id: number, body: PaperlessBody) => Effect.Effect<Live, E, PaperlessNgxOpContext>;
|
|
87
|
+
readonly destroy: (id: number) => Effect.Effect<unknown, E, PaperlessNgxOpContext>;
|
|
59
88
|
}
|
|
60
89
|
//# sourceMappingURL=matching-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matching-types.d.ts","sourceRoot":"","sources":["../../src/paperless/matching-types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"matching-types.d.ts","sourceRoot":"","sources":["../../src/paperless/matching-types.ts"],"names":[],"mappings":"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"}
|