Skip to content

Commit d1f51a1

Browse files
ouiliameclaude
andcommitted
fix(docs): recover staging's enriched Table doc + never drop manual content
The merge resolution deleted staging's relocated blocks/table.mdx, which carried substantial enrichment our integrations/table.mdx (reseeded from the older tools/ version) lacked: Creating Tables (column types/constraints), Filter Operators, Combining Filters, Sort Specification, Built-in Columns, Limits, and Notes. Recomposed integrations/table.mdx with that content — Creating Tables inside the intro manual section, the reference tail in a notes manual section. Generator fix uncovered en route: a manual section whose insertion anchor is missing in the generated markdown (e.g. notes with no "## Notes" heading) was silently dropped on regen. Unplaceable sections now append at the end instead — manual content is never lost. Verified idempotent across double regeneration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fd58363 commit d1f51a1

2 files changed

Lines changed: 127 additions & 13 deletions

File tree

apps/docs/content/docs/en/integrations/table.mdx

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,28 @@ Tables allow you to create and manage custom data tables directly within Sim. St
2727
- Batch operations for bulk inserts
2828
- Bulk updates and deletes by filter
2929
- Up to 10,000 rows per table, 100 tables per workspace
30+
31+
## Creating Tables
32+
33+
Tables are created from the **Tables** section in the sidebar. Each table requires:
34+
- **Name**: Alphanumeric with underscores (e.g., `customer_leads`)
35+
- **Description**: Optional description of the table's purpose
36+
- **Schema**: Define columns with name, type, and optional constraints
37+
38+
### Column Types
39+
40+
| Type | Description | Example Values |
41+
|------|-------------|----------------|
42+
| `string` | Text data | `"John Doe"`, `"active"` |
43+
| `number` | Numeric data | `42`, `99.99` |
44+
| `boolean` | True/false values | `true`, `false` |
45+
| `date` | Date/time values | `"2024-01-15T10:30:00Z"` |
46+
| `json` | Complex nested data | `{"address": {"city": "NYC"}}` |
47+
48+
### Column Constraints
49+
50+
- **Required**: Column must have a value (cannot be null)
51+
- **Unique**: Values must be unique across all rows (enables upsert matching)
3052
{/* MANUAL-CONTENT-END */}
3153

3254

@@ -240,4 +262,99 @@ Get the schema configuration of a table
240262
| `columns` | array | Column definitions |
241263
| `message` | string | Status message |
242264

