@btst/stack 2.11.6 → 2.11.7

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.
@@ -4,6 +4,7 @@ const LucideIcons = require('lucide-react');
4
4
  const z = require('zod');
5
5
  const types = require('../types.cjs');
6
6
  const validationSchemas = require('../validation-schemas.cjs');
7
+ const helpers = require('../../auto-form/helpers.cjs');
7
8
 
8
9
  function toNumber(value) {
9
10
  if (value == null || value === "") return void 0;
@@ -20,7 +21,7 @@ function getPlaceholder(prop) {
20
21
  return prop.inputProps?.placeholder || prop.placeholder;
21
22
  }
22
23
  function getLabel(prop, key) {
23
- return prop.label || prop.title || key;
24
+ return prop.label || prop.title || helpers.beautifyObjectName(key);
24
25
  }
25
26
  const textFieldDefinition = types.defineComponent({
26
27
  type: "text",
@@ -2,6 +2,7 @@ import { FolderOpen, List, Mail, Lock, Globe, Phone, Calendar, AlignLeft, Toggle
2
2
  import { z } from 'zod';
3
3
  import { defineComponent } from '../types.mjs';
4
4
  import { baseMetaSchemaWithPlaceholder, stringValidationSchema, DEFAULT_VALUE_SCHEMAS, numberValidationSchema, baseMetaSchema, booleanValidationSchema, enumOptionsSchema, dateValidationSchema, objectValidationSchema, arrayValidationSchema } from '../validation-schemas.mjs';
5
+ import { beautifyObjectName } from '../../auto-form/helpers.mjs';
5
6
 
6
7
  function toNumber(value) {
7
8
  if (value == null || value === "") return void 0;
@@ -18,7 +19,7 @@ function getPlaceholder(prop) {
18
19
  return prop.inputProps?.placeholder || prop.placeholder;
19
20
  }
20
21
  function getLabel(prop, key) {
21
- return prop.label || prop.title || key;
22
+ return prop.label || prop.title || beautifyObjectName(key);
22
23
  }
23
24
  const textFieldDefinition = defineComponent({
24
25
  type: "text",
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const helpers = require('../auto-form/helpers.cjs');
4
+
3
5
  function fieldsToProperties(fields, components, includeStepGroup = false) {
4
6
  const properties = {};
5
7
  for (const field of fields) {
@@ -80,7 +82,7 @@ function propertiesToFields(properties, requiredSet, components, stepGroupMap) {
80
82
  id: key,
81
83
  type: "text",
82
84
  props: {
83
- label: prop.title || key,
85
+ label: prop.label || prop.title || helpers.beautifyObjectName(key),
84
86
  description: prop.description,
85
87
  placeholder: prop.placeholder,
86
88
  required: isRequired
@@ -1,3 +1,5 @@
1
+ import { beautifyObjectName } from '../auto-form/helpers.mjs';
2
+
1
3
  function fieldsToProperties(fields, components, includeStepGroup = false) {
2
4
  const properties = {};
3
5
  for (const field of fields) {
@@ -78,7 +80,7 @@ function propertiesToFields(properties, requiredSet, components, stepGroupMap) {
78
80
  id: key,
79
81
  type: "text",
80
82
  props: {
81
- label: prop.title || key,
83
+ label: prop.label || prop.title || beautifyObjectName(key),
82
84
  description: prop.description,
83
85
  placeholder: prop.placeholder,
84
86
  required: isRequired
@@ -1,4 +1,4 @@
1
- export { B as BoardListResult, C as CreateKanbanTaskInput, i as KANBAN_QUERY_KEYS, b as KanbanApiContext, K as KanbanApiRouter, c as KanbanBackendHooks, a as KanbanRouteKey, e as createKanbanTask, f as findOrCreateKanbanBoard, g as getAllBoards, d as getBoardById, h as getKanbanColumnsByBoardId, k as kanbanBackendPlugin } from '../../../shared/stack.f6MrG7ys.cjs';
1
+ export { B as BoardListResult, C as CreateKanbanTaskInput, i as KANBAN_QUERY_KEYS, b as KanbanApiContext, K as KanbanApiRouter, c as KanbanBackendHooks, a as KanbanRouteKey, e as createKanbanTask, f as findOrCreateKanbanBoard, g as getAllBoards, d as getBoardById, h as getKanbanColumnsByBoardId, k as kanbanBackendPlugin } from '../../../shared/stack.Rtcvl8sS.cjs';
2
2
  import { B as BoardWithColumns, S as SerializedBoardWithColumns, C as ColumnWithTasks, a as SerializedColumn, T as Task, b as SerializedTask } from '../../../shared/stack.DJaKVY7v.cjs';
3
3
  import '@btst/stack/plugins/api';
4
4
  import '@btst/db';
@@ -1,4 +1,4 @@
1
- export { B as BoardListResult, C as CreateKanbanTaskInput, i as KANBAN_QUERY_KEYS, b as KanbanApiContext, K as KanbanApiRouter, c as KanbanBackendHooks, a as KanbanRouteKey, e as createKanbanTask, f as findOrCreateKanbanBoard, g as getAllBoards, d as getBoardById, h as getKanbanColumnsByBoardId, k as kanbanBackendPlugin } from '../../../shared/stack.BzKW7ToW.mjs';
1
+ export { B as BoardListResult, C as CreateKanbanTaskInput, i as KANBAN_QUERY_KEYS, b as KanbanApiContext, K as KanbanApiRouter, c as KanbanBackendHooks, a as KanbanRouteKey, e as createKanbanTask, f as findOrCreateKanbanBoard, g as getAllBoards, d as getBoardById, h as getKanbanColumnsByBoardId, k as kanbanBackendPlugin } from '../../../shared/stack.HE_IvqV5.mjs';
2
2
  import { B as BoardWithColumns, S as SerializedBoardWithColumns, C as ColumnWithTasks, a as SerializedColumn, T as Task, b as SerializedTask } from '../../../shared/stack.DJaKVY7v.mjs';
3
3
  import '@btst/stack/plugins/api';
4
4
  import '@btst/db';
@@ -1,4 +1,4 @@
1
- export { B as BoardListResult, C as CreateKanbanTaskInput, i as KANBAN_QUERY_KEYS, b as KanbanApiContext, K as KanbanApiRouter, c as KanbanBackendHooks, a as KanbanRouteKey, e as createKanbanTask, f as findOrCreateKanbanBoard, g as getAllBoards, d as getBoardById, h as getKanbanColumnsByBoardId, k as kanbanBackendPlugin } from '../../../shared/stack.9dFHtvXR.js';
1
+ export { B as BoardListResult, C as CreateKanbanTaskInput, i as KANBAN_QUERY_KEYS, b as KanbanApiContext, K as KanbanApiRouter, c as KanbanBackendHooks, a as KanbanRouteKey, e as createKanbanTask, f as findOrCreateKanbanBoard, g as getAllBoards, d as getBoardById, h as getKanbanColumnsByBoardId, k as kanbanBackendPlugin } from '../../../shared/stack.D4Cea8II.js';
2
2
  import { B as BoardWithColumns, S as SerializedBoardWithColumns, C as ColumnWithTasks, a as SerializedColumn, T as Task, b as SerializedTask } from '../../../shared/stack.DJaKVY7v.js';
3
3
  import '@btst/stack/plugins/api';
4
4
  import '@btst/db';
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { K as KanbanApiRouter, j as BoardsListDiscriminator } from '../../shared/stack.f6MrG7ys.cjs';
2
+ import { K as KanbanApiRouter, j as BoardsListDiscriminator } from '../../shared/stack.Rtcvl8sS.cjs';
3
3
  import { createApiClient } from '@btst/stack/plugins/client';
4
4
  import { S as SerializedBoardWithColumns } from '../../shared/stack.DJaKVY7v.cjs';
5
5
  import '@btst/stack/plugins/api';
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { K as KanbanApiRouter, j as BoardsListDiscriminator } from '../../shared/stack.BzKW7ToW.mjs';
2
+ import { K as KanbanApiRouter, j as BoardsListDiscriminator } from '../../shared/stack.HE_IvqV5.mjs';
3
3
  import { createApiClient } from '@btst/stack/plugins/client';
4
4
  import { S as SerializedBoardWithColumns } from '../../shared/stack.DJaKVY7v.mjs';
5
5
  import '@btst/stack/plugins/api';
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { K as KanbanApiRouter, j as BoardsListDiscriminator } from '../../shared/stack.9dFHtvXR.js';
2
+ import { K as KanbanApiRouter, j as BoardsListDiscriminator } from '../../shared/stack.D4Cea8II.js';
3
3
  import { createApiClient } from '@btst/stack/plugins/client';
4
4
  import { S as SerializedBoardWithColumns } from '../../shared/stack.DJaKVY7v.js';
5
5
  import '@btst/stack/plugins/api';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btst/stack",
3
- "version": "2.11.6",
3
+ "version": "2.11.7",
4
4
  "description": "A composable, plugin-based library for building full-stack applications.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -107,6 +107,93 @@ describe("jsonSchemaToFieldsAndSteps", () => {
107
107
  });
108
108
  });
109
109
 
110
+ describe("label resolution", () => {
111
+ // Label resolution must mirror what `AutoForm` shows on the public form,
112
+ // so a Zod-seeded schema (whose properties only carry `description`,
113
+ // not `label`/`title`) reads identically in the admin canvas.
114
+ // See `auto-form/fields/object.tsx` → `beautifyObjectName(name)`.
115
+
116
+ it("uses an explicit `label` when present", () => {
117
+ const schema: JSONSchema = {
118
+ type: "object",
119
+ properties: {
120
+ primaryGoal: {
121
+ type: "string",
122
+ label: "What's your main focus?",
123
+ },
124
+ },
125
+ };
126
+
127
+ const { fields } = jsonSchemaToFieldsAndSteps(schema, defaultComponents);
128
+ expect(fields[0]?.props.label).toBe("What's your main focus?");
129
+ });
130
+
131
+ it("falls back to JSON Schema `title` when `label` is absent", () => {
132
+ const schema: JSONSchema = {
133
+ type: "object",
134
+ properties: {
135
+ primaryGoal: {
136
+ type: "string",
137
+ title: "Primary Goal (titled)",
138
+ },
139
+ },
140
+ };
141
+
142
+ const { fields } = jsonSchemaToFieldsAndSteps(schema, defaultComponents);
143
+ expect(fields[0]?.props.label).toBe("Primary Goal (titled)");
144
+ });
145
+
146
+ it("humanises the field key when no `label` or `title` is present", () => {
147
+ // This is the regression: previously the admin showed the raw key
148
+ // (`primaryGoal`) when no label/title was set, while the public form
149
+ // showed `Primary Goal`. Now both paths agree.
150
+ const schema: JSONSchema = {
151
+ type: "object",
152
+ properties: {
153
+ primaryGoal: { type: "string" },
154
+ riskTolerance: {
155
+ type: "string",
156
+ enum: ["low", "moderate", "high"],
157
+ },
158
+ noInjections: { type: "boolean", fieldType: "switch" },
159
+ email: { type: "string", format: "email" },
160
+ age: { type: "number" },
161
+ notes: { type: "string", fieldType: "textarea" },
162
+ },
163
+ };
164
+
165
+ const { fields } = jsonSchemaToFieldsAndSteps(schema, defaultComponents);
166
+ const labels = Object.fromEntries(
167
+ fields.map((f) => [f.id, f.props.label]),
168
+ );
169
+
170
+ expect(labels).toEqual({
171
+ primaryGoal: "Primary Goal",
172
+ riskTolerance: "Risk Tolerance",
173
+ noInjections: "No Injections",
174
+ email: "Email",
175
+ age: "Age",
176
+ notes: "Notes",
177
+ });
178
+ });
179
+
180
+ it("humanises the field key in the unknown-field-type fallback", () => {
181
+ // When no component matches, propertiesToFields creates a generic
182
+ // text field. That branch must humanise the key too.
183
+ const schema: JSONSchema = {
184
+ type: "object",
185
+ properties: {
186
+ mysteriousField: {
187
+ // no `type` — falls through to the generic text fallback
188
+ } as JSONSchema["properties"][string],
189
+ },
190
+ };
191
+
192
+ const { fields } = jsonSchemaToFieldsAndSteps(schema, defaultComponents);
193
+ expect(fields[0]?.props.label).toBe("Mysterious Field");
194
+ });
195
+ });
196
+
110
197
  describe("multi-step: Path A — per-property stepGroup", () => {
111
198
  // Canonical format written by the visual FormBuilder when saving.
112
199
  const schema: JSONSchema = {
@@ -7,9 +7,9 @@ import { QueryClient } from '@tanstack/react-query';
7
7
 
8
8
  declare const createBoardSchema: z.ZodObject<{
9
9
  description: z.ZodOptional<z.ZodString>;
10
+ name: z.ZodString;
10
11
  createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
11
12
  updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
12
- name: z.ZodString;
13
13
  slug: z.ZodOptional<z.ZodString>;
14
14
  ownerId: z.ZodOptional<z.ZodString>;
15
15
  organizationId: z.ZodOptional<z.ZodString>;
@@ -28,8 +28,8 @@ declare const createColumnSchema: z.ZodObject<{
28
28
  title: z.ZodString;
29
29
  createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
30
30
  updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
31
- boardId: z.ZodString;
32
31
  order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
32
+ boardId: z.ZodString;
33
33
  }, z.core.$strip>;
34
34
  declare const updateColumnSchema: z.ZodObject<{
35
35
  createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
@@ -360,17 +360,17 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
360
360
  method: "PUT";
361
361
  body: better_call.StandardSchemaV1<{
362
362
  description?: string | undefined;
363
+ name?: string | undefined;
363
364
  createdAt?: unknown;
364
365
  updatedAt?: unknown;
365
- name?: string | undefined;
366
366
  slug?: string | undefined;
367
367
  ownerId?: string | undefined;
368
368
  organizationId?: string | undefined;
369
369
  }, {
370
370
  description?: string | undefined;
371
+ name?: string | undefined;
371
372
  createdAt?: unknown;
372
373
  updatedAt?: unknown;
373
- name?: string | undefined;
374
374
  slug?: string | undefined;
375
375
  ownerId?: string | undefined;
376
376
  organizationId?: string | undefined;
@@ -404,14 +404,14 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
404
404
  title?: string | undefined;
405
405
  createdAt?: unknown;
406
406
  updatedAt?: unknown;
407
- boardId?: string | undefined;
408
407
  order?: number | undefined;
408
+ boardId?: string | undefined;
409
409
  }, {
410
410
  title?: string | undefined;
411
411
  createdAt?: unknown;
412
412
  updatedAt?: unknown;
413
- boardId?: string | undefined;
414
413
  order?: number | undefined;
414
+ boardId?: string | undefined;
415
415
  }>;
416
416
  }, Column>;
417
417
  readonly deleteColumn: better_call.StrictEndpoint<"/columns/:id", {} & {
@@ -7,9 +7,9 @@ import { QueryClient } from '@tanstack/react-query';
7
7
 
8
8
  declare const createBoardSchema: z.ZodObject<{
9
9
  description: z.ZodOptional<z.ZodString>;
10
+ name: z.ZodString;
10
11
  createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
11
12
  updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
12
- name: z.ZodString;
13
13
  slug: z.ZodOptional<z.ZodString>;
14
14
  ownerId: z.ZodOptional<z.ZodString>;
15
15
  organizationId: z.ZodOptional<z.ZodString>;
@@ -28,8 +28,8 @@ declare const createColumnSchema: z.ZodObject<{
28
28
  title: z.ZodString;
29
29
  createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
30
30
  updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
31
- boardId: z.ZodString;
32
31
  order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
32
+ boardId: z.ZodString;
33
33
  }, z.core.$strip>;
34
34
  declare const updateColumnSchema: z.ZodObject<{
35
35
  createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
@@ -360,17 +360,17 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
360
360
  method: "PUT";
361
361
  body: better_call.StandardSchemaV1<{
362
362
  description?: string | undefined;
363
+ name?: string | undefined;
363
364
  createdAt?: unknown;
364
365
  updatedAt?: unknown;
365
- name?: string | undefined;
366
366
  slug?: string | undefined;
367
367
  ownerId?: string | undefined;
368
368
  organizationId?: string | undefined;
369
369
  }, {
370
370
  description?: string | undefined;
371
+ name?: string | undefined;
371
372
  createdAt?: unknown;
372
373
  updatedAt?: unknown;
373
- name?: string | undefined;
374
374
  slug?: string | undefined;
375
375
  ownerId?: string | undefined;
376
376
  organizationId?: string | undefined;
@@ -404,14 +404,14 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
404
404
  title?: string | undefined;
405
405
  createdAt?: unknown;
406
406
  updatedAt?: unknown;
407
- boardId?: string | undefined;
408
407
  order?: number | undefined;
408
+ boardId?: string | undefined;
409
409
  }, {
410
410
  title?: string | undefined;
411
411
  createdAt?: unknown;
412
412
  updatedAt?: unknown;
413
- boardId?: string | undefined;
414
413
  order?: number | undefined;
414
+ boardId?: string | undefined;
415
415
  }>;
416
416
  }, Column>;
417
417
  readonly deleteColumn: better_call.StrictEndpoint<"/columns/:id", {} & {
@@ -7,9 +7,9 @@ import { QueryClient } from '@tanstack/react-query';
7
7
 
8
8
  declare const createBoardSchema: z.ZodObject<{
9
9
  description: z.ZodOptional<z.ZodString>;
10
+ name: z.ZodString;
10
11
  createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
11
12
  updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
12
- name: z.ZodString;
13
13
  slug: z.ZodOptional<z.ZodString>;
14
14
  ownerId: z.ZodOptional<z.ZodString>;
15
15
  organizationId: z.ZodOptional<z.ZodString>;
@@ -28,8 +28,8 @@ declare const createColumnSchema: z.ZodObject<{
28
28
  title: z.ZodString;
29
29
  createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
30
30
  updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
31
- boardId: z.ZodString;
32
31
  order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
32
+ boardId: z.ZodString;
33
33
  }, z.core.$strip>;
34
34
  declare const updateColumnSchema: z.ZodObject<{
35
35
  createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
@@ -360,17 +360,17 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
360
360
  method: "PUT";
361
361
  body: better_call.StandardSchemaV1<{
362
362
  description?: string | undefined;
363
+ name?: string | undefined;
363
364
  createdAt?: unknown;
364
365
  updatedAt?: unknown;
365
- name?: string | undefined;
366
366
  slug?: string | undefined;
367
367
  ownerId?: string | undefined;
368
368
  organizationId?: string | undefined;
369
369
  }, {
370
370
  description?: string | undefined;
371
+ name?: string | undefined;
371
372
  createdAt?: unknown;
372
373
  updatedAt?: unknown;
373
- name?: string | undefined;
374
374
  slug?: string | undefined;
375
375
  ownerId?: string | undefined;
376
376
  organizationId?: string | undefined;
@@ -404,14 +404,14 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
404
404
  title?: string | undefined;
405
405
  createdAt?: unknown;
406
406
  updatedAt?: unknown;
407
- boardId?: string | undefined;
408
407
  order?: number | undefined;
408
+ boardId?: string | undefined;
409
409
  }, {
410
410
  title?: string | undefined;
411
411
  createdAt?: unknown;
412
412
  updatedAt?: unknown;
413
- boardId?: string | undefined;
414
413
  order?: number | undefined;
414
+ boardId?: string | undefined;
415
415
  }>;
416
416
  }, Column>;
417
417
  readonly deleteColumn: better_call.StrictEndpoint<"/columns/:id", {} & {