pgkiln 0.39.0 → 0.41.0

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.
Files changed (58) hide show
  1. package/SECURITY.md +1 -0
  2. package/db/migrations/095_rest_catalogs.sql +59 -0
  3. package/db/migrations/096_developer_email.sql +15 -0
  4. package/docs/apex-feature-parity.md +14 -11
  5. package/docs/guide/03-builder.md +56 -2
  6. package/docs/guide/04-pages-and-regions.md +43 -4
  7. package/docs/guide/12-development.md +23 -3
  8. package/docs/guide/19-rest-data-sources.md +39 -1
  9. package/examples/hr/hr_58_facet_charts.sql +17 -0
  10. package/examples/hr/hr_59_gantt_editing.sql +21 -0
  11. package/examples/hr/hr_60_tree_charts.sql +46 -0
  12. package/package.json +1 -1
  13. package/public/app.css +49 -0
  14. package/public/app.js +126 -0
  15. package/public/builder.css +1 -1
  16. package/public/sw.js +5 -2
  17. package/src/app.ts +6 -0
  18. package/src/blueprint-from-app.ts +240 -0
  19. package/src/builder/blueprints.ts +31 -1
  20. package/src/builder/find-workspace.ts +120 -0
  21. package/src/builder/home.ts +2 -0
  22. package/src/builder/mail.ts +39 -0
  23. package/src/builder/region-settings.ts +29 -6
  24. package/src/builder/rest-catalogs.ts +424 -0
  25. package/src/builder/routes.ts +32 -6
  26. package/src/builder/shared.ts +2 -0
  27. package/src/builder/workspace-transfer.ts +136 -0
  28. package/src/i18n/ar.ts +14 -0
  29. package/src/i18n/cs.ts +14 -0
  30. package/src/i18n/da.ts +14 -0
  31. package/src/i18n/de.ts +14 -0
  32. package/src/i18n/el.ts +14 -0
  33. package/src/i18n/es.ts +14 -0
  34. package/src/i18n/fi.ts +14 -0
  35. package/src/i18n/fr.ts +14 -0
  36. package/src/i18n/he.ts +14 -0
  37. package/src/i18n/it.ts +14 -0
  38. package/src/i18n/ja.ts +14 -0
  39. package/src/i18n/ko.ts +14 -0
  40. package/src/i18n/nb.ts +14 -0
  41. package/src/i18n/pl.ts +14 -0
  42. package/src/i18n/pt.ts +14 -0
  43. package/src/i18n/ru.ts +14 -0
  44. package/src/i18n/sv.ts +14 -0
  45. package/src/i18n/tr.ts +14 -0
  46. package/src/i18n/uk.ts +14 -0
  47. package/src/i18n/zh.ts +14 -0
  48. package/src/i18n.ts +28 -0
  49. package/src/restcatalog.ts +605 -0
  50. package/src/runtime/charts.ts +296 -12
  51. package/src/runtime/data-reporter.ts +48 -16
  52. package/src/runtime/facet-state.ts +3 -0
  53. package/src/runtime/facets.ts +25 -0
  54. package/src/runtime/gantt-move.ts +63 -0
  55. package/src/runtime/regions.ts +3 -0
  56. package/src/runtime/routes.ts +39 -0
  57. package/src/websources.ts +11 -3
  58. package/src/workspace-export.ts +240 -0
