@k8ordo/form 0.1.0 → 0.1.1
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 +6 -0
- package/dist/derive/form-fields.mjs +25 -0
- package/dist/index.d.mts +2 -2
- package/docs/GUIDE.md +2 -1
- package/docs/llms.txt +8 -3
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -96,6 +96,12 @@ async per-field checks, components that render no input of their own, and what
|
|
|
96
96
|
the package guarantees (nothing dropped in silence, native validation kept
|
|
97
97
|
without JavaScript, secrets never echoed).
|
|
98
98
|
|
|
99
|
+
A check HTML cannot express — a `refine`, a regex the `pattern` attribute
|
|
100
|
+
would reinterpret — is returned in `dropped` (typed as `DroppedCheck`, exported
|
|
101
|
+
from both entries) and, outside production, logged once per schema with
|
|
102
|
+
`console.warn`, so it is seen without anyone remembering to read it. It still
|
|
103
|
+
runs on the server.
|
|
104
|
+
|
|
99
105
|
## AI Agent Documentation
|
|
100
106
|
|
|
101
107
|
The docs ship **inside the package**, so an agent always reads the exact
|
|
@@ -21,6 +21,30 @@ const patternFlags = (schema, source) => {
|
|
|
21
21
|
/** What a `datetime-local` control actually submits: no seconds, no zone. */
|
|
22
22
|
const DATETIME_LOCAL_PROBE = "2000-01-01T00:00";
|
|
23
23
|
/**
|
|
24
|
+
* Schemas whose `dropped` list has already been reported. `formFields` is not
|
|
25
|
+
* memoized, so a schema derived in every request would otherwise warn on
|
|
26
|
+
* every request; keyed by the schema object, an HMR re-evaluation still gets
|
|
27
|
+
* its warning back, because it is a new object.
|
|
28
|
+
*/
|
|
29
|
+
const warned = /* @__PURE__ */ new WeakSet();
|
|
30
|
+
/**
|
|
31
|
+
* `dropped` is returned, but a return value is only seen by whoever reads
|
|
32
|
+
* it. Outside production the list is also written to the console, once per
|
|
33
|
+
* schema, so the checks the browser will never run are noticed without
|
|
34
|
+
* anyone remembering to look.
|
|
35
|
+
*/
|
|
36
|
+
const warnDropped = (schema, dropped) => {
|
|
37
|
+
if (process.env.NODE_ENV === "production") return;
|
|
38
|
+
if (dropped.length === 0 || warned.has(schema)) return;
|
|
39
|
+
warned.add(schema);
|
|
40
|
+
const lines = dropped.map(({ field, reason }) => ` - ${field}: ${reason}`);
|
|
41
|
+
console.warn([
|
|
42
|
+
"[@k8ordo/form] クライアントでは検査されないチェックがあります(サーバーでは検査されます)。",
|
|
43
|
+
...lines,
|
|
44
|
+
" ブラウザ側でも検査するには、formFields の戻り値 dropped を確認してください。"
|
|
45
|
+
].join("\n"));
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
24
48
|
* Derive input attributes and messages from one zod object schema.
|
|
25
49
|
*
|
|
26
50
|
* Call this on the server — in a Server Component or at module scope. The
|
|
@@ -72,6 +96,7 @@ const formFields = (input) => {
|
|
|
72
96
|
field: "(schema)",
|
|
73
97
|
reason: `${String(objectChecks)}件のオブジェクト階層のチェック(refine など)は HTML の制約属性に落ちないため、クライアントでは検査されません`
|
|
74
98
|
});
|
|
99
|
+
warnDropped(schema, dropped);
|
|
75
100
|
return {
|
|
76
101
|
fields,
|
|
77
102
|
arrays,
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncCheck, useAsyncCheck } from "./async-check.mjs";
|
|
2
2
|
import { Rule } from "./rules/rules.mjs";
|
|
3
|
-
import { DerivedArray, DerivedField, FieldInput, FormFields, FormState, ValidityFlag } from "./types.mjs";
|
|
3
|
+
import { DerivedArray, DerivedField, DroppedCheck, FieldInput, FormFields, FormState, ValidityFlag } from "./types.mjs";
|
|
4
4
|
import { HiddenValue } from "./hidden-value.mjs";
|
|
5
5
|
import { ArrayView, FieldView, RowView, UseFormReturn, useForm } from "./use-form.mjs";
|
|
6
|
-
export { type ArrayView, type AsyncCheck, type DerivedArray, type DerivedField, type FieldInput, type FieldView, type FormFields, type FormState, HiddenValue, type RowView, type Rule, type UseFormReturn, type ValidityFlag, useAsyncCheck, useForm };
|
|
6
|
+
export { type ArrayView, type AsyncCheck, type DerivedArray, type DerivedField, type DroppedCheck, type FieldInput, type FieldView, type FormFields, type FormState, HiddenValue, type RowView, type Rule, type UseFormReturn, type ValidityFlag, useAsyncCheck, useForm };
|
package/docs/GUIDE.md
CHANGED
|
@@ -121,7 +121,8 @@ cross-field rules, an exclusive bound on a float, a regex whose flags or
|
|
|
121
121
|
anchoring the `pattern` attribute would silently reinterpret, a
|
|
122
122
|
`z.iso.datetime()` no `datetime-local` control can ever satisfy — are returned
|
|
123
123
|
in `dropped`. They still run on the server; you are told they do not run on
|
|
124
|
-
the client.
|
|
124
|
+
the client. Outside production `formFields` also logs the list once per schema
|
|
125
|
+
with `console.warn`, so it is seen without anyone remembering to read it.
|
|
125
126
|
|
|
126
127
|
**A schema this package cannot express fails at derive time.** `z.record`,
|
|
127
128
|
tuples, a repeat nested inside a repeat, nullable objects, keys containing
|
package/docs/llms.txt
CHANGED
|
@@ -23,10 +23,15 @@ When installed via npm, these docs live under `node_modules/@k8ordo/form/docs/`.
|
|
|
23
23
|
`field(path)` accessor giving input attributes, the current error, and
|
|
24
24
|
`invalid` / `required`, an `array(path)` accessor for repeated rows, and
|
|
25
25
|
`isDirty`. Also `useAsyncCheck` for server-answered per-field checks and
|
|
26
|
-
`HiddenValue` for components that render no input of their own.
|
|
26
|
+
`HiddenValue` for components that render no input of their own. The types
|
|
27
|
+
of the `formFields` result (`FormFields`, `DerivedField`, `DerivedArray`,
|
|
28
|
+
`DroppedCheck`) are exported here as well, since the result crosses to the
|
|
29
|
+
client as a prop.
|
|
27
30
|
- `@k8ordo/form/server` — server. `formFields(schema)` derives serializable
|
|
28
|
-
fields plus a `dropped` list of checks HTML cannot express
|
|
29
|
-
|
|
31
|
+
fields plus a `dropped` list of checks HTML cannot express (outside
|
|
32
|
+
production the list is also logged once per schema with `console.warn`),
|
|
33
|
+
and throws on a schema no form can represent;
|
|
34
|
+
`parseForm(schema, formData)` validates a
|
|
30
35
|
submission and returns typed data or per-field errors with the submitted
|
|
31
36
|
values. `defineForm(schema, rules)` attaches cross-field rules (`sameAs`,
|
|
32
37
|
`minChecked`, `requiredWhen`) typed against the schema's paths.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k8ordo/form",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Derive HTML constraint attributes and per-field errors from one zod schema. Works without JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"constraint-validation",
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"zod"
|
|
12
12
|
],
|
|
13
13
|
"homepage": "https://ordo.k8o.me",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/k35o/k8ordo/issues"
|
|
16
|
+
},
|
|
14
17
|
"license": "MIT",
|
|
15
18
|
"author": "k8o <kosakanoki@gmail.com>",
|
|
16
19
|
"repository": {
|
|
@@ -39,9 +42,11 @@
|
|
|
39
42
|
"registry": "https://registry.npmjs.org"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
45
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
42
46
|
"@types/react": "19.2.18",
|
|
43
47
|
"@vitejs/plugin-react": "6.0.5",
|
|
44
48
|
"@vitest/browser-playwright": "4.1.10",
|
|
49
|
+
"publint": "0.3.23",
|
|
45
50
|
"react": "19.2.8",
|
|
46
51
|
"react-dom": "19.2.8",
|
|
47
52
|
"typescript": "7.0.2",
|
|
@@ -71,6 +76,7 @@
|
|
|
71
76
|
"test": "vp test",
|
|
72
77
|
"typecheck": "tsc --noEmit",
|
|
73
78
|
"check": "vp check",
|
|
74
|
-
"check:write": "vp check --fix"
|
|
79
|
+
"check:write": "vp check --fix",
|
|
80
|
+
"check:package": "publint && attw --pack . --profile esm-only"
|
|
75
81
|
}
|
|
76
82
|
}
|