Skip to content

Commit 7e19462

Browse files
wagnertclaude
andcommitted
Merge branch 'develop' into staging
Release v2.0.0: AppSheet Field Type Support and Validation Enhancement (SOSO-247) Breaking Changes: - Replaced generic types with 27 AppSheet-specific field types - Removed shorthand field format - Renamed 'enum' property to 'allowedValues' - Comprehensive validation for all field types Includes: - Type System Extension (27 AppSheet types) - Modular Validation Architecture (3 validator classes) - Enhanced SchemaInspector with smart enum detection - Complete documentation (MIGRATION.md) - 126 tests, 81.88% coverage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2 parents fddf7d9 + 09c300e commit 7e19462

File tree

17 files changed

+5650
-149
lines changed

17 files changed

+5650
-149
lines changed

CLAUDE.md

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,18 @@ npx appsheet inspect --help # After npm install (uses bin entry)
9797
- Ensures type safety and allows swapping implementations in tests
9898

9999
**DynamicTable** (`src/client/DynamicTable.ts`)
100-
- Schema-aware table client with runtime validation
101-
- Validates field types, required fields, and enum values based on TableDefinition
100+
- Schema-aware table client with comprehensive AppSheet field type validation
101+
- Validates all 27 AppSheet field types (Email, URL, Phone, Enum, EnumList, etc.)
102+
- Format validation (email addresses, URLs, phone numbers, dates, percentages)
103+
- Required field validation and enum value constraints
102104
- Created by SchemaManager, not instantiated directly
103105

106+
**Validators** (`src/utils/validators/`)
107+
- **BaseTypeValidator**: JavaScript primitive type validation (string, number, boolean, array)
108+
- **FormatValidator**: Format-specific validation (Email, URL, Phone, Date, DateTime, Percent)
109+
- **AppSheetTypeValidator**: Main orchestrator for AppSheet field type validation
110+
- Modular, reusable validation logic across the codebase
111+
104112
**SchemaLoader** (`src/utils/SchemaLoader.ts`)
105113
- Loads schema from YAML/JSON files
106114
- Resolves environment variables with `${VAR_NAME}` syntax
@@ -122,8 +130,11 @@ npx appsheet inspect --help # After npm install (uses bin entry)
122130
### CLI Tool
123131

124132
**SchemaInspector** (`src/cli/SchemaInspector.ts`)
125-
- Introspects AppSheet tables by fetching sample data
126-
- Infers field types from actual data
133+
- Introspects AppSheet tables by analyzing up to 100 rows
134+
- Automatically detects all 27 AppSheet field types from actual data
135+
- Smart Enum detection: Identifies enum fields based on unique value ratio
136+
- Extracts `allowedValues` for Enum/EnumList fields automatically
137+
- Pattern detection for Email, URL, Phone, Date, DateTime, Percent
127138
- Guesses key fields (looks for: id, key, ID, Key, _RowNumber)
128139
- Converts table names to schema names (e.g., "extract_user" → "users")
129140

@@ -139,21 +150,35 @@ CLI binary name: `appsheet` (defined in package.json bin field)
139150

140151
## Key Design Patterns
141152

