cogsbox-shape 0.5.214 → 0.5.216

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.
@@ -1 +1 @@
1
- export { createShapePlugin, validateShapeRefines, wireShapeValidationOptions, type InferShapeBoxState, type ShapeRefineInfo, type ShapeSchemaBox, type ShapeSchemaBoxEntry, } from "./plugin.js";
1
+ export { createShapePlugin, validateShapeKeys, validateShapeRefines, wireShapeValidationOptions, type InferShapeBoxState, type ShapeRefineInfo, type ShapeSchemaBox, type ShapeSchemaBoxEntry, } from "./plugin.js";
@@ -1 +1 @@
1
- export { createShapePlugin, validateShapeRefines, wireShapeValidationOptions, } from "./plugin.js";
1
+ export { createShapePlugin, validateShapeKeys, validateShapeRefines, wireShapeValidationOptions, } from "./plugin.js";
@@ -1,3 +1,4 @@
1
+ import type { ChainMethodContext } from "cogsbox-state";
1
2
  import { z } from "zod";
2
3
  /** Minimal shape of a createSchemaBox entry — matches journalSchemaBox.journalTechnical etc. */
3
4
  export type ShapeRefineInfo = {
@@ -63,11 +64,36 @@ type UpdateParams = {
63
64
  }>) => void;
64
65
  clearZodErrors?: (paths: string[][]) => void;
65
66
  };
67
+ type ShapeKeyValidationParams = {
68
+ stateKey: string;
69
+ path: string[];
70
+ keys?: readonly string[];
71
+ getState?: () => unknown;
72
+ };
66
73
  export declare function wireShapeValidationOptions(box: ShapeSchemaBox, params: TransformStateParams): void;
67
74
  /** Cross-field refine errors only — field rules are handled by state via setOptions. */
68
75
  export declare function validateShapeRefines(box: ShapeSchemaBox, params: FormUpdateParams): void;
69
76
  export declare function validateShapeRefinesOnUpdate(box: ShapeSchemaBox, params: UpdateParams): void;
77
+ export declare function validateShapeKeys(box: ShapeSchemaBox, params: ShapeKeyValidationParams): {
78
+ success: boolean;
79
+ results: {
80
+ key: string;
81
+ path: string[];
82
+ success: boolean;
83
+ data: any;
84
+ }[];
85
+ };
70
86
  export declare function createShapePlugin<const TBox extends ShapeSchemaBox>(box: TBox): import("cogsbox-state").CogsPluginBuilder<"shape", {
71
87
  logs: boolean | undefined;
72
- }, unknown, unknown, never, {}, true, true, true, false, false, true, InferShapeBoxState<TBox>>;
88
+ }, unknown, unknown, never, {
89
+ validateGroup: import("cogsbox-state").ChainMethodDefinition<(ctx: ChainMethodContext<any, any>, keys?: readonly string[] | undefined) => {
90
+ success: boolean;
91
+ results: {
92
+ key: string;
93
+ path: string[];
94
+ success: boolean;
95
+ data: any;
96
+ }[];
97
+ }>;
98
+ }, true, true, true, true, false, true, InferShapeBoxState<TBox>>;
73
99
  export {};
@@ -108,6 +108,41 @@ function addValidationIssues(params, issues) {
108
108
  params.addZodErrors(issues);
109
109
  notifyValidationPaths(params.stateKey, issues.map((issue) => issue.path));
110
110
  }
