@rio-cloud/cdk-v2-constructs 9.0.0-alpha.9 → 9.0.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/docs/AGENTS_DOCUMENTATION.md +16 -265
- package/lib/sbom-catalog/lambda/handler.cjs +38 -1
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/package.json +1 -1
- package/version.json +1 -1
|
@@ -28,260 +28,36 @@ Use `lib/**/*.d.ts` for generated type information and JSDoc-derived annotations
|
|
|
28
28
|
|
|
29
29
|
Prefer `import * as rio from '@rio-cloud-internal/cdk-v2-constructs';` unless an exported subpath is explicitly available in the installed `package.json`.
|
|
30
30
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
Starting with `9.0.0`, this package is published as
|
|
34
|
-
`@rio-cloud-internal/cdk-v2-constructs` in the RIO CodeArtifact `internal`
|
|
35
|
-
repository. This is a package and installation breaking change for consumers:
|
|
36
|
-
|
|
37
|
-
- Replace the dependency and every import/subpath reference from
|
|
38
|
-
`@rio-cloud/cdk-v2-constructs` with `@rio-cloud-internal/cdk-v2-constructs`.
|
|
39
|
-
Preserve any subpath after the package name.
|
|
40
|
-
- Authenticate npm before installing dependencies. Run the login command in
|
|
41
|
-
the consuming workspace before `npm ci` or `npm install`:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
aws codeartifact login --region eu-west-1 --tool npm --domain rio \
|
|
45
|
-
--domain-owner 577146897785 --repository internal \
|
|
46
|
-
--namespace @rio-cloud-internal
|
|
47
|
-
npm ci
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
- In CodeBuild or CodePipeline, run the same login command immediately before
|
|
51
|
-
the dependency installation in every relevant synth, branch, and auxiliary
|
|
52
|
-
build step. The build role must be allowed to call
|
|
53
|
-
`codeartifact:GetAuthorizationToken`, `codeartifact:GetRepositoryEndpoint`,
|
|
54
|
-
`codeartifact:ReadFromRepository`, and
|
|
55
|
-
`sts:GetServiceBearerToken` for the RIO `internal` repository. Do not commit
|
|
56
|
-
the generated npm credentials or an authentication token.
|
|
57
|
-
|
|
58
|
-
For a CDK `CodeBuildStep`, the relevant permissions are equivalent to:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
new iam.PolicyStatement({
|
|
62
|
-
actions: ['codeartifact:GetAuthorizationToken'],
|
|
63
|
-
resources: ['arn:aws:codeartifact:eu-west-1:577146897785:domain/rio'],
|
|
64
|
-
});
|
|
65
|
-
new iam.PolicyStatement({
|
|
66
|
-
actions: ['sts:GetServiceBearerToken'],
|
|
67
|
-
resources: ['*'],
|
|
68
|
-
conditions: {
|
|
69
|
-
StringEquals: { 'sts:AWSServiceName': 'codeartifact.amazonaws.com' },
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
new iam.PolicyStatement({
|
|
73
|
-
actions: ['codeartifact:GetRepositoryEndpoint', 'codeartifact:ReadFromRepository'],
|
|
74
|
-
resources: ['arn:aws:codeartifact:eu-west-1:577146897785:repository/rio/internal'],
|
|
75
|
-
});
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Ensure these statements are attached to the actual CodeBuild synth or build
|
|
79
|
-
role. Adding only the npm login command is insufficient.
|
|
80
|
-
- Regenerate the lockfile after authenticating. Do not reuse the integrity hash
|
|
81
|
-
from the public npm tarball when the resolved URL changes to CodeArtifact.
|
|
82
|
-
|
|
83
|
-
For example, the package dependency and root import change as follows:
|
|
84
|
-
|
|
85
|
-
```diff
|
|
86
|
-
-"@rio-cloud/cdk-v2-constructs": "..."
|
|
87
|
-
+"@rio-cloud-internal/cdk-v2-constructs": "..."
|
|
88
|
-
|
|
89
|
-
-import * as rio from '@rio-cloud/cdk-v2-constructs';
|
|
90
|
-
+import * as rio from '@rio-cloud-internal/cdk-v2-constructs';
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
The old public package name is not an alias for the internal package. A
|
|
94
|
-
consumer that keeps the old name, or runs `npm ci` before CodeArtifact login,
|
|
95
|
-
will fail to resolve the migrated package.
|
|
96
|
-
|
|
97
|
-
Read the relevant declaration comments and examples before writing or changing infrastructure code.
|
|
98
|
-
|
|
99
|
-
## Migration guidance for `9.0.0`
|
|
100
|
-
|
|
101
|
-
This section applies when upgrading a consuming project to `9.0.0` or
|
|
102
|
-
later. Confirm the installed package version and its `package.json` exports
|
|
103
|
-
before applying it. The guidance below is based on the implementation and
|
|
104
|
-
tests in this release; it intentionally does not prescribe replacements for
|
|
105
|
-
environment variables for which this wrapper exposes no one-to-one prop.
|
|
106
|
-
|
|
107
|
-
### Datadog Lambda instrumentation: Datadog v5 environment handling
|
|
108
|
-
|
|
109
|
-
`DatadogLambdaInstrumentation` now uses `datadog-cdk-constructs-v2` v5. Before
|
|
110
|
-
calling `addLambdaFunctions()`, the construct rejects a Lambda whose CDK
|
|
111
|
-
environment already contains any of these variables:
|
|
112
|
-
|
|
113
|
-
```text
|
|
114
|
-
DD_TRACE_ENABLED
|
|
115
|
-
DD_MERGE_XRAY_TRACES
|
|
116
|
-
DD_LOGS_INJECTION
|
|
117
|
-
DD_SERVERLESS_LOGS_ENABLED
|
|
118
|
-
DD_CAPTURE_LAMBDA_PAYLOAD
|
|
119
|
-
DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING
|
|
120
|
-
DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING
|
|
121
|
-
DD_LOG_LEVEL
|
|
122
|
-
DD_APPSEC_ENABLED
|
|
123
|
-
DD_SERVERLESS_APPSEC_ENABLED
|
|
124
|
-
AWS_LAMBDA_EXEC_WRAPPER
|
|
125
|
-
DD_TAGS
|
|
126
|
-
```
|
|
31
|
+
## Versioned migration guides
|
|
127
32
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Lambda constructor and from any `addEnvironment()` call made before
|
|
131
|
-
`addLambdaFunctions()`.
|
|
132
|
-
|
|
133
|
-
Use the instrumentation props for settings that have a corresponding public
|
|
134
|
-
prop. The direct mappings established by this package are:
|
|
135
|
-
|
|
136
|
-
| Lambda environment variable | `DatadogLambdaInstrumentation` prop |
|
|
137
|
-
| --- | --- |
|
|
138
|
-
| `DD_TRACE_ENABLED` | `enableDatadogTracing` |
|
|
139
|
-
| `DD_MERGE_XRAY_TRACES` | `enableMergeXrayTraces` |
|
|
140
|
-
| `DD_LOGS_INJECTION` | `injectLogContext` |
|
|
141
|
-
| `DD_SERVERLESS_LOGS_ENABLED` | `enableDatadogLogs` |
|
|
142
|
-
| `DD_CAPTURE_LAMBDA_PAYLOAD` | `captureLambdaPayload` |
|
|
143
|
-
| `DD_LOG_LEVEL` | `logLevel` |
|
|
144
|
-
| `DD_TAGS` | `tags` |
|
|
145
|
-
|
|
146
|
-
The wrapper also exposes `enableDatadogASM` and `datadogAppSecMode`, but the
|
|
147
|
-
repository does not document a mechanical mapping for every AppSec-related
|
|
148
|
-
environment variable. Do not invent one; inspect the installed declarations
|
|
149
|
-
and the Datadog v5 behavior for the desired AppSec configuration. The same
|
|
150
|
-
applies to the two cloud-payload-tagging variables and
|
|
151
|
-
`AWS_LAMBDA_EXEC_WRAPPER`, for which this wrapper has no same-named prop.
|
|
152
|
-
|
|
153
|
-
If a per-function override is intentional, apply it only after instrumentation:
|
|
33
|
+
For the breaking namespace migration and all `9.0.0` upgrade guidance, read
|
|
34
|
+
the [migration guide for `9.0.0`](./migration_guide.md).
|
|
154
35
|
|
|
155
|
-
|
|
156
|
-
datadog.addLambdaFunctions([handler]);
|
|
157
|
-
handler.addEnvironment('DD_LOG_LEVEL', 'debug');
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
An override of `DD_TAGS` at that point replaces all tags generated by the
|
|
161
|
-
construct, including Git metadata added through `addGitCommitMetadata()`.
|
|
162
|
-
`addLambdaFunctions()` validates the complete batch before changing any of its
|
|
163
|
-
functions. The validation covers the underlying CDK `Function` environment,
|
|
164
|
-
including `SingletonFunction` and values added with `addEnvironment()`; it
|
|
165
|
-
does not inspect `CfnFunction` escape-hatch overrides.
|
|
36
|
+
## Usage Guidance
|
|
166
37
|
|
|
167
|
-
|
|
168
|
-
`DD_TAGS`. For snapshot tests that must disable it, set this exact context key
|
|
169
|
-
on the test `App` to either boolean `false` or string `"false"`:
|
|
38
|
+
### General
|
|
170
39
|
|
|
171
|
-
|
|
172
|
-
const app = new App({
|
|
173
|
-
context: {
|
|
174
|
-
'@rio-cloud-internal/cdk-v2-constructs:enableSourceCodeIntegration': false,
|
|
175
|
-
},
|
|
176
|
-
});
|
|
177
|
-
```
|
|
40
|
+
Prefer RIO constructs over raw AWS CDK constructs when the use case matches. These constructs encode RIO infrastructure defaults, Datadog tags, shared secrets, team and account SSM parameters, and monitoring conventions.
|
|
178
41
|
|
|
179
|
-
Do not
|
|
180
|
-
version props remain required; choose versions compatible with the installed
|
|
181
|
-
Datadog Lambda Node and extension layer releases rather than copying stale
|
|
182
|
-
values from tests.
|
|
42
|
+
Do not set construct attributes explicitly when the value you plan to set is already the construct default. Prefer relying on defaults unless you are intentionally changing behavior and that intent is clear in the code.
|
|
183
43
|
|
|
184
|
-
|
|
44
|
+
Preserve the target repository's existing stack boundaries and scripts when maintaining an existing project.
|
|
185
45
|
|
|
186
|
-
|
|
187
|
-
`@rio-cloud/rio-license-checker` as a direct dev dependency and commit the
|
|
188
|
-
corresponding lockfile:
|
|
46
|
+
### Observability
|
|
189
47
|
|
|
190
|
-
|
|
191
|
-
npm install --save-dev @rio-cloud/rio-license-checker
|
|
192
|
-
```
|
|
48
|
+
Watchful is RIO's monitoring and alerting abstraction. Prefer `rio.watchfulv2.Watchful` and `rio.datadogv2`. Use legacy `watchful` or `datadog` only when maintaining existing code that already depends on those APIs.
|
|
193
49
|
|
|
194
|
-
|
|
195
|
-
construct no longer supplies this package transitively. Add it to the package
|
|
196
|
-
whose `npm ci` precedes the call:
|
|
197
|
-
|
|
198
|
-
| Generated pipeline feature | Workspace in which the checker is invoked | Package that needs the dev dependency |
|
|
199
|
-
| --- | --- | --- |
|
|
200
|
-
| Infrastructure synth | `infrastructure/` | `infrastructure/package.json` |
|
|
201
|
-
| `gradleBuild` | repository root | root `package.json` |
|
|
202
|
-
| `npmBuild` | repository root | root `package.json` |
|
|
203
|
-
|
|
204
|
-
If a project enables more than one of these generated build paths, make the
|
|
205
|
-
checker available in each corresponding workspace. A custom main/branch or
|
|
206
|
-
vulnerability buildspec is loaded instead of the generated one, so inspect
|
|
207
|
-
that file separately for its own license-check command and install location.
|
|
208
|
-
The package's release notes link to the internal [RIO license-check
|
|
209
|
-
guidance](https://confluence.collaboration-man.com/spaces/RIOSHIPPER/pages/448924008/License+Checks).
|
|
210
|
-
|
|
211
|
-
### Contribution imports and package dependencies
|
|
212
|
-
|
|
213
|
-
Contribution constructs are no longer exported from the package root. Use the
|
|
214
|
-
owner-level subpaths that are present in the installed package's `exports` map:
|
|
215
|
-
|
|
216
|
-
| Owner | Internal import path in `9.0.0` |
|
|
217
|
-
| --- | --- |
|
|
218
|
-
| Team Claid | `@rio-cloud-internal/cdk-v2-constructs/contributions/team-claid` |
|
|
219
|
-
| Team Outbound Order Book | `@rio-cloud-internal/cdk-v2-constructs/contributions/team-outbound-order-book` |
|
|
220
|
-
| Team Shipper Inbound Blue | `@rio-cloud-internal/cdk-v2-constructs/contributions/team-shipper-inbound-blue` |
|
|
221
|
-
| Smart Route / GitLab Runner | `@rio-cloud-internal/cdk-v2-constructs/contributions/smart-route` |
|
|
222
|
-
| Team Transport | `@rio-cloud-internal/cdk-v2-constructs/contributions/team-transport` |
|
|
223
|
-
| CoP Frontend | `@rio-cloud-internal/cdk-v2-constructs/contributions/cop-frontend` |
|
|
224
|
-
|
|
225
|
-
For example, change a root import while keeping the named imports:
|
|
226
|
-
|
|
227
|
-
```diff
|
|
228
|
-
-import { PipelineStack, PipelineType } from '@rio-cloud-internal/cdk-v2-constructs';
|
|
229
|
-
+import { PipelineStack, PipelineType } from '@rio-cloud-internal/cdk-v2-constructs/contributions/team-transport';
|
|
230
|
-
```
|
|
50
|
+
Do not add raw CloudWatch metrics, alarms, or monitoring resources for agent-generated changes. Use RIO monitoring constructs and Datadog-based abstractions for observability.
|
|
231
51
|
|
|
232
|
-
|
|
233
|
-
Import its pipeline, Datadog, and synthetics constructs from the single
|
|
234
|
-
owner-level path above. Do not infer additional public subpaths from the
|
|
235
|
-
source directory layout; the installed `package.json` `exports` map is the
|
|
236
|
-
authority.
|
|
52
|
+
Treat `rio.SesObservability` logs as PII. Do not forward those logs to third-party services and do not extend retention beyond the construct default.
|
|
237
53
|
|
|
238
|
-
|
|
239
|
-
`@pepperize/cdk-autoscaling-gitlab-runner` as a direct project dependency:
|
|
54
|
+
### RIO Infrastructure Defaults
|
|
240
55
|
|
|
241
|
-
|
|
242
|
-
npm install @pepperize/cdk-autoscaling-gitlab-runner
|
|
243
|
-
```
|
|
56
|
+
RIO infrastructure defaults are the baseline VPC, hosted zone, and team/account values provided by the RIO environment. Use `rio.RioLandingZone` helpers for default VPC, hosted zone, team name, team identifier, team email, team alert Slack channel, and account name. Avoid hard-coded VPC IDs, hosted-zone IDs, or parameter names when a helper exists.
|
|
244
57
|
|
|
245
|
-
|
|
246
|
-
that a consuming project can obtain transitively. This additional dependency
|
|
247
|
-
is required only by projects importing the Smart Route GitLab Runner
|
|
248
|
-
constructs.
|
|
249
|
-
|
|
250
|
-
### TypeScript resolver required for contribution subpaths
|
|
251
|
-
|
|
252
|
-
The contribution imports depend on Node package export maps. A legacy
|
|
253
|
-
`moduleResolution: "node"` configuration does not resolve these imports
|
|
254
|
-
reliably. Use a resolver that honors `exports` and keep the `module` and
|
|
255
|
-
`moduleResolution` settings compatible. For example, a CommonJS-oriented
|
|
256
|
-
project can use:
|
|
257
|
-
|
|
258
|
-
```json
|
|
259
|
-
{
|
|
260
|
-
"compilerOptions": {
|
|
261
|
-
"module": "Node16",
|
|
262
|
-
"moduleResolution": "node16"
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
```
|
|
58
|
+
### Services
|
|
266
59
|
|
|
267
|
-
|
|
268
|
-
resolution mode with its existing bundler-compatible module setting. Do not
|
|
269
|
-
change only `moduleResolution` in a configuration whose `module` setting is
|
|
270
|
-
incompatible; preserve the consuming project's module model and verify it with
|
|
271
|
-
the project's typecheck and synth commands.
|
|
272
|
-
|
|
273
|
-
### Team Transport CodeBuild runtime options
|
|
274
|
-
|
|
275
|
-
This is an alpha.4 pipeline feature rather than a breaking migration, but it
|
|
276
|
-
is relevant when updating pipeline code. Generated main, branch, and
|
|
277
|
-
vulnerability buildspecs continue to use Node.js 24 by default. To require an
|
|
278
|
-
exact toolchain, set `codeBuildOptions.nodejsVersion` and/or
|
|
279
|
-
`codeBuildOptions.npmVersion` to an exact `major.minor.patch` value. The
|
|
280
|
-
generated install phase checks the selected versions before installing project
|
|
281
|
-
dependencies; it does not install npm globally. These options affect only
|
|
282
|
-
generated buildspecs. A custom buildspec supplied through
|
|
283
|
-
`partialBuildSpecPath` or `vulnerabilityPartialBuildSpecPath` is responsible
|
|
284
|
-
for its own runtime and version checks.
|
|
60
|
+
Use `rio.RioFargateService` for ECS/Fargate services when possible.
|
|
285
61
|
|
|
286
62
|
### CloudFront certificates added in v9
|
|
287
63
|
|
|
@@ -309,31 +85,6 @@ certificate. Use `certificateArn` only for integrations that require a string
|
|
|
309
85
|
ARN. Changing the domain or hosted zone replaces the certificate; validation
|
|
310
86
|
CNAME records are retained for renewal.
|
|
311
87
|
|
|
312
|
-
## Usage Guidance
|
|
313
|
-
|
|
314
|
-
### General
|
|
315
|
-
|
|
316
|
-
Prefer RIO constructs over raw AWS CDK constructs when the use case matches. These constructs encode RIO infrastructure defaults, Datadog tags, shared secrets, team and account SSM parameters, and monitoring conventions.
|
|
317
|
-
|
|
318
|
-
Do not set construct attributes explicitly when the value you plan to set is already the construct default. Prefer relying on defaults unless you are intentionally changing behavior and that intent is clear in the code.
|
|
319
|
-
|
|
320
|
-
Preserve the target repository's existing stack boundaries and scripts when maintaining an existing project.
|
|
321
|
-
|
|
322
|
-
### Observability
|
|
323
|
-
|
|
324
|
-
Watchful is RIO's monitoring and alerting abstraction. Prefer `rio.watchfulv2.Watchful` and `rio.datadogv2`. Use legacy `watchful` or `datadog` only when maintaining existing code that already depends on those APIs.
|
|
325
|
-
|
|
326
|
-
Do not add raw CloudWatch metrics, alarms, or monitoring resources for agent-generated changes. Use RIO monitoring constructs and Datadog-based abstractions for observability.
|
|
327
|
-
|
|
328
|
-
Treat `rio.SesObservability` logs as PII. Do not forward those logs to third-party services and do not extend retention beyond the construct default.
|
|
329
|
-
|
|
330
|
-
### RIO Infrastructure Defaults
|
|
331
|
-
|
|
332
|
-
RIO infrastructure defaults are the baseline VPC, hosted zone, and team/account values provided by the RIO environment. Use `rio.RioLandingZone` helpers for default VPC, hosted zone, team name, team identifier, team email, team alert Slack channel, and account name. Avoid hard-coded VPC IDs, hosted-zone IDs, or parameter names when a helper exists.
|
|
333
|
-
|
|
334
|
-
### Services
|
|
335
|
-
|
|
336
|
-
Use `rio.RioFargateService` for ECS/Fargate services when possible.
|
|
337
88
|
### Kafka
|
|
338
89
|
|
|
339
90
|
Use `rio.KafkaTopicV4` for new Kafka topics. Set audience and recovery policy deliberately.
|
|
@@ -38779,6 +38779,7 @@ __export(util_exports, {
|
|
|
38779
38779
|
required: () => required,
|
|
38780
38780
|
safeExtend: () => safeExtend,
|
|
38781
38781
|
shallowClone: () => shallowClone,
|
|
38782
|
+
sizeCaps: () => sizeCaps,
|
|
38782
38783
|
slugify: () => slugify,
|
|
38783
38784
|
stringifyPrimitive: () => stringifyPrimitive,
|
|
38784
38785
|
toZod: () => toZod,
|
|
@@ -39298,6 +39299,18 @@ function prefixIssues(path, issues) {
|
|
|
39298
39299
|
function unwrapMessage(message) {
|
|
39299
39300
|
return typeof message === "string" ? message : message?.message;
|
|
39300
39301
|
}
|
|
39302
|
+
function sizeCaps(defChecks) {
|
|
39303
|
+
const caps = [];
|
|
39304
|
+
for (const ch of defChecks ?? []) {
|
|
39305
|
+
const d5 = ch._zod.def;
|
|
39306
|
+
if (!/_(length|size)$|_equals$/.test(d5.check))
|
|
39307
|
+
break;
|
|
39308
|
+
const max = d5.maximum ?? d5.length ?? d5.size;
|
|
39309
|
+
if (max >= 0)
|
|
39310
|
+
caps.push([max, ch]);
|
|
39311
|
+
}
|
|
39312
|
+
return caps;
|
|
39313
|
+
}
|
|
39301
39314
|
function attachSchema(issues, start, inst) {
|
|
39302
39315
|
var _a4;
|
|
39303
39316
|
for (let i5 = start; i5 < issues.length; i5++) {
|
|
@@ -40219,7 +40232,7 @@ ${content.join("\n")}
|
|
|
40219
40232
|
var version = {
|
|
40220
40233
|
major: 4,
|
|
40221
40234
|
minor: 6,
|
|
40222
|
-
patch:
|
|
40235
|
+
patch: 7
|
|
40223
40236
|
};
|
|
40224
40237
|
|
|
40225
40238
|
// node_modules/zod/v4/core/schemas.js
|
|
@@ -40727,6 +40740,29 @@ var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
|
|
|
40727
40740
|
return payload;
|
|
40728
40741
|
};
|
|
40729
40742
|
});
|
|
40743
|
+
function capSize(inst, size) {
|
|
40744
|
+
const caps = sizeCaps(inst._zod.def.checks);
|
|
40745
|
+
if (!caps.length)
|
|
40746
|
+
return;
|
|
40747
|
+
const cap = Math.min(...caps.map((c5) => c5[0]));
|
|
40748
|
+
const parse3 = inst._zod.parse;
|
|
40749
|
+
inst._zod.parse = (payload, ctx) => {
|
|
40750
|
+
const n3 = size(payload.value);
|
|
40751
|
+
if (n3 > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
40752
|
+
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
40753
|
+
if (n3 > max && ch._zod.def.when(payload)) {
|
|
40754
|
+
const start = payload.issues.length;
|
|
40755
|
+
ch._zod.check(payload);
|
|
40756
|
+
payload.issues[start].continue = false;
|
|
40757
|
+
attachSchema(payload.issues, start, inst);
|
|
40758
|
+
return payload;
|
|
40759
|
+
}
|
|
40760
|
+
}
|
|
40761
|
+
}
|
|
40762
|
+
return parse3(payload, ctx);
|
|
40763
|
+
};
|
|
40764
|
+
}
|
|
40765
|
+
var arraySize = (input) => Array.isArray(input) ? input.length : -1;
|
|
40730
40766
|
function handleArrayResult(result, final, index) {
|
|
40731
40767
|
if (result.issues.length) {
|
|
40732
40768
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -40770,6 +40806,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
40770
40806
|
}
|
|
40771
40807
|
return payload;
|
|
40772
40808
|
};
|
|
40809
|
+
capSize(inst, arraySize);
|
|
40773
40810
|
});
|
|
40774
40811
|
function handlePropertyResult(result, final, key, input, optin, optout) {
|
|
40775
40812
|
const isPresent = key in input;
|
|
@@ -140,6 +140,33 @@ test("continue parsing despite array size error", () => {
|
|
|
140
140
|
`);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
test("an upper size bound fails before any element is parsed", () => {
|
|
144
|
+
let parsed = 0;
|
|
145
|
+
const el = z.string().refine(() => ++parsed);
|
|
146
|
+
let refined = 0;
|
|
147
|
+
const schema = z
|
|
148
|
+
.array(el)
|
|
149
|
+
.max(2, "too many")
|
|
150
|
+
.refine(() => ++refined);
|
|
151
|
+
expect(schema.safeParse([1, 2, 3]).error!.issues).toMatchObject([{ code: "too_big", path: [], message: "too many" }]);
|
|
152
|
+
expect(z.array(el).length(2).safeParse(["a", "b", "c"]).error!.issues).toMatchObject([
|
|
153
|
+
{ code: "too_big", exact: true },
|
|
154
|
+
]);
|
|
155
|
+
expect(z.object({ a: z.array(el).max(1) }).safeParse({ a: [1, 2] }).error!.issues).toMatchObject([
|
|
156
|
+
{ code: "too_big", path: ["a"] },
|
|
157
|
+
]);
|
|
158
|
+
expect([parsed, refined]).toEqual([0, 0]);
|
|
159
|
+
|
|
160
|
+
// a check that may rewrite the value ends the gate
|
|
161
|
+
expect(
|
|
162
|
+
z
|
|
163
|
+
.array(z.number())
|
|
164
|
+
.overwrite((a) => a.slice(0, 2))
|
|
165
|
+
.max(2)
|
|
166
|
+
.parse([1, 2, 3])
|
|
167
|
+
).toEqual([1, 2]);
|
|
168
|
+
});
|
|
169
|
+
|
|
143
170
|
test("parse should fail given sparse array", () => {
|
|
144
171
|
const schema = z.array(z.string()).nonempty().min(1).max(3);
|
|
145
172
|
const result = schema.safeParse(new Array(3));
|
|
@@ -97,6 +97,13 @@ test("failing when map is bigger than max() ", () => {
|
|
|
97
97
|
expect(result.success).toEqual(false);
|
|
98
98
|
expect(result.error!.issues.length).toEqual(1);
|
|
99
99
|
expect(result.error!.issues[0].code).toEqual("too_big");
|
|
100
|
+
const bad = new Map([
|
|
101
|
+
[1, 1],
|
|
102
|
+
[2, 2],
|
|
103
|
+
]);
|
|
104
|
+
const capped = z.map(z.string(), z.string()).max(1);
|
|
105
|
+
expect(capped.safeParse(bad).error!.issues).toMatchObject([{ code: "too_big" }]);
|
|
106
|
+
expect(capped.safeParse(new Set([1, 2])).error!.issues[0]).toMatchObject({ code: "invalid_type", expected: "map" });
|
|
100
107
|
});
|
|
101
108
|
|
|
102
109
|
test("failing when map does not match size() ", () => {
|
|
@@ -83,6 +83,12 @@ test("failing when set is bigger than max() ", () => {
|
|
|
83
83
|
expect(result.success).toEqual(false);
|
|
84
84
|
expect(result.error!.issues.length).toEqual(1);
|
|
85
85
|
expect(result.error!.issues[0].code).toEqual("too_big");
|
|
86
|
+
expect(
|
|
87
|
+
z
|
|
88
|
+
.set(z.string())
|
|
89
|
+
.max(1)
|
|
90
|
+
.safeParse(new Set([1, 2])).error!.issues
|
|
91
|
+
).toMatchObject([{ code: "too_big" }]);
|
|
86
92
|
});
|
|
87
93
|
|
|
88
94
|
test("failing when set does not match size() ", () => {
|
|
@@ -1551,6 +1551,12 @@ function generateNullableCheck(
|
|
|
1551
1551
|
return outputVar;
|
|
1552
1552
|
}
|
|
1553
1553
|
|
|
1554
|
+
function generateSizeGate(doc: Doc, schema: SomeType, size: string): void {
|
|
1555
|
+
for (const [max, check] of util.sizeCaps(schema._zod.def.checks)) {
|
|
1556
|
+
doc.write(`if (${size} > ${numericOperand(max, check._zod.def.check)}) return INVALID;`);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1554
1560
|
function generateArrayCheck(
|
|
1555
1561
|
doc: Doc,
|
|
1556
1562
|
ctx: CompileContext,
|
|
@@ -1560,6 +1566,7 @@ function generateArrayCheck(
|
|
|
1560
1566
|
): string | null {
|
|
1561
1567
|
const def = schema._zod.def as unknown as { element: SomeType };
|
|
1562
1568
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
1569
|
+
generateSizeGate(doc, schema, `${accessor}.length`);
|
|
1563
1570
|
|
|
1564
1571
|
// Build a new array with validated/transformed elements.
|
|
1565
1572
|
const outputVar = buildsValue ? newVar(ctx) : null;
|
|
@@ -2094,6 +2101,7 @@ function generateMapCheck(doc: Doc, ctx: CompileContext, schema: SomeType, acces
|
|
|
2094
2101
|
const def = schema._zod.def as unknown as { keyType: SomeType; valueType: SomeType };
|
|
2095
2102
|
|
|
2096
2103
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
2104
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
2097
2105
|
|
|
2098
2106
|
const outputVar = newVar(ctx);
|
|
2099
2107
|
const kVar = newVar(ctx);
|
|
@@ -2115,6 +2123,7 @@ function generateSetCheck(doc: Doc, ctx: CompileContext, schema: SomeType, acces
|
|
|
2115
2123
|
const def = schema._zod.def as unknown as { valueType: SomeType };
|
|
2116
2124
|
|
|
2117
2125
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
2126
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
2118
2127
|
|
|
2119
2128
|
const outputVar = newVar(ctx);
|
|
2120
2129
|
const valVar = newVar(ctx);
|
|
@@ -1844,6 +1844,34 @@ export interface $ZodArrayInternals<T extends SomeType = $ZodType> extends _$Zod
|
|
|
1844
1844
|
|
|
1845
1845
|
export interface $ZodArray<T extends SomeType = $ZodType> extends $ZodType<any, any, $ZodArrayInternals<T>> {}
|
|
1846
1846
|
|
|
1847
|
+
// an oversized container fails its leading size checks before any element is parsed
|
|
1848
|
+
function capSize(inst: $ZodType, size: (input: any) => number): void {
|
|
1849
|
+
const caps = util.sizeCaps(inst._zod.def.checks);
|
|
1850
|
+
if (!caps.length) return;
|
|
1851
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
1852
|
+
const parse = inst._zod.parse;
|
|
1853
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1854
|
+
const n = size(payload.value);
|
|
1855
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
1856
|
+
for (const [max, ch] of util.sizeCaps(inst._zod.def.checks)) {
|
|
1857
|
+
if (n > max && ch._zod.def.when!(payload)) {
|
|
1858
|
+
const start = payload.issues.length;
|
|
1859
|
+
ch._zod.check(payload as ParsePayload<never>);
|
|
1860
|
+
// the value is still the raw input, so no later check may read it
|
|
1861
|
+
(payload.issues[start] as { continue?: boolean }).continue = false;
|
|
1862
|
+
util.attachSchema(payload.issues, start, inst);
|
|
1863
|
+
return payload;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
return parse(payload, ctx);
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
const arraySize = (input: unknown): number => (Array.isArray(input) ? input.length : -1);
|
|
1872
|
+
const mapSize = (input: unknown): number => (input instanceof Map ? input.size : -1);
|
|
1873
|
+
const setSize = (input: unknown): number => (input instanceof Set ? input.size : -1);
|
|
1874
|
+
|
|
1847
1875
|
function handleArrayResult(result: ParsePayload<any>, final: ParsePayload<any[]>, index: number) {
|
|
1848
1876
|
if (result.issues.length) {
|
|
1849
1877
|
final.issues.push(...util.prefixIssues(index, result.issues));
|
|
@@ -1899,6 +1927,7 @@ export const $ZodArray: core.$constructor<$ZodArray> = /*@__PURE__*/ core.$const
|
|
|
1899
1927
|
|
|
1900
1928
|
return payload; //handleArrayResultsAsync(parseResults, final);
|
|
1901
1929
|
};
|
|
1930
|
+
capSize(inst, arraySize);
|
|
1902
1931
|
});
|
|
1903
1932
|
|
|
1904
1933
|
//////////////////////////////////////////
|
|
@@ -3218,8 +3247,11 @@ export type $InferZodRecordInput<
|
|
|
3218
3247
|
: Record<core.input<Key> & PropertyKey, core.input<Value>>;
|
|
3219
3248
|
|
|
3220
3249
|
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType>
|
|
3221
|
-
extends $ZodTypeInternals
|
|
3250
|
+
extends $ZodTypeInternals {
|
|
3222
3251
|
def: $ZodRecordDef<Key, Value>;
|
|
3252
|
+
// members rather than base type arguments, which TypeScript 7.1 reports as circular for `z.json()`
|
|
3253
|
+
output: $InferZodRecordOutput<Key, Value>;
|
|
3254
|
+
input: $InferZodRecordInput<Key, Value>;
|
|
3223
3255
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey<Record<PropertyKey, unknown>>;
|
|
3224
3256
|
optin?: "optional" | undefined;
|
|
3225
3257
|
optout?: "optional" | undefined;
|
|
@@ -3480,6 +3512,7 @@ export const $ZodMap: core.$constructor<$ZodMap> = /*@__PURE__*/ core.$construct
|
|
|
3480
3512
|
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
3481
3513
|
return payload;
|
|
3482
3514
|
};
|
|
3515
|
+
capSize(inst, mapSize);
|
|
3483
3516
|
});
|
|
3484
3517
|
|
|
3485
3518
|
function handleMapResult(
|
|
@@ -3582,6 +3615,7 @@ export const $ZodSet: core.$constructor<$ZodSet> = /*@__PURE__*/ core.$construct
|
|
|
3582
3615
|
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
3583
3616
|
return payload;
|
|
3584
3617
|
};
|
|
3618
|
+
capSize(inst, setSize);
|
|
3585
3619
|
});
|
|
3586
3620
|
|
|
3587
3621
|
function handleSetResult(result: ParsePayload, final: ParsePayload<Set<any>>) {
|
|
@@ -935,6 +935,19 @@ export function unwrapMessage(message: string | { message: string } | undefined
|
|
|
935
935
|
}
|
|
936
936
|
|
|
937
937
|
/* A check holds no link back to the schema it is attached to — the same check instance is shared by every clone of that schema — so the owner is stamped onto the issues a check just raised, at the only point where both are in scope. Runs on the failure path only; `start` is the issue count from before the check ran. */
|
|
938
|
+
/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */
|
|
939
|
+
export function sizeCaps(defChecks: checks.$ZodCheck<never>[] | undefined): [number, checks.$ZodCheck<never>][] {
|
|
940
|
+
const caps: [number, checks.$ZodCheck<never>][] = [];
|
|
941
|
+
for (const ch of defChecks ?? []) {
|
|
942
|
+
const d = ch._zod.def as any;
|
|
943
|
+
// a later check may rewrite the value
|
|
944
|
+
if (!/_(length|size)$|_equals$/.test(d.check)) break;
|
|
945
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
946
|
+
if (max >= 0) caps.push([max, ch]);
|
|
947
|
+
}
|
|
948
|
+
return caps;
|
|
949
|
+
}
|
|
950
|
+
|
|
938
951
|
export function attachSchema(issues: errors.$ZodRawIssue[], start: number, inst: schemas.$ZodType): void {
|
|
939
952
|
for (let i = start; i < issues.length; i++) {
|
|
940
953
|
(issues[i] as any).schema ??= inst;
|
|
@@ -1241,9 +1241,15 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
1241
1241
|
doc.write(`}`);
|
|
1242
1242
|
return outputVar;
|
|
1243
1243
|
}
|
|
1244
|
+
function generateSizeGate(doc, schema, size) {
|
|
1245
|
+
for (const [max, check] of util.sizeCaps(schema._zod.def.checks)) {
|
|
1246
|
+
doc.write(`if (${size} > ${numericOperand(max, check._zod.def.check)}) return INVALID;`);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1244
1249
|
function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
1245
1250
|
const def = schema._zod.def;
|
|
1246
1251
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
1252
|
+
generateSizeGate(doc, schema, `${accessor}.length`);
|
|
1247
1253
|
// Build a new array with validated/transformed elements.
|
|
1248
1254
|
const outputVar = buildsValue ? newVar(ctx) : null;
|
|
1249
1255
|
const iVar = newVar(ctx);
|
|
@@ -1707,6 +1713,7 @@ function literalPropertyKey(ctx, key) {
|
|
|
1707
1713
|
function generateMapCheck(doc, ctx, schema, accessor) {
|
|
1708
1714
|
const def = schema._zod.def;
|
|
1709
1715
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
1716
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
1710
1717
|
const outputVar = newVar(ctx);
|
|
1711
1718
|
const kVar = newVar(ctx);
|
|
1712
1719
|
const valVar = newVar(ctx);
|
|
@@ -1723,6 +1730,7 @@ function generateMapCheck(doc, ctx, schema, accessor) {
|
|
|
1723
1730
|
function generateSetCheck(doc, ctx, schema, accessor) {
|
|
1724
1731
|
const def = schema._zod.def;
|
|
1725
1732
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
1733
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
1726
1734
|
const outputVar = newVar(ctx);
|
|
1727
1735
|
const valVar = newVar(ctx);
|
|
1728
1736
|
doc.write(`const ${outputVar} = new Set();`);
|
|
@@ -1210,9 +1210,15 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
1210
1210
|
doc.write(`}`);
|
|
1211
1211
|
return outputVar;
|
|
1212
1212
|
}
|
|
1213
|
+
function generateSizeGate(doc, schema, size) {
|
|
1214
|
+
for (const [max, check] of util.sizeCaps(schema._zod.def.checks)) {
|
|
1215
|
+
doc.write(`if (${size} > ${numericOperand(max, check._zod.def.check)}) return INVALID;`);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1213
1218
|
function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
1214
1219
|
const def = schema._zod.def;
|
|
1215
1220
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
1221
|
+
generateSizeGate(doc, schema, `${accessor}.length`);
|
|
1216
1222
|
// Build a new array with validated/transformed elements.
|
|
1217
1223
|
const outputVar = buildsValue ? newVar(ctx) : null;
|
|
1218
1224
|
const iVar = newVar(ctx);
|
|
@@ -1676,6 +1682,7 @@ function literalPropertyKey(ctx, key) {
|
|
|
1676
1682
|
function generateMapCheck(doc, ctx, schema, accessor) {
|
|
1677
1683
|
const def = schema._zod.def;
|
|
1678
1684
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
1685
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
1679
1686
|
const outputVar = newVar(ctx);
|
|
1680
1687
|
const kVar = newVar(ctx);
|
|
1681
1688
|
const valVar = newVar(ctx);
|
|
@@ -1692,6 +1699,7 @@ function generateMapCheck(doc, ctx, schema, accessor) {
|
|
|
1692
1699
|
function generateSetCheck(doc, ctx, schema, accessor) {
|
|
1693
1700
|
const def = schema._zod.def;
|
|
1694
1701
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
1702
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
1695
1703
|
const outputVar = newVar(ctx);
|
|
1696
1704
|
const valVar = newVar(ctx);
|
|
1697
1705
|
doc.write(`const ${outputVar} = new Set();`);
|
|
@@ -860,6 +860,33 @@ exports.$ZodDate = core.$constructor("$ZodDate", (inst, def) => {
|
|
|
860
860
|
return payload;
|
|
861
861
|
};
|
|
862
862
|
});
|
|
863
|
+
// an oversized container fails its leading size checks before any element is parsed
|
|
864
|
+
function capSize(inst, size) {
|
|
865
|
+
const caps = util.sizeCaps(inst._zod.def.checks);
|
|
866
|
+
if (!caps.length)
|
|
867
|
+
return;
|
|
868
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
869
|
+
const parse = inst._zod.parse;
|
|
870
|
+
inst._zod.parse = (payload, ctx) => {
|
|
871
|
+
const n = size(payload.value);
|
|
872
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
873
|
+
for (const [max, ch] of util.sizeCaps(inst._zod.def.checks)) {
|
|
874
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
875
|
+
const start = payload.issues.length;
|
|
876
|
+
ch._zod.check(payload);
|
|
877
|
+
// the value is still the raw input, so no later check may read it
|
|
878
|
+
payload.issues[start].continue = false;
|
|
879
|
+
util.attachSchema(payload.issues, start, inst);
|
|
880
|
+
return payload;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
return parse(payload, ctx);
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
const arraySize = (input) => (Array.isArray(input) ? input.length : -1);
|
|
888
|
+
const mapSize = (input) => (input instanceof Map ? input.size : -1);
|
|
889
|
+
const setSize = (input) => (input instanceof Set ? input.size : -1);
|
|
863
890
|
function handleArrayResult(result, final, index) {
|
|
864
891
|
if (result.issues.length) {
|
|
865
892
|
final.issues.push(...util.prefixIssues(index, result.issues));
|
|
@@ -905,6 +932,7 @@ exports.$ZodArray = core.$constructor("$ZodArray", (inst, def) => {
|
|
|
905
932
|
}
|
|
906
933
|
return payload; //handleArrayResultsAsync(parseResults, final);
|
|
907
934
|
};
|
|
935
|
+
capSize(inst, arraySize);
|
|
908
936
|
});
|
|
909
937
|
function handlePropertyResult(result, final, key, input, optin, optout) {
|
|
910
938
|
const isPresent = key in input;
|
|
@@ -1942,6 +1970,7 @@ exports.$ZodMap = core.$constructor("$ZodMap", (inst, def) => {
|
|
|
1942
1970
|
return Promise.all(proms).then(() => payload);
|
|
1943
1971
|
return payload;
|
|
1944
1972
|
};
|
|
1973
|
+
capSize(inst, mapSize);
|
|
1945
1974
|
});
|
|
1946
1975
|
function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
|
|
1947
1976
|
if (keyResult.issues.length) {
|
|
@@ -2011,6 +2040,7 @@ exports.$ZodSet = core.$constructor("$ZodSet", (inst, def) => {
|
|
|
2011
2040
|
return Promise.all(proms).then(() => payload);
|
|
2012
2041
|
return payload;
|
|
2013
2042
|
};
|
|
2043
|
+
capSize(inst, setSize);
|
|
2014
2044
|
});
|
|
2015
2045
|
function handleSetResult(result, final) {
|
|
2016
2046
|
if (result.issues.length) {
|
|
@@ -834,8 +834,10 @@ export type $InferZodRecordOutput<Key extends $ZodRecordKey = $ZodRecordKey, Val
|
|
|
834
834
|
export type $InferZodRecordInput<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> = Key extends $partial ? Partial<Record<core.input<Key> & PropertyKey, core.input<Value>>> : [
|
|
835
835
|
Value
|
|
836
836
|
] extends [OptionalInSchema] ? Partial<Record<core.input<Key> & PropertyKey, core.input<Value>>> : Record<core.input<Key> & PropertyKey, core.input<Value>>;
|
|
837
|
-
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodTypeInternals
|
|
837
|
+
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodTypeInternals {
|
|
838
838
|
def: $ZodRecordDef<Key, Value>;
|
|
839
|
+
output: $InferZodRecordOutput<Key, Value>;
|
|
840
|
+
input: $InferZodRecordInput<Key, Value>;
|
|
839
841
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey<Record<PropertyKey, unknown>>;
|
|
840
842
|
optin?: "optional" | undefined;
|
|
841
843
|
optout?: "optional" | undefined;
|
|
@@ -834,8 +834,10 @@ export type $InferZodRecordOutput<Key extends $ZodRecordKey = $ZodRecordKey, Val
|
|
|
834
834
|
export type $InferZodRecordInput<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> = Key extends $partial ? Partial<Record<core.input<Key> & PropertyKey, core.input<Value>>> : [
|
|
835
835
|
Value
|
|
836
836
|
] extends [OptionalInSchema] ? Partial<Record<core.input<Key> & PropertyKey, core.input<Value>>> : Record<core.input<Key> & PropertyKey, core.input<Value>>;
|
|
837
|
-
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodTypeInternals
|
|
837
|
+
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodTypeInternals {
|
|
838
838
|
def: $ZodRecordDef<Key, Value>;
|
|
839
|
+
output: $InferZodRecordOutput<Key, Value>;
|
|
840
|
+
input: $InferZodRecordInput<Key, Value>;
|
|
839
841
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey<Record<PropertyKey, unknown>>;
|
|
840
842
|
optin?: "optional" | undefined;
|
|
841
843
|
optout?: "optional" | undefined;
|
|
@@ -816,6 +816,33 @@ export const $ZodDate = /*@__PURE__*/ core.$constructor("$ZodDate", (inst, def)
|
|
|
816
816
|
return payload;
|
|
817
817
|
};
|
|
818
818
|
});
|
|
819
|
+
// an oversized container fails its leading size checks before any element is parsed
|
|
820
|
+
function capSize(inst, size) {
|
|
821
|
+
const caps = util.sizeCaps(inst._zod.def.checks);
|
|
822
|
+
if (!caps.length)
|
|
823
|
+
return;
|
|
824
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
825
|
+
const parse = inst._zod.parse;
|
|
826
|
+
inst._zod.parse = (payload, ctx) => {
|
|
827
|
+
const n = size(payload.value);
|
|
828
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
829
|
+
for (const [max, ch] of util.sizeCaps(inst._zod.def.checks)) {
|
|
830
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
831
|
+
const start = payload.issues.length;
|
|
832
|
+
ch._zod.check(payload);
|
|
833
|
+
// the value is still the raw input, so no later check may read it
|
|
834
|
+
payload.issues[start].continue = false;
|
|
835
|
+
util.attachSchema(payload.issues, start, inst);
|
|
836
|
+
return payload;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return parse(payload, ctx);
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
const arraySize = (input) => (Array.isArray(input) ? input.length : -1);
|
|
844
|
+
const mapSize = (input) => (input instanceof Map ? input.size : -1);
|
|
845
|
+
const setSize = (input) => (input instanceof Set ? input.size : -1);
|
|
819
846
|
function handleArrayResult(result, final, index) {
|
|
820
847
|
if (result.issues.length) {
|
|
821
848
|
final.issues.push(...util.prefixIssues(index, result.issues));
|
|
@@ -861,6 +888,7 @@ export const $ZodArray = /*@__PURE__*/ core.$constructor("$ZodArray", (inst, def
|
|
|
861
888
|
}
|
|
862
889
|
return payload; //handleArrayResultsAsync(parseResults, final);
|
|
863
890
|
};
|
|
891
|
+
capSize(inst, arraySize);
|
|
864
892
|
});
|
|
865
893
|
function handlePropertyResult(result, final, key, input, optin, optout) {
|
|
866
894
|
const isPresent = key in input;
|
|
@@ -1898,6 +1926,7 @@ export const $ZodMap = /*@__PURE__*/ core.$constructor("$ZodMap", (inst, def) =>
|
|
|
1898
1926
|
return Promise.all(proms).then(() => payload);
|
|
1899
1927
|
return payload;
|
|
1900
1928
|
};
|
|
1929
|
+
capSize(inst, mapSize);
|
|
1901
1930
|
});
|
|
1902
1931
|
function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
|
|
1903
1932
|
if (keyResult.issues.length) {
|
|
@@ -1967,6 +1996,7 @@ export const $ZodSet = /*@__PURE__*/ core.$constructor("$ZodSet", (inst, def) =>
|
|
|
1967
1996
|
return Promise.all(proms).then(() => payload);
|
|
1968
1997
|
return payload;
|
|
1969
1998
|
};
|
|
1999
|
+
capSize(inst, setSize);
|
|
1970
2000
|
});
|
|
1971
2001
|
function handleSetResult(result, final) {
|
|
1972
2002
|
if (result.issues.length) {
|
|
@@ -46,6 +46,7 @@ exports.aborted = aborted;
|
|
|
46
46
|
exports.explicitlyAborted = explicitlyAborted;
|
|
47
47
|
exports.prefixIssues = prefixIssues;
|
|
48
48
|
exports.unwrapMessage = unwrapMessage;
|
|
49
|
+
exports.sizeCaps = sizeCaps;
|
|
49
50
|
exports.attachSchema = attachSchema;
|
|
50
51
|
exports.finalizeIssue = finalizeIssue;
|
|
51
52
|
exports.getSizableOrigin = getSizableOrigin;
|
|
@@ -620,6 +621,20 @@ function unwrapMessage(message) {
|
|
|
620
621
|
return typeof message === "string" ? message : message?.message;
|
|
621
622
|
}
|
|
622
623
|
/* A check holds no link back to the schema it is attached to — the same check instance is shared by every clone of that schema — so the owner is stamped onto the issues a check just raised, at the only point where both are in scope. Runs on the failure path only; `start` is the issue count from before the check ran. */
|
|
624
|
+
/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */
|
|
625
|
+
function sizeCaps(defChecks) {
|
|
626
|
+
const caps = [];
|
|
627
|
+
for (const ch of defChecks ?? []) {
|
|
628
|
+
const d = ch._zod.def;
|
|
629
|
+
// a later check may rewrite the value
|
|
630
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
631
|
+
break;
|
|
632
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
633
|
+
if (max >= 0)
|
|
634
|
+
caps.push([max, ch]);
|
|
635
|
+
}
|
|
636
|
+
return caps;
|
|
637
|
+
}
|
|
623
638
|
function attachSchema(issues, start, inst) {
|
|
624
639
|
var _a;
|
|
625
640
|
for (let i = start; i < issues.length; i++) {
|
|
@@ -221,6 +221,8 @@ export declare function prefixIssues(path: PropertyKey, issues: errors.$ZodRawIs
|
|
|
221
221
|
export declare function unwrapMessage(message: string | {
|
|
222
222
|
message: string;
|
|
223
223
|
} | undefined | null): string | undefined;
|
|
224
|
+
/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */
|
|
225
|
+
export declare function sizeCaps(defChecks: checks.$ZodCheck<never>[] | undefined): [number, checks.$ZodCheck<never>][];
|
|
224
226
|
export declare function attachSchema(issues: errors.$ZodRawIssue[], start: number, inst: schemas.$ZodType): void;
|
|
225
227
|
export declare function finalizeIssue(iss: errors.$ZodRawIssue, ctx: schemas.ParseContextInternal | undefined, config: $ZodConfig): errors.$ZodIssue;
|
|
226
228
|
export declare function getSizableOrigin(input: any): "set" | "map" | "file" | "unknown";
|
|
@@ -221,6 +221,8 @@ export declare function prefixIssues(path: PropertyKey, issues: errors.$ZodRawIs
|
|
|
221
221
|
export declare function unwrapMessage(message: string | {
|
|
222
222
|
message: string;
|
|
223
223
|
} | undefined | null): string | undefined;
|
|
224
|
+
/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */
|
|
225
|
+
export declare function sizeCaps(defChecks: checks.$ZodCheck<never>[] | undefined): [number, checks.$ZodCheck<never>][];
|
|
224
226
|
export declare function attachSchema(issues: errors.$ZodRawIssue[], start: number, inst: schemas.$ZodType): void;
|
|
225
227
|
export declare function finalizeIssue(iss: errors.$ZodRawIssue, ctx: schemas.ParseContextInternal | undefined, config: $ZodConfig): errors.$ZodIssue;
|
|
226
228
|
export declare function getSizableOrigin(input: any): "set" | "map" | "file" | "unknown";
|
|
@@ -550,6 +550,20 @@ export function unwrapMessage(message) {
|
|
|
550
550
|
return typeof message === "string" ? message : message?.message;
|
|
551
551
|
}
|
|
552
552
|
/* A check holds no link back to the schema it is attached to — the same check instance is shared by every clone of that schema — so the owner is stamped onto the issues a check just raised, at the only point where both are in scope. Runs on the failure path only; `start` is the issue count from before the check ran. */
|
|
553
|
+
/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */
|
|
554
|
+
export function sizeCaps(defChecks) {
|
|
555
|
+
const caps = [];
|
|
556
|
+
for (const ch of defChecks ?? []) {
|
|
557
|
+
const d = ch._zod.def;
|
|
558
|
+
// a later check may rewrite the value
|
|
559
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
560
|
+
break;
|
|
561
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
562
|
+
if (max >= 0)
|
|
563
|
+
caps.push([max, ch]);
|
|
564
|
+
}
|
|
565
|
+
return caps;
|
|
566
|
+
}
|
|
553
567
|
export function attachSchema(issues, start, inst) {
|
|
554
568
|
var _a;
|
|
555
569
|
for (let i = start; i < issues.length; i++) {
|
package/package.json
CHANGED
package/version.json
CHANGED