cogsbox-shape 0.5.218 → 0.5.219

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.
@@ -68,6 +68,8 @@ type ShapeKeyValidationParams = {
68
68
  path: string[];
69
69
  keys?: readonly string[];
70
70
  getState?: () => unknown;
71
+ /** When true (default), writes filtered issues to shadow validation metadata. */
72
+ persist?: boolean;
71
73
  };
72
74
  export declare function wireShapeValidationOptions(box: ShapeSchemaBox, params: TransformStateParams): void;
73
75
  /** Cross-field refine errors only — field rules are handled by state via setOptions. */
@@ -117,6 +117,80 @@ function addValidationIssues(params, issues) {
117
117
  params.addZodErrors(issues);
118
118
  notifyValidationPaths(params.stateKey, issues.map((issue) => issue.path));
119
119
  }
120
+ function createShadowValidationBridge(stateKey) {
121
+ const store = getGlobalStore.getState();
122
+ return {
123
+ stateKey,
124
+ getState: () => store.getShadowValue(stateKey, []),
125
+ addZodErrors: (issues) => {
126
+ for (const error of issues) {
127
+ const errorPath = error.path;
128
+ const currentMeta = store.getShadowMetadata(stateKey, errorPath) || {};
129
+ store.setShadowMetadata(stateKey, errorPath, {
130
+ ...currentMeta,
131
+ validation: {
132
+ status: "INVALID",
133
+ errors: [
134
+ {
135
+ source: "client",
136
+ message: error.message,
137
+ severity: "error",
138
+ code: error.code,
139
+ },
140
+ ],
141
+ lastValidated: Date.now(),
142
+ validatedValue: undefined,
143
+ },
144
+ });
145
+ }
146
+ },
147
+ clearZodErrors: (paths) => {
148
+ for (const path of paths) {
149
+ const currentMeta = store.getShadowMetadata(stateKey, path) || {};
150
+ store.setShadowMetadata(stateKey, path, {
151
+ ...currentMeta,
152
+ validation: {
153
+ status: "NOT_VALIDATED",
154
+ errors: [],
155
+ lastValidated: Date.now(),
156
+ validatedValue: undefined,
157
+ },
158
+ });
159
+ }
160
+ },
161
+ };
162
+ }
163
+ function notifyStateComponents(stateKey) {
164
+ const store = getGlobalStore.getState();
165
+ const stateEntry = store.getShadowMetadata(stateKey, []);
166
+ if (!stateEntry?.components)
167
+ return;
168
+ const updates = new Set();
169
+ stateEntry.components.forEach((component) => {
170
+ const reactiveTypes = component
171
+ ? Array.isArray(component.reactiveType)
172
+ ? component.reactiveType
173
+ : [component.reactiveType || "component"]
174
+ : null;
175
+ if (!reactiveTypes?.includes("none")) {
176
+ updates.add(() => component.forceUpdate());
177
+ }
178
+ });
179
+ queueMicrotask(() => {
180
+ updates.forEach((update) => update());
181
+ });
182
+ }
183
+ function persistValidateGroupResults(params, keys, mapped) {
184
+ const validationParams = createShadowValidationBridge(params.stateKey);
185
+ const keyPaths = keys.map((key) => [...params.path, key]);
186
+ const activeKeys = new Set(mapped.map((issue) => pathKey(issue.path)));
187
+ const stalePaths = keyPaths.filter((targetPath) => !activeKeys.has(pathKey(targetPath)));
188
+ clearValidationPaths(validationParams, stalePaths);
189
+ if (mapped.length > 0) {
190
+ addValidationIssues(validationParams, mapped);
191
+ }
192
+ notifyStateComponents(params.stateKey);
193
+ }
120
194
  function issueMatchesSelectedKeys(issue, parentPath, selectedKeys) {
121
195
  const issuePath = issue.path.map(String);
122
196
  if (issuePath.length <= parentPath.length)
@@ -263,7 +337,11 @@ export function validateShapeKeys(box, params) {
263
337
  const rootState = params.getState?.() ?? getGlobalStore.getState().getShadowValue(params.stateKey, []);
264
338
  const result = clientSchema.safeParse(rootState);
265
339
  const selectedKeys = params.keys ? new Set(params.keys) : null;
340
+ const shouldPersist = params.persist !== false && !!params.keys?.length;
266
341
  if (result.success) {
342
+ if (shouldPersist) {
343
+ persistValidateGroupResults(params, params.keys, []);
344
+ }
267
345
  return {
268
346
  success: true,
269
347
  results: params.keys?.map((key) => ({
@@ -278,6 +356,9 @@ export function validateShapeKeys(box, params) {
278
356
  ? result.error.issues.filter((issue) => issueMatchesSelectedKeys(issue, params.path, selectedKeys))
279
357
  : result.error.issues;
280
358
  const mapped = mapZodIssues(issues);
359
+ if (shouldPersist) {
360
+ persistValidateGroupResults(params, params.keys, mapped);
361
+ }
281
362
  return {
282
363
  success: mapped.length === 0,
283
364
  results: params.keys?.map((key) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cogsbox-shape",
3
- "version": "0.5.218",
3
+ "version": "0.5.219",
4
4
  "description": "A TypeScript library for creating type-safe database schemas with Zod validation, SQL type definitions, and automatic client/server transformations. Unifies client, server, and database types through a single schema definition, with built-in support for relationships and serialization.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",