111
+ function setValidationIssues(stateKey, issues) {
112
+ if (issues.length === 0)
113
+ return;
114
+ const store = getGlobalStore.getState();
115
+ for (const issue of issues) {
116
+ const currentMeta = store.getShadowMetadata(stateKey, issue.path) || {};
117
+ store.setShadowMetadata(stateKey, issue.path, {
118
+ ...currentMeta,
119
+ validation: {
120
+ status: "INVALID",
121
+ errors: [
122
+ {
123
+ source: "client",
124
+ message: issue.message,
125
+ severity: "error",
126
+ code: issue.code,
127
+ },
128
+ ],
129
+ lastValidated: Date.now(),
130
+ validatedValue: store.getShadowValue(stateKey, issue.path),
131
+ },
132
+ });
133
+ }
134
+ notifyValidationPaths(stateKey, issues.map((issue) => issue.path));
135
+ }
136
+ function issueMatchesSelectedKeys(issue, parentPath, selectedKeys) {
137
+ const issuePath = issue.path.map(String);
138
+ if (issuePath.length <= parentPath.length)
139
+ return false;
140
+ for (let index = 0; index < parentPath.length; index++) {
141
+ if (issuePath[index] !== parentPath[index])
142
+ return false;
143
+ }
144
+ return selectedKeys.has(issuePath[parentPath.length]);
145
+ }
111
146
  function getRelatedFields(entry, field) {
112
147
  const groupIndexes = entry.refineInfo?.fieldToGroup[field];
113
148
  if (!groupIndexes?.length)
@@ -138,7 +173,10 @@ function getChangedObjectFields(oldValue, newValue) {
138
173
  const fields = new Set();
139
174
  const oldRecord = oldValue;
140
175
  const newRecord = newValue;
141
- for (const key of new Set([...Object.keys(oldRecord), ...Object.keys(newRecord)])) {
176
+ for (const key of new Set([
177
+ ...Object.keys(oldRecord),
178
+ ...Object.keys(newRecord),
179
+ ])) {
142
180
  if (!Object.is(oldRecord[key], newRecord[key]))
143
181
  fields.add(key);
144
182
  }
@@ -233,6 +271,64 @@ export function validateShapeRefinesOnUpdate(box, params) {
233
271
  return;
234
272
  applyRefineValidation(box, params, target, params.getState());
235
273
  }
274
+ export function validateShapeKeys(box, params) {
275
+ const entry = box[params.stateKey];
276
+ const clientSchema = entry?.validators?.client ?? entry?.schemas.client;
277
+ if (!entry || !clientSchema)
278
+ return { success: true, results: [] };
279
+ const store = getGlobalStore.getState();
280
+ const rootState = params.getState?.() ?? store.getShadowValue(params.stateKey, []);
281
+ const result = clientSchema.safeParse(rootState);
282
+ const selectedKeys = params.keys ? new Set(params.keys) : null;
283
+ const targetPaths = params.keys?.map((key) => [...params.path, key]) ??
284
+ (result.success
285
+ ? []
286
+ : mapZodIssues(result.error.issues).map((issue) => issue.path));
287
+ if (result.success) {
288
+ clearValidationPaths({
289
+ stateKey: params.stateKey,
290
+ getState: () => rootState,
291
+ addZodErrors: () => { },
292
+ }, targetPaths);
293
+ return {
294
+ success: true,
295
+ results: params.keys?.map((key) => ({
296
+ key,
297
+ path: [...params.path, key],
298
+ success: true,
299
+ data: store.getShadowValue(params.stateKey, [...params.path, key]),
300
+ })) ?? [],
301
+ };
302
+ }
303
+ const issues = selectedKeys
304
+ ? result.error.issues.filter((issue) => issueMatchesSelectedKeys(issue, params.path, selectedKeys))
305
+ : result.error.issues;
306
+ const mapped = mapZodIssues(issues);
307
+ const activeKeys = new Set(mapped.map((issue) => pathKey(issue.path)));
308
+ const stalePaths = targetPaths.filter((targetPath) => !activeKeys.has(pathKey(targetPath)));
309
+ clearValidationPaths({
310
+ stateKey: params.stateKey,
311
+ getState: () => rootState,
312
+ addZodErrors: () => { },
313
+ }, stalePaths);
314
+ setValidationIssues(params.stateKey, mapped);
315
+ return {
316
+ success: mapped.length === 0,
317
+ results: params.keys?.map((key) => {
318
+ const keyPath = [...params.path, key];
319
+ const keyIssues = mapped.filter((issue) => issue.path[params.path.length] === key);
320
+ return {
321
+ key,
322
+ path: keyPath,
323
+ success: keyIssues.length === 0,
324
+ data: keyIssues.length === 0
325
+ ? store.getShadowValue(params.stateKey, keyPath)
326
+ : undefined,
327
+ error: keyIssues.length === 0 ? undefined : { issues: keyIssues },
328
+ };
329
+ }) ?? [],
330
+ };
331
+ }
236
332
  function buildInitialState(box) {
237
333
  const state = {};
238
334
  for (const key of Object.keys(box)) {
@@ -263,5 +359,13 @@ export function createShapePlugin(box) {
263
359
  })
264
360
  .onUpdate((params) => {
265
361
  validateShapeRefinesOnUpdate(box, params);
266
- });
362
+ })
363
+ .methods((m) => ({
364
+ validateGroup: m.object((ctx, keys) => validateShapeKeys(box, {
365
+ stateKey: ctx.stateKey,
366
+ path: ctx.path,
367
+ keys,
368
+ getState: ctx.$get,
369
+ })),
370
+ }));
267
371
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cogsbox-shape",
3
- "version": "0.5.214",
3
+ "version": "0.5.216",
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",
@@ -65,7 +65,6 @@
65
65
  "author": "",
66
66
  "license": "MIT",
67
67
  "dependencies": {
68
- "cogsbox-state": "^0.5.481",
69
68
  "commander": "^13.1.0",
70
69
  "kysely": "^0.29.2",
71
70
  "tsx": "^4.19.3",