142-
### Schema Structure
153+
### Schema Structure (v2.0.0)
143154
```yaml
144155
connections:
145156
<connection-name>:
146157
appId: ${ENV_VAR}
147158
applicationAccessKey: ${ENV_VAR}
148-
runAsUserEmail: user@example.com # Optional: global user for all operations in this connection
159+
runAsUserEmail: user@example.com # Optional: global user for all operations
149160
tables:
150161
<schema-table-name>:
151162
tableName: <actual-appsheet-table-name>
152163
keyField: <primary-key-field>
153164
fields:
154-
<field-name>: <type> # or full FieldDefinition object
165+
<field-name>:
166+
type: <AppSheetFieldType> # Required: Text, Email, Number, Enum, etc.
167+
required: <boolean> # Optional: default false
168+
allowedValues: [...] # Optional: for Enum/EnumList
169+
description: <string> # Optional
155170
```
156171
172+
**AppSheet Field Types (27 total):**
173+
- **Core**: Text, Number, Date, DateTime, Time, Duration, YesNo
174+
- **Specialized Text**: Name, Email, URL, Phone, Address
175+
- **Specialized Numbers**: Decimal, Percent, Price
176+
- **Selection**: Enum, EnumList
177+
- **Media**: Image, File, Drawing, Signature
178+
- **Tracking**: ChangeCounter, ChangeTimestamp, ChangeLocation
179+
- **References**: Ref, RefList
180+
- **Special**: Color, Show
181+
157182
### Two Usage Patterns
158183
159184
**Pattern 1: Direct Client**
@@ -174,11 +199,48 @@ const table = db.table<Type>('connection', 'tableName');
174199
await table.findAll();
175200
```
176201

202+
### Validation Examples
203+
204+
**Schema Definition with AppSheet Types:**
205+
```yaml
206+
fields:
207+
email:
208+
type: Email
209+
required: true
210+
status:
211+
type: Enum
212+
required: true
213+
allowedValues: ["Active", "Inactive", "Pending"]
214+
tags:
215+
type: EnumList
216+
allowedValues: ["JavaScript", "TypeScript", "React"]
217+
discount:
218+
type: Percent
219+
required: false
220+
website:
221+
type: URL
222+
```
223+
224+
**Validation Errors:**
225+
```typescript
226+
// Invalid email format
227+
await table.add([{ email: 'invalid' }]);
228+
// ❌ ValidationError: Field "email" must be a valid email address
229+
230+
// Invalid enum value
231+
await table.add([{ status: 'Unknown' }]);
232+
// ❌ ValidationError: Field "status" must be one of: Active, Inactive, Pending
233+
234+
// Invalid percentage
235+
await table.add([{ discount: 1.5 }]);
236+
// ❌ ValidationError: Field "discount" must be between 0.00 and 1.00
237+
```
238+
177239
### Error Handling
178240
179241
All errors extend `AppSheetError` with specific subtypes:
180242
- `AuthenticationError` (401/403)
181-
- `ValidationError` (400)
243+
- `ValidationError` (400) - Now includes field-level validation errors
182244
- `NotFoundError` (404)
183245
- `RateLimitError` (429)
184246
- `NetworkError` (no response)
@@ -216,6 +278,44 @@ Retry logic applies to network errors and 5xx server errors (max 3 attempts by d
216278

217279
**Note**: The AppSheet API may return responses in either format. The AppSheetClient automatically normalizes both formats to the standard `{ Rows: [...], Warnings?: [...] }` structure for consistent handling.
218280

281+
## Breaking Changes (v2.0.0)
282+
283+
**⚠️ IMPORTANT**: Version 2.0.0 introduces breaking changes. See MIGRATION.md for upgrade guide.
284+
285+
### Removed Features
286+
- ❌ Old generic types (`'string'`, `'number'`, `'boolean'`, `'date'`, `'array'`, `'object'`) are no longer supported
287+
- ❌ Shorthand string format for field definitions (`"email": "string"`) is no longer supported
288+
- ❌ `enum` property renamed to `allowedValues`
289+
290+
### New Requirements
291+
- ✅ All fields must use full FieldDefinition object with `type` property
292+
- ✅ Only AppSheet-specific types are supported (Text, Email, Number, etc.)
293+
- ✅ Schema validation is stricter and more comprehensive
294+
295+
### Migration Example
296+
```yaml
297+
# ❌ Old schema (v1.x) - NO LONGER WORKS
298+
fields:
299+
email: string
300+
age: number
301+
status:
302+
type: string
303+
enum: ["Active", "Inactive"]
304+
305+
# ✅ New schema (v2.0.0)
306+
fields:
307+
email:
308+
type: Email
309+
required: true
310+
age:
311+
type: Number
312+
required: false
313+
status:
314+
type: Enum
315+
required: true
316+
allowedValues: ["Active", "Inactive"]
317+
```
318+
219319
## Documentation
220320

221321
All public APIs use TSDoc comments with:

0 commit comments

Comments
 (0)