243-
265+
{/* MANUAL-CONTENT-START:notes */}
266+
## Filter Operators
267+
268+
Filters use MongoDB-style operators for flexible querying:
269+
270+
| Operator | Description | Example |
271+
|----------|-------------|---------|
272+
| `$eq` | Equals | `{"status": {"$eq": "active"}}` or `{"status": "active"}` |
273+
| `$ne` | Not equals | `{"status": {"$ne": "deleted"}}` |
274+
| `$gt` | Greater than | `{"age": {"$gt": 18}}` |
275+
| `$gte` | Greater than or equal | `{"score": {"$gte": 80}}` |
276+
| `$lt` | Less than | `{"price": {"$lt": 100}}` |
277+
| `$lte` | Less than or equal | `{"quantity": {"$lte": 10}}` |
278+
| `$in` | In array | `{"status": {"$in": ["active", "pending"]}}` |
279+
| `$nin` | Not in array | `{"type": {"$nin": ["spam", "blocked"]}}` |
280+
| `$contains` | String contains (case-insensitive) | `{"email": {"$contains": "@gmail.com"}}` |
281+
| `$ncontains` | Does not contain (case-insensitive; matches empty cells) | `{"email": {"$ncontains": "@spam.com"}}` |
282+
| `$startsWith` | Starts with (case-insensitive) | `{"name": {"$startsWith": "Dr."}}` |
283+
| `$endsWith` | Ends with (case-insensitive) | `{"file": {"$endsWith": ".pdf"}}` |
284+
| `$empty` | Cell is empty (`true`) or non-empty (`false`) | `{"phone": {"$empty": true}}` |
285+
286+
### Combining Filters
287+
288+
Multiple field conditions are combined with AND logic:
289+
290+
```json
291+
{
292+
"status": "active",
293+
"age": {"$gte": 18}
294+
}
295+
```
296+
297+
Use `$or` for OR logic:
298+
299+
```json
300+
{
301+
"$or": [
302+
{"status": "active"},
303+
{"status": "pending"}
304+
]
305+
}
306+
```
307+
308+
## Sort Specification
309+
310+
Specify sort order with column names and direction:
311+
312+
```json
313+
{
314+
"createdAt": "desc"
315+
}
316+
```
317+
318+
Multi-column sorting:
319+
320+
```json
321+
{
322+
"priority": "desc",
323+
"name": "asc"
324+
}
325+
```
326+
327+
## Built-in Columns
328+
329+
Every row automatically includes:
330+
331+
| Column | Type | Description |
332+
|--------|------|-------------|
333+
| `id` | string | Unique row identifier |
334+
| `createdAt` | date | When the row was created |
335+
| `updatedAt` | date | When the row was last modified |
336+
337+
These can be used in filters and sorting.
338+
339+
## Limits
340+
341+
| Resource | Limit |
342+
|----------|-------|
343+
| Tables per workspace | 100 |
344+
| Rows per table | 10,000 |
345+
| Columns per table | 50 |
346+
| Max row size | 100KB |
347+
| String value length | 10,000 characters |
348+
| Query limit | 1,000 rows |
349+
| Batch insert size | 1,000 rows |
350+
| Bulk update/delete | 1,000 rows |
351+
352+
## Notes
353+
354+
- Category: `blocks`
355+
- Type: `table`
356+
- Tables are scoped to workspaces and accessible from any workflow within that workspace
357+
- Data persists across workflow executions
358+
- Use unique constraints to enable upsert functionality
359+
- The visual filter/sort builder provides an easy way to construct queries without writing JSON
360+
{/* MANUAL-CONTENT-END */}

scripts/generate-docs.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2561,20 +2561,17 @@ function mergeWithManualContent(
25612561
}
25622562

25632563
const insertionPoint = insertionPoints[sectionName]
2564+
const wrapped = `{/* MANUAL-CONTENT-START:${sectionName} */}\n${content}\n{/* MANUAL-CONTENT-END */}`
25642565

2565-
if (insertionPoint) {
2566-
const match = mergedContent.match(insertionPoint.regex)
2567-
2568-
if (match && match.index !== undefined) {
2569-
const insertPosition = match.index + match[0].length
2570-
mergedContent = `${mergedContent.slice(0, insertPosition)}\n\n{/* MANUAL-CONTENT-START:${sectionName} */}\n${content}\n{/* MANUAL-CONTENT-END */}\n${mergedContent.slice(insertPosition)}`
2571-
} else {
2572-
console.log(
2573-
`Could not find insertion point for ${sectionName}, regex pattern: ${insertionPoint.regex}`
2574-
)
2575-
}
2566+
const match = insertionPoint ? mergedContent.match(insertionPoint.regex) : null
2567+
if (match && match.index !== undefined) {
2568+
const insertPosition = match.index + match[0].length
2569+
mergedContent = `${mergedContent.slice(0, insertPosition)}\n\n${wrapped}\n${mergedContent.slice(insertPosition)}`
25762570
} else {
2577-
console.log(`No insertion point defined for section ${sectionName}`)
2571+
// Never drop manual content: when the anchor is missing (e.g. a `notes`
2572+
// section with no generated "## Notes" heading), append at the end.
2573+
console.log(`No insertion anchor for manual section "${sectionName}" — appending at end`)
2574+
mergedContent = `${mergedContent.replace(/\s*$/, '')}\n\n${wrapped}\n`
25782575
}
25792576
})
25802577

0 commit comments

Comments
 (0)