package/SECURITY.md CHANGED
@@ -72,6 +72,7 @@ first version (MVP). Every finding below has a regression test in
72
72
  | Builder screens like APEX's (sprint 61) | The sign-in page's workspace is checked after the password (only the developer's workspaces; a wrong one answers like a wrong password, failures are throttled and logged as before); *Remember workspace and username* is an HttpOnly cookie for `/builder` holding no secret, read defensively and escaped; the redirect after sign-in is a `/builder` path only. Workspace message and banner: administrators and the workspace's administrators, CSRF, plain text escaped, the banner colour from a fixed list. Utilization: the same. SQL Workshop home: your own recent commands only (by id and username), the schema checked against the schemas the session's connection may use (and set as a parameter of `set_config`). Application groups: every query bound to the current workspace; groups and applications of other workspaces are ignored. App Gallery: keys are names from `examples/gallery/gallery.json`, never paths; sample apps (shipped SQL as the owner, demo accounts with known passwords) are for administrators only; starter apps go through the blueprint review and its signed create step. Cross application reports: fixed SQL per topic, the workspace id as a parameter. |
73
73
  | Workspace preferences, extension links, Manage backups (sprint 62) | Preferences and links: administrators and the workspace's administrators, CSRF, logged. The SQL Workshop preference is checked in `developer()` for every `/builder/sql` GET and POST before a route runs, so no SQL Workshop route can skip it; it is not a sandbox (a developer of several workspaces uses it in another; isolation is the boundary). RESTful services off: the module lookup answers 404 before authentication or any handler SQL. Extension links: only `http://`/`https://` URLs without spaces, quotes or angle brackets (checked in Node and by a CHECK constraint), escaped, opened with `rel="noopener noreferrer"`. Manage backups: only the current workspace's applications, through the existing `meta.backup_app`. SQL Workshop utilities: fixed catalogue SQL chosen by a key from a fixed list (own-property lookup), run read only with a statement timeout on the SQL Workshop's connection (an isolated workspace's developer login sees only its roles' schemas); the Database Monitor shows other sessions' query texts, so it is for administrators only and cancels nothing. |
74
74
  | Approval vacation rules and expiration (sprint 64) | A vacation rule is always the signed-in user's own (`meta.app_user()` in a security-definer function; no user field is read from the form); its table is closed to the runtime roles; the delegate's rights are computed in `meta.task_rights` on every call and only for tasks the user owns by name or is assigned (never role ownership), so they end with the rule. Dates are checked as dates; CSRF and an in-app `next`. The expiry tick runs as the owner from the scheduler only (no grant). |
75
+ | Blueprint from an application (sprint 66) | Builder only, CSRF; the application must be in the developer's current workspace (administrators: any). The catalog is read as the owner but only for tables the application's database role may SELECT, never `meta`. Sample rows are opt-in (the page warns about personal data), read in a read-only transaction with a statement timeout through `devDbForApp` (an isolated workspace's developer login), at most 20 per table. The result only fills the editor: creating still goes through the signed review. |
75
76
  | Drawers, built-in template components, Theme Roller additions (0.29.0) | Dialog positions and sizes, base styles, dark-mode colours, item and report-column template options only reach the page from fixed lists (checked when saved and again when rendered: a hand-edited value is ignored); the browser gets dialog shapes as JSON values from those lists. Built-in template components pass the same template checks as plug-ins; *Copy into this application* takes a static id from the fixed list, needs CSRF and the application in the developer's workspace, and never overwrites the application's own component. |
76
77
  | Report row selection across pages (0.29.0) | `POST …/report/<id>/select` needs the CSRF token, page access and a visible report region whose `selection` names the item (and the item visible); it only changes that item's session state; values are bounded (5000, 400 characters, no `:`) and treated as user input, like a submit; output is escaped. |
77
78
  | Instance settings (0.29.0) | Administrators only, with CSRF; only whole numbers within each setting's range are stored (a bad stored value falls back to the environment variable or default); the configuration overview never shows secrets (connection strings, keys: only whether they are set); changes are logged.
@@ -0,0 +1,59 @@
1
+ -- =====================================================================
2
+ -- 095: REST source catalogs (APEX: Workspace Utilities → REST Source
3
+ -- Catalogs)
4
+ --
5
+ -- A catalog describes one web service for a workspace: its base URL and
6
+ -- its services (an endpoint each: path with {parameters}, method,
7
+ -- parameters, row selector, columns, write-back operations). Developers of
8
+ -- the workspace create a REST data source in any of its applications from a
9
+ -- catalog service, so the service is described once, not in every
10
+ -- application. A catalog is entered by hand or read from an OpenAPI 3 (or
11
+ -- Swagger 2) document.
12
+ --
13
+ -- A data source made from a catalog is a copy (meta.rest_source): changing
14
+ -- the catalog later doesn't change it. Credentials stay with the
15
+ -- application (web credentials), never in a catalog.
16
+ --
17
+ -- Workspace data: not part of an application's export; the workspace
18
+ -- export (Workspace utilities → Export) carries the catalogs.
19
+ -- =====================================================================
20
+ create table meta.rest_catalog (
21
+ id serial primary key,
22
+ workspace_id int not null references meta.workspace on delete cascade,
23
+ name text not null check (name ~ '^\S(.{0,58}\S)?$'),
24
+ description text check (length(description) <= 2000),
25
+ -- e.g. https://api.example.com/v1 (no trailing slash: service paths start with /)
26
+ base_url text not null check (base_url ~ '^https?://[^\s<>"{}]+$' and base_url !~ '/$' and length(base_url) <= 2000),
27
+ -- where it came from: by hand, or an OpenAPI document (its title and version are kept)
28
+ source text not null default 'manual' check (source in ('manual', 'openapi')),
29
+ api_version text check (length(api_version) <= 100),
30
+ created_by text,
31
+ created_at timestamptz not null default now(),
32
+ updated_at timestamptz not null default now()
33
+ );
34
+ create unique index rest_catalog_name_key on meta.rest_catalog (workspace_id, lower(name));
35
+
36
+ create table meta.rest_catalog_service (
37
+ id serial primary key,
38
+ catalog_id int not null references meta.rest_catalog on delete cascade,
39
+ -- the REST data source's name when one is made from it
40
+ name text not null check (name ~ '^[A-Z][A-Z0-9_]{0,59}$'),
41
+ description text check (length(description) <= 2000),
42
+ -- after the catalog's base URL, e.g. /cities/{city}/weather?units=metric
43
+ path text not null check (path ~ '^/[^\s<>"]*$' and length(path) <= 2000),
44
+ method text not null default 'GET' check (method in ('GET', 'POST', 'PUT', 'PATCH', 'DELETE')),
45
+ -- as meta.rest_source (030, 036)
46
+ params jsonb not null default '[]' check (jsonb_typeof(params) = 'array'),
47
+ headers jsonb not null default '{}' check (jsonb_typeof(headers) = 'object'),
48
+ body text,
49
+ row_selector text,
50
+ columns jsonb not null default '[]' check (jsonb_typeof(columns) = 'array'),
51
+ key_columns text[] not null default '{}',
52
+ operations jsonb not null default '{}' check (jsonb_typeof(operations) = 'object'),
53
+ position int not null default 0,
54
+ unique (catalog_id, name)
55
+ );
56
+
57
+ revoke all on meta.rest_catalog, meta.rest_catalog_service from public;
58
+ comment on table meta.rest_catalog is 'REST source catalogs (095): a workspace''s descriptions of web services; applications make REST data sources from their services.';
59
+ comment on table meta.rest_catalog_service is 'A service (endpoint) of a REST source catalog (095): copied into meta.rest_source by "From a catalog".';
@@ -0,0 +1,15 @@
1
+ -- =====================================================================
2
+ -- 096: developers' e-mail addresses and "Find my workspace" (APEX: the
3
+ -- workspace sign-in page → Find My Workspace)
4
+ --
5
+ -- meta.developer.email: optional; a developer sets their own on the
6
+ -- Developers page, administrators set anyone's. "Find my workspace" on the
7
+ -- builder's sign-in page mails the developer accounts with that address the
8
+ -- workspaces they belong to, through the mail service administrators choose
9
+ -- for the builder (meta.setting builder_mail_service and builder_mail_from).
10
+ -- The page answers the same whether or not an account has the address.
11
+ -- =====================================================================
12
+ alter table meta.developer
13
+ add column email text check (email is null or (email ~ '^[^@\s<>"(),;:\\]+@[^@\s<>"(),;:\\]+\.[^@\s<>"(),;:\\]+$' and length(email) <= 254));
14
+ create index developer_email_idx on meta.developer (lower(email)) where email is not null;
15
+ comment on column meta.developer.email is 'The developer''s e-mail address (096): "Find my workspace" sends their workspaces to it.';
@@ -7,28 +7,29 @@ open item and open an issue or pull request; see [CONTRIBUTING.md](../CONTRIBUTI
7
7
  Legend: ✅ available · 🟡 partial (see notes) · ❌ not yet · ➖ not planned (a deliberate choice,
8
8
  or better served by the PostgreSQL ecosystem; see the notes and [extensions](guide/15-extensions.md))
9
9
 
10
- Last reviewed: 2026-10-13 (sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
10
+ Last reviewed: 2026-10-14 (sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
11
11
 
12
12
  ## At a glance
13
13
 
14
14
  | Area | ✅ | 🟡 | ❌ | ➖ | In short |
15
15
  |---|---:|---:|---:|---:|---|
16
16
  | App Builder and development | 20 | 0 | 0 | 0 | Page Designer with drag-and-drop and a code editor, wizards, search, where used, an Advisor, a CLI with one file per component, page locks and comments, supporting objects, working copies with a three-way merge, theme/library/boilerplate apps with subscriptions; App Builder AI (pages, SQL and table descriptions) |
17
- | Regions | 23 | 0 | 0 | 0 | All everyday regions, a search region over search configurations and a URL region; sixteen chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; interactive grids with single row, group by and chart views; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
17
+ | Regions | 23 | 0 | 0 | 0 | All everyday regions, a search region over search configurations and a URL region; twenty-two chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; interactive grids with single row, group by and chart views; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
18
18
  | Items | 13 | 0 | 0 | 0 | All common items, file upload (several files per item), rich text and Markdown editors, star rating, combobox, date range, QR code, password reveal, display image and geocoded address |
19
19
  | Logic and processing | 17 | 0 | 0 | 1 | User preferences and application settings; all dynamic action events and actions, Ajax callbacks and an error handling function; Core APEX model complete with computations, conditional branches, build options and menu buttons, download, chain and workflow processes; JavaScript from static application files in dynamic actions; region, item, dynamic action and process plug-ins |
20
20
  | Security | 22 | 0 | 0 | 0 | An editable login page and Forgot password; a session timeout warning; On par or stricter (CSP without `unsafe-inline`); OIDC, SAML and LDAP; header authentication behind a proxy; database accounts; custom authentication |
21
21
  | User interface | 12 | 0 | 0 | 0 | Region templates incl. hero, inline dialog and drawer, wizard and carousel; Universal Theme-like and responsive; a Theme Roller with style variants and conditional, dynamic styles; about 1,700 icons with Font APEX-like modifiers |
22
22
  | Globalization | 6 | 0 | 0 | 0 | One translated app like 26.1 with dynamic translations of table values; number format masks and automatic time zone; twenty-two built-in languages |
23
- | Data and integration | 12 | 0 | 0 | 2 | Generate DDL and schema comparison; `meta.data_export` and data export downloads (CSV, JSON, XML, HTML, Excel, PDF); e-mail through SMTP (password or OAuth2), Microsoft Graph, Amazon SES and HTTP APIs; REST APIs via PostgREST, REST data sources that write back and synchronise, web credentials with OAuth2 grants, CSV/XLSX/JSON/XML loading with saved definitions and unloading, SQL scripts and Quick SQL, report PDFs and document templates |
23
+ | Data and integration | 13 | 0 | 0 | 2 | REST source catalogs from OpenAPI documents; Generate DDL and schema comparison; `meta.data_export` and data export downloads (CSV, JSON, XML, HTML, Excel, PDF); e-mail through SMTP (password or OAuth2), Microsoft Graph, Amazon SES and HTTP APIs; REST APIs via PostgREST, REST data sources that write back and synchronise, web credentials with OAuth2 grants, CSV/XLSX/JSON/XML loading with saved definitions and unloading, SQL scripts and Quick SQL, report PDFs and document templates |
24
24
  | Workflow, automation and AI | 6 | 0 | 0 | 0 | Scheduled automations with several actions and runs from SQL, approvals, a task list and workflows with parallel branches, versions and invoke-API steps; AI with Claude or OpenAI: *Generate text with AI*, an assistant region with tools, natural-language report filters and blueprints |
25
- | Administration | 10 | 0 | 0 | 0 | An APEX-like sign-in with a workspace; workspace message, environment banner and utilization; isolated workspaces with their own database logins and roles, and workspace administrators; application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Top SQL per app; debug messages per request; an install/upgrade log |
26
- | **Total** | **141** | **0** | **0** | **3** | 144 APEX features compared: 98% available, none partial or missing |
25
+ | Administration | 11 | 0 | 0 | 0 | An APEX-like sign-in with a workspace; a workspace's components exported and imported as one file; workspace message, environment banner and utilization; isolated workspaces with their own database logins and roles, and workspace administrators; application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Top SQL per app; debug messages per request; an install/upgrade log |
26
+ | **Total** | **143** | **0** | **0** | **3** | 146 APEX features compared: 98% available, none partial or missing |
27
27
 
28
28
  (Counts are of the rows in the tables below. A review on 2026-10-06 added 18 rows for APEX features that were
29
29
  not compared before, one on 2026-10-12 added two more (property help, application availability), and one on
30
30
  2026-10-13 compared the builder's screens with APEX 26.1 and added four (App Gallery, application groups, cross
31
- application reports, Manage Service), so the share available dropped without anything being removed.)
31
+ application reports, Manage Service), so the share available dropped without anything being removed. Sprint 67 added
32
+ two, REST source catalogs and the workspace export, with their features.)
32
33
 
33
34
  ## App Builder and development
34
35
 
@@ -64,10 +65,10 @@ application reports, Manage Service), so the share available dropped without any
64
65
  | Interactive grid | ✅ | Inline edit, add and delete rows, lists of values, required columns, per-row errors, all-or-nothing save, signed row keys, search and paging; **aggregates** over the whole result (developer and user defined), **frozen columns**, column **reorder/resize/hide** (Actions → Columns, or drag and drop), per-user layouts and **saved grid reports** (private and public), **master-detail** (signed row selection, details refreshed in place), a **row actions menu** (edit, duplicate, delete, links) and **copy/paste** of cell ranges (tab-separated, spreadsheet compatible) ([chapter 4](guide/04-pages-and-regions.md)) |
