DevelopmentResource Framework
Resource Routes
Resource routes
Describe how a table or view appears in the list and drilldown, and which behaviors are enabled. Routes are defined in packages/resource-framework/registries/resource-routes.ts. When a static entry is missing, the components can load a row from the resource_routes database table.
What a route controls
- table and id columns, optional schema
- search configuration (
enableSearch,searchBy) - columns to display (and their labels, widths, links)
- edit policy (allowed/denied columns, scope)
- drilldown behavior (prefix, custom href, permanent edit mode)
- creation behavior (scopes, optional dialog / onClick)
- per‑resource caching (
force_no_cache), sidebar scoping, page labels
Minimal example
export const RESOURCE_ROUTES = {
invoices: {
table: "invoices",
idColumn: "invoice_id",
enableSearch: true,
searchBy: "invoice_nr,recipient_company,status",
},
} as const;
```typescript
### Columns
- Use `defineColumns` for convenience or provide a raw `columns` array with `column_name` and optional display metadata.
- Optionally add `href` with `{{column}}` placeholders to link to related entities.
### Edit policy
- Enable edits with `edit.enabled: true`
- Use `allowedColumns` / `deniedColumns` to restrict which fields can be updated
- Gate edits behind a `scope` string if needed
### Caching
- Set `force_no_cache: true` to always send `Cache-Control: no-cache`
- Set `force_no_cache: false` to always allow cache
- Omit to fall back to the scope‑based default (see caching.md)
### Company ownership
- Receipts, invoices, and quotes use `author_company_id` as their company ownership key.
- Credit notes use `company_id` as their company ownership key.
You can explicitly control this per resource with `companyIdColumn` in the route definition. This determines which column is used for scoping, filtering, and mutation checks:
```typescript
export const RESOURCE_ROUTES = {
invoices: {
table: "invoices",
idColumn: "invoice_id",
companyIdColumn: "author_company_id",
},
quotes: {
table: "quotes",
idColumn: "quote_id",
companyIdColumn: "author_company_id",
},
credit_notes: {
table: "credit_notes",
idColumn: "credit_note_id",
companyIdColumn: "company_id",
},
receipts: {
table: "receipts",
idColumn: "receipt_id",
companyIdColumn: "author_company_id",
},
} as const;
```typescript
### Static vs database‑driven
- If a static entry is present, it is used as‑is
- If missing, the components try to load `resource_routes` for the current `resource_name` or `table` and map fields into `ResourceRoute`
### Categories (tabbed edit)
- Add `categories?: string[]` to declare the tabs order
- Add `category?: string` per column to group fields into those tabs on the drilldown edit page