@betterstart/cli 0.1.71 → 0.1.73

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/dist/cli.js CHANGED
@@ -84,7 +84,7 @@ function walkFields(fields, callback, options = DEFAULT_WALK_OPTIONS) {
84
84
  function walk(fieldsToWalk, depth, parent) {
85
85
  for (const field of fieldsToWalk) {
86
86
  callback(field, depth, parent);
87
- if (options.includeGroups && field.type === "group" && field.fields) {
87
+ if (options.includeGroups && (field.type === "group" || field.type === "section") && field.fields) {
88
88
  walk(field.fields, depth + 1, field);
89
89
  }
90
90
  if (options.includeLists && field.type === "list" && field.fields) {
@@ -140,7 +140,7 @@ function flattenFields(fields) {
140
140
  function flattenFieldsWithoutIdCheck(fields) {
141
141
  const flattened = [];
142
142
  for (const field of fields) {
143
- if (field.type === "group" && field.fields) {
143
+ if ((field.type === "group" || field.type === "section") && field.fields) {
144
144
  flattened.push(...flattenFieldsWithoutIdCheck(field.fields));
145
145
  } else if (field.type === "tabs" && field.tabs) {
146
146
  for (const tab of field.tabs) {
@@ -3353,12 +3353,12 @@ var FIELD_TYPES = {
3353
3353
  TABS: "tabs",
3354
3354
  LIST: "list",
3355
3355
  SEPARATOR: "separator",
3356
- BREAK: "break",
3356
+ SECTION: "section",
3357
3357
  SELECT: "select",
3358
3358
  RELATIONSHIP: "relationship",
3359
3359
  CURRICULUM: "curriculum"
3360
3360
  };
3361
- var LAYOUT_FIELD_TYPES = [FIELD_TYPES.SEPARATOR, FIELD_TYPES.BREAK];
3361
+ var LAYOUT_FIELD_TYPES = [FIELD_TYPES.SEPARATOR];
3362
3362
  var NESTED_FIELD_TYPES = [FIELD_TYPES.GROUP, FIELD_TYPES.TABS, FIELD_TYPES.LIST];
3363
3363
  var RICH_TEXT_FIELD_TYPES = [FIELD_TYPES.MARKDOWN, FIELD_TYPES.TEXT];
3364
3364
  var LONG_TEXT_FIELD_TYPES = [
@@ -6139,7 +6139,7 @@ function generateFieldJSXCore(field, indent = " ") {
6139
6139
  const fieldType = getFormFieldType(field);
6140
6140
  const label = field.label || field.name;
6141
6141
  const hintJSX = field.hint ? `${indent} <FormDescription>${field.hint}</FormDescription>` : "";
6142
- if (field.type === "group" && field.fields) return renderGroupField(field, indent, label);
6142
+ if ((field.type === "group" || field.type === "section") && field.fields) return renderGroupField(field, indent, label);
6143
6143
  if (field.type === "separator") return renderSeparatorField(field, indent);
6144
6144
  if (field.type === "boolean") return renderBooleanField(field, indent, label, hintJSX);
6145
6145
  if (field.type === "image") return renderImageField(field, indent, label, hintJSX);
@@ -6969,42 +6969,50 @@ ${hasDraft ? ` <Button
6969
6969
  // src/generators/form/form-single.ts
6970
6970
  import fs21 from "fs";
6971
6971
  import path21 from "path";
6972
- function parseCardGroups(allFormFields) {
6972
+ function parseCardGroups(allFormFields, schemaLabel) {
6973
+ const sections = allFormFields.filter((f) => f.type === "section" && f.fields);
6974
+ const nonSections = allFormFields.filter((f) => f.type !== "section" && !isLayoutField(f.type));
6975
+ if (sections.length === 0) {
6976
+ const title = nonSections[0]?.label || nonSections[0]?.name || schemaLabel;
6977
+ return [
6978
+ {
6979
+ title,
6980
+ description: "",
6981
+ hint: "",
6982
+ varPrefix: toCamelCase(nonSections[0]?.name || "form"),
6983
+ componentName: `${toPascalCase(nonSections[0]?.name || "form")}Card`,
6984
+ fields: nonSections,
6985
+ flatFields: flattenFields(nonSections).filter((f) => !isLayoutField(f.type))
6986
+ }
6987
+ ];
6988
+ }
6973
6989
  const groups = [];
6974
- let currentFields = [];
6975
- let nextTitle = "";
6976
- let nextDescription = "";
6977
- for (const field of allFormFields) {
6978
- if (field.type === "break") {
6979
- if (currentFields.length > 0) {
6980
- groups.push(buildGroup(currentFields, nextTitle, nextDescription));
6981
- }
6982
- nextTitle = field.label || "";
6983
- nextDescription = field.hint || "";
6984
- currentFields = [];
6985
- continue;
6986
- }
6987
- if (field.type === "separator") continue;
6988
- currentFields.push(field);
6990
+ for (const section of sections) {
6991
+ const innerFields = section.fields || [];
6992
+ groups.push({
6993
+ title: section.label || section.name,
6994
+ description: section.description || "",
6995
+ hint: section.hint || "",
6996
+ varPrefix: toCamelCase(section.name),
6997
+ componentName: `${toPascalCase(section.name)}Card`,
6998
+ fields: innerFields,
6999
+ flatFields: flattenFields(innerFields).filter((f) => !isLayoutField(f.type))
7000
+ });
6989
7001
  }
6990
- if (currentFields.length > 0) {
6991
- groups.push(buildGroup(currentFields, nextTitle, nextDescription));
7002
+ if (nonSections.length > 0) {
7003
+ const title = nonSections[0]?.label || nonSections[0]?.name || "General";
7004
+ groups.unshift({
7005
+ title,
7006
+ description: "",
7007
+ hint: "",
7008
+ varPrefix: toCamelCase(nonSections[0]?.name || "general"),
7009
+ componentName: `${toPascalCase(nonSections[0]?.name || "General")}Card`,
7010
+ fields: nonSections,
7011
+ flatFields: flattenFields(nonSections).filter((f) => !isLayoutField(f.type))
7012
+ });
6992
7013
  }
6993
7014
  return groups;
6994
7015
  }
6995
- function buildGroup(fields, titleOverride, description) {
6996
- const firstField = fields[0];
6997
- const title = titleOverride || firstField.label || firstField.name;
6998
- const varPrefix = toCamelCase(firstField.name);
6999
- return {
7000
- title,
7001
- description,
7002
- varPrefix,
7003
- componentName: `${toPascalCase(firstField.name)}Card`,
7004
- fields,
7005
- flatFields: flattenFields(fields).filter((f) => !isLayoutField(f.type))
7006
- };
7007
- }
7008
7016
  function analyzeGroup(fields) {
7009
7017
  const tabFieldNames = /* @__PURE__ */ new Set();
7010
7018
  for (const f of fields) {
@@ -7033,7 +7041,7 @@ function analyzeGroup(fields) {
7033
7041
  const hasTabsField = fields.some((f) => f.type === "tabs");
7034
7042
  const tabsField = fields.find((f) => f.type === "tabs");
7035
7043
  const firstTabName = tabsField?.tabs?.[0]?.name || "";
7036
- return { relFields, listFieldsWithNested, hasTabsField, tabsField, firstTabName, tabFieldNames };
7044
+ return { relFields, listFieldsWithNested, hasTabsField, firstTabName, tabFieldNames };
7037
7045
  }
7038
7046
  function buildGroupFieldsJSX(group3, analysis, skipLabel) {
7039
7047
  const indent = " ";
@@ -7083,7 +7091,6 @@ function generateCardComponent(group3, schema, analysis) {
7083
7091
  const fieldsJSX = buildGroupFieldsJSX(group3, analysis, isSingleField);
7084
7092
  const relState = buildGroupRelState(analysis);
7085
7093
  const fieldArrayHooks = buildGroupFieldArrayHooks(analysis);
7086
- const needsReact = analysis.relFields.length > 0 || analysis.listFieldsWithNested.length > 0;
7087
7094
  const descriptionLine = group3.description ? `
7088
7095
  <CardDescription>${group3.description}</CardDescription>` : "";
7089
7096
  return `const ${group3.varPrefix}Schema = z.object({
@@ -7125,15 +7132,16 @@ ${fieldArrayHooks}
7125
7132
  )
7126
7133
  mutation.mutate(cleaned as Upsert${Singular}Input)
7127
7134
  })}>
7128
- <Card>
7135
+ <Card className="material-sm!">
7129
7136
  <CardHeader>
7130
7137
  <CardTitle>${group3.title}</CardTitle>${descriptionLine}
7131
7138
  </CardHeader>
7132
7139
  <CardContent className="space-y-6">
7133
7140
  ${fieldsJSX}
7134
7141
  </CardContent>
7135
- <CardFooter>
7136
- <Button type="submit" disabled={isPending} size="sm">
7142
+ <CardFooter>${group3.hint ? `
7143
+ <p className="text-sm text-muted-foreground">${group3.hint}</p>` : ""}
7144
+ <Button type="submit" disabled={isPending} size="sm" className="ml-auto">
7137
7145
  {isPending ? 'Saving...' : 'Save'}
7138
7146
  </Button>
7139
7147
  </CardFooter>
@@ -7154,7 +7162,7 @@ function generateSingleForm(schema, cwd, pagesDir, options = {}) {
7154
7162
  const allFormFields = schema.fields.filter(
7155
7163
  (f) => !f.primaryKey && f.name !== "createdAt" && f.name !== "updatedAt"
7156
7164
  );
7157
- const cardGroups = parseCardGroups(allFormFields);
7165
+ const cardGroups = parseCardGroups(allFormFields, schema.label);
7158
7166
  const hasBoolean = hasFieldType(schema.fields, "boolean");
7159
7167
  const hasImage = hasFieldType(schema.fields, "image");
7160
7168
  const hasVideo = hasFieldType(schema.fields, "video");
@@ -10080,9 +10088,25 @@ function defaultSettingsSchema() {
10080
10088
  description: "General Settings",
10081
10089
  icon: "Settings",
10082
10090
  fields: [
10083
- { name: "siteName", type: "string", label: "Site Name", default: "BetterStart" },
10084
- { name: "break1", type: "break" },
10085
- { name: "logo", type: "image", label: "Logo" }
10091
+ {
10092
+ type: "section",
10093
+ name: "siteSettings",
10094
+ label: "Site Settings",
10095
+ description: "General settings for the site",
10096
+ fields: [
10097
+ { name: "appName", type: "string", label: "App Name", hint: "Displayed in the sidebar and throughout the dashboard", default: "BetterStart" },
10098
+ { name: "appDescription", type: "text", label: "App Description", hint: "A brief description of the application" }
10099
+ ]
10100
+ },
10101
+ {
10102
+ type: "section",
10103
+ name: "branding",
10104
+ label: "Branding",
10105
+ description: "Logo and visual identity",
10106
+ fields: [
10107
+ { name: "logo", type: "image", label: "Logo" }
10108
+ ]
10109
+ }
10086
10110
  ]
10087
10111
  },
10088
10112
  null,