65
66
  | Interactive grid views: single row view, chart view, group by | ✅ | (sprint 54) **Single row view**: one row of the search as a form with first/previous/next/last and *Add row*, from the Actions or row actions menu, saved by the grid's own process with the same checks; **group by** and **chart** set up in the Actions menu over every row of the search, as for the interactive report; `views` limits them; Save comes back to the same search, page and view ([chapter 4](guide/04-pages-and-regions.md#grid-interactive-grid)). No pivot view on grids (the interactive report has one), no editing in the single row view of columns the grid doesn't show |
66
67
  | Form (automatic row processing) | ✅ | Fetch, insert, update, delete, in a page or a modal dialog. Detects rows deleted meanwhile. (sprint 50) **Lost update detection** (APEX: *Prevent Lost Updates* and *Lock Row*): the page carries a checksum of the row's form columns (`meta.row_version`, independent of time zone and date format, as the app's role); *Save* and *Delete* lock the row and refuse when it changed meanwhile; off per form with `{"lost_update": false}` ([chapter 4](guide/04-pages-and-regions.md#form)) |
67
- | Charts | ✅ | Bar, column, stacked, line, area, combination (columns + lines), scatter, bubble, donut, pie, gauge, funnel, radar, **Gantt** (start/end, progress, milestones, dependencies, a today line, a time axis from hours to years), **pyramid** (area-proportional segments, or two series back to back) and **polar** (polar area); (sprint 63) **range** (floating columns from low to high), **box plot** (from one value per row or five statistics) and **stock** (candlesticks from open, high, low and close); multi-series, tooltips, data table, palette checked for colour-vision deficiency; drill-down links on chart marks (checksummed, only to pages the user may open). Drawn on the server as SVG without inline styles. **Missing:** other Oracle JET types (e.g. sunburst, treemap, timeline, picto), editing a Gantt by drag and drop |
68
+ | Charts | ✅ | Bar, column, stacked, line, area, combination (columns + lines), scatter, bubble, donut, pie, gauge, funnel, radar, **Gantt** (start/end, progress, milestones, dependencies, a today line, a time axis from hours to years), **pyramid** (area-proportional segments, or two series back to back) and **polar** (polar area); (sprint 63) **range** (floating columns from low to high), **box plot** (from one value per row or five statistics) and **stock** (candlesticks from open, high, low and close); multi-series, tooltips, data table, palette checked for colour-vision deficiency; drill-down links on chart marks (checksummed, only to pages the user may open). Drawn on the server as SVG without inline styles. (sprint 69) **Gantt editing**: drag a task or its end, or the arrow keys, runs the region's SQL as the app's role. (sprint 70) **treemap** (squarified, two levels shown), **sunburst** (up to four rings) from `node_id` / `parent_id` columns, and **timeline** (lanes by a `series` column, points and periods, overlaps in rows). **Missing:** other Oracle JET types (e.g. picto, NBox, Sankey) |
68
69
  | Cards and metric cards (26.1 metric card template) | ✅ | Cards from SQL, with a KPI "metric" style |
69
70
  | Calendar | ✅ | Month, week, day and list views (agenda list on phones); create on click (a checksummed link with the slot); drag and drop to move events through the developer's move SQL, run as the app's role (CSRF, a *who may drag* authorization, only events the user sees). Works without JavaScript; dragging adds on top ([chapter 4](guide/04-pages-and-regions.md#calendar)) |
70
- | Faceted search | ✅ | Checkbox, range (predefined, or a custom from/to on numbers and dates), star rating and search facets with live counts that honour the other facets; exclude on checkbox facets (26.1). Values travel as query parameters, never as SQL text. **Missing:** facet charts |
71
+ | Faceted search | ✅ | Checkbox, range (predefined, or a custom from/to on numbers and dates), star rating and search facets with live counts that honour the other facets; exclude on checkbox facets (26.1). Values travel as query parameters, never as SQL text. (sprint 65) **Facet charts**: a bar or pie chart of a facet's counts, each mark filtering on its value |
71
72
  | Smart filters | ✅ | One search field with filter chips and suggestions over a report, the same facet types; URL-based, works without JavaScript ([chapter 4](guide/04-pages-and-regions.md#smart_filters)) |
72
73
  | Static content, dynamic content | ✅ | `static` (HTML with substitutions) and `dynamic` (a SELECT returning HTML) |
73
74
  | Breadcrumb | ✅ | Automatic, from the page's breadcrumb parent |
@@ -193,7 +194,8 @@ application reports, Manage Service), so the share available dropped without any
193
194
  | Printing, document generator (PDF) | ✅ | **Document templates**: a query (with JSON columns for lines) fills an HTML template with Mustache-style tags, drawn as PDF with a report layout; buttons and links download them. Report PDF with **report layouts** and a print stylesheet on every page. No Word/Excel templates or DOCX/XLSX output |
194
195
  | `APEX_DATA_EXPORT` (a query to CSV, XLSX, PDF, HTML or JSON from PL/SQL) | ✅ | (sprint 53) `meta.data_export(query, format, options)` returns CSV, JSON, XML or HTML as `bytea` with the caller's privileges; the download process's `{"export": …}` sends a query's rows as CSV, JSON, XML, HTML, Excel or PDF |
195
196
  | SQL Workshop utilities: schema comparison, generate DDL | ✅ | (sprint 56) SQL Workshop → **DDL**: a schema's objects (types, sequences, tables, functions, views, constraints, indexes, triggers, RLS and policies, comments, grants) from the catalog, in an order that runs, unqualified so it also creates them in another schema. **Compare**: two schemas by their DDL (only in one, different, with a diff) and a change script that makes the target like the source (tables column by column; drops commented out for review). Also `pgkiln ddl`, `pgkiln compare` and the MCP tools `generate_ddl`, `compare_schemas` ([chapter 3](guide/03-builder.md#sql-workshop)). Two schemas of the same database only (APEX: also within one workspace) |
196
- | Data Reporter: self-service reports for business users (26.1) | ✅ | A **Data Reporter** region ([chapter 4](guide/04-pages-and-regions.md#data_reporter-data-reporter)): the developer offers tables and views with chosen columns, labels and format masks; signed-in users pick columns, filter, group with totals (count, sum, average, minimum, maximum), sort and chart, and save reports privately or shared with the app's users. Runs as the app's role (grants and RLS apply); works without JavaScript and fits phones. One source per report (offer a view to combine tables); no downloads from a reporter yet |
197
+ | Data Reporter: self-service reports for business users (26.1) | ✅ | A **Data Reporter** region ([chapter 4](guide/04-pages-and-regions.md#data_reporter-data-reporter)): the developer offers tables and views with chosen columns, labels and format masks; signed-in users pick columns, filter, group with totals (count, sum, average, minimum, maximum), sort and chart, and save reports privately or shared with the app's users. Runs as the app's role (grants and RLS apply); works without JavaScript and fits phones. (sprint 68) A **welcome page** like 26.1's: a greeting (the developer's own, or pgkiln's), the sources as cards that start a report, the user's reports latest first, shared ones, and a search. One source per report (offer a view to combine tables); no downloads from a reporter yet |
198
+ | REST Source Catalogs (Workspace Utilities) | ✅ | (sprint 67) Workspace utilities → **REST Source Catalogs**: a workspace's web services with a base URL and services, from an **OpenAPI 3 / Swagger 2.0** document (file, pasted or read from a URL on the allow-list), a catalog file or by hand: parameters (under the service's own names), row selector, typed columns and write-back operations from the response schemas and collection/item paths, with notes on what can't be used. An application's *REST data sources → From a REST source catalog* makes a data source from a service, with its own web credential ([chapter 19](guide/19-rest-data-sources.md#rest-source-catalogs)). **Missing:** YAML documents (convert to JSON), APEX's built-in catalogs (e.g. Oracle Fusion) |
197
199
  | JSON sources, duality views (24.2) | ➖ | PostgreSQL `jsonb` works in any SQL region, form or grid source |
198
200
  | Remote servers / database links | ➖ | `postgres_fdw` or `dblink` |
199
201
  | E-mail: `APEX_MAIL`, the Send E-Mail process, e-mail templates | ✅ | (sprint 50) `meta.send_mail`, `meta.send_mail_template`, `meta.add_mail_attachment` and `meta.mail_status`, queued in the caller's transaction and sent by the server after the commit with retries; the **send_email** process; Shared Components → **E-mail templates** (`#NAME#` escaped in HTML, `#NAME!RAW#`; exported). Further than APEX (SMTP with a password only, through `UTL_SMTP`): **mail services** for SMTP with a password or **OAuth2** (XOAUTH2, e.g. Exchange Online after the end of basic authentication), **Microsoft 365 through Graph**, **Amazon SES**, **Resend, Postmark, SendGrid and Mailgun**, or log only; encrypted write-only secrets, allowed senders, a service, From address and daily limit per application, a mail log with retry and cancel ([chapter 6](guide/06-processing.md#sending-e-mail)). No bounce or delivery webhooks, no mail in workflows other than from SQL steps |
@@ -207,13 +209,13 @@ application reports, Manage Service), so the share available dropped without any
207
209
  | Automations (scheduled) | ✅ | Shared Components → Automations: cron schedules with time zones, once or per row of a query, **several ordered actions** with their own conditions, **error handling** (stop, skip the row and continue, or disable; row errors in the run history), roles, run history and Run now, **on-demand runs from SQL** with `meta.run_automation()` (like `APEX_AUTOMATION.EXECUTE`, synchronous in the caller's transaction), safe with several servers ([chapter 6](guide/06-processing.md#automations)) |
208
210
  | AI assistant, natural-language reports (NL2IR), AI agents and tools (26.1) | ✅ | Region type **AI assistant**: a conversation per session, context queries (RAG over developer queries, run as the app's role, read-only), and **tools** the model may call: SQL with bound arguments checked against declared parameters (read-only unless marked as writing, row limit, timeout) and REST data sources, each optionally behind an authorization scheme. **Natural-language report filters**: an "Ask in your own words" box turns a question into the report's normal filters, search and sort, limited to its visible columns ([chapter 4](guide/04-pages-and-regions.md)). Agents are defined per region (not as shared components); answers are not streamed. `pgvector` covers semantic search on the data side |
209
211
  | *Generate Text with AI* process, structured outputs (26.1) | ✅ | **AI services** (Workspace utilities, administrators): Claude through `@anthropic-ai/sdk` or OpenAI through `openai`, encrypted write-only keys (or `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`), per-app access with daily request and token limits, a usage log. Page process `ai_generate` (text into an item, or structured output into several items with a schema built from the items or your own) and a dynamic action that runs it without a page submit; `meta.ai_generate` / `ai_result` / `ai_available` from SQL ([chapter 6](guide/06-processing.md)). Prompts, item values included, go to the chosen provider |
210
- | Blueprints, spec-driven development (26.1) | ✅ | Create → **From a blueprint**: a JSON spec of tables (types, required, unique, allowed values, references), pages, navigation and sample data; optionally drafted by AI from a description; always reviewed (problems, SQL, pages, menu) before the application is created in one transaction; saved blueprints. **Missing:** a blueprint from an existing application |
212
+ | Blueprints, spec-driven development (26.1) | ✅ | Create → **From a blueprint**: a JSON spec of tables (types, required, unique, allowed values, references), pages, navigation and sample data; optionally drafted by AI from a description; always reviewed (problems, SQL, pages, menu) before the application is created in one transaction; saved blueprints; (sprint 66) **a blueprint from an existing application** (its tables, pages, menu and optionally sample rows, with notes on what didn't carry over) |
211
213
 
212
214
  ## Administration
213
215
 
214
216
  | APEX | pgkiln | Notes |
215
217
  |---|---|---|
216
- | Developer accounts, workspace sign-in | ✅ | (sprint 61) The builder's sign-in page like APEX's: workspace (optional; it becomes the current one, a wrong one answers like a wrong password), username, password with a Show button, *Remember workspace and username*, a link to Administration |
218
+ | Developer accounts, workspace sign-in | ✅ | (sprint 61) The builder's sign-in page like APEX's: workspace (optional; it becomes the current one, a wrong one answers like a wrong password), username, password with a Show button, *Remember workspace and username*, a link to Administration. (sprint 68) **Find my workspace**: developers' e-mail addresses, and a mail with their workspaces through the builder's mail service (the same answer for every address, limited per address and IP). **Missing:** the sign-in page's language links (the builder is in English only) |
217
219
  | Workspace message, environment banner, workspace utilization, preferences and extension links (Manage Service) | ✅ | (sprint 61) An **Administration** menu in the icon rail; administrators and workspace administrators set a **workspace message** (on the App Builder home) and an **environment banner** (a coloured label on every builder page of the workspace), and see **workspace utilization** (applications, pages, page views, users, static files, schema storage) ([chapter 3](guide/03-builder.md#workspace-message-and-environment-banner)). (sprint 62) **Workspace preferences**: the SQL Workshop and the applications' RESTful services (REST modules) on or off per workspace; **extension links** in an Extensions menu of the rail ([chapter 3](guide/03-builder.md#workspace-preferences)). **Missing:** the account login controls of APEX's preferences (pgkiln's password policy and sign-in throttling are installation-wide) |
218
220
  | Instance administration, install/upgrade logs (26.1) | ✅ | Versioned migrations (`npm run db:migrate`), every run logged; Workspace utilities → **Installation** (administrators): server version, install and upgrade runs with errors, applied migrations, and warnings for migrations the database misses or the server doesn't know ([chapter 3](guide/03-builder.md)). Workspace utilities → **Instance settings**: session length and sign-in throttling (stored in the database, over the environment variables) and an overview of the server's configuration without secrets; a server whose database lacks migrations says so (503) or applies them (`MIGRATE_ON_START`). Other settings stay environment variables |
219
221
  | Debug messages | ✅ | Debug levels 1–9 per app; `meta.debug(level, text)` and `meta.debug_enabled(level)` from application SQL (APEX_DEBUG); timed entries per request (page steps, regions, processes, branches, errors, SQL notices); Activity → **Debug messages** viewer per page view with filters and the slowest step highlighted; retention 1–90 days; password item values are never recorded ([chapter 6](guide/06-processing.md)). (sprint 50) Debug for **one session** from the developer toolbar, the application staying out of debug. **Missing:** debug entries for background jobs and REST requests |
@@ -222,6 +224,7 @@ application reports, Manage Service), so the share available dropped without any
222
224
  | Automatic application backups, page groups | ✅ | (sprint 51) **Backups**: before every import that replaces an application (CLI, MCP, working copy merge, restore), daily when it changed, and by hand; the newest 25 (configurable) are kept; download and restore from the builder ([chapter 3](guide/03-builder.md#backups)); (sprint 62) Workspace utilities → **Manage backups** across the workspace's applications, with a backup of all of them at once. (sprint 58) **Page groups**: Shared Components → Page groups, a page's *Page group*, the page list by group with a filter ([chapter 3](guide/03-builder.md#page-groups)) |
223
225
  | Application availability (Available, Developers only, Restricted access, Unavailable; build status *Run only*) | ✅ | (sprint 51) Available, available to developers only (a builder session in the same browser), restricted to named users, or unavailable with a message, for pages, file downloads, REST modules and PostgREST; build status **Run only** refuses builder changes as if the application were locked, while `pgkiln import --replace` still deploys. Installation settings: not exported, kept by an import ([chapter 3](guide/03-builder.md#availability-and-build-status)) |
224
226
  | Monitoring (top SQL) | ✅ | Activity per app; Top SQL per app's database role from `pg_stat_statements` (sortable, resettable) |
227
+ | Workspace export and import (Workspace Utilities → Export) | ✅ | (sprint 67) Workspace utilities → **Export and import** (administrators and the workspace's administrators): settings (message, banner, preferences), developers and workspace administrators, application groups, extension links, REST source catalogs, SQL scripts, blueprints and data generators as one file; imported into the current workspace in one transaction, keeping or replacing components with the same name and never deleting ([chapter 3](guide/03-builder.md#export-and-import)). Applications are exported on their own; isolation, database roles and passwords never leave the installation |
225
228
  | Workspaces (multi-tenant) | ✅ | Workspaces group applications and developers: the builder shows and opens only the applications of a developer's workspaces (administrators: all), a current workspace with a switcher, new and imported applications go into it, administrators add workspaces, choose their developers and move applications ([chapter 3](guide/03-builder.md#workspaces)). (sprint 60) **Isolated workspaces** are a tenant boundary: the applications run on a PostgreSQL login of the workspace's own and its developers' SQL Workshop on another, with row-level security on pgkiln's tables, so SQL that resets its role can't reach other workspaces' applications, data, sessions or accounts; **workspace database roles** (APEX: workspace schemas) assigned by administrators; **workspace administrators** who manage their workspace's developers; SQL scripts, blueprints and sample data per workspace ([isolated workspaces](guide/03-builder.md#isolated-workspaces)). **Missing:** user directories per workspace (accounts are installation-wide, visible to the workspaces whose applications they use), developers created by a workspace administrator |
226
229
 
227
230
  ## Different on purpose
@@ -15,10 +15,20 @@ workspace and switch in your account menu. **Remember workspace and username** k
15
15
  HttpOnly cookie for `/builder`, no password); signing in without the tick forgets them. *Administration* under the
16
16
  form signs in and opens Workspace utilities.
17
17
 
18
+ **Find my workspace** under the form (APEX: Find My Workspace) asks for an e-mail address and mails the developer
19
+ accounts with that address their user name and the workspaces they belong to. It needs a mail service for the
20
+ builder: Workspace utilities → Mail services → **Builder mail** (a service and a From address among its senders);
21
+ without one the page says to ask an administrator. The page answers the same whether or not an account has the
22
+ address, the mail leaves after the answer, and it sends at most three mails an hour to an address and handles ten
23
+ requests an hour from an IP address. Developers set their own address on the Developers page (migration 096);
24
+ administrators set anyone's.
25
+
18
26
  On the **Developers** page you can:
19
27
 
20
28
  - change your own password (minimum 8 characters; other builder sessions of yours end);
21
- - as an **administrator**: add developer accounts (developers or administrators), make a developer
29
+ - set your **e-mail address** (optional; *Find my workspace* sends your workspaces to it);
30
+ - as an **administrator**: add developer accounts (developers or administrators, with an e-mail address), change
31
+ their e-mail addresses, make a developer
22
32
  an administrator or the other way round, and remove other developers (their sessions end
23
33
  immediately).
24
34
 
@@ -92,6 +102,32 @@ Links), added on the workspace's page by administrators and the workspace's admi
92
102
  `https://` URL, an optional description and an order. While the workspace is current an **Extensions** icon in the
93
103
  rail opens them, each in a new tab (`rel="noopener noreferrer"`).
94
104
 
105
+ ### Export and import
106
+
107
+ Workspace utilities → **Export and import** (`/builder/workspace-export`; APEX: Workspace Utilities → Export), for
108
+ administrators and the workspace's administrators: the current workspace's components as one JSON file (format
109
+ `pgkiln-workspace/1`), to copy them to another workspace or installation or keep them in version control next to the
110
+ applications' files. Choose what goes in:
111
+
112
+ | Component | In the file |
113
+ |---|---|
114
+ | Settings | Description, [workspace message, environment banner](#workspace-message-and-environment-banner) and [preferences](#workspace-preferences) |
115
+ | Developers | User names and who is a workspace administrator (never passwords) |
116
+ | Application groups | Names, descriptions and the aliases of their applications |
117
+ | Extension links | Label, URL, description, order |
118
+ | REST source catalogs | Every [catalog](19-rest-data-sources.md#rest-source-catalogs) with its services |
119
+ | SQL scripts, blueprints, data generators | The SQL Workshop's saved work |
120
+
121
+ Never in the file: the workspace's name, its [isolation](#isolated-workspaces) and database roles, passwords and
122
+ secrets, script runs and other history. **Applications are exported on their own** (an application's *Export*).
123
+
124
+ **Import** reads such a file into the current workspace, for the components you choose. Components with a name the
125
+ workspace already has are kept, or replaced with *Replace components with the same name*; nothing is deleted. A
126
+ developer is added only when this installation has a developer of that name (add them under *Developers* first); an
127
+ application group takes the workspace's applications with those aliases. The import is one transaction: a value the
128
+ installation refuses (an invalid URL, a catalog service that doesn't pass the checks) changes nothing, and the page
129
+ says what was added, kept and replaced.
130
+
95
131
  ### Workspace utilization
96
132
 
97
133
  Administration menu → **Workspace utilization** (`/builder/workspaces/<id>/utilization`; APEX: Workspace
@@ -353,6 +389,24 @@ in **one transaction**: if anything fails, nothing is created. Creation only acc
353
389
  text the review showed you (it is signed with your session); change it and review again. **Save**
354
390
  keeps a blueprint in the list (`meta.blueprint`, with the application last created from it).
355
391
 
392
+ **From an application** (on the Blueprints page; APEX 26.1: a blueprint from an application) opens a blueprint of an
393
+ application of the current workspace in the editor, for a copy, a new version or a test system:
394
+
395
+ - **tables**: the tables its regions read (a form's table, the first `schema.table` after `FROM` in a query) that the
396
+ application's database role may read, with their columns: types (integers, numbers, dates, timestamps, booleans,
397
+ text; other types become text, binary columns are left out), *required* (NOT NULL without a default), *unique*
398
+ (a one-column unique constraint), allowed values (an enum, or a `CHECK (col IN (…))`) and references to another of
399
+ these tables' `id`. Every blueprint table gets an `id`: an old key with another name stays a required, unique column,
400
+ and a reference to it a plain column;
401
+ - **pages**: a report with its form page becomes `report_form`, and grids, cards, calendars, charts, maps, faceted
402
+ searches and forms keep their type and page number; other pages become `blank` pages with their name;
403
+ - **navigation**: the menu entries of those pages;
404
+ - **sample rows** only when ticked: up to 20 per table, read read-only through the application's developer
405
+ connection. They are copied into the blueprint as they are, so leave this off for personal or confidential data.
406
+
407
+ The new name, alias and schema end in *copy*; a list of **notes** says what didn't carry over. Nothing is created
408
+ until you review and confirm it, as for any blueprint.
409
+
356
410
  ### Importing
357
411
 
358
412
  **Import** (a tile, or `/builder/import`): paste the JSON of an export and optionally give a new
@@ -555,7 +609,7 @@ out, other keys are kept, columns the query no longer returns stay listed so you
555
609
  | `chart` | Chart type (also Gantt, pyramid, polar, range, box plot and stock, with the columns each expects), the text when there are no rows, the gauge's range and thresholds, and the drill-down link (page and items, `#column#` and `#series#`); lists the query's columns |
556
610
  | `cards` | Cards or KPI tiles, the text when there are no rows, and the link (page and items) |
557
611
  | `calendar` | The views and the one shown first, the hours of the week and day views, the edit link of each event, the create-on-click link (`#start#`, `#end#`, `#date#`), and drag and drop (the SQL with `:EVENT_ID`, `:NEW_START`, `:NEW_END`, the key column, who may drag); warns when the query lacks `start_date` or `title` |
558
- | `facets` | The report region it filters and a search field on/off; per column of that report: facet on/off, label, type (checkboxes, ranges, star rating), values shown, exclude, ranges (`..1000; 1000..3000 = Middle; 3000..`), from/to and order |
612
+ | `facets` | The report region it filters and a search field on/off; per column of that report: facet on/off, label, type (checkboxes, ranges, star rating), values shown, exclude, ranges (`..1000; 1000..3000 = Middle; 3000..`), from/to, a chart of the counts (bar or pie) and order |
559
613
  | `smart_filters` | The same per-column facets, the suggestions per facet and the search field's placeholder |
560
614
  | `display_selector` | Tabs or a select list, "Show all", remember the choice; per other region of the page: in a tab and the tab name (saved in that region's settings) |
561
615
  | `ai_assistant` | The AI service (those the application may use), system prompt, welcome text, placeholder, error message, tool rounds per question, questions per conversation, public or not, and the context queries and tools as JSON (checked when saving: query shapes, parameter types, REST data sources and authorization schemes that exist) ([AI assistant](04-pages-and-regions.md#ai_assistant-ai-assistant)) |
@@ -137,7 +137,7 @@ database only checks the shape (at most 12 names of lower case letters, digits a
137
137
  | [`report`](#report-interactive-report) | Read-only table from a SELECT, with search, filters, sorting, control break, aggregates, highlights, computed columns, group by, pivot and chart views, row selection, saved reports, paging and CSV/Excel/PDF download |
138
138
  | [`grid`](#grid-interactive-grid) | Editable table on one database table, with aggregates, frozen, movable and resizable columns, saved grid reports, a row actions menu, master-detail, copy/paste of cells, and single row, group by and chart views |
139
139
  | [`form`](#form) | Fields for one row of a table, with automatic fetch and save |
140
- | [`chart`](#chart) | Bar, column, stacked, line, area, combo, scatter, bubble, donut, pie, gauge, funnel, radar, Gantt, pyramid, polar, range, box plot or stock chart from a SELECT, with drill-down links |
140
+ | [`chart`](#chart) | Bar, column, stacked, line, area, combo, scatter, bubble, donut, pie, gauge, funnel, radar, Gantt, pyramid, polar, range, box plot, stock, treemap, sunburst or timeline chart from a SELECT, with drill-down links |
141
141
  | [`cards`](#cards) | Cards or KPI tiles from a SELECT |
142
142
  | [`calendar`](#calendar) | Month, week, day and list views of dated rows, with create on click and drag and drop |
143
143
  | [`facets`](#facets-faceted-search) | Checkbox, range and star filters with counts and a search field for a report |
@@ -506,11 +506,14 @@ Attributes:
506
506
 
507
507
  | Key | Meaning |
508
508
  |---|---|
509
- | `kind` | `bar` (default), `column`, `stacked`, `line`, `area`, `combo`, `scatter`, `bubble`, `donut`, `pie`, `gauge`, `funnel`, `radar`, `gantt`, `pyramid`, `polar`, `range`, `boxplot` or `stock` |
509
+ | `kind` | `bar` (default), `column`, `stacked`, `line`, `area`, `combo`, `scatter`, `bubble`, `donut`, `pie`, `gauge`, `funnel`, `radar`, `gantt`, `pyramid`, `polar`, `range`, `boxplot`, `stock`, `treemap`, `sunburst` or `timeline` |
510
510
  | `link` | Drill-down: `{"page": 2, "items": {"P2_DEPTNO": "#deptno#"}}` makes every data point a link (see below) |
511
511
  | `gauge` | For `gauge`: `{"min": 0, "max": 120, "warning": 80, "critical": 100}` (all optional) |
512
512
  | `format_mask` | A number format mask for the values in labels, tips and the data table, e.g. `"FML999G990"` (see [number formats](14-globalization.md#number-formats)) |
513
513
  | `empty` | Text when there are no rows |
514
+ | `gantt_move` | For `gantt` with a `task_id` column: SQL that gives a task new dates, run with `:TASK_ID`, `:NEW_START` and `:NEW_END` ([below](#dragging-tasks-on-a-gantt-chart)) |
515
+ | `gantt_move_authz` | Who may drag: an authorization scheme, or `MUST_NOT_BE_PUBLIC_USER`; empty: everyone who sees the chart |
516
+ | `gantt_snap` | `day` or `hour`: the step of a drag; default days, or hours when a task has a time |
514
517
 
515
518
  | Kind | Best for | Notes |
516
519
  |---|---|---|
@@ -526,6 +529,9 @@ Attributes:
526
529
  | `funnel` | stages of a process | the first series, in the query's order (sort it); each stage shows its share of the first stage |
527
530
  | `radar` | several measures per series, side by side | **one axis per row** (3 to 12 rows), one polygon per series, all on one scale from zero |
528
531
  | `gantt` | tasks over time | **label, start, end** (dates or timestamps; an empty end, or one equal to the start, is a milestone ◆), then optional columns **by name**: `progress` (0 to 100, the filled part of the bar), `task_id` and `depends_on` (the ids a task waits for: `3`, `3,4` or an array). A time axis in hours, days, weeks, months or years, a dashed line for now (in the session's time zone, like the timestamps the query returns), and elbow lines from the end of each predecessor to the start of the task. Rows without a start are left out |
532
+ | `treemap` | parts of a whole in a hierarchy | **label, value**, then optional columns **by name** `node_id` and `parent_id` (a node's parent; without `node_id` the label is the id). Rectangles sized by value (a node's own value plus its children's), squarified; the top level as coloured groups with their children inside. One root with children: its children are the top level. Cycles and unknown parents make roots |
533
+ | `sunburst` | the same, as rings | Like `treemap`: the top level as the inner ring, children outwards (up to four rings), the total in the centre and a legend of the top level |
534
+ | `timeline` | events and periods over time | **label, start, end** (an empty end is a point in time), and an optional column named `series`: a lane per series. Items that overlap in a lane get rows of their own |
529
535
  | `pyramid` | levels of a hierarchy, or two groups compared per band | **one series**: a triangle cut into segments from the top (the first row) down, each segment's **area** in proportion to its value (≤ 8; more fold into "Other"). **Two series**: back-to-back bars (a population pyramid), the first series to the left, both on one scale; negative values count as their size |
530
536
  | `polar` | values per period or direction (months, weekdays) | a polar area chart: **one equal sector per row** (up to 24) clockwise from 12 o'clock, the radius in proportion to the value on rings from zero; several series share a row's sector |
531
537
  | `range` | a span per category (lowest and highest, from and to) | **low and high** columns (in either order): a floating column from one to the other; each further pair of columns is another range per row (up to four, with a legend). The axis doesn't have to start at zero |
@@ -613,6 +619,28 @@ A Gantt chart reads dates as their wall clock (a `timestamptz` in the session's
613
619
  time only when it is not midnight, and has its own data table (label, start, end, progress,
614
620
  dependencies). Its rows count toward the chart's row limit (`max_rows`, default 1000).
615
621
 
622
+ #### Dragging tasks on a Gantt chart
623
+
624
+ With `gantt_move` (builder: Chart settings → *Gantt: drag and drop*) and a `task_id` column, users who pass
625
+ `gantt_move_authz` change the plan on the chart itself (APEX: the Gantt chart's task dragging):
626
+
627
+ - **drag a task** to move it (start and end by the same number of days or hours);
628
+ - **drag the end of a bar** (its right edge) to make it longer or shorter; a milestone only moves;
629
+ - **with the keyboard**: focus a task, the arrow keys move it, Shift and the arrow keys change its end, Enter saves,
630
+ Escape cancels. A line under the chart says the new dates while you drag or press keys.
631
+
632
+ The server checks the dates (`YYYY-MM-DD`, or `YYYY-MM-DDTHH:MM` by the hour; the end not before the start) and that
633
+ the task is a row the chart's query shows this user, then runs the SQL as the application's database role (row level
634
+ security applies) and sends the chart back. A milestone gets the same start and end. A click without a drag still
635
+ follows the task's drill-down link. Example (HR example part 59):
636
+
637
+ ```sql
638
+ update hr.project_task
639
+ set starts = :NEW_START::date,
640
+ ends = case when ends is null then null else :NEW_END::date end -- a milestone keeps no end
641
+ where id = :TASK_ID::int
642
+ ```
643
+
616
644
  Up to 8 series; two or more get a legend. When an axis has many labels, only some are shown, and in a
617
645
  narrow chart (a region of a few columns, a phone) every other one of those. Every chart has hover/focus **tooltips** and a
618
646
  **Data table** toggle (the accessible alternative). Colours come from a palette checked for
@@ -748,6 +776,11 @@ Counts take the search and all *other* facets into account. Three kinds of facet
748
776
  With `"search": true` the panel starts with a search field: the same search as the report's own
749
777
  (`r<id>_q`, the row as text contains the term).
750
778
 
779
+ **Facet charts** (APEX: facet charts): with `"chart": "bar"` or `"chart": "pie"` a facet shows its counts as a chart,
780
+ collapsed under its heading (*Chart*). Each bar or slice, and each row of the chart's data table, links to the page
781
+ filtered on that value (a checkbox facet's value, or a range), the other filters kept. Values with no rows are left out
782
+ of the chart. In the HR sample, page 21 has a bar chart of jobs and a pie chart of salary ranges.
783
+
751
784
  Attributes:
752
785
 
753
786
  ```json
@@ -774,6 +807,7 @@ Attributes:
774
807
  | `facets[].ranges` | range: `[{"from": …, "to": …, "label": …}]`, numbers or `YYYY-MM-DD` dates; either bound may be left out (at most 20) |
775
808
  | `facets[].custom` | range: `true` adds *from*/*to* fields (default: only when there are no `ranges`) |
776
809
  | `facets[].max` | star: the highest rating, 2–10 (default 5) |
810
+ | `facets[].chart` | `bar` or `pie`: a chart of the facet's counts under it (faceted search only) |
777
811
 
778
812
  Only filters that a facet on the page allows are read from the URL: a value for a column without a
779
813
  facet, a range that isn't one of the facet's own, or a *from*/*to* on a facet without `custom`
@@ -1054,8 +1088,11 @@ and dates, a [format mask](14-globalization.md). New sources offer all columns e
1054
1088
  ones at first. A view that shows exactly what business users may see is often the best source;
1055
1089
  the builder warns when the application's database role may not read it.
1056
1090
 
1057
- **Users** choose a source and *Start*, then, in the report's editor (a plain form: it works
1058
- without JavaScript, and the URL of a result can be bookmarked or sent):
1091
+ **Users** start on the region's **welcome page** (APEX 26.1: the Data Reporter's welcome page): a greeting, the data
1092
+ sources as cards (label, description, number of columns), their own reports with the latest changed first, and the
1093
+ reports others shared; with more than six reports (or a search term) a **search** over names and descriptions. A
1094
+ source's card opens a new report in the editor (a plain form: it works without JavaScript, and the URL of a result
1095
+ can be bookmarked or sent):
1059
1096
 
1060
1097
  - **Columns** to show (all offered columns when none are ticked);
1061
1098
  - up to five **filters** (column, operator, value; the operators of interactive report filters);
@@ -1092,6 +1129,8 @@ Attributes (written by the region's **Settings**):
1092
1129
  | `sharing` | `true` | `false`: reports stay private |
1093
1130
  | `share_authz` | | An authorization scheme: only users that pass it may share reports |
1094
1131
  | `page_size` | `25` | Rows per page of a detail report (5 to 200) |
1132
+ | `welcome` | `true` | `false`: the compact start (a list of sources and *Start*) instead of the welcome page |
1133
+ | `welcome_title`, `welcome_text` | | The welcome page's greeting instead of pgkiln's (translated like other application texts) |
1095
1134
  | `empty` | `No data found.` | Text when there are no rows |
1096
1135
 
1097
1136
  The sources travel with the application export (they are the region's attributes); users'
@@ -25,6 +25,11 @@ src/
25
25
  appfiles.ts application export as one file per component (dir layout, static ids) and back
26
26
  blueprint.ts blueprints (migration 063): checkBlueprint (names, types, references, pages, sample rows), tableOrder,
27
27
  blueprintSql, buildBlueprint (tables, grants, rows, pages via meta.generate_page, menu), the AI draft schema
28
+ blueprint-from-app.ts (sprint 66) blueprintFromApp: an application's tables (catalog), pages and menu as a blueprint, notes; sample rows
29
+ restcatalog.ts (095) REST source catalogs: checks, fromOpenApi (OpenAPI 3 / Swagger 2 → services: parameters with "key",
30
+ rows and columns from the response schema, write-back from collection and item paths, notes), catalog
31
+ files, load/insert/replace, sourceFromService
32
+ workspace-export.ts (sprint 67) a workspace's components as a file (pgkiln-workspace/1) and importWorkspace (one transaction)
28
33
  subscriptions.ts application types and subscriptions (migration 056): offers, subscribe, refresh, publish, in sync
29
34
  workingcopy.ts working copies (migration 055): create, three-way compare per component (base, main, copy),
30
35
  merge into the main application or refresh the copy, both through cli/replace.ts
@@ -115,11 +120,13 @@ src/
115
120
  style (user choice, default), themeCss() (only hex values and constants reach the CSS)
116
121
  template-options.ts template options: the fixed CSS class list per region and button, templateClasses() (unknown values ignored)
117
122
  regions.ts region shell + chart (drill-down links, gauge settings)/cards/dynamic dispatch with row limits, lazy placeholder and cache, buttons (menu buttons, badges)
118
- report.ts, report-views.ts (group by, pivot, chart), compute.ts (computed column expressions), grid.ts (aggregates, row actions, Actions menu, single row view, layoutFromForm), grid-layout.ts (column layouts: clean, arrange, per user), master-detail.ts (signed master row selection, details), facets.ts, items.ts
123
+ report.ts, report-views.ts (group by, pivot, chart), compute.ts (computed column expressions), grid.ts (aggregates, row actions, Actions menu, single row view, layoutFromForm), grid-layout.ts (column layouts: clean, arrange, per user), master-detail.ts (signed master row selection, details), facets.ts (facetChart: a facet's counts as a chart, sprint 65), items.ts
119
124
  (report.ts: paging with row ranges and max_rows, keyset paging (keysetPlan, seekCondition, signed r<id>_k), pagerNav, streamed CSV/Excel downloads with a cursor;
120
125
  items.ts: lovOptions, searchLov/lovLookup for popup LOVs, served by POST /a/:alias/:page/lov/:item/search in routes.ts)
121
126
  region-cache.ts region caching (keys per scope, CSRF placeholder, invalidation on submit) and lazy regions (GET …/region/:id is in routes.ts)
122
- charts.ts server-rendered charts (SVG and CSS classes): bar … radar, gauges, Gantt (time axis, dependencies), pyramid, polar, range, box plot (quantile, boxes), stock, drill-down marks, data table
127
+ gantt-move.ts (sprint 69) Gantt drag and drop: ganttEditable, targetTime, moveGanttTask (the task in the region's
128
+ query, gantt_move with :TASK_ID/:NEW_START/:NEW_END); the dragging itself is in app.js
129
+ charts.ts server-rendered charts (SVG and CSS classes): bar … radar, gauges, Gantt (time axis, dependencies), pyramid, polar, range, box plot (quantile, boxes), stock, (sprint 70) treemap and sunburst (buildTree, squarify), timeline, drill-down marks, data table
123
130
  calendar.ts calendar region: month/week/day/list views, create links, drag and drop (moveEvent, moveCalendarEvent;
124
131
  the route POST …/calendar/:id/move is in routes.ts)
125
132
  links.ts page links with checksums; fillItems() fills #column# in link items
@@ -189,6 +196,11 @@ src/
189
196
  backupTick() for the scheduler's daily backups of changed applications
190
197
  workspace-backups.ts Workspace utilities → Manage backups (sprint 62): the backups of every application of the current
191
198
  workspace, back them all up (only the changed ones by default)
199
+ rest-catalogs.ts Workspace utilities → REST Source Catalogs (095): list, import (file, pasted, URL), a catalog and its
200
+ services, download; catalogPicker and "from a catalog" for an application's REST data sources
201
+ workspace-transfer.ts Workspace utilities → Export and import (sprint 67, workspace administrators)
202
+ find-workspace.ts (096) Find my workspace: builderMail (Mail services → Builder mail), workspacesMail, the page (same answer
203
+ for every address, mail after the answer, limits per address and IP)
192
204
  availability.ts Application → Availability (migration 083): status, message, users, build status (Run only is
193
205
  enforced by locks.ts blockingLock); availabilityBadge() in the application header
194
206
  feedback.ts Application → Feedback (migration 084): the setting, the list with filters, status and answers
@@ -247,7 +259,8 @@ src/
247
259
  (093) workspace preferences (sql_workshop: checked in ui.ts developer() for /builder/sql…;
248
260
  rest_services: checked in runtime/rest.ts) and extension links (the rail's Extensions menu in shell())
249
261
  locks.ts page and application locks (blockingLock, checked in ui.ts developer() for every builder POST; appOfPath), developer comments, administrators
250
- blueprints.ts Create → From a blueprint: list, JSON editor, AI draft, review (signed with the session), create in one transaction
262
+ blueprints.ts Create → From a blueprint: list, JSON editor, AI draft, review (signed with the session), create in one transaction;
263
+ (sprint 66) From an application
251
264
  ai-builder.ts App Builder AI (migration 062): the builder's AI service (meta.builder_ai), SQL Workshop → AI (SQL from a
252
265
  question, shown not run; explain), describe tables (meta.ai_table_note, COMMENT ON, AI drafts),
253
266
  create pages with AI (proposals checked by checkProposals, created with meta.generate_page)
@@ -311,6 +324,12 @@ test/
311
324
  ai-assistant.test.ts AI assistant region (context, tools as the app role, writes, REST, histories, limits, sessions), OpenAI,
312
325
  natural-language report filters, builder settings; against ai-script-mock.ts
313
326
  blueprints.test.ts blueprints: checks and SQL, review then create (rows, pages, grants), one transaction, AI draft, save
327
+ blueprint-from-app.test.ts a blueprint of HR: checks clean, pages and menu, notes, a working copy with sample rows, workspaces
328
+ rest-catalogs.test.ts OpenAPI/Swagger reading, parameter keys, catalog files, the builder's pages, a data source from a service
329
+ workspace-transfer.test.ts a workspace's export, import into another workspace (added, kept, replaced, all or nothing), groups, access
330
+ tree-charts.test.ts treemap and sunburst (the hierarchy, cycles, squarify), timeline (lanes, rows, points and periods)
331
+ gantt-move.test.ts an editable Gantt's markup, the move route, dates, who may drag, the builder's settings
332
+ find-workspace.test.ts developers' addresses, builder mail, the workspaces mail, the same answer, limits
314
333
  ai-builder.test.ts App Builder AI: the builder's service, SQL from a question, explain, describe tables, pages with AI
315
334
  ai-script-mock.ts a scripted mock of Claude (SSE, tool_use with a thinking block) and OpenAI (tool calls), reply by reply
316
335
  ai-mock.ts a local mock of the Claude Messages API (SSE stream) and OpenAI Chat Completions
@@ -320,6 +339,7 @@ test/
320
339
  e2e/items.test.ts sprint 26 item types in a browser: editors, tags, stars, dates, reveal; without JavaScript
321
340
  e2e/designer.test.ts page designer: panes per width, drag and drop, keyboard, Arrange buttons, builder theme
322
341
  e2e/calendar.test.ts calendar drag and drop and create on click, view switching, chart drill-down
342
+ e2e/gantt.test.ts Gantt drag and drop: moving a task, its end, the keyboard, a click still drills down, the phone
323
343
  e2e/globalization.test.ts the browser's time zone (sign-in, app.js), no-JavaScript fallback, a masked number item
324
344
  e2e/grid.test.ts interactive grid in a browser: master-detail refresh, move/resize columns, row menu, copy/paste; without JavaScript
325
345
  e2e/page-logic.test.ts dialog_closed refreshes a region without a reload, download process in a browser, dialog link without JavaScript
@@ -111,7 +111,7 @@ Shared Components → **REST data sources** → + Add.
111
111
  | URL | `https://api.example.com/v1/cities/{city}/weather`: `{name}` is a path parameter. The host is fixed: parameters can only come after it |
112
112
  | Method | `GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
113
113
  | Web credential | The name of a web credential, or empty |
114
- | Parameters | JSON: `[{"name": "city", "in": "path", "default": "&P1_CITY.", "required": true}, {"name": "units", "in": "query", "default": "metric"}]`. `in` is `path`, `query`, `header` or `body`. Defaults may use `&ITEM.` substitutions |
114
+ | Parameters | JSON: `[{"name": "city", "in": "path", "default": "&P1_CITY.", "required": true}, {"name": "units", "in": "query", "default": "metric"}]`. `in` is `path`, `query`, `header` or `body`. Defaults may use `&ITEM.` substitutions. `key`: the service's own name for a query, header or body parameter when it isn't lower case with `_`, e.g. `{"name": "page_size", "in": "query", "key": "pageSize"}`; `Authorization`, `Cookie`, `Host` and the transport headers can't be header parameters |
115
115
  | Headers | JSON: extra request headers, e.g. `{"Accept-Language": "en"}`. Not for secrets (use a web credential); `Authorization`, `Cookie`, `Host` and the transport headers can't be set |
116
116
  | Body | For `POST`, `PUT`, `PATCH`: a JSON template, `{name}` becomes the parameter's value as a JSON string. Empty: the `body` parameters as a JSON object |
117
117
  | Row selector | Where the rows are in the response: `items`, `data.results`, `$.list[*]`. Empty: the response itself (an array, or one object as one row) |
@@ -238,6 +238,44 @@ nothing. Two runs of one source never overlap. The last 100 runs per source are
238
238
  application's synchronisations start switched off. `AUTOMATIONS=off` stops scheduled and queued
239
239
  runs on that server.
240
240
 
241
+ ## REST source catalogs
242
+
243
+ Workspace utilities → **REST Source Catalogs** (APEX: REST Source Catalogs) describes a web service once for the
244
+ workspace: a **base URL** (e.g. `https://api.example.com/v1`) and its **services**, each an endpoint with a path after
245
+ the base URL (`/pets/{pet_id}`), a method, and the same parameters, headers, body, row selector, columns, key columns
246
+ and operations as a [REST data source](#rest-data-sources). Every developer of the workspace manages its catalogs.
247
+
248
+ A catalog comes from:
249
+
250
+ - an **OpenAPI 3.x or Swagger 2.0 document** in JSON (*Import a catalog*: upload `openapi.json`, paste it, or give its
251
+ URL, which the server reads, so the host must be on the [allow-list](#server-configuration-and-the-allow-list));
252
+ - a **catalog file** downloaded from another workspace or installation (*Download* on the catalog's page);
253
+ - **by hand**: a name and base URL, then *Add a service*.
254
+
255
+ Reading an OpenAPI document, pgkiln takes for each `GET`, `POST`, `PUT`, `PATCH` and `DELETE` operation:
256
+
257
+ | From the document | Becomes |
258
+ |---|---|
259
+ | `operationId` (or the method and path) | The service's name, e.g. `listPets` → `LIST_PETS` |
260
+ | `servers[0].url` (variables at their defaults; Swagger 2: `schemes`, `host`, `basePath`) | The base URL. A relative one is read against the document's URL; or type the base URL |
261
+ | `path`, `query` and `header` parameters (also the path's own) | Parameters: `petId` → `pet_id`, with `"key": "petId"` when the service's name differs; a schema `default` (or an `example`) as the default |
262
+ | The scalar properties of a JSON request body | `body` parameters (nested objects and lists need a body template) |
263
+ | The JSON schema of the `200`/`201` (or `default`) response | The row selector (a list, or the list property of an object such as `items`, `data` or `results`) and the columns with their types (`integer`, `number`, `boolean`, `date`, `date-time` → `timestamp`, objects and lists → `json`) |
264
+ | A collection `GET /pets` with `GET`, `PUT`/`PATCH`, `DELETE /pets/{petId}` and `POST /pets` | Key columns and [write-back operations](#writing-back-from-forms-and-grids) on the collection's service, when the item's parameter names a column (`pet_id`, else `id`) |
265
+
266
+ `$ref`s inside the document and `allOf` are followed. What a data source can't use (cookie and form parameters, the
267
+ `Authorization` header, external `$ref`s, `HEAD` and `OPTIONS`) is listed after the import, never dropped silently.
268
+ YAML documents: convert them to JSON first (most services offer `openapi.json` too).
269
+
270
+ **Making a data source from a catalog**: an application's Shared Components → REST data sources → + Add shows *From a
271
+ REST source catalog* when the application's workspace has catalogs: pick a service, optionally another name and one
272
+ of the application's web credentials. The data source is a **copy** (URL = base URL + path): changing or deleting the
273
+ catalog later doesn't change it, and *Replace from a document* on a catalog's page replaces only the catalog's
274
+ services. Credentials never belong to a catalog: each application signs in with its own web credential.
275
+
276
+ Catalogs belong to the workspace (migration 095): they are not part of an application's export, but of the
277
+ [workspace export](03-builder.md#export-and-import).
278
+
241
279
  ## The `invoke_api` process
242
280
 
243
281
  A page process of type `invoke_api` ([chapter 6](06-processing.md#processes)) calls a web service.
@@ -0,0 +1,17 @@
1
+ -- =====================================================================
2
+ -- HR example, part 58: facet charts
3
+ -- (docs/guide/04-pages-and-regions.md, faceted search)
4
+ --
5
+ -- The faceted search on page 21 shows a bar chart of the jobs and a pie
6
+ -- chart of the salary ranges under their facets; a bar or a slice filters
7
+ -- the report on its value.
8
+ -- =====================================================================
9
+
10
+ update meta.region r
11
+ set config = jsonb_set(r.config, '{facets}', (
12
+ select jsonb_agg(case f->>'column' when 'job' then f || '{"chart": "bar"}'
13
+ when 'salary' then f || '{"chart": "pie"}'
14
+ else f end order by n)
15
+ from jsonb_array_elements(r.config->'facets') with ordinality x(f, n)))
16
+ from meta.page p join meta.app a on a.id = p.app_id
17
+ where p.id = r.page_id and a.alias = 'hr' and p.page_no = 21 and r.type = 'facets';