@btst/plugin-cms 1.0.0-beta.0 → 1.2.0-beta.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.
Files changed (76) hide show
  1. package/dist/api/getters.cjs +37 -25
  2. package/dist/api/getters.mjs +37 -25
  3. package/dist/api/index.cjs +1 -0
  4. package/dist/api/index.d.cts +17 -8
  5. package/dist/api/index.d.mts +17 -8
  6. package/dist/api/index.d.ts +17 -8
  7. package/dist/api/index.mjs +1 -1
  8. package/dist/api/mutations.cjs +46 -19
  9. package/dist/api/mutations.mjs +46 -20
  10. package/dist/api/operations.cjs +586 -177
  11. package/dist/api/operations.mjs +585 -178
  12. package/dist/api/plugin.cjs +56 -7
  13. package/dist/api/plugin.mjs +57 -8
  14. package/dist/api/publication.cjs +8 -0
  15. package/dist/api/publication.mjs +6 -0
  16. package/dist/client/components/forms/content-form.cjs +107 -1
  17. package/dist/client/components/forms/content-form.mjs +108 -2
  18. package/dist/client/components/pages/content-editor-page.internal.cjs +23 -5
  19. package/dist/client/components/pages/content-editor-page.internal.mjs +23 -5
  20. package/dist/client/components/pages/content-list-page.internal.cjs +3 -0
  21. package/dist/client/components/pages/content-list-page.internal.mjs +3 -0
  22. package/dist/client/components/pages/dashboard-page.internal.cjs +10 -30
  23. package/dist/client/components/pages/dashboard-page.internal.mjs +10 -30
  24. package/dist/client/components/revision-history.cjs +161 -0
  25. package/dist/client/components/revision-history.mjs +159 -0
  26. package/dist/client/components/shared/content-type-card.cjs +56 -0
  27. package/dist/client/components/shared/content-type-card.mjs +54 -0
  28. package/dist/client/components/shared/empty-state.cjs +18 -1
  29. package/dist/client/components/shared/empty-state.mjs +19 -2
  30. package/dist/client/hooks/cms-hooks.cjs +18 -2
  31. package/dist/client/hooks/cms-hooks.mjs +17 -3
  32. package/dist/client/hooks/index.cjs +2 -0
  33. package/dist/client/hooks/index.d.cts +306 -2
  34. package/dist/client/hooks/index.d.mts +306 -2
  35. package/dist/client/hooks/index.d.ts +306 -2
  36. package/dist/client/hooks/index.mjs +1 -1
  37. package/dist/client/index.d.cts +55 -2
  38. package/dist/client/index.d.mts +55 -2
  39. package/dist/client/index.d.ts +55 -2
  40. package/dist/db.cjs +25 -0
  41. package/dist/db.mjs +25 -0
  42. package/dist/permissions.cjs +2 -0
  43. package/dist/permissions.d.cts +1 -0
  44. package/dist/permissions.d.mts +1 -0
  45. package/dist/permissions.d.ts +1 -0
  46. package/dist/permissions.mjs +2 -0
  47. package/dist/query-keys.cjs +31 -1
  48. package/dist/query-keys.d.cts +1 -1
  49. package/dist/query-keys.d.mts +1 -1
  50. package/dist/query-keys.d.ts +1 -1
  51. package/dist/query-keys.mjs +31 -1
  52. package/dist/shared/{plugin-cms.Csx7tNDO.d.mts → plugin-cms.DAAUZ41w.d.mts} +314 -81
  53. package/dist/shared/{plugin-cms.eNW9_FO5.d.ts → plugin-cms.DJ_293QU.d.cts} +314 -81
  54. package/dist/shared/{plugin-cms.Bptwe33B.d.cts → plugin-cms.DlUSv7wz.d.ts} +314 -81
  55. package/dist/types.d.cts +38 -2
  56. package/dist/types.d.mts +38 -2
  57. package/dist/types.d.ts +38 -2
  58. package/dist/ui/src/components/auto-form/config.cjs +2 -0
  59. package/dist/ui/src/components/auto-form/config.mjs +2 -0
  60. package/dist/ui/src/components/auto-form/fields/file.cjs +68 -0
  61. package/dist/ui/src/components/auto-form/fields/file.mjs +63 -0
  62. package/dist/ui/src/components/auto-form/fields/object.cjs +9 -2
  63. package/dist/ui/src/components/auto-form/fields/object.mjs +9 -2
  64. package/dist/ui/src/components/auto-form/helpers.cjs +9 -0
  65. package/dist/ui/src/components/auto-form/helpers.mjs +9 -0
  66. package/dist/ui/src/components/auto-form/index.cjs +29 -4
  67. package/dist/ui/src/components/auto-form/index.mjs +31 -6
  68. package/dist/ui/src/components/auto-form/stepped-auto-form.cjs +34 -29
  69. package/dist/ui/src/components/auto-form/stepped-auto-form.mjs +35 -30
  70. package/dist/ui/src/components/sheet.cjs +126 -0
  71. package/dist/ui/src/components/sheet.mjs +105 -0
  72. package/dist/ui/src/lib/form-visibility.cjs +20 -0
  73. package/dist/ui/src/lib/form-visibility.mjs +18 -0
  74. package/dist/ui/src/lib/schema-converter.cjs +101 -0
  75. package/dist/ui/src/lib/schema-converter.mjs +100 -1
  76. package/package.json +5 -4
