@weave-kit/engine 0.5.0 → 0.7.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.
- package/CHANGELOG.md +76 -0
- package/README.md +7 -7
- package/dist/adapters/auth/index.d.ts +4 -2
- package/dist/adapters/auth/index.d.ts.map +1 -1
- package/dist/adapters/auth/index.js +1 -0
- package/dist/adapters/auth/index.js.map +1 -1
- package/dist/adapters/auth/source.d.ts +4 -4
- package/dist/adapters/auth/source.d.ts.map +1 -1
- package/dist/adapters/auth/subject.d.ts +22 -0
- package/dist/adapters/auth/subject.d.ts.map +1 -0
- package/dist/adapters/auth/subject.js +42 -0
- package/dist/adapters/auth/subject.js.map +1 -0
- package/dist/adapters/auth/verify.d.ts +12 -0
- package/dist/adapters/auth/verify.d.ts.map +1 -0
- package/dist/adapters/auth/verify.js +2 -0
- package/dist/adapters/auth/verify.js.map +1 -0
- package/dist/adapters/events/index.d.ts +2 -1
- package/dist/adapters/events/index.d.ts.map +1 -1
- package/dist/adapters/events/index.js +2 -1
- package/dist/adapters/events/index.js.map +1 -1
- package/dist/adapters/mcp/generate.d.ts +3 -3
- package/dist/adapters/mcp/generate.d.ts.map +1 -1
- package/dist/adapters/mcp/generate.js +34 -11
- package/dist/adapters/mcp/generate.js.map +1 -1
- package/dist/adapters/mcp/guardrails.d.ts +1 -1
- package/dist/adapters/mcp/http.d.ts +3 -1
- package/dist/adapters/mcp/http.d.ts.map +1 -1
- package/dist/adapters/mcp/http.js +2 -2
- package/dist/adapters/mcp/http.js.map +1 -1
- package/dist/adapters/mcp/index.d.ts +13 -4
- package/dist/adapters/mcp/index.d.ts.map +1 -1
- package/dist/adapters/mcp/index.js +12 -8
- package/dist/adapters/mcp/index.js.map +1 -1
- package/dist/adapters/mcp/session.d.ts +5 -5
- package/dist/adapters/mcp/session.d.ts.map +1 -1
- package/dist/adapters/mcp/tools.d.ts +6 -0
- package/dist/adapters/mcp/tools.d.ts.map +1 -1
- package/dist/adapters/mcp/tools.js +38 -14
- package/dist/adapters/mcp/tools.js.map +1 -1
- package/dist/adapters/mcp/types.d.ts +3 -1
- package/dist/adapters/mcp/types.d.ts.map +1 -1
- package/dist/adapters/mcp/types.js +1 -1
- package/dist/adapters/mcp/types.js.map +1 -1
- package/dist/adapters/openapi/document.d.ts.map +1 -1
- package/dist/adapters/openapi/document.js +72 -2
- package/dist/adapters/openapi/document.js.map +1 -1
- package/dist/adapters/openapi/schema.d.ts.map +1 -1
- package/dist/adapters/openapi/schema.js +40 -4
- package/dist/adapters/openapi/schema.js.map +1 -1
- package/dist/adapters/openapi/types.d.ts +1 -0
- package/dist/adapters/openapi/types.d.ts.map +1 -1
- package/dist/adapters/openapi/types.js +2 -0
- package/dist/adapters/openapi/types.js.map +1 -1
- package/dist/adapters/rest/approvals.d.ts +2 -2
- package/dist/adapters/rest/approvals.js +2 -2
- package/dist/adapters/rest/audit.d.ts +2 -2
- package/dist/adapters/rest/audit.js +2 -2
- package/dist/adapters/rest/common.d.ts +3 -3
- package/dist/adapters/rest/common.d.ts.map +1 -1
- package/dist/adapters/rest/common.js +1 -1
- package/dist/adapters/rest/guardrails.d.ts +1 -1
- package/dist/adapters/rest/guardrails.js +1 -1
- package/dist/adapters/rest/identities.d.ts +4 -4
- package/dist/adapters/rest/identities.d.ts.map +1 -1
- package/dist/adapters/rest/identities.js +3 -3
- package/dist/adapters/rest/identities.js.map +1 -1
- package/dist/adapters/rest/identityAdmin.d.ts +18 -0
- package/dist/adapters/rest/identityAdmin.d.ts.map +1 -0
- package/dist/adapters/rest/identityAdmin.js +58 -0
- package/dist/adapters/rest/identityAdmin.js.map +1 -0
- package/dist/adapters/rest/index.d.ts +4 -0
- package/dist/adapters/rest/index.d.ts.map +1 -1
- package/dist/adapters/rest/index.js +3 -0
- package/dist/adapters/rest/index.js.map +1 -1
- package/dist/adapters/rest/metadata.d.ts +1 -1
- package/dist/adapters/rest/metadata.js +1 -1
- package/dist/adapters/rest/pages.d.ts +1 -1
- package/dist/adapters/rest/pages.d.ts.map +1 -1
- package/dist/adapters/rest/permissions.d.ts +1 -1
- package/dist/adapters/rest/permissions.js +1 -1
- package/dist/adapters/rest/plugin.d.ts +2 -2
- package/dist/adapters/rest/plugin.d.ts.map +1 -1
- package/dist/adapters/rest/schemas.d.ts +1 -1
- package/dist/adapters/rest/schemas.d.ts.map +1 -1
- package/dist/adapters/rest/workflow.d.ts +15 -0
- package/dist/adapters/rest/workflow.d.ts.map +1 -0
- package/dist/adapters/rest/workflow.js +89 -0
- package/dist/adapters/rest/workflow.js.map +1 -0
- package/dist/adapters/rest/workflowSource.d.ts +15 -0
- package/dist/adapters/rest/workflowSource.d.ts.map +1 -0
- package/dist/adapters/rest/workflowSource.js +63 -0
- package/dist/adapters/rest/workflowSource.js.map +1 -0
- package/dist/cli/commands/build.js +1 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/connect.d.ts +1 -1
- package/dist/cli/commands/default-view.d.ts +2 -2
- package/dist/cli/commands/default-view.js +2 -2
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +18 -9
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/identity.d.ts +15 -0
- package/dist/cli/commands/identity.d.ts.map +1 -0
- package/dist/cli/commands/identity.js +115 -0
- package/dist/cli/commands/identity.js.map +1 -0
- package/dist/cli/commands/introspect.d.ts.map +1 -1
- package/dist/cli/commands/introspect.js +23 -0
- package/dist/cli/commands/introspect.js.map +1 -1
- package/dist/cli/commands/mcp-config.js +1 -1
- package/dist/cli/commands/mcp-config.js.map +1 -1
- package/dist/cli/commands/migrate.js +2 -2
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/cli/commands/module.d.ts +2 -2
- package/dist/cli/commands/module.d.ts.map +1 -1
- package/dist/cli/commands/module.js +2 -2
- package/dist/cli/commands/module.js.map +1 -1
- package/dist/cli/commands/object-create.d.ts.map +1 -1
- package/dist/cli/commands/object-create.js +15 -15
- package/dist/cli/commands/object-create.js.map +1 -1
- package/dist/cli/commands/workflow-close.d.ts +9 -0
- package/dist/cli/commands/workflow-close.d.ts.map +1 -0
- package/dist/cli/commands/workflow-close.js +48 -0
- package/dist/cli/commands/workflow-close.js.map +1 -0
- package/dist/cli/commands/workflow-migrate.d.ts +11 -0
- package/dist/cli/commands/workflow-migrate.d.ts.map +1 -0
- package/dist/cli/commands/workflow-migrate.js +120 -0
- package/dist/cli/commands/workflow-migrate.js.map +1 -0
- package/dist/cli/commands/workflow-open.d.ts +10 -0
- package/dist/cli/commands/workflow-open.d.ts.map +1 -0
- package/dist/cli/commands/workflow-open.js +112 -0
- package/dist/cli/commands/workflow-open.js.map +1 -0
- package/dist/cli/commands/workflow-starter.d.ts +10 -0
- package/dist/cli/commands/workflow-starter.d.ts.map +1 -0
- package/dist/cli/commands/workflow-starter.js +29 -0
- package/dist/cli/commands/workflow-starter.js.map +1 -0
- package/dist/cli/commands/workflow-switch.d.ts +10 -0
- package/dist/cli/commands/workflow-switch.d.ts.map +1 -0
- package/dist/cli/commands/workflow-switch.js +60 -0
- package/dist/cli/commands/workflow-switch.js.map +1 -0
- package/dist/cli/commands/workflow-upgrade.d.ts +12 -0
- package/dist/cli/commands/workflow-upgrade.d.ts.map +1 -0
- package/dist/cli/commands/workflow-upgrade.js +116 -0
- package/dist/cli/commands/workflow-upgrade.js.map +1 -0
- package/dist/cli/index.js +72 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/project-types/manifest.d.ts +25 -0
- package/dist/cli/project-types/manifest.d.ts.map +1 -0
- package/dist/cli/project-types/manifest.js +40 -0
- package/dist/cli/project-types/manifest.js.map +1 -0
- package/dist/cli/ready-screen.js +1 -1
- package/dist/cli/ready-screen.js.map +1 -1
- package/dist/cli/scaffold.d.ts.map +1 -1
- package/dist/cli/scaffold.js +22 -34
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli/types/commands.d.ts +46 -0
- package/dist/cli/types/commands.d.ts.map +1 -1
- package/dist/cli/types/index.d.ts +1 -1
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/types/values.d.ts +9 -0
- package/dist/cli/types/values.d.ts.map +1 -1
- package/dist/cli/types/values.js +9 -0
- package/dist/cli/types/values.js.map +1 -1
- package/dist/core/api/error.d.ts.map +1 -1
- package/dist/core/api/error.js +7 -4
- package/dist/core/api/error.js.map +1 -1
- package/dist/core/audit/types.d.ts +4 -2
- package/dist/core/audit/types.d.ts.map +1 -1
- package/dist/core/audit/types.js +2 -0
- package/dist/core/audit/types.js.map +1 -1
- package/dist/core/formula/validate.d.ts.map +1 -1
- package/dist/core/formula/validate.js +6 -0
- package/dist/core/formula/validate.js.map +1 -1
- package/dist/core/i18n/ar.d.ts.map +1 -1
- package/dist/core/i18n/ar.js +38 -4
- package/dist/core/i18n/ar.js.map +1 -1
- package/dist/core/i18n/de.d.ts.map +1 -1
- package/dist/core/i18n/de.js +38 -4
- package/dist/core/i18n/de.js.map +1 -1
- package/dist/core/i18n/en.d.ts +39 -5
- package/dist/core/i18n/en.d.ts.map +1 -1
- package/dist/core/i18n/en.js +39 -5
- package/dist/core/i18n/en.js.map +1 -1
- package/dist/core/i18n/es.d.ts.map +1 -1
- package/dist/core/i18n/es.js +38 -4
- package/dist/core/i18n/es.js.map +1 -1
- package/dist/core/i18n/fr.d.ts.map +1 -1
- package/dist/core/i18n/fr.js +38 -4
- package/dist/core/i18n/fr.js.map +1 -1
- package/dist/core/i18n/hi.d.ts.map +1 -1
- package/dist/core/i18n/hi.js +38 -4
- package/dist/core/i18n/hi.js.map +1 -1
- package/dist/core/i18n/id.d.ts.map +1 -1
- package/dist/core/i18n/id.js +38 -4
- package/dist/core/i18n/id.js.map +1 -1
- package/dist/core/i18n/ja.d.ts.map +1 -1
- package/dist/core/i18n/ja.js +38 -4
- package/dist/core/i18n/ja.js.map +1 -1
- package/dist/core/i18n/ko.d.ts.map +1 -1
- package/dist/core/i18n/ko.js +38 -4
- package/dist/core/i18n/ko.js.map +1 -1
- package/dist/core/i18n/pt.d.ts.map +1 -1
- package/dist/core/i18n/pt.js +38 -4
- package/dist/core/i18n/pt.js.map +1 -1
- package/dist/core/i18n/ru.d.ts.map +1 -1
- package/dist/core/i18n/ru.js +38 -4
- package/dist/core/i18n/ru.js.map +1 -1
- package/dist/core/i18n/vi.d.ts.map +1 -1
- package/dist/core/i18n/vi.js +38 -4
- package/dist/core/i18n/vi.js.map +1 -1
- package/dist/core/i18n/zh-hant.d.ts.map +1 -1
- package/dist/core/i18n/zh-hant.js +38 -4
- package/dist/core/i18n/zh-hant.js.map +1 -1
- package/dist/core/i18n/zh.d.ts.map +1 -1
- package/dist/core/i18n/zh.js +39 -5
- package/dist/core/i18n/zh.js.map +1 -1
- package/dist/core/object/describe.d.ts +34 -3
- package/dist/core/object/describe.d.ts.map +1 -1
- package/dist/core/object/describe.js +48 -8
- package/dist/core/object/describe.js.map +1 -1
- package/dist/core/object/gen-types.d.ts.map +1 -1
- package/dist/core/object/gen-types.js +12 -1
- package/dist/core/object/gen-types.js.map +1 -1
- package/dist/core/object/graph.d.ts.map +1 -1
- package/dist/core/object/graph.js +52 -22
- package/dist/core/object/graph.js.map +1 -1
- package/dist/core/object/index.d.ts +5 -1
- package/dist/core/object/index.d.ts.map +1 -1
- package/dist/core/object/index.js +5 -1
- package/dist/core/object/index.js.map +1 -1
- package/dist/core/object/migrations.d.ts.map +1 -1
- package/dist/core/object/migrations.js +39 -0
- package/dist/core/object/migrations.js.map +1 -1
- package/dist/core/object/parse.d.ts +7 -0
- package/dist/core/object/parse.d.ts.map +1 -1
- package/dist/core/object/parse.js +32 -1
- package/dist/core/object/parse.js.map +1 -1
- package/dist/core/object/record-key.d.ts +19 -0
- package/dist/core/object/record-key.d.ts.map +1 -0
- package/dist/core/object/record-key.js +100 -0
- package/dist/core/object/record-key.js.map +1 -0
- package/dist/core/object/schema-version.d.ts +1 -1
- package/dist/core/object/schema-version.js +1 -1
- package/dist/core/object/system-objects.d.ts +16 -0
- package/dist/core/object/system-objects.d.ts.map +1 -0
- package/dist/core/object/system-objects.js +72 -0
- package/dist/core/object/system-objects.js.map +1 -0
- package/dist/core/object/validate/field.d.ts.map +1 -1
- package/dist/core/object/validate/field.js +235 -35
- package/dist/core/object/validate/field.js.map +1 -1
- package/dist/core/object/validate/formulas.d.ts.map +1 -1
- package/dist/core/object/validate/formulas.js +6 -0
- package/dist/core/object/validate/formulas.js.map +1 -1
- package/dist/core/object/validate/object.d.ts +2 -0
- package/dist/core/object/validate/object.d.ts.map +1 -1
- package/dist/core/object/validate/object.js +51 -19
- package/dist/core/object/validate/object.js.map +1 -1
- package/dist/core/object/validate/permissions.d.ts.map +1 -1
- package/dist/core/object/validate/permissions.js +4 -0
- package/dist/core/object/validate/permissions.js.map +1 -1
- package/dist/core/object/validate/primitives.d.ts +0 -1
- package/dist/core/object/validate/primitives.d.ts.map +1 -1
- package/dist/core/object/validate/primitives.js +1 -2
- package/dist/core/object/validate/primitives.js.map +1 -1
- package/dist/core/object/validate/workflow.d.ts +10 -0
- package/dist/core/object/validate/workflow.d.ts.map +1 -0
- package/dist/core/object/validate/workflow.js +143 -0
- package/dist/core/object/validate/workflow.js.map +1 -0
- package/dist/core/object/workflow-hash.d.ts +10 -0
- package/dist/core/object/workflow-hash.d.ts.map +1 -0
- package/dist/core/object/workflow-hash.js +27 -0
- package/dist/core/object/workflow-hash.js.map +1 -0
- package/dist/core/object/workflow-migrations.d.ts +27 -0
- package/dist/core/object/workflow-migrations.d.ts.map +1 -0
- package/dist/core/object/workflow-migrations.js +125 -0
- package/dist/core/object/workflow-migrations.js.map +1 -0
- package/dist/core/provider/event/index.d.ts +1 -1
- package/dist/core/provider/event/index.d.ts.map +1 -1
- package/dist/core/provider/event/index.js.map +1 -1
- package/dist/core/provider/event/types.d.ts +17 -2
- package/dist/core/provider/event/types.d.ts.map +1 -1
- package/dist/core/provider/event/types.js +2 -1
- package/dist/core/provider/event/types.js.map +1 -1
- package/dist/core/provider/identity/directory.d.ts +90 -0
- package/dist/core/provider/identity/directory.d.ts.map +1 -0
- package/dist/core/provider/identity/directory.js +3 -0
- package/dist/core/provider/identity/directory.js.map +1 -0
- package/dist/core/provider/identity/index.d.ts +5 -1
- package/dist/core/provider/identity/index.d.ts.map +1 -1
- package/dist/core/provider/identity/index.js +2 -1
- package/dist/core/provider/identity/index.js.map +1 -1
- package/dist/core/provider/identity/source.d.ts +22 -0
- package/dist/core/provider/identity/source.d.ts.map +1 -0
- package/dist/core/provider/identity/source.js +3 -0
- package/dist/core/provider/identity/source.js.map +1 -0
- package/dist/core/provider/identity/types.d.ts +62 -7
- package/dist/core/provider/identity/types.d.ts.map +1 -1
- package/dist/core/provider/identity/types.js +13 -0
- package/dist/core/provider/identity/types.js.map +1 -1
- package/dist/core/proxy/types.d.ts +4 -4
- package/dist/core/proxy/types.d.ts.map +1 -1
- package/dist/core/rbac/authorize.d.ts +10 -9
- package/dist/core/rbac/authorize.d.ts.map +1 -1
- package/dist/core/rbac/authorize.js +23 -18
- package/dist/core/rbac/authorize.js.map +1 -1
- package/dist/core/rbac/details.d.ts +33 -0
- package/dist/core/rbac/details.d.ts.map +1 -0
- package/dist/core/rbac/details.js +74 -0
- package/dist/core/rbac/details.js.map +1 -0
- package/dist/core/rbac/fields.d.ts +2 -1
- package/dist/core/rbac/fields.d.ts.map +1 -1
- package/dist/core/rbac/fields.js +3 -2
- package/dist/core/rbac/fields.js.map +1 -1
- package/dist/core/rbac/index.d.ts +3 -2
- package/dist/core/rbac/index.d.ts.map +1 -1
- package/dist/core/rbac/index.js +2 -1
- package/dist/core/rbac/index.js.map +1 -1
- package/dist/core/rbac/resolve.d.ts +3 -1
- package/dist/core/rbac/resolve.d.ts.map +1 -1
- package/dist/core/rbac/resolve.js +17 -9
- package/dist/core/rbac/resolve.js.map +1 -1
- package/dist/core/rbac/rls.d.ts +6 -0
- package/dist/core/rbac/rls.d.ts.map +1 -1
- package/dist/core/rbac/rls.js +52 -7
- package/dist/core/rbac/rls.js.map +1 -1
- package/dist/core/rbac/rowScope.d.ts +13 -6
- package/dist/core/rbac/rowScope.d.ts.map +1 -1
- package/dist/core/rbac/rowScope.js +88 -16
- package/dist/core/rbac/rowScope.js.map +1 -1
- package/dist/core/rbac/types.d.ts +6 -7
- package/dist/core/rbac/types.d.ts.map +1 -1
- package/dist/core/script/types.d.ts +1 -1
- package/dist/core/script/types.d.ts.map +1 -1
- package/dist/core/storage/diff.d.ts +4 -2
- package/dist/core/storage/diff.d.ts.map +1 -1
- package/dist/core/storage/diff.js +20 -17
- package/dist/core/storage/diff.js.map +1 -1
- package/dist/core/storage/index.d.ts +7 -1
- package/dist/core/storage/index.d.ts.map +1 -1
- package/dist/core/storage/index.js +6 -1
- package/dist/core/storage/index.js.map +1 -1
- package/dist/core/storage/inspect.d.ts +12 -3
- package/dist/core/storage/inspect.d.ts.map +1 -1
- package/dist/core/storage/inspect.js +39 -22
- package/dist/core/storage/inspect.js.map +1 -1
- package/dist/core/storage/introspect.d.ts +9 -2
- package/dist/core/storage/introspect.d.ts.map +1 -1
- package/dist/core/storage/introspect.js +100 -43
- package/dist/core/storage/introspect.js.map +1 -1
- package/dist/core/storage/link-table.d.ts +47 -0
- package/dist/core/storage/link-table.d.ts.map +1 -0
- package/dist/core/storage/link-table.js +110 -0
- package/dist/core/storage/link-table.js.map +1 -0
- package/dist/core/storage/map.d.ts.map +1 -1
- package/dist/core/storage/map.js +135 -81
- package/dist/core/storage/map.js.map +1 -1
- package/dist/core/storage/meta.d.ts +6 -3
- package/dist/core/storage/meta.d.ts.map +1 -1
- package/dist/core/storage/meta.js +9 -5
- package/dist/core/storage/meta.js.map +1 -1
- package/dist/core/storage/migrate.d.ts.map +1 -1
- package/dist/core/storage/migrate.js +144 -11
- package/dist/core/storage/migrate.js.map +1 -1
- package/dist/core/storage/record-key-sql.d.ts +19 -0
- package/dist/core/storage/record-key-sql.d.ts.map +1 -0
- package/dist/core/storage/record-key-sql.js +43 -0
- package/dist/core/storage/record-key-sql.js.map +1 -0
- package/dist/core/storage/record-meta.d.ts +68 -0
- package/dist/core/storage/record-meta.d.ts.map +1 -0
- package/dist/core/storage/record-meta.js +108 -0
- package/dist/core/storage/record-meta.js.map +1 -0
- package/dist/core/storage/report.d.ts.map +1 -1
- package/dist/core/storage/report.js +17 -7
- package/dist/core/storage/report.js.map +1 -1
- package/dist/core/storage/sql-literals.d.ts +9 -0
- package/dist/core/storage/sql-literals.d.ts.map +1 -0
- package/dist/core/storage/sql-literals.js +13 -0
- package/dist/core/storage/sql-literals.js.map +1 -0
- package/dist/core/storage/system-tables.d.ts +44 -0
- package/dist/core/storage/system-tables.d.ts.map +1 -0
- package/dist/core/storage/system-tables.js +268 -0
- package/dist/core/storage/system-tables.js.map +1 -0
- package/dist/core/tools/policies.d.ts +2 -2
- package/dist/core/tools/policies.js +2 -2
- package/dist/core/tools/types.d.ts +6 -6
- package/dist/core/tools/types.d.ts.map +1 -1
- package/dist/core/tools/values.d.ts +5 -0
- package/dist/core/tools/values.d.ts.map +1 -1
- package/dist/core/tools/values.js +9 -1
- package/dist/core/tools/values.js.map +1 -1
- package/dist/core/types/currency.d.ts +9 -0
- package/dist/core/types/currency.d.ts.map +1 -0
- package/dist/core/types/currency.js +28 -0
- package/dist/core/types/currency.js.map +1 -0
- package/dist/core/types/field-type.d.ts +4 -1
- package/dist/core/types/field-type.d.ts.map +1 -1
- package/dist/core/types/fields.d.ts +105 -19
- package/dist/core/types/fields.d.ts.map +1 -1
- package/dist/core/types/index.d.ts +8 -6
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js +4 -3
- package/dist/core/types/index.js.map +1 -1
- package/dist/core/types/object.d.ts +18 -1
- package/dist/core/types/object.d.ts.map +1 -1
- package/dist/core/types/permission.d.ts +5 -0
- package/dist/core/types/permission.d.ts.map +1 -1
- package/dist/core/types/primaryField.d.ts +6 -1
- package/dist/core/types/primaryField.d.ts.map +1 -1
- package/dist/core/types/primaryField.js +8 -1
- package/dist/core/types/primaryField.js.map +1 -1
- package/dist/core/types/registry.d.ts +6 -4
- package/dist/core/types/registry.d.ts.map +1 -1
- package/dist/core/types/registry.js +40 -30
- package/dist/core/types/registry.js.map +1 -1
- package/dist/core/types/values.d.ts +97 -27
- package/dist/core/types/values.d.ts.map +1 -1
- package/dist/core/types/values.js +64 -29
- package/dist/core/types/values.js.map +1 -1
- package/dist/core/types/workflow.d.ts +140 -0
- package/dist/core/types/workflow.d.ts.map +1 -0
- package/dist/core/types/workflow.js +49 -0
- package/dist/core/types/workflow.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/event/bus.d.ts.map +1 -1
- package/dist/infrastructure/event/bus.js +14 -0
- package/dist/infrastructure/event/bus.js.map +1 -1
- package/dist/infrastructure/identity.d.ts +2 -2
- package/dist/infrastructure/identity.d.ts.map +1 -1
- package/dist/infrastructure/identity.js.map +1 -1
- package/dist/layout-format.d.ts +6 -6
- package/dist/layout-format.js +4 -4
- package/dist/runtime/data-access/builder.d.ts +15 -5
- package/dist/runtime/data-access/builder.d.ts.map +1 -1
- package/dist/runtime/data-access/builder.js +222 -30
- package/dist/runtime/data-access/builder.js.map +1 -1
- package/dist/runtime/data-access/details.d.ts.map +1 -1
- package/dist/runtime/data-access/details.js +7 -2
- package/dist/runtime/data-access/details.js.map +1 -1
- package/dist/runtime/data-access/formula.d.ts +11 -3
- package/dist/runtime/data-access/formula.d.ts.map +1 -1
- package/dist/runtime/data-access/formula.js +82 -19
- package/dist/runtime/data-access/formula.js.map +1 -1
- package/dist/runtime/data-access/index.d.ts +1 -1
- package/dist/runtime/data-access/index.d.ts.map +1 -1
- package/dist/runtime/data-access/index.js +1 -1
- package/dist/runtime/data-access/index.js.map +1 -1
- package/dist/runtime/data-access/link.d.ts +7 -0
- package/dist/runtime/data-access/link.d.ts.map +1 -0
- package/dist/runtime/data-access/link.js +80 -0
- package/dist/runtime/data-access/link.js.map +1 -0
- package/dist/runtime/data-access/query.d.ts +48 -3
- package/dist/runtime/data-access/query.d.ts.map +1 -1
- package/dist/runtime/data-access/query.js +381 -45
- package/dist/runtime/data-access/query.js.map +1 -1
- package/dist/runtime/data-access/rbac.d.ts.map +1 -1
- package/dist/runtime/data-access/rbac.js +134 -16
- package/dist/runtime/data-access/rbac.js.map +1 -1
- package/dist/runtime/data-access/seqno.d.ts +0 -2
- package/dist/runtime/data-access/seqno.d.ts.map +1 -1
- package/dist/runtime/data-access/seqno.js +0 -9
- package/dist/runtime/data-access/seqno.js.map +1 -1
- package/dist/runtime/data-access/sql-executor.d.ts +13 -3
- package/dist/runtime/data-access/sql-executor.d.ts.map +1 -1
- package/dist/runtime/data-access/sql-executor.js +20 -14
- package/dist/runtime/data-access/sql-executor.js.map +1 -1
- package/dist/runtime/data-access/sql-gate.d.ts +4 -4
- package/dist/runtime/data-access/sql-gate.d.ts.map +1 -1
- package/dist/runtime/data-access/sql-gate.js +5 -5
- package/dist/runtime/data-access/sql-gate.js.map +1 -1
- package/dist/runtime/data-access/tx.d.ts +1 -1
- package/dist/runtime/data-access/tx.js +1 -1
- package/dist/runtime/data-access/types.d.ts +31 -3
- package/dist/runtime/data-access/types.d.ts.map +1 -1
- package/dist/runtime/data-access/validate.d.ts.map +1 -1
- package/dist/runtime/data-access/validate.js +79 -15
- package/dist/runtime/data-access/validate.js.map +1 -1
- package/dist/runtime/data-access/workflow.d.ts +146 -0
- package/dist/runtime/data-access/workflow.d.ts.map +1 -0
- package/dist/runtime/data-access/workflow.js +636 -0
- package/dist/runtime/data-access/workflow.js.map +1 -0
- package/dist/runtime/engine.d.ts +89 -14
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +123 -26
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/fieldtypes/loader.d.ts.map +1 -1
- package/dist/runtime/fieldtypes/loader.js +12 -1
- package/dist/runtime/fieldtypes/loader.js.map +1 -1
- package/dist/runtime/git/guardrailSource.d.ts +1 -1
- package/dist/runtime/git/index.d.ts +4 -2
- package/dist/runtime/git/index.d.ts.map +1 -1
- package/dist/runtime/git/index.js +2 -1
- package/dist/runtime/git/index.js.map +1 -1
- package/dist/runtime/git/layoutSource.d.ts +1 -1
- package/dist/runtime/git/loader.d.ts.map +1 -1
- package/dist/runtime/git/loader.js +18 -6
- package/dist/runtime/git/loader.js.map +1 -1
- package/dist/runtime/git/pageCatalog.d.ts +1 -1
- package/dist/runtime/git/schemaChange.d.ts +22 -0
- package/dist/runtime/git/schemaChange.d.ts.map +1 -1
- package/dist/runtime/git/schemaChange.js +28 -2
- package/dist/runtime/git/schemaChange.js.map +1 -1
- package/dist/runtime/git/schemaSource.d.ts +1 -1
- package/dist/runtime/git/sourceFile.d.ts +1 -1
- package/dist/runtime/git/sourceFile.js +1 -1
- package/dist/runtime/git/sourceTransaction.d.ts +1 -1
- package/dist/runtime/git/workflowSource.d.ts +40 -0
- package/dist/runtime/git/workflowSource.d.ts.map +1 -0
- package/dist/runtime/git/workflowSource.js +45 -0
- package/dist/runtime/git/workflowSource.js.map +1 -0
- package/dist/runtime/identity/admin.d.ts +18 -0
- package/dist/runtime/identity/admin.d.ts.map +1 -0
- package/dist/runtime/identity/admin.js +27 -0
- package/dist/runtime/identity/admin.js.map +1 -0
- package/dist/runtime/identity/directory.d.ts +12 -0
- package/dist/runtime/identity/directory.d.ts.map +1 -0
- package/dist/runtime/identity/directory.js +22 -0
- package/dist/runtime/identity/directory.js.map +1 -0
- package/dist/runtime/identity/index.d.ts +11 -0
- package/dist/runtime/identity/index.d.ts.map +1 -0
- package/dist/runtime/identity/index.js +8 -0
- package/dist/runtime/identity/index.js.map +1 -0
- package/dist/runtime/identity/resolve.d.ts +10 -0
- package/dist/runtime/identity/resolve.d.ts.map +1 -0
- package/dist/runtime/identity/resolve.js +16 -0
- package/dist/runtime/identity/resolve.js.map +1 -0
- package/dist/runtime/identity/sources/function.d.ts +10 -0
- package/dist/runtime/identity/sources/function.d.ts.map +1 -0
- package/dist/runtime/identity/sources/function.js +9 -0
- package/dist/runtime/identity/sources/function.js.map +1 -0
- package/dist/runtime/identity/sources/pg.d.ts +42 -0
- package/dist/runtime/identity/sources/pg.d.ts.map +1 -0
- package/dist/runtime/identity/sources/pg.js +121 -0
- package/dist/runtime/identity/sources/pg.js.map +1 -0
- package/dist/runtime/identity/store.d.ts +27 -0
- package/dist/runtime/identity/store.d.ts.map +1 -0
- package/dist/runtime/identity/store.js +139 -0
- package/dist/runtime/identity/store.js.map +1 -0
- package/dist/runtime/identity/sync.d.ts +34 -0
- package/dist/runtime/identity/sync.d.ts.map +1 -0
- package/dist/runtime/identity/sync.js +149 -0
- package/dist/runtime/identity/sync.js.map +1 -0
- package/dist/runtime/metadata/cache.d.ts +0 -2
- package/dist/runtime/metadata/cache.d.ts.map +1 -1
- package/dist/runtime/metadata/cache.js +0 -11
- package/dist/runtime/metadata/cache.js.map +1 -1
- package/dist/runtime/metadata/index.d.ts +1 -1
- package/dist/runtime/metadata/index.d.ts.map +1 -1
- package/dist/runtime/metadata/index.js +1 -1
- package/dist/runtime/metadata/index.js.map +1 -1
- package/dist/runtime/record-meta/index.d.ts +2 -0
- package/dist/runtime/record-meta/index.d.ts.map +1 -0
- package/dist/runtime/record-meta/index.js +2 -0
- package/dist/runtime/record-meta/index.js.map +1 -0
- package/dist/runtime/record-meta/store.d.ts +43 -0
- package/dist/runtime/record-meta/store.d.ts.map +1 -0
- package/dist/runtime/record-meta/store.js +88 -0
- package/dist/runtime/record-meta/store.js.map +1 -0
- package/dist/runtime/sql-analyzer/index.d.ts.map +1 -1
- package/dist/runtime/sql-analyzer/index.js +59 -0
- package/dist/runtime/sql-analyzer/index.js.map +1 -1
- package/dist/runtime/tools/executor.d.ts +11 -11
- package/dist/runtime/tools/executor.d.ts.map +1 -1
- package/dist/runtime/tools/executor.js +6 -6
- package/dist/runtime/tools/executor.js.map +1 -1
- package/dist/runtime/tools/index.d.ts +2 -0
- package/dist/runtime/tools/index.d.ts.map +1 -1
- package/dist/runtime/tools/index.js +1 -0
- package/dist/runtime/tools/index.js.map +1 -1
- package/dist/runtime/tools/policies.d.ts +22 -5
- package/dist/runtime/tools/policies.d.ts.map +1 -1
- package/dist/runtime/tools/policies.js +42 -12
- package/dist/runtime/tools/policies.js.map +1 -1
- package/dist/runtime/tunnel/connector.d.ts +1 -1
- package/dist/runtime/tunnel/forwarder.js +1 -1
- package/dist/runtime/tunnel/framing.d.ts +1 -1
- package/dist/runtime/tunnel/server.d.ts +1 -1
- package/dist/subsystems/approvals/index.d.ts +4 -4
- package/dist/subsystems/approvals/index.d.ts.map +1 -1
- package/dist/subsystems/approvals/index.js +5 -6
- package/dist/subsystems/approvals/index.js.map +1 -1
- package/dist/subsystems/approvals/store.d.ts +1 -3
- package/dist/subsystems/approvals/store.d.ts.map +1 -1
- package/dist/subsystems/approvals/store.js +1 -16
- package/dist/subsystems/approvals/store.js.map +1 -1
- package/dist/subsystems/audit/index.d.ts +1 -1
- package/dist/subsystems/audit/index.d.ts.map +1 -1
- package/dist/subsystems/audit/index.js +2 -3
- package/dist/subsystems/audit/index.js.map +1 -1
- package/dist/subsystems/audit/store.d.ts +0 -2
- package/dist/subsystems/audit/store.d.ts.map +1 -1
- package/dist/subsystems/audit/store.js +0 -21
- package/dist/subsystems/audit/store.js.map +1 -1
- package/dist/subsystems/quota/store.d.ts +9 -0
- package/dist/subsystems/quota/store.d.ts.map +1 -1
- package/dist/subsystems/quota/store.js +0 -8
- package/dist/subsystems/quota/store.js.map +1 -1
- package/dist/subsystems/script/backend/isolated-vm.js +4 -4
- package/dist/subsystems/script/backend/types.d.ts +2 -2
- package/dist/subsystems/script/backend/types.d.ts.map +1 -1
- package/dist/subsystems/script/bridge.d.ts +1 -1
- package/dist/subsystems/script/bridge.d.ts.map +1 -1
- package/dist/subsystems/script/bridge.js +6 -4
- package/dist/subsystems/script/bridge.js.map +1 -1
- package/dist/subsystems/script/dispatcher.d.ts.map +1 -1
- package/dist/subsystems/script/dispatcher.js +3 -1
- package/dist/subsystems/script/dispatcher.js.map +1 -1
- package/dist/subsystems/workflow/index.d.ts +4 -0
- package/dist/subsystems/workflow/index.d.ts.map +1 -0
- package/dist/subsystems/workflow/index.js +3 -0
- package/dist/subsystems/workflow/index.js.map +1 -0
- package/dist/subsystems/workflow/scheduler.d.ts +27 -0
- package/dist/subsystems/workflow/scheduler.d.ts.map +1 -0
- package/dist/subsystems/workflow/scheduler.js +109 -0
- package/dist/subsystems/workflow/scheduler.js.map +1 -0
- package/dist/subsystems/workflow/store.d.ts +10 -0
- package/dist/subsystems/workflow/store.d.ts.map +1 -0
- package/dist/subsystems/workflow/store.js +44 -0
- package/dist/subsystems/workflow/store.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +9 -5
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import { SchemaError,
|
|
2
|
-
import { DETAILS_COLUMNS, FIELD_TYPES } from '../../core/index.js';
|
|
1
|
+
import { SchemaError, primaryFieldsOf, encodeRecordKey, decodeRecordKey, canonicalizePrimaryValue } from '../../core/index.js';
|
|
2
|
+
import { DETAILS_COLUMNS, FIELD_TYPES, isSideTableVirtualField, RECORD_META_ID_FIELD, recordKeySql, recordMetaTableName } from '../../core/index.js';
|
|
3
3
|
import { AUDIT_ACTOR_TYPES, DATA_ACTIONS } from '../../core/audit/index.js';
|
|
4
4
|
import { NOOP_SCRIPT_DISPATCHER, SCRIPT_HOOKS } from '../../core/index.js';
|
|
5
|
+
import { evaluateTransition } from '../tools/policies.js';
|
|
5
6
|
import { buildCountSql, buildFindSql, scopeSuffix } from './builder.js';
|
|
6
7
|
import { deleteDetailsChildren, insertDetails } from './details.js';
|
|
8
|
+
import { insertLinks, replaceLinks } from './link.js';
|
|
9
|
+
import { runWorkflowTransition, getWorkflowStatus, acquireWorkflowLock, releaseWorkflowLock, getWorkflowHistory, getWorkflowTodos, overrideWorkflow, } from './workflow.js';
|
|
7
10
|
import { computeFormulas } from './formula.js';
|
|
8
|
-
import {
|
|
11
|
+
import { generateSeqNo } from './seqno.js';
|
|
9
12
|
import { validateRecord } from './validate.js';
|
|
10
13
|
import { WRITE_MODES } from './values.js';
|
|
14
|
+
import { upsertRecordMeta, deleteRecordMeta } from '../record-meta/index.js';
|
|
11
15
|
const q = (id) => `"${id}"`;
|
|
16
|
+
/** cross-object formula authorization derived from the request context */
|
|
17
|
+
function formulaAuth(ctx) {
|
|
18
|
+
return { subject: ctx.subject, roles: ctx.subject?.roles ?? [], locale: ctx.locale };
|
|
19
|
+
}
|
|
12
20
|
/** PG error 42703 = undefined_column: a query referenced a column that doesn't exist */
|
|
13
21
|
function isUndefinedColumn(error) {
|
|
14
22
|
return typeof error === 'object' && error !== null && error.code === '42703';
|
|
@@ -82,7 +90,7 @@ function scriptUserOf(ctx) {
|
|
|
82
90
|
return {
|
|
83
91
|
id: ctx.subject?.id ?? 'system',
|
|
84
92
|
roles: ctx.subject?.roles ?? [],
|
|
85
|
-
|
|
93
|
+
departmentId: ctx.subject?.departmentId,
|
|
86
94
|
};
|
|
87
95
|
}
|
|
88
96
|
const PARENT_COLUMNS = new Set([
|
|
@@ -102,7 +110,99 @@ function requireDef(ctx, objectName) {
|
|
|
102
110
|
return def;
|
|
103
111
|
}
|
|
104
112
|
function bctx(ctx, objectName) {
|
|
105
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
object: objectName,
|
|
115
|
+
locale: ctx.locale,
|
|
116
|
+
allowParentCols: isDetailsChild(ctx.registry, objectName),
|
|
117
|
+
lookup: ctx.registry,
|
|
118
|
+
...(ctx.subject === undefined ? {} : { subject: ctx.subject }),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** hidden select column carrying the SQL-computed record_key for a fetched row */
|
|
122
|
+
const META_KEY_COL = '__weave_record_key';
|
|
123
|
+
/** select expression for the SQL-computed record_key (lossless for temporal keys) */
|
|
124
|
+
function recordKeySelect(def) {
|
|
125
|
+
return `${recordKeySql(def, (name) => q(name))} AS ${q(META_KEY_COL)}`;
|
|
126
|
+
}
|
|
127
|
+
/** the record_key of a row, from its declared primary fields (declaration order) */
|
|
128
|
+
function recordKeyOfRow(def, record) {
|
|
129
|
+
return encodeRecordKey(primaryFieldsOf(def).map((f) => canonicalizePrimaryValue(record[f.name])));
|
|
130
|
+
}
|
|
131
|
+
/** declared primary field names, in declaration order */
|
|
132
|
+
function primaryNames(def) {
|
|
133
|
+
return primaryFieldsOf(def).map((f) => f.name);
|
|
134
|
+
}
|
|
135
|
+
/** decode an external id (the record_key, for single and composite keys alike) into primary values */
|
|
136
|
+
function pkValuesOf(def, id, ctx) {
|
|
137
|
+
const names = primaryNames(def);
|
|
138
|
+
let values;
|
|
139
|
+
try {
|
|
140
|
+
values = decodeRecordKey(id);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
throw new SchemaError('recordKey.invalid', { key: id }, ctx.locale);
|
|
144
|
+
}
|
|
145
|
+
if (values.length !== names.length) {
|
|
146
|
+
throw new SchemaError('recordKey.invalid', { key: id }, ctx.locale);
|
|
147
|
+
}
|
|
148
|
+
return values;
|
|
149
|
+
}
|
|
150
|
+
/** primary-key filter object for `find` (declared names zipped with values) */
|
|
151
|
+
function pkFilter(def, values) {
|
|
152
|
+
const filter = {};
|
|
153
|
+
primaryNames(def).forEach((name, i) => {
|
|
154
|
+
filter[name] = values[i];
|
|
155
|
+
});
|
|
156
|
+
return filter;
|
|
157
|
+
}
|
|
158
|
+
/** `"a" = $1 AND "b" = $2` predicate for the primary names, starting at `startIndex` */
|
|
159
|
+
function pkWhereSql(def, startIndex) {
|
|
160
|
+
return primaryNames(def)
|
|
161
|
+
.map((name, i) => `${q(name)} = $${startIndex + i}`)
|
|
162
|
+
.join(' AND ');
|
|
163
|
+
}
|
|
164
|
+
/** the external id of a record: always its record_key (single and composite keys alike) */
|
|
165
|
+
function externalIdOf(def, record) {
|
|
166
|
+
return recordKeyOfRow(def, record);
|
|
167
|
+
}
|
|
168
|
+
/** true when the query references a side-table virtual field (`weave_*` minus the derived `weave_id`) */
|
|
169
|
+
function needsSideTable(opts) {
|
|
170
|
+
if ((opts.fields ?? []).some((f) => isSideTableVirtualField(f)))
|
|
171
|
+
return true;
|
|
172
|
+
if ((opts.sort ?? []).some((s) => isSideTableVirtualField(s.field)))
|
|
173
|
+
return true;
|
|
174
|
+
const filter = opts.filter;
|
|
175
|
+
if (filter !== undefined) {
|
|
176
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
177
|
+
if (key === '$or') {
|
|
178
|
+
if (Array.isArray(value) &&
|
|
179
|
+
value.some((group) => group !== null &&
|
|
180
|
+
typeof group === 'object' &&
|
|
181
|
+
Object.keys(group).some((k) => isSideTableVirtualField(k)))) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else if (isSideTableVirtualField(key)) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Narrow `ToolDataAccess` over this data-access for guardrail policies: a policy
|
|
194
|
+
* calls `ctx.dataAccess.find(obj, opts, { subject? })` with no pool/registry, so
|
|
195
|
+
* those are injected from the execution context (mirrors the tool executor's
|
|
196
|
+
* wrapper; `...c` lets a policy override the subject per call).
|
|
197
|
+
*/
|
|
198
|
+
function toolDataAccessOver(inner, base) {
|
|
199
|
+
return {
|
|
200
|
+
find: (n, o, c) => inner.find(n, o, { ...base, ...c }),
|
|
201
|
+
findOne: (n, id, c) => inner.findOne(n, id, { ...base, ...c }),
|
|
202
|
+
create: (n, d, c) => inner.create(n, d, { ...base, ...c }),
|
|
203
|
+
update: (n, id, changes, c) => inner.update(n, id, changes, { ...base, ...c }),
|
|
204
|
+
delete: (n, id, c) => inner.delete(n, id, { ...base, ...c }),
|
|
205
|
+
};
|
|
106
206
|
}
|
|
107
207
|
/**
|
|
108
208
|
* Serialize a value for binding to a DB column. pg (node-postgres) auto-stringifies
|
|
@@ -111,7 +211,10 @@ function bctx(ctx, objectName) {
|
|
|
111
211
|
* (arrays/objects/numbers/booleans) to valid JSON text. `null` stays SQL NULL.
|
|
112
212
|
*/
|
|
113
213
|
function dbJsonValue(field, value) {
|
|
114
|
-
if (field !== undefined &&
|
|
214
|
+
if (field !== undefined &&
|
|
215
|
+
(field.type === FIELD_TYPES.JSON || field.type === FIELD_TYPES.JSONB) &&
|
|
216
|
+
value !== null &&
|
|
217
|
+
typeof value !== 'string') {
|
|
115
218
|
return JSON.stringify(value);
|
|
116
219
|
}
|
|
117
220
|
return value;
|
|
@@ -120,17 +223,26 @@ function dbJsonValue(field, value) {
|
|
|
120
223
|
export class DefaultObjectDataAccess {
|
|
121
224
|
audit;
|
|
122
225
|
script;
|
|
123
|
-
/**
|
|
226
|
+
/** audit diff replay: attach before/after row snapshots to update/delete audit events */
|
|
124
227
|
replay;
|
|
125
|
-
/**
|
|
228
|
+
/** live events: publish committed writes to the bus (undefined = zero overhead) */
|
|
126
229
|
events;
|
|
127
230
|
/** objects currently dispatching onLoad — skips re-entrant onLoad (a hook re-reading the same object) */
|
|
128
231
|
onLoadInFlight = new Set();
|
|
232
|
+
/** guardrail policies shared with the open-contract (empty = no policy gate on transitions) */
|
|
233
|
+
policies;
|
|
234
|
+
/** approval queue used when a policy or a transition requires approval */
|
|
235
|
+
approvals;
|
|
236
|
+
/** workflow timer handle: re-arm/cancel a record's `onTimeout` on state changes */
|
|
237
|
+
workflowTimers;
|
|
129
238
|
constructor(options = {}) {
|
|
130
239
|
this.audit = options.audit;
|
|
131
240
|
this.script = options.script ?? NOOP_SCRIPT_DISPATCHER;
|
|
132
241
|
this.replay = options.replay ?? false;
|
|
133
242
|
this.events = options.events;
|
|
243
|
+
this.policies = options.policies ?? [];
|
|
244
|
+
this.approvals = options.approvals;
|
|
245
|
+
this.workflowTimers = options.workflowTimers;
|
|
134
246
|
}
|
|
135
247
|
/**
|
|
136
248
|
* Run the read hook (`onLoad`) over a fetched batch. The hook receives the
|
|
@@ -168,13 +280,14 @@ export class DefaultObjectDataAccess {
|
|
|
168
280
|
* hook failure → the surrounding transaction rolls back. Returns the
|
|
169
281
|
* possibly-modified changes from beforeUpdate (undefined = keep original).
|
|
170
282
|
*/
|
|
171
|
-
async runBeforeHook(hook, objectName, record, changes, ctx) {
|
|
283
|
+
async runBeforeHook(hook, objectName, record, changes, ctx, extra) {
|
|
172
284
|
if (!this.script.has(objectName, hook))
|
|
173
285
|
return undefined;
|
|
174
286
|
const result = await this.script.dispatch(objectName, hook, {
|
|
175
287
|
record,
|
|
176
288
|
changes,
|
|
177
289
|
user: scriptUserOf(ctx),
|
|
290
|
+
...(extra ?? {}),
|
|
178
291
|
});
|
|
179
292
|
return result.changes;
|
|
180
293
|
}
|
|
@@ -183,7 +296,7 @@ export class DefaultObjectDataAccess {
|
|
|
183
296
|
* committed, so a hook failure is a non-fatal warning: recorded to audit and
|
|
184
297
|
* delivered via `ctx.onWarnings`, never rethrown.
|
|
185
298
|
*/
|
|
186
|
-
async runAfterHook(hook, action, objectName, record, changes, ctx, warnings, objectId) {
|
|
299
|
+
async runAfterHook(hook, action, objectName, record, changes, ctx, warnings, objectId, extra) {
|
|
187
300
|
if (!this.script.has(objectName, hook))
|
|
188
301
|
return;
|
|
189
302
|
try {
|
|
@@ -191,6 +304,7 @@ export class DefaultObjectDataAccess {
|
|
|
191
304
|
record,
|
|
192
305
|
changes,
|
|
193
306
|
user: scriptUserOf(ctx),
|
|
307
|
+
...(extra ?? {}),
|
|
194
308
|
});
|
|
195
309
|
}
|
|
196
310
|
catch (error) {
|
|
@@ -207,26 +321,33 @@ export class DefaultObjectDataAccess {
|
|
|
207
321
|
async find(objectName, opts, ctx) {
|
|
208
322
|
const def = requireDef(ctx, objectName);
|
|
209
323
|
const q = ctx.client ?? ctx.pool;
|
|
210
|
-
|
|
324
|
+
// `weave_*` virtual fields live in the engine side table; when referenced,
|
|
325
|
+
// LEFT JOIN it and select/filter/sort them in SQL (never customer columns)
|
|
326
|
+
const meta = needsSideTable(opts) ? { table: recordMetaTableName(def.name) } : undefined;
|
|
327
|
+
const buildCtx = { ...bctx(ctx, objectName), ...(meta === undefined ? {} : { meta }) };
|
|
328
|
+
const { sql, params } = buildFindSql(def, opts, buildCtx, ctx.rowScope, opts.exclude);
|
|
211
329
|
const { rows } = await runTableQuery(q, objectName, sql, params, ctx.locale);
|
|
212
|
-
const { sql: countSql, params: countParams } = buildCountSql(def, opts,
|
|
330
|
+
const { sql: countSql, params: countParams } = buildCountSql(def, opts, buildCtx, ctx.rowScope);
|
|
213
331
|
const { rows: countRows } = await runTableQuery(q, objectName, countSql, countParams, ctx.locale);
|
|
214
332
|
const loaded = await this.runOnLoad(objectName, rows, ctx);
|
|
215
333
|
return { rows: loaded, total: countRows[0].total };
|
|
216
334
|
}
|
|
217
335
|
async findOne(objectName, id, ctx) {
|
|
218
336
|
const def = requireDef(ctx, objectName);
|
|
219
|
-
|
|
220
|
-
if (pk === undefined) {
|
|
337
|
+
if (primaryNames(def).length === 0) {
|
|
221
338
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
222
339
|
}
|
|
223
|
-
|
|
340
|
+
// project every declared column plus the derived `weave_id` (the record's
|
|
341
|
+
// external id) so a fetched record is self-identifying
|
|
342
|
+
const cols = def.fields.filter((f) => f.type !== FIELD_TYPES.DETAILS).map((f) => f.name);
|
|
343
|
+
if (isDetailsChild(ctx.registry, objectName))
|
|
344
|
+
cols.push(...PARENT_COLUMNS);
|
|
345
|
+
const result = await this.find(objectName, { filter: pkFilter(def, pkValuesOf(def, id, ctx)), limit: 1, fields: [...cols, RECORD_META_ID_FIELD] }, ctx);
|
|
224
346
|
return result.rows[0] ?? null;
|
|
225
347
|
}
|
|
226
348
|
async create(objectName, data, ctx) {
|
|
227
349
|
const def = requireDef(ctx, objectName);
|
|
228
|
-
|
|
229
|
-
if (pk === undefined) {
|
|
350
|
+
if (primaryNames(def).length === 0) {
|
|
230
351
|
throw new SchemaError('data.recordNotFound', { object: objectName }, ctx.locale);
|
|
231
352
|
}
|
|
232
353
|
let client;
|
|
@@ -261,14 +382,16 @@ export class DefaultObjectDataAccess {
|
|
|
261
382
|
if (payload[field.name] !== undefined)
|
|
262
383
|
continue;
|
|
263
384
|
record[field.name] =
|
|
264
|
-
(field.type === FIELD_TYPES.
|
|
385
|
+
(field.type === FIELD_TYPES.DATE ||
|
|
386
|
+
field.type === FIELD_TYPES.TIMESTAMP ||
|
|
387
|
+
field.type === FIELD_TYPES.TIMESTAMPTZ) &&
|
|
388
|
+
raw.default === 'now'
|
|
265
389
|
? now.toISOString()
|
|
266
390
|
: raw.default;
|
|
267
391
|
}
|
|
268
392
|
Object.assign(record, payload);
|
|
269
393
|
const seqFields = def.fields.filter((f) => f.type === FIELD_TYPES.SEQ_NO);
|
|
270
394
|
if (seqFields.length > 0) {
|
|
271
|
-
await ensureSeqTable(client);
|
|
272
395
|
for (const f of seqFields)
|
|
273
396
|
record[f.name] = await generateSeqNo(client, def.name, f, now);
|
|
274
397
|
}
|
|
@@ -279,29 +402,37 @@ export class DefaultObjectDataAccess {
|
|
|
279
402
|
record[DETAILS_COLUMNS.PARENT_IDX] = res.rows[0].n;
|
|
280
403
|
}
|
|
281
404
|
const cols = [
|
|
282
|
-
...def.fields
|
|
405
|
+
...def.fields
|
|
406
|
+
.filter((f) => f.type !== FIELD_TYPES.DETAILS && f.type !== FIELD_TYPES.MULTI_RELATION)
|
|
407
|
+
.map((f) => f.name),
|
|
283
408
|
...(child ? [...PARENT_COLUMNS] : []),
|
|
284
409
|
];
|
|
285
410
|
const fieldByName = new Map(def.fields.map((f) => [f.name, f]));
|
|
286
411
|
const values = cols.map((c) => dbJsonValue(fieldByName.get(c), record[c] ?? null));
|
|
287
412
|
const placeholders = cols.map((_, i) => `$${i + 1}`).join(', ');
|
|
288
|
-
await runTableQuery(client, def.name, `INSERT INTO ${q(def.name)} (${cols.map(q).join(', ')}) VALUES (${placeholders})`, values, ctx.locale);
|
|
289
|
-
|
|
413
|
+
const insertRes = await runTableQuery(client, def.name, `INSERT INTO ${q(def.name)} (${cols.map(q).join(', ')}) VALUES (${placeholders}) RETURNING ${recordKeySql(def, q)} AS ${q(META_KEY_COL)}`, values, ctx.locale);
|
|
414
|
+
const metaKey = String(insertRes.rows[0]?.[META_KEY_COL] ?? '');
|
|
415
|
+
const externalId = metaKey;
|
|
416
|
+
record[RECORD_META_ID_FIELD] = externalId;
|
|
417
|
+
await insertDetails(client, def, externalId, payload, ctx.registry, ctx.locale);
|
|
418
|
+
await insertLinks(client, def, primaryFieldsOf(def).map((f) => record[f.name]), payload, ctx.registry, ctx.locale);
|
|
290
419
|
// compute formula fields AFTER children exist (aggregates see them), then persist
|
|
291
|
-
await computeFormulas(def, record, client, ctx.registry, now);
|
|
420
|
+
await computeFormulas(def, record, client, ctx.registry, now, externalId, formulaAuth(ctx));
|
|
292
421
|
const formulaCols = def.fields
|
|
293
422
|
.filter((f) => f.formula !== undefined)
|
|
294
423
|
.map((f) => f.name);
|
|
295
424
|
if (formulaCols.length > 0) {
|
|
296
425
|
const setSql = formulaCols.map((c, i) => `${q(c)} = $${i + 1}`).join(', ');
|
|
297
426
|
const formulaValues = formulaCols.map((c) => record[c] ?? null);
|
|
298
|
-
|
|
427
|
+
const pkValues = pkValuesOf(def, externalId, ctx);
|
|
428
|
+
await runTableQuery(client, def.name, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${pkWhereSql(def, formulaCols.length + 1)}`, [...formulaValues, ...pkValues], ctx.locale);
|
|
299
429
|
}
|
|
430
|
+
await this.writeRecordMeta(client, def, metaKey, ctx, now, true);
|
|
300
431
|
if (owned)
|
|
301
432
|
await client.query('COMMIT');
|
|
302
|
-
auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName,
|
|
303
|
-
this.events?.publishRecordChange('created', objectName,
|
|
304
|
-
await this.runAfterHook(SCRIPT_HOOKS.AFTER_UPDATE, DATA_ACTIONS.CREATE, objectName, record, payload, ctx, warnings,
|
|
433
|
+
auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName, externalId, record);
|
|
434
|
+
this.events?.publishRecordChange('created', objectName, externalId);
|
|
435
|
+
await this.runAfterHook(SCRIPT_HOOKS.AFTER_UPDATE, DATA_ACTIONS.CREATE, objectName, record, payload, ctx, warnings, externalId);
|
|
305
436
|
if (warnings.length > 0)
|
|
306
437
|
ctx.onWarnings?.(warnings);
|
|
307
438
|
const loaded = await this.runOnLoad(objectName, [record], ctx);
|
|
@@ -310,7 +441,10 @@ export class DefaultObjectDataAccess {
|
|
|
310
441
|
catch (err) {
|
|
311
442
|
if (owned)
|
|
312
443
|
await client.query('ROLLBACK');
|
|
313
|
-
|
|
444
|
+
const failedId = primaryNames(def).every((n) => data[n] !== undefined)
|
|
445
|
+
? externalIdOf(def, data)
|
|
446
|
+
: undefined;
|
|
447
|
+
auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName, failedId, data, err);
|
|
314
448
|
throw err;
|
|
315
449
|
}
|
|
316
450
|
finally {
|
|
@@ -320,10 +454,10 @@ export class DefaultObjectDataAccess {
|
|
|
320
454
|
}
|
|
321
455
|
async update(objectName, id, changes, ctx) {
|
|
322
456
|
const def = requireDef(ctx, objectName);
|
|
323
|
-
|
|
324
|
-
if (pk === undefined) {
|
|
457
|
+
if (primaryNames(def).length === 0) {
|
|
325
458
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
326
459
|
}
|
|
460
|
+
const pkValues = pkValuesOf(def, id, ctx);
|
|
327
461
|
let client;
|
|
328
462
|
let owned = false;
|
|
329
463
|
if (ctx.client !== undefined) {
|
|
@@ -338,21 +472,31 @@ export class DefaultObjectDataAccess {
|
|
|
338
472
|
if (owned)
|
|
339
473
|
await client.query('BEGIN');
|
|
340
474
|
await validateRecord(def, changes, WRITE_MODES.UPDATE, { pool: client, registry: ctx.registry, locale: ctx.locale });
|
|
341
|
-
const { sql, params } = buildFindSql(def, { filter:
|
|
475
|
+
const { sql, params } = buildFindSql(def, { filter: pkFilter(def, pkValues), limit: 1 }, bctx(ctx, objectName), ctx.rowScope, undefined, [recordKeySelect(def)]);
|
|
342
476
|
const { rows } = await runTableQuery(client, objectName, sql, params, ctx.locale);
|
|
343
|
-
const
|
|
344
|
-
if (
|
|
477
|
+
const raw = rows[0];
|
|
478
|
+
if (raw === undefined) {
|
|
345
479
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
346
480
|
}
|
|
481
|
+
const metaKey = String(raw[META_KEY_COL] ?? '');
|
|
482
|
+
const existing = { ...raw };
|
|
483
|
+
delete existing[META_KEY_COL];
|
|
347
484
|
// validate → beforeUpdate; hooks see the pre-update record and may rewrite changes
|
|
348
485
|
await this.runBeforeHook(SCRIPT_HOOKS.VALIDATE, objectName, existing, changes, ctx);
|
|
349
486
|
let payload = changes;
|
|
350
487
|
const before = await this.runBeforeHook(SCRIPT_HOOKS.BEFORE_UPDATE, objectName, existing, changes, ctx);
|
|
351
488
|
if (before !== undefined)
|
|
352
489
|
payload = before;
|
|
490
|
+
// primary keys are immutable: reject any attempt to change them (drift-free record_key)
|
|
491
|
+
for (const name of primaryNames(def)) {
|
|
492
|
+
if (payload[name] !== undefined) {
|
|
493
|
+
throw new SchemaError('object.primary.mutable', { object: objectName, field: name }, ctx.locale);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
353
496
|
const now = new Date();
|
|
354
497
|
const record = { ...existing, ...payload };
|
|
355
|
-
|
|
498
|
+
record[RECORD_META_ID_FIELD] = metaKey;
|
|
499
|
+
await computeFormulas(def, record, client, ctx.registry, now, metaKey, formulaAuth(ctx));
|
|
356
500
|
const settable = new Set();
|
|
357
501
|
for (const key of Object.keys(payload)) {
|
|
358
502
|
if (isDetailsChild(ctx.registry, def.name) && PARENT_COLUMNS.has(key)) {
|
|
@@ -360,21 +504,25 @@ export class DefaultObjectDataAccess {
|
|
|
360
504
|
continue;
|
|
361
505
|
}
|
|
362
506
|
const field = def.fields.find((f) => f.name === key);
|
|
363
|
-
if (field !== undefined && field.type !== FIELD_TYPES.DETAILS)
|
|
507
|
+
if (field !== undefined && field.type !== FIELD_TYPES.DETAILS && field.type !== FIELD_TYPES.MULTI_RELATION) {
|
|
364
508
|
settable.add(key);
|
|
509
|
+
}
|
|
365
510
|
}
|
|
366
511
|
for (const field of def.fields) {
|
|
367
512
|
if (field.formula !== undefined)
|
|
368
513
|
settable.add(field.name);
|
|
369
514
|
}
|
|
370
|
-
|
|
515
|
+
for (const name of primaryNames(def))
|
|
516
|
+
settable.delete(name);
|
|
371
517
|
if (settable.size > 0) {
|
|
372
518
|
const cols = [...settable];
|
|
373
519
|
const setSql = cols.map((c, i) => `${q(c)} = $${i + 1}`).join(', ');
|
|
374
|
-
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, cols.length +
|
|
520
|
+
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, cols.length + pkValues.length) : undefined;
|
|
375
521
|
const values = cols.map((c) => dbJsonValue(def.fields.find((f) => f.name === c), record[c] ?? null));
|
|
376
|
-
await runTableQuery(client, objectName, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${
|
|
522
|
+
await runTableQuery(client, objectName, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${pkWhereSql(def, cols.length + 1)}${scope !== undefined ? ` AND (${scope.sql})` : ''}`, [...values, ...pkValues, ...(scope?.params ?? [])], ctx.locale);
|
|
377
523
|
}
|
|
524
|
+
await this.writeRecordMeta(client, def, metaKey, ctx, now, false);
|
|
525
|
+
await replaceLinks(client, def, pkValues, payload, ctx.registry, ctx.locale);
|
|
378
526
|
if (owned)
|
|
379
527
|
await client.query('COMMIT');
|
|
380
528
|
auditWrite(this.audit, ctx, DATA_ACTIONS.UPDATE, objectName, id, payload, undefined, this.replay ? existing : undefined, this.replay ? record : undefined);
|
|
@@ -396,12 +544,195 @@ export class DefaultObjectDataAccess {
|
|
|
396
544
|
client.release();
|
|
397
545
|
}
|
|
398
546
|
}
|
|
547
|
+
/**
|
|
548
|
+
* Fire a workflow action against the three-layer runtime (instance/step/
|
|
549
|
+
* workitem). Runs in one transaction: the instance row is locked, the current
|
|
550
|
+
* step's workitems are quorum-evaluated, the new step/workitems are opened and
|
|
551
|
+
* the side-table status mirror is updated. The customer row is never touched.
|
|
552
|
+
*/
|
|
553
|
+
async transition(objectName, id, action, ctx, payload) {
|
|
554
|
+
const def = requireDef(ctx, objectName);
|
|
555
|
+
if (def.workflow === undefined) {
|
|
556
|
+
throw new SchemaError('workflow.transition.unknown', { object: objectName, action }, ctx.locale);
|
|
557
|
+
}
|
|
558
|
+
if (primaryNames(def).length === 0) {
|
|
559
|
+
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
560
|
+
}
|
|
561
|
+
const pkValues = pkValuesOf(def, id, ctx);
|
|
562
|
+
let client;
|
|
563
|
+
let owned = false;
|
|
564
|
+
if (ctx.client !== undefined) {
|
|
565
|
+
client = ctx.client;
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
owned = true;
|
|
569
|
+
client = await ctx.pool.connect();
|
|
570
|
+
}
|
|
571
|
+
try {
|
|
572
|
+
if (owned)
|
|
573
|
+
await client.query('BEGIN');
|
|
574
|
+
// the customer record must exist (transitions never create records)
|
|
575
|
+
const { sql, params } = buildFindSql(def, { filter: pkFilter(def, pkValues), limit: 1 }, bctx(ctx, objectName), undefined, undefined, [recordKeySelect(def)]);
|
|
576
|
+
const found = await runTableQuery(client, objectName, sql, params, ctx.locale);
|
|
577
|
+
if (found.rows[0] === undefined) {
|
|
578
|
+
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
579
|
+
}
|
|
580
|
+
// guardrail policy + approval gate (shared policy set with the open contract):
|
|
581
|
+
// a policy self-filters on `workflow.transition.<object>.<action>`; a node may
|
|
582
|
+
// also declare `requiresApproval`. deny → error; requireApproval → pending.
|
|
583
|
+
const currentNode = await getWorkflowStatus(client, def, id, ctx.subject);
|
|
584
|
+
const nodeDef = currentNode.node === undefined ? undefined : def.workflow.nodes.find((n) => n.id === currentNode.node);
|
|
585
|
+
const requireApproval = nodeDef?.requiresApproval === true;
|
|
586
|
+
if (this.policies.length > 0 || requireApproval) {
|
|
587
|
+
const actorId = ctx.subject?.id ?? 'system';
|
|
588
|
+
const guardrailCtx = {
|
|
589
|
+
actor: { key: actorId, label: actorId, onBehalfOf: actorId },
|
|
590
|
+
subject: ctx.subject ?? { id: 'system', roles: [] },
|
|
591
|
+
action: `workflow.transition.${def.name}.${action}`,
|
|
592
|
+
args: { object: def.name, id, action },
|
|
593
|
+
dataAccess: toolDataAccessOver(this, {
|
|
594
|
+
pool: ctx.pool,
|
|
595
|
+
registry: ctx.registry,
|
|
596
|
+
...(ctx.locale === undefined ? {} : { locale: ctx.locale }),
|
|
597
|
+
...(ctx.client === undefined ? {} : { client: ctx.client }),
|
|
598
|
+
...(ctx.subject === undefined ? {} : { subject: ctx.subject }),
|
|
599
|
+
}),
|
|
600
|
+
};
|
|
601
|
+
const gate = await evaluateTransition(this.policies, this.approvals, guardrailCtx, requireApproval);
|
|
602
|
+
if (gate.kind === 'deny') {
|
|
603
|
+
throw new SchemaError(gate.code, { object: objectName, action, reason: gate.reason ?? '' }, ctx.locale);
|
|
604
|
+
}
|
|
605
|
+
if (gate.kind === 'pending') {
|
|
606
|
+
throw new SchemaError('workflow.transition.pending', { object: objectName, action, approvalKey: gate.approvalKey }, ctx.locale);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const outcome = await runWorkflowTransition(client, def, id, action, ctx.subject, payload, ctx.locale);
|
|
610
|
+
if (owned)
|
|
611
|
+
await client.query('COMMIT');
|
|
612
|
+
auditWrite(this.audit, ctx, DATA_ACTIONS.TRANSITION, objectName, id, {
|
|
613
|
+
action,
|
|
614
|
+
node: outcome.toNodeId ?? null,
|
|
615
|
+
from: outcome.fromNodeId ?? null,
|
|
616
|
+
...(def.workflowHash === undefined ? {} : { workflowHash: def.workflowHash }),
|
|
617
|
+
});
|
|
618
|
+
this.events?.publishRecordChange('updated', objectName, id);
|
|
619
|
+
this.events?.publishRecordTransitioned(objectName, id, outcome.fromNodeId ?? '', outcome.toNodeId ?? '', action, def.workflow.version, def.workflowHash);
|
|
620
|
+
if (outcome.nodeId !== undefined) {
|
|
621
|
+
await this.workflowTimers?.sync(objectName, id, outcome.nodeId).catch(() => { });
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
await this.workflowTimers?.cancel(objectName, id).catch(() => { });
|
|
625
|
+
}
|
|
626
|
+
const updated = await this.findOne(objectName, id, ctx);
|
|
627
|
+
const transitionInfo = { from: outcome.fromNodeId ?? '', to: outcome.toNodeId ?? '' };
|
|
628
|
+
const warnings = [];
|
|
629
|
+
if (updated !== null) {
|
|
630
|
+
await this.runAfterHook(SCRIPT_HOOKS.ON_EXIT, DATA_ACTIONS.TRANSITION, objectName, updated, {}, ctx, warnings, id, { transition: transitionInfo, state: outcome.fromNodeId });
|
|
631
|
+
await this.runAfterHook(SCRIPT_HOOKS.ON_ENTER, DATA_ACTIONS.TRANSITION, objectName, updated, {}, ctx, warnings, id, { transition: transitionInfo, state: outcome.toNodeId });
|
|
632
|
+
await this.runAfterHook(SCRIPT_HOOKS.AFTER_TRANSITION, DATA_ACTIONS.TRANSITION, objectName, updated, {}, ctx, warnings, id, { transition: transitionInfo, state: outcome.toNodeId });
|
|
633
|
+
}
|
|
634
|
+
if (warnings.length > 0)
|
|
635
|
+
ctx.onWarnings?.(warnings);
|
|
636
|
+
return updated;
|
|
637
|
+
}
|
|
638
|
+
catch (err) {
|
|
639
|
+
if (owned)
|
|
640
|
+
await client.query('ROLLBACK');
|
|
641
|
+
auditWrite(this.audit, ctx, DATA_ACTIONS.TRANSITION, objectName, id, { action }, err);
|
|
642
|
+
throw err;
|
|
643
|
+
}
|
|
644
|
+
finally {
|
|
645
|
+
if (owned)
|
|
646
|
+
client.release();
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Read a record's workflow status (state/node/actions/own workitems).
|
|
651
|
+
*/
|
|
652
|
+
async workflowStatus(objectName, id, ctx) {
|
|
653
|
+
const def = requireDef(ctx, objectName);
|
|
654
|
+
if (def.workflow === undefined) {
|
|
655
|
+
throw new SchemaError('workflow.transition.unknown', { object: objectName, action: 'status' }, ctx.locale);
|
|
656
|
+
}
|
|
657
|
+
return getWorkflowStatus(ctx.client ?? ctx.pool, def, id, ctx.subject);
|
|
658
|
+
}
|
|
659
|
+
/** Acquire/renew the caller's presence lock on the current step (TTL lease). */
|
|
660
|
+
async acquireWorkflowLock(objectName, id, ctx) {
|
|
661
|
+
const def = requireDef(ctx, objectName);
|
|
662
|
+
return acquireWorkflowLock(ctx.pool, def, id, ctx.subject, ctx.locale);
|
|
663
|
+
}
|
|
664
|
+
/** Release the caller's presence lock. */
|
|
665
|
+
async releaseWorkflowLock(objectName, id, ctx) {
|
|
666
|
+
const def = requireDef(ctx, objectName);
|
|
667
|
+
await releaseWorkflowLock(ctx.pool, def, id, ctx.subject);
|
|
668
|
+
}
|
|
669
|
+
/** Read a record's workflow history (steps + workitems). */
|
|
670
|
+
async workflowHistory(objectName, id, ctx) {
|
|
671
|
+
const def = requireDef(ctx, objectName);
|
|
672
|
+
if (def.workflow === undefined) {
|
|
673
|
+
throw new SchemaError('workflow.transition.unknown', { object: objectName, action: 'history' }, ctx.locale);
|
|
674
|
+
}
|
|
675
|
+
return getWorkflowHistory(ctx.client ?? ctx.pool, def, id);
|
|
676
|
+
}
|
|
677
|
+
/** The subject's pending workitems across all objects. */
|
|
678
|
+
async workflowTodos(ctx) {
|
|
679
|
+
return getWorkflowTodos(ctx.pool, ctx.subject);
|
|
680
|
+
}
|
|
681
|
+
/** Admin override: jump the record to a node or terminate the instance. */
|
|
682
|
+
async overrideWorkflow(objectName, id, patch, ctx) {
|
|
683
|
+
const def = requireDef(ctx, objectName);
|
|
684
|
+
if (def.workflow === undefined) {
|
|
685
|
+
throw new SchemaError('workflow.transition.unknown', { object: objectName, action: 'override' }, ctx.locale);
|
|
686
|
+
}
|
|
687
|
+
let client;
|
|
688
|
+
let owned = false;
|
|
689
|
+
if (ctx.client !== undefined) {
|
|
690
|
+
client = ctx.client;
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
owned = true;
|
|
694
|
+
client = await ctx.pool.connect();
|
|
695
|
+
}
|
|
696
|
+
try {
|
|
697
|
+
if (owned)
|
|
698
|
+
await client.query('BEGIN');
|
|
699
|
+
const result = await overrideWorkflow(client, def, id, patch, ctx.subject, ctx.locale);
|
|
700
|
+
if (owned)
|
|
701
|
+
await client.query('COMMIT');
|
|
702
|
+
if (result.nodeId !== undefined) {
|
|
703
|
+
await this.workflowTimers?.sync(objectName, id, result.nodeId).catch(() => { });
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
await this.workflowTimers?.cancel(objectName, id).catch(() => { });
|
|
707
|
+
}
|
|
708
|
+
return result;
|
|
709
|
+
}
|
|
710
|
+
catch (err) {
|
|
711
|
+
if (owned)
|
|
712
|
+
await client.query('ROLLBACK');
|
|
713
|
+
throw err;
|
|
714
|
+
}
|
|
715
|
+
finally {
|
|
716
|
+
if (owned)
|
|
717
|
+
client.release();
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Upsert a record's sparse metadata side-table row (status/owner/timestamps)
|
|
722
|
+
* inside the caller's transaction. `created` also stamps the creation facts.
|
|
723
|
+
*/
|
|
724
|
+
async writeRecordMeta(client, def, key, ctx, now, created) {
|
|
725
|
+
const actor = ctx.subject?.id ?? 'system';
|
|
726
|
+
await upsertRecordMeta(client, def.name, key, created
|
|
727
|
+
? { createdBy: actor, modifiedBy: actor, createdTime: now, modifiedTime: now }
|
|
728
|
+
: { modifiedBy: actor, modifiedTime: now });
|
|
729
|
+
}
|
|
399
730
|
async delete(objectName, id, ctx) {
|
|
400
731
|
const def = requireDef(ctx, objectName);
|
|
401
|
-
|
|
402
|
-
if (pk === undefined) {
|
|
732
|
+
if (primaryNames(def).length === 0) {
|
|
403
733
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
404
734
|
}
|
|
735
|
+
const pkValues = pkValuesOf(def, id, ctx);
|
|
405
736
|
let client;
|
|
406
737
|
let owned = false;
|
|
407
738
|
if (ctx.client !== undefined) {
|
|
@@ -415,22 +746,27 @@ export class DefaultObjectDataAccess {
|
|
|
415
746
|
try {
|
|
416
747
|
if (owned)
|
|
417
748
|
await client.query('BEGIN');
|
|
418
|
-
const { sql, params } = buildFindSql(def, { filter:
|
|
749
|
+
const { sql, params } = buildFindSql(def, { filter: pkFilter(def, pkValues), limit: 1 }, bctx(ctx, objectName), ctx.rowScope, undefined, [recordKeySelect(def)]);
|
|
419
750
|
const { rows } = await runTableQuery(client, objectName, sql, params, ctx.locale);
|
|
420
|
-
const
|
|
421
|
-
if (
|
|
751
|
+
const raw = rows[0];
|
|
752
|
+
if (raw === undefined) {
|
|
422
753
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
423
754
|
}
|
|
755
|
+
const metaKey = String(raw[META_KEY_COL] ?? '');
|
|
756
|
+
const existing = { ...raw };
|
|
757
|
+
delete existing[META_KEY_COL];
|
|
424
758
|
await this.runBeforeHook(SCRIPT_HOOKS.BEFORE_DELETE, objectName, existing, {}, ctx);
|
|
425
759
|
await deleteDetailsChildren(client, def, id, ctx.registry);
|
|
426
|
-
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope,
|
|
427
|
-
const res = await runTableQuery(client, objectName, `DELETE FROM ${q(def.name)} WHERE ${
|
|
760
|
+
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, pkValues.length) : undefined;
|
|
761
|
+
const res = await runTableQuery(client, objectName, `DELETE FROM ${q(def.name)} WHERE ${pkWhereSql(def, 1)}${scope !== undefined ? ` AND (${scope.sql})` : ''}`, [...pkValues, ...(scope?.params ?? [])], ctx.locale);
|
|
428
762
|
if (res.rowCount === 0)
|
|
429
763
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
764
|
+
await deleteRecordMeta(client, def.name, metaKey);
|
|
430
765
|
if (owned)
|
|
431
766
|
await client.query('COMMIT');
|
|
432
767
|
auditWrite(this.audit, ctx, DATA_ACTIONS.DELETE, objectName, id, undefined, undefined, this.replay ? existing : undefined);
|
|
433
768
|
this.events?.publishRecordChange('deleted', objectName, id);
|
|
769
|
+
await this.workflowTimers?.cancel(objectName, id).catch(() => { });
|
|
434
770
|
await this.runAfterHook(SCRIPT_HOOKS.AFTER_DELETE, DATA_ACTIONS.DELETE, objectName, existing, {}, ctx, warnings, id);
|
|
435
771
|
if (warnings.length > 0)
|
|
436
772
|
ctx.onWarnings?.(warnings);
|