Skip to content

Commit 07b8bce

Browse files
Copilothotlong
andcommitted
fix: Align field naming with @objectstack/spec protocol (autonumber, minLength, maxLength)
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 8c60f19 commit 07b8bce

6 files changed

Lines changed: 65 additions & 9 deletions

File tree

packages/foundation/core/src/util.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export function convertIntrospectedSchemaToObjects(
111111
if (foreignKey) {
112112
// This is a lookup field
113113
fieldConfig = {
114+
name: column.name,
114115
type: 'lookup',
115116
reference_to: foreignKey.referencedTable,
116117
label: toTitleCase(column.name),
@@ -121,6 +122,7 @@ export function convertIntrospectedSchemaToObjects(
121122
const fieldType = mapDatabaseTypeToFieldType(column.type);
122123

123124
fieldConfig = {
125+
name: column.name,
124126
type: fieldType,
125127
label: toTitleCase(column.name),
126128
required: !column.nullable
@@ -133,7 +135,7 @@ export function convertIntrospectedSchemaToObjects(
133135

134136
// Add max length for text fields
135137
if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {
136-
fieldConfig.max_length = column.maxLength;
138+
fieldConfig.maxLength = column.maxLength;
137139
}
138140

139141
// Add default value

packages/foundation/types/src/field.ts

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,43 @@ export interface FieldOption {
113113
* Extends the Protocol Field definition with runtime-specific properties.
114114
* The Protocol Constitution (SpecField) defines the core field schema.
115115
* This adds runtime conveniences and extensions.
116+
*
117+
* We make certain spec fields optional since Zod applies defaults at parse time.
116118
*/
117-
export interface FieldConfig extends Omit<Field, 'type' | 'options'> {
119+
export interface FieldConfig extends Omit<Field, 'type' | 'options' | 'required' | 'multiple' | 'unique' | 'deleteBehavior' | 'hidden' | 'readonly' | 'encryption' | 'index' | 'externalId'> {
118120
/** The data type of the field (extended with runtime types) */
119121
type: FieldType;
120122

121123
/** Options for select fields (extended to allow number values) */
122124
options?: FieldOption[];
123125

126+
/** Whether the field is mandatory. Defaults to false. */
127+
required?: boolean;
128+
129+
/** Whether the field allows multiple values. */
130+
multiple?: boolean;
131+
132+
/** Whether the field is unique in the table. */
133+
unique?: boolean;
134+
135+
/** Delete behavior for relationships */
136+
deleteBehavior?: 'set_null' | 'cascade' | 'restrict';
137+
138+
/** Whether the field is hidden from default UI/API response. */
139+
hidden?: boolean;
140+
141+
/** Whether the field is read-only in UI. */
142+
readonly?: boolean;
143+
144+
/** Whether the field is encrypted */
145+
encryption?: boolean;
146+
147+
/** Whether to create a database index for this field. */
148+
index?: boolean;
149+
150+
/** Whether this is an external ID field */
151+
externalId?: boolean;
152+
124153
/**
125154
* RUNTIME EXTENSIONS BELOW
126155
* These properties are NOT in the wire protocol but are useful for the runtime.
@@ -174,10 +203,35 @@ export interface FieldConfig extends Omit<Field, 'type' | 'options'> {
174203

175204
/**
176205
* Regular expression pattern for validation.
177-
* @deprecated Use SpecField validation pattern instead
206+
* @deprecated Use validation.pattern instead
178207
*/
179208
regex?: string;
180209

210+
/**
211+
* Field validation configuration.
212+
* Defines validation rules applied at the field level.
213+
*/
214+
validation?: {
215+
/** Format validation (email, url, etc.) */
216+
format?: 'email' | 'url' | 'phone' | 'date' | 'datetime';
217+
/** Allowed protocols for URL validation */
218+
protocols?: string[];
219+
/** Minimum value for numbers */
220+
min?: number;
221+
/** Maximum value for numbers */
222+
max?: number;
223+
/** Minimum length for strings */
224+
min_length?: number;
225+
/** Maximum length for strings */
226+
max_length?: number;
227+
/** Regular expression pattern for validation */
228+
pattern?: string;
229+
/** Regex pattern (alias for pattern) */
230+
regex?: string;
231+
/** Custom validation message */
232+
message?: string;
233+
};
234+
181235
/**
182236
* AI context for the field.
183237
* Provides semantic information for AI tools.

packages/runtime/server/src/adapters/graphql.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function mapFieldTypeToGraphQL(field: FieldConfig, isInput: boolean = false): Gr
7676
case 'currency':
7777
case 'percent':
7878
return GraphQLFloat;
79-
case 'auto_number':
79+
case 'autonumber':
8080
return GraphQLInt;
8181
case 'boolean':
8282
return GraphQLBoolean;

packages/runtime/server/src/metadata.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ export function createMetadataHandler(app: IObjectQL, options?: MetadataHandlerO
197197
options: field.options,
198198
min: field.min,
199199
max: field.max,
200-
min_length: field.min_length,
201-
max_length: field.max_length,
200+
minLength: field.minLength,
201+
maxLength: field.maxLength,
202202
regex: field.regex
203203
});
204204
}

packages/tools/cli/src/commands/generate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ function mapFieldTypeToTs(field: FieldConfig): string {
107107
case 'number':
108108
case 'currency':
109109
case 'percent':
110-
case 'auto_number':
110+
case 'autonumber':
111111
return 'number';
112112

113113
case 'boolean':

packages/tools/cli/src/commands/sync.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ function generateObjectDefinition(table: IntrospectedTable, schema: Introspected
189189
field.unique = true;
190190
}
191191

192-
// Add max_length for text-based fields
192+
// Add maxLength for text-based fields
193193
if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {
194-
field.max_length = column.maxLength;
194+
field.maxLength = column.maxLength;
195195
}
196196

197197
if (column.defaultValue !== undefined && column.defaultValue !== null) {

0 commit comments

Comments
 (0)