@@ -0,0 +1,18 @@
1
+ function matchesShowIf(condition, values) {
2
+ if (!condition) return true;
3
+ const value = Object.hasOwn(values, condition.field) ? values[condition.field] : void 0;
4
+ switch (condition.operator) {
5
+ case "equals":
6
+ return value === condition.value;
7
+ case "notEquals":
8
+ return value !== condition.value;
9
+ case "in":
10
+ return Array.isArray(condition.value) && condition.value.includes(value);
11
+ case "isTruthy":
12
+ return Boolean(value);
13
+ default:
14
+ return false;
15
+ }
16
+ }
17
+
18
+ export { matchesShowIf };
@@ -1,7 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  const z = require('zod');
4
+ const formVisibility = require('./form-visibility.cjs');
4
5
 
6
+ const displaySchemas = /* @__PURE__ */ new WeakMap();
7
+ function getFormDisplaySchema(schema) {
8
+ const cached = displaySchemas.get(schema);
9
+ if (cached) return cached;
10
+ const metadata = schema.meta();
11
+ if (schema instanceof z.z.ZodPipe && metadata?.properties) {
12
+ const display = z.z.fromJSONSchema(metadata);
13
+ displaySchemas.set(schema, display);
14
+ return display;
15
+ }
16
+ return void 0;
17
+ }
5
18
  function zodToFormSchema(schema, metadata) {
6
19
  const jsonSchema = z.z.toJSONSchema(schema, {
7
20
  unrepresentable: "any",
@@ -106,8 +119,94 @@ function attachStepsMetadata(schema, jsonSchema) {
106
119
  stepGroupMap
107
120
  });
108
121
  }
122
+ function hasVisibilityRules(schema) {
123
+ return Boolean(schema.steps?.some((step) => step.showIf) || Object.values(schema.properties ?? {}).some((prop) => prop.showIf || prop.properties && hasVisibilityRules(prop) || prop.items && hasVisibilityRules(prop.items)));
124
+ }
125
+ function resolveVisibleSchema(schema, values) {
126
+ const data = { ...values };
127
+ for (const [key, prop] of Object.entries(schema.properties ?? {})) {
128
+ if (data[key] === void 0 && prop.default !== void 0) Object.defineProperty(data, key, { value: prop.default, enumerable: true, writable: true, configurable: true });
129
+ }
130
+ const comparisonValues = { ...data };
131
+ const visibility = /* @__PURE__ */ new Map();
132
+ const resolving = [];
133
+ const isVisible = (key) => {
134
+ if (visibility.has(key)) return visibility.get(key);
135
+ const cycleStart = resolving.indexOf(key);
136
+ if (cycleStart !== -1) {
137
+ for (const field of resolving.slice(cycleStart)) visibility.set(field, false);
138
+ return false;
139
+ }
140
+ const prop = schema.properties?.[key];
141
+ if (!prop) return true;
142
+ resolving.push(key);
143
+ const matches = (condition) => {
144
+ if (!condition) return true;
145
+ const sourceVisible = isVisible(condition.field);
146
+ return formVisibility.matchesShowIf(condition, { [condition.field]: sourceVisible && Object.hasOwn(comparisonValues, condition.field) ? comparisonValues[condition.field] : void 0 });
147
+ };
148
+ const step = schema.steps?.[prop.stepGroup ?? schema.stepGroupMap?.[key] ?? 0];
149
+ const result = matches(step?.showIf) && matches(prop.showIf);
150
+ resolving.pop();
151
+ if (!visibility.has(key)) visibility.set(key, result);
152
+ return visibility.get(key);
153
+ };
154
+ const properties = /* @__PURE__ */ Object.create(null);
155
+ for (const [key, prop] of Object.entries(schema.properties ?? {})) {
156
+ if (!isVisible(key)) {
157
+ Reflect.deleteProperty(data, key);
158
+ continue;
159
+ }
160
+ const { showIf: _showIf, ...visibleProp } = prop;
161
+ if (prop.properties && data[key] && typeof data[key] === "object" && !Array.isArray(data[key])) {
162
+ const nested = resolveVisibleSchema(prop, data[key]);
163
+ Object.assign(visibleProp, nested.schema);
164
+ data[key] = nested.data;
165
+ }
166
+ properties[key] = visibleProp;
167
+ }
168
+ return { schema: { ...schema, properties, required: schema.required?.filter((key) => key in properties), steps: schema.steps?.map(({ showIf: _showIf, ...step }) => step) }, data };
169
+ }
109
170
  function formSchemaToZod(jsonSchema) {
171
+ if (jsonSchema.default !== void 0 && hasVisibilityRules(jsonSchema)) {
172
+ const { default: defaultValue, ...contentSchema } = jsonSchema;
173
+ return formSchemaToZod(contentSchema).prefault(defaultValue).meta({ ...jsonSchema });
174
+ }
175
+ if (jsonSchema.steps?.some((step) => step.showIf) || Object.values(jsonSchema.properties ?? {}).some((prop) => prop.showIf)) {
176
+ const display = z.z.fromJSONSchema(jsonSchema);
177
+ const shape = Object.fromEntries(Object.entries(display.shape).map(([key]) => [key, z.z.unknown().optional()]));
178
+ const conditional = z.z.object(shape).passthrough().transform((data, ctx) => {
179
+ const { schema: visibleSchema, data: visibleData } = resolveVisibleSchema(jsonSchema, data);
180
+ const result = formSchemaToZod(visibleSchema).safeParse(visibleData);
181
+ if (!result.success) {
182
+ for (const issue of result.error.issues) ctx.addIssue({ ...issue });
183
+ return z.z.NEVER;
184
+ }
185
+ return result.data;
186
+ }).meta({ ...jsonSchema });
187
+ displaySchemas.set(conditional, display);
188
+ return conditional;
189
+ }
110
190
  let schema = z.z.fromJSONSchema(jsonSchema);
191
+ if (schema instanceof z.z.ZodObject) {
192
+ const nestedShape = {};
193
+ for (const [key, prop] of Object.entries(jsonSchema.properties ?? {})) {
194
+ if (!hasVisibilityRules({ properties: { [key]: prop } })) continue;
195
+ let nested;
196
+ if (prop.type === "object" && prop.properties) nested = formSchemaToZod(prop);
197
+ if (prop.type === "array" && prop.items?.properties) {
198
+ let array = z.z.array(formSchemaToZod(prop.items));
199
+ if (typeof prop.minItems === "number") array = array.min(prop.minItems);
200
+ if (typeof prop.maxItems === "number") array = array.max(prop.maxItems);
201
+ nested = array;
202
+ }
203
+ if (nested) {
204
+ if (!jsonSchema.required?.includes(key)) nested = nested.optional();
205
+ nestedShape[key] = prop.default !== void 0 ? nested.prefault(prop.default) : nested;
206
+ }
207
+ }
208
+ if (Object.keys(nestedShape).length) schema = schema.extend(nestedShape);
209
+ }
111
210
  if (schema && typeof schema.passthrough === "function") {
112
211
  schema = schema.passthrough();
113
212
  }
@@ -127,7 +226,9 @@ function getStepGroupMap(jsonSchema) {
127
226
  }
128
227
 
129
228
  exports.formSchemaToZod = formSchemaToZod;
229
+ exports.getFormDisplaySchema = getFormDisplaySchema;
130
230
  exports.getStepGroupMap = getStepGroupMap;
131
231
  exports.getSteps = getSteps;
132
232
  exports.hasSteps = hasSteps;
233
+ exports.resolveVisibleSchema = resolveVisibleSchema;
133
234
  exports.zodToFormSchema = zodToFormSchema;
@@ -1,5 +1,18 @@
1
1
  import { z } from 'zod';
2
+ import { matchesShowIf } from './form-visibility.mjs';
2
3
 
4
+ const displaySchemas = /* @__PURE__ */ new WeakMap();
5
+ function getFormDisplaySchema(schema) {
6
+ const cached = displaySchemas.get(schema);
7
+ if (cached) return cached;
8
+ const metadata = schema.meta();
9
+ if (schema instanceof z.ZodPipe && metadata?.properties) {
10
+ const display = z.fromJSONSchema(metadata);
11
+ displaySchemas.set(schema, display);
12
+ return display;
13
+ }
14
+ return void 0;
15
+ }
3
16
  function zodToFormSchema(schema, metadata) {
4
17
  const jsonSchema = z.toJSONSchema(schema, {
5
18
  unrepresentable: "any",
@@ -104,8 +117,94 @@ function attachStepsMetadata(schema, jsonSchema) {
104
117
  stepGroupMap
105
118
  });
106
119
  }
120
+ function hasVisibilityRules(schema) {
121
+ return Boolean(schema.steps?.some((step) => step.showIf) || Object.values(schema.properties ?? {}).some((prop) => prop.showIf || prop.properties && hasVisibilityRules(prop) || prop.items && hasVisibilityRules(prop.items)));
122
+ }
123
+ function resolveVisibleSchema(schema, values) {
124
+ const data = { ...values };
125
+ for (const [key, prop] of Object.entries(schema.properties ?? {})) {
126
+ if (data[key] === void 0 && prop.default !== void 0) Object.defineProperty(data, key, { value: prop.default, enumerable: true, writable: true, configurable: true });
127
+ }
128
+ const comparisonValues = { ...data };
129
+ const visibility = /* @__PURE__ */ new Map();
130
+ const resolving = [];
131
+ const isVisible = (key) => {
132
+ if (visibility.has(key)) return visibility.get(key);
133
+ const cycleStart = resolving.indexOf(key);
134
+ if (cycleStart !== -1) {
135
+ for (const field of resolving.slice(cycleStart)) visibility.set(field, false);
136
+ return false;
137
+ }
138
+ const prop = schema.properties?.[key];
139
+ if (!prop) return true;
140
+ resolving.push(key);
141
+ const matches = (condition) => {
142
+ if (!condition) return true;
143
+ const sourceVisible = isVisible(condition.field);
144
+ return matchesShowIf(condition, { [condition.field]: sourceVisible && Object.hasOwn(comparisonValues, condition.field) ? comparisonValues[condition.field] : void 0 });
145
+ };
146
+ const step = schema.steps?.[prop.stepGroup ?? schema.stepGroupMap?.[key] ?? 0];
147
+ const result = matches(step?.showIf) && matches(prop.showIf);
148
+ resolving.pop();
149
+ if (!visibility.has(key)) visibility.set(key, result);
150
+ return visibility.get(key);
151
+ };
152
+ const properties = /* @__PURE__ */ Object.create(null);
153
+ for (const [key, prop] of Object.entries(schema.properties ?? {})) {
154
+ if (!isVisible(key)) {
155
+ Reflect.deleteProperty(data, key);
156
+ continue;
157
+ }
158
+ const { showIf: _showIf, ...visibleProp } = prop;
159
+ if (prop.properties && data[key] && typeof data[key] === "object" && !Array.isArray(data[key])) {
160
+ const nested = resolveVisibleSchema(prop, data[key]);
161
+ Object.assign(visibleProp, nested.schema);
162
+ data[key] = nested.data;
163
+ }
164
+ properties[key] = visibleProp;
165
+ }
166
+ return { schema: { ...schema, properties, required: schema.required?.filter((key) => key in properties), steps: schema.steps?.map(({ showIf: _showIf, ...step }) => step) }, data };
167
+ }
107
168
  function formSchemaToZod(jsonSchema) {
169
+ if (jsonSchema.default !== void 0 && hasVisibilityRules(jsonSchema)) {
170
+ const { default: defaultValue, ...contentSchema } = jsonSchema;
171
+ return formSchemaToZod(contentSchema).prefault(defaultValue).meta({ ...jsonSchema });
172
+ }
173
+ if (jsonSchema.steps?.some((step) => step.showIf) || Object.values(jsonSchema.properties ?? {}).some((prop) => prop.showIf)) {
174
+ const display = z.fromJSONSchema(jsonSchema);
175
+ const shape = Object.fromEntries(Object.entries(display.shape).map(([key]) => [key, z.unknown().optional()]));
176
+ const conditional = z.object(shape).passthrough().transform((data, ctx) => {
177
+ const { schema: visibleSchema, data: visibleData } = resolveVisibleSchema(jsonSchema, data);
178
+ const result = formSchemaToZod(visibleSchema).safeParse(visibleData);
179
+ if (!result.success) {
180
+ for (const issue of result.error.issues) ctx.addIssue({ ...issue });
181
+ return z.NEVER;
182
+ }
183
+ return result.data;
184
+ }).meta({ ...jsonSchema });
185
+ displaySchemas.set(conditional, display);
186
+ return conditional;
187
+ }
108
188
  let schema = z.fromJSONSchema(jsonSchema);
189
+ if (schema instanceof z.ZodObject) {
190
+ const nestedShape = {};
191
+ for (const [key, prop] of Object.entries(jsonSchema.properties ?? {})) {
192
+ if (!hasVisibilityRules({ properties: { [key]: prop } })) continue;
193
+ let nested;
194
+ if (prop.type === "object" && prop.properties) nested = formSchemaToZod(prop);
195
+ if (prop.type === "array" && prop.items?.properties) {
196
+ let array = z.array(formSchemaToZod(prop.items));
197
+ if (typeof prop.minItems === "number") array = array.min(prop.minItems);
198
+ if (typeof prop.maxItems === "number") array = array.max(prop.maxItems);
199
+ nested = array;
200
+ }
201
+ if (nested) {
202
+ if (!jsonSchema.required?.includes(key)) nested = nested.optional();
203
+ nestedShape[key] = prop.default !== void 0 ? nested.prefault(prop.default) : nested;
204
+ }
205
+ }
206
+ if (Object.keys(nestedShape).length) schema = schema.extend(nestedShape);
207
+ }
109
208
  if (schema && typeof schema.passthrough === "function") {
110
209
  schema = schema.passthrough();
111
210
  }
@@ -124,4 +223,4 @@ function getStepGroupMap(jsonSchema) {
124
223
  return jsonSchema.stepGroupMap ?? extractStepGroupMap(jsonSchema);
125
224
  }
126
225
 
127
- export { formSchemaToZod, getStepGroupMap, getSteps, hasSteps, zodToFormSchema };
226
+ export { formSchemaToZod, getFormDisplaySchema, getStepGroupMap, getSteps, hasSteps, resolveVisibleSchema, zodToFormSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btst/plugin-cms",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.2.0-beta.0",
4
4
  "type": "module",
5
5
  "description": "CMS plugin for the BTST core runtime.",
6
6
  "license": "MIT",
@@ -142,13 +142,14 @@
142
142
  "zod": "^4.2.1"
143
143
  },
144
144
  "peerDependencies": {
145
- "@btst/stack": ">=6.0.0-beta.0 <7.0.0",
145
+ "@btst/stack": ">=6.2.0-beta.0 <6.2.0",
146
146
  "@btst/yar": ">=1.3.2",
147
147
  "@tanstack/react-query": "^5.0.0",
148
148
  "react": ">=19.2.6",
149
149
  "react-dom": ">=19.2.6"
150
150
  },
151
151
  "devDependencies": {
152
+ "better-auth": "1.7.14",
152
153
  "@btst/yar": "1.3.2",
153
154
  "@tanstack/react-query": "5.105.0",
154
155
  "@types/react": "^19.3.0",
@@ -161,10 +162,10 @@
161
162
  "@btst/adapter-memory": "3.0.1",
162
163
  "jsdom": "^28.1.0",
163
164
  "@types/slug": "^5.0.9",
164
- "@btst/stack": "6.0.0-beta.0",
165
+ "@btst/stack": "6.2.0-beta.0",
165
166
  "@workspace/ui": "0.0.0"
166
167
  },
167
- "gitHead": "ac7a6206d81e36262baf4392255575b4dc9bf6b5",
168
+ "gitHead": "a4bbf36fd6f07909353ea84aa22de491bbefc260",
168
169
  "scripts": {
169
170
  "build": "unbuild --clean",
170
171
  "typecheck": "tsc --project tsconfig.json && tsc --project tsconfig.typecheck.json",