@weave-kit/engine 0.4.0 → 0.6.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 +61 -0
- package/README.md +6 -6
- 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 +47 -7
- 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/field-add.d.ts.map +1 -1
- package/dist/cli/commands/field-add.js +12 -6
- package/dist/cli/commands/field-add.js.map +1 -1
- package/dist/cli/commands/field-types.d.ts.map +1 -1
- package/dist/cli/commands/field-types.js +10 -1
- package/dist/cli/commands/field-types.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/schema-map.d.ts.map +1 -1
- package/dist/cli/commands/schema-map.js +6 -0
- package/dist/cli/commands/schema-map.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 +74 -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 +21 -34
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli/types/commands.d.ts +48 -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 +59 -3
- 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 +59 -3
- package/dist/core/i18n/de.js.map +1 -1
- package/dist/core/i18n/en.d.ts +60 -4
- package/dist/core/i18n/en.d.ts.map +1 -1
- package/dist/core/i18n/en.js +60 -4
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +59 -3
- 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 +60 -4
- package/dist/core/i18n/zh.js.map +1 -1
- package/dist/core/object/describe.d.ts +62 -3
- package/dist/core/object/describe.d.ts.map +1 -1
- package/dist/core/object/describe.js +81 -11
- 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 +14 -1
- package/dist/core/object/gen-types.js.map +1 -1
- package/dist/core/object/graph.d.ts +3 -0
- package/dist/core/object/graph.d.ts.map +1 -1
- package/dist/core/object/graph.js +90 -14
- package/dist/core/object/graph.js.map +1 -1
- package/dist/core/object/index.d.ts +6 -2
- 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 +45 -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/registry.js +1 -1
- package/dist/core/object/registry.js.map +1 -1
- 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/constraints.d.ts +9 -0
- package/dist/core/object/validate/constraints.d.ts.map +1 -0
- package/dist/core/object/validate/constraints.js +45 -0
- package/dist/core/object/validate/constraints.js.map +1 -0
- package/dist/core/object/validate/field.d.ts.map +1 -1
- package/dist/core/object/validate/field.js +339 -66
- 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 +54 -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 +10 -2
- package/dist/core/storage/diff.d.ts.map +1 -1
- package/dist/core/storage/diff.js +40 -18
- 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 +14 -5
- package/dist/core/storage/map.d.ts.map +1 -1
- package/dist/core/storage/map.js +207 -39
- 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 +10 -0
- package/dist/core/storage/report.d.ts.map +1 -1
- package/dist/core/storage/report.js +31 -9
- 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 +60 -6
- package/dist/core/types/field-type.d.ts.map +1 -1
- package/dist/core/types/field-type.js +19 -3
- package/dist/core/types/field-type.js.map +1 -1
- package/dist/core/types/fields.d.ts +118 -20
- package/dist/core/types/fields.d.ts.map +1 -1
- package/dist/core/types/index.d.ts +11 -9
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js +5 -4
- package/dist/core/types/index.js.map +1 -1
- package/dist/core/types/object.d.ts +27 -2
- 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 +102 -27
- package/dist/core/types/values.d.ts.map +1 -1
- package/dist/core/types/values.js +68 -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 +399 -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 +186 -39
- 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 +84 -2
- 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 +1 -1
- 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 +7 -3
|
@@ -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';
|
|
@@ -21,6 +29,21 @@ function undefinedColumnOf(error) {
|
|
|
21
29
|
const m = /column "([^"]+)" of relation/.exec(message);
|
|
22
30
|
return m?.[1];
|
|
23
31
|
}
|
|
32
|
+
/** PG error 23505 = unique_violation: a unique constraint (column or object constraint) was hit */
|
|
33
|
+
function isUniqueViolation(error) {
|
|
34
|
+
return typeof error === 'object' && error !== null && error.code === '23505';
|
|
35
|
+
}
|
|
36
|
+
/** readable field list behind a unique violation (from the detail `Key (a, b)=(...)`) */
|
|
37
|
+
function uniqueFieldsOf(error) {
|
|
38
|
+
const detail = error?.detail;
|
|
39
|
+
if (typeof detail === 'string') {
|
|
40
|
+
const m = /Key \(([^)]+)\)/.exec(detail);
|
|
41
|
+
if (m?.[1] !== undefined)
|
|
42
|
+
return m[1];
|
|
43
|
+
}
|
|
44
|
+
const constraint = error?.constraint;
|
|
45
|
+
return typeof constraint === 'string' ? constraint : '?';
|
|
46
|
+
}
|
|
24
47
|
/**
|
|
25
48
|
* Run a SQL statement against an object's table, mapping PG `undefined_column`
|
|
26
49
|
* (42703) — a schema/DB drift (schema declares a field the table lacks) — to an
|
|
@@ -35,6 +58,9 @@ async function runTableQuery(q, objectName, sql, params, locale) {
|
|
|
35
58
|
const field = undefinedColumnOf(error);
|
|
36
59
|
throw new SchemaError('data.schemaDrift', { object: objectName, field: field ?? '' }, locale);
|
|
37
60
|
}
|
|
61
|
+
if (isUniqueViolation(error)) {
|
|
62
|
+
throw new SchemaError('data.unique', { object: objectName, fields: uniqueFieldsOf(error) }, locale);
|
|
63
|
+
}
|
|
38
64
|
throw error;
|
|
39
65
|
}
|
|
40
66
|
}
|
|
@@ -64,7 +90,7 @@ function scriptUserOf(ctx) {
|
|
|
64
90
|
return {
|
|
65
91
|
id: ctx.subject?.id ?? 'system',
|
|
66
92
|
roles: ctx.subject?.roles ?? [],
|
|
67
|
-
|
|
93
|
+
departmentId: ctx.subject?.departmentId,
|
|
68
94
|
};
|
|
69
95
|
}
|
|
70
96
|
const PARENT_COLUMNS = new Set([
|
|
@@ -84,7 +110,99 @@ function requireDef(ctx, objectName) {
|
|
|
84
110
|
return def;
|
|
85
111
|
}
|
|
86
112
|
function bctx(ctx, objectName) {
|
|
87
|
-
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
|
+
};
|
|
88
206
|
}
|
|
89
207
|
/**
|
|
90
208
|
* Serialize a value for binding to a DB column. pg (node-postgres) auto-stringifies
|
|
@@ -93,7 +211,10 @@ function bctx(ctx, objectName) {
|
|
|
93
211
|
* (arrays/objects/numbers/booleans) to valid JSON text. `null` stays SQL NULL.
|
|
94
212
|
*/
|
|
95
213
|
function dbJsonValue(field, value) {
|
|
96
|
-
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') {
|
|
97
218
|
return JSON.stringify(value);
|
|
98
219
|
}
|
|
99
220
|
return value;
|
|
@@ -102,17 +223,26 @@ function dbJsonValue(field, value) {
|
|
|
102
223
|
export class DefaultObjectDataAccess {
|
|
103
224
|
audit;
|
|
104
225
|
script;
|
|
105
|
-
/**
|
|
226
|
+
/** audit diff replay: attach before/after row snapshots to update/delete audit events */
|
|
106
227
|
replay;
|
|
107
|
-
/**
|
|
228
|
+
/** live events: publish committed writes to the bus (undefined = zero overhead) */
|
|
108
229
|
events;
|
|
109
230
|
/** objects currently dispatching onLoad — skips re-entrant onLoad (a hook re-reading the same object) */
|
|
110
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;
|
|
111
238
|
constructor(options = {}) {
|
|
112
239
|
this.audit = options.audit;
|
|
113
240
|
this.script = options.script ?? NOOP_SCRIPT_DISPATCHER;
|
|
114
241
|
this.replay = options.replay ?? false;
|
|
115
242
|
this.events = options.events;
|
|
243
|
+
this.policies = options.policies ?? [];
|
|
244
|
+
this.approvals = options.approvals;
|
|
245
|
+
this.workflowTimers = options.workflowTimers;
|
|
116
246
|
}
|
|
117
247
|
/**
|
|
118
248
|
* Run the read hook (`onLoad`) over a fetched batch. The hook receives the
|
|
@@ -150,13 +280,14 @@ export class DefaultObjectDataAccess {
|
|
|
150
280
|
* hook failure → the surrounding transaction rolls back. Returns the
|
|
151
281
|
* possibly-modified changes from beforeUpdate (undefined = keep original).
|
|
152
282
|
*/
|
|
153
|
-
async runBeforeHook(hook, objectName, record, changes, ctx) {
|
|
283
|
+
async runBeforeHook(hook, objectName, record, changes, ctx, extra) {
|
|
154
284
|
if (!this.script.has(objectName, hook))
|
|
155
285
|
return undefined;
|
|
156
286
|
const result = await this.script.dispatch(objectName, hook, {
|
|
157
287
|
record,
|
|
158
288
|
changes,
|
|
159
289
|
user: scriptUserOf(ctx),
|
|
290
|
+
...(extra ?? {}),
|
|
160
291
|
});
|
|
161
292
|
return result.changes;
|
|
162
293
|
}
|
|
@@ -165,7 +296,7 @@ export class DefaultObjectDataAccess {
|
|
|
165
296
|
* committed, so a hook failure is a non-fatal warning: recorded to audit and
|
|
166
297
|
* delivered via `ctx.onWarnings`, never rethrown.
|
|
167
298
|
*/
|
|
168
|
-
async runAfterHook(hook, action, objectName, record, changes, ctx, warnings, objectId) {
|
|
299
|
+
async runAfterHook(hook, action, objectName, record, changes, ctx, warnings, objectId, extra) {
|
|
169
300
|
if (!this.script.has(objectName, hook))
|
|
170
301
|
return;
|
|
171
302
|
try {
|
|
@@ -173,6 +304,7 @@ export class DefaultObjectDataAccess {
|
|
|
173
304
|
record,
|
|
174
305
|
changes,
|
|
175
306
|
user: scriptUserOf(ctx),
|
|
307
|
+
...(extra ?? {}),
|
|
176
308
|
});
|
|
177
309
|
}
|
|
178
310
|
catch (error) {
|
|
@@ -189,26 +321,33 @@ export class DefaultObjectDataAccess {
|
|
|
189
321
|
async find(objectName, opts, ctx) {
|
|
190
322
|
const def = requireDef(ctx, objectName);
|
|
191
323
|
const q = ctx.client ?? ctx.pool;
|
|
192
|
-
|
|
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);
|
|
193
329
|
const { rows } = await runTableQuery(q, objectName, sql, params, ctx.locale);
|
|
194
|
-
const { sql: countSql, params: countParams } = buildCountSql(def, opts,
|
|
330
|
+
const { sql: countSql, params: countParams } = buildCountSql(def, opts, buildCtx, ctx.rowScope);
|
|
195
331
|
const { rows: countRows } = await runTableQuery(q, objectName, countSql, countParams, ctx.locale);
|
|
196
332
|
const loaded = await this.runOnLoad(objectName, rows, ctx);
|
|
197
333
|
return { rows: loaded, total: countRows[0].total };
|
|
198
334
|
}
|
|
199
335
|
async findOne(objectName, id, ctx) {
|
|
200
336
|
const def = requireDef(ctx, objectName);
|
|
201
|
-
|
|
202
|
-
if (pk === undefined) {
|
|
337
|
+
if (primaryNames(def).length === 0) {
|
|
203
338
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
204
339
|
}
|
|
205
|
-
|
|
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);
|
|
206
346
|
return result.rows[0] ?? null;
|
|
207
347
|
}
|
|
208
348
|
async create(objectName, data, ctx) {
|
|
209
349
|
const def = requireDef(ctx, objectName);
|
|
210
|
-
|
|
211
|
-
if (pk === undefined) {
|
|
350
|
+
if (primaryNames(def).length === 0) {
|
|
212
351
|
throw new SchemaError('data.recordNotFound', { object: objectName }, ctx.locale);
|
|
213
352
|
}
|
|
214
353
|
let client;
|
|
@@ -243,14 +382,16 @@ export class DefaultObjectDataAccess {
|
|
|
243
382
|
if (payload[field.name] !== undefined)
|
|
244
383
|
continue;
|
|
245
384
|
record[field.name] =
|
|
246
|
-
(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'
|
|
247
389
|
? now.toISOString()
|
|
248
390
|
: raw.default;
|
|
249
391
|
}
|
|
250
392
|
Object.assign(record, payload);
|
|
251
393
|
const seqFields = def.fields.filter((f) => f.type === FIELD_TYPES.SEQ_NO);
|
|
252
394
|
if (seqFields.length > 0) {
|
|
253
|
-
await ensureSeqTable(client);
|
|
254
395
|
for (const f of seqFields)
|
|
255
396
|
record[f.name] = await generateSeqNo(client, def.name, f, now);
|
|
256
397
|
}
|
|
@@ -261,29 +402,37 @@ export class DefaultObjectDataAccess {
|
|
|
261
402
|
record[DETAILS_COLUMNS.PARENT_IDX] = res.rows[0].n;
|
|
262
403
|
}
|
|
263
404
|
const cols = [
|
|
264
|
-
...def.fields
|
|
405
|
+
...def.fields
|
|
406
|
+
.filter((f) => f.type !== FIELD_TYPES.DETAILS && f.type !== FIELD_TYPES.MULTI_RELATION)
|
|
407
|
+
.map((f) => f.name),
|
|
265
408
|
...(child ? [...PARENT_COLUMNS] : []),
|
|
266
409
|
];
|
|
267
410
|
const fieldByName = new Map(def.fields.map((f) => [f.name, f]));
|
|
268
411
|
const values = cols.map((c) => dbJsonValue(fieldByName.get(c), record[c] ?? null));
|
|
269
412
|
const placeholders = cols.map((_, i) => `$${i + 1}`).join(', ');
|
|
270
|
-
await runTableQuery(client, def.name, `INSERT INTO ${q(def.name)} (${cols.map(q).join(', ')}) VALUES (${placeholders})`, values, ctx.locale);
|
|
271
|
-
|
|
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);
|
|
272
419
|
// compute formula fields AFTER children exist (aggregates see them), then persist
|
|
273
|
-
await computeFormulas(def, record, client, ctx.registry, now);
|
|
420
|
+
await computeFormulas(def, record, client, ctx.registry, now, externalId, formulaAuth(ctx));
|
|
274
421
|
const formulaCols = def.fields
|
|
275
422
|
.filter((f) => f.formula !== undefined)
|
|
276
423
|
.map((f) => f.name);
|
|
277
424
|
if (formulaCols.length > 0) {
|
|
278
425
|
const setSql = formulaCols.map((c, i) => `${q(c)} = $${i + 1}`).join(', ');
|
|
279
426
|
const formulaValues = formulaCols.map((c) => record[c] ?? null);
|
|
280
|
-
|
|
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);
|
|
281
429
|
}
|
|
430
|
+
await this.writeRecordMeta(client, def, metaKey, ctx, now, true);
|
|
282
431
|
if (owned)
|
|
283
432
|
await client.query('COMMIT');
|
|
284
|
-
auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName,
|
|
285
|
-
this.events?.publishRecordChange('created', objectName,
|
|
286
|
-
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);
|
|
287
436
|
if (warnings.length > 0)
|
|
288
437
|
ctx.onWarnings?.(warnings);
|
|
289
438
|
const loaded = await this.runOnLoad(objectName, [record], ctx);
|
|
@@ -292,7 +441,10 @@ export class DefaultObjectDataAccess {
|
|
|
292
441
|
catch (err) {
|
|
293
442
|
if (owned)
|
|
294
443
|
await client.query('ROLLBACK');
|
|
295
|
-
|
|
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);
|
|
296
448
|
throw err;
|
|
297
449
|
}
|
|
298
450
|
finally {
|
|
@@ -302,10 +454,10 @@ export class DefaultObjectDataAccess {
|
|
|
302
454
|
}
|
|
303
455
|
async update(objectName, id, changes, ctx) {
|
|
304
456
|
const def = requireDef(ctx, objectName);
|
|
305
|
-
|
|
306
|
-
if (pk === undefined) {
|
|
457
|
+
if (primaryNames(def).length === 0) {
|
|
307
458
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
308
459
|
}
|
|
460
|
+
const pkValues = pkValuesOf(def, id, ctx);
|
|
309
461
|
let client;
|
|
310
462
|
let owned = false;
|
|
311
463
|
if (ctx.client !== undefined) {
|
|
@@ -320,21 +472,31 @@ export class DefaultObjectDataAccess {
|
|
|
320
472
|
if (owned)
|
|
321
473
|
await client.query('BEGIN');
|
|
322
474
|
await validateRecord(def, changes, WRITE_MODES.UPDATE, { pool: client, registry: ctx.registry, locale: ctx.locale });
|
|
323
|
-
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)]);
|
|
324
476
|
const { rows } = await runTableQuery(client, objectName, sql, params, ctx.locale);
|
|
325
|
-
const
|
|
326
|
-
if (
|
|
477
|
+
const raw = rows[0];
|
|
478
|
+
if (raw === undefined) {
|
|
327
479
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
328
480
|
}
|
|
481
|
+
const metaKey = String(raw[META_KEY_COL] ?? '');
|
|
482
|
+
const existing = { ...raw };
|
|
483
|
+
delete existing[META_KEY_COL];
|
|
329
484
|
// validate → beforeUpdate; hooks see the pre-update record and may rewrite changes
|
|
330
485
|
await this.runBeforeHook(SCRIPT_HOOKS.VALIDATE, objectName, existing, changes, ctx);
|
|
331
486
|
let payload = changes;
|
|
332
487
|
const before = await this.runBeforeHook(SCRIPT_HOOKS.BEFORE_UPDATE, objectName, existing, changes, ctx);
|
|
333
488
|
if (before !== undefined)
|
|
334
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
|
+
}
|
|
335
496
|
const now = new Date();
|
|
336
497
|
const record = { ...existing, ...payload };
|
|
337
|
-
|
|
498
|
+
record[RECORD_META_ID_FIELD] = metaKey;
|
|
499
|
+
await computeFormulas(def, record, client, ctx.registry, now, metaKey, formulaAuth(ctx));
|
|
338
500
|
const settable = new Set();
|
|
339
501
|
for (const key of Object.keys(payload)) {
|
|
340
502
|
if (isDetailsChild(ctx.registry, def.name) && PARENT_COLUMNS.has(key)) {
|
|
@@ -342,21 +504,25 @@ export class DefaultObjectDataAccess {
|
|
|
342
504
|
continue;
|
|
343
505
|
}
|
|
344
506
|
const field = def.fields.find((f) => f.name === key);
|
|
345
|
-
if (field !== undefined && field.type !== FIELD_TYPES.DETAILS)
|
|
507
|
+
if (field !== undefined && field.type !== FIELD_TYPES.DETAILS && field.type !== FIELD_TYPES.MULTI_RELATION) {
|
|
346
508
|
settable.add(key);
|
|
509
|
+
}
|
|
347
510
|
}
|
|
348
511
|
for (const field of def.fields) {
|
|
349
512
|
if (field.formula !== undefined)
|
|
350
513
|
settable.add(field.name);
|
|
351
514
|
}
|
|
352
|
-
|
|
515
|
+
for (const name of primaryNames(def))
|
|
516
|
+
settable.delete(name);
|
|
353
517
|
if (settable.size > 0) {
|
|
354
518
|
const cols = [...settable];
|
|
355
519
|
const setSql = cols.map((c, i) => `${q(c)} = $${i + 1}`).join(', ');
|
|
356
|
-
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, cols.length +
|
|
520
|
+
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, cols.length + pkValues.length) : undefined;
|
|
357
521
|
const values = cols.map((c) => dbJsonValue(def.fields.find((f) => f.name === c), record[c] ?? null));
|
|
358
|
-
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);
|
|
359
523
|
}
|
|
524
|
+
await this.writeRecordMeta(client, def, metaKey, ctx, now, false);
|
|
525
|
+
await replaceLinks(client, def, pkValues, payload, ctx.registry, ctx.locale);
|
|
360
526
|
if (owned)
|
|
361
527
|
await client.query('COMMIT');
|
|
362
528
|
auditWrite(this.audit, ctx, DATA_ACTIONS.UPDATE, objectName, id, payload, undefined, this.replay ? existing : undefined, this.replay ? record : undefined);
|
|
@@ -378,12 +544,195 @@ export class DefaultObjectDataAccess {
|
|
|
378
544
|
client.release();
|
|
379
545
|
}
|
|
380
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
|
+
}
|
|
381
730
|
async delete(objectName, id, ctx) {
|
|
382
731
|
const def = requireDef(ctx, objectName);
|
|
383
|
-
|
|
384
|
-
if (pk === undefined) {
|
|
732
|
+
if (primaryNames(def).length === 0) {
|
|
385
733
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
386
734
|
}
|
|
735
|
+
const pkValues = pkValuesOf(def, id, ctx);
|
|
387
736
|
let client;
|
|
388
737
|
let owned = false;
|
|
389
738
|
if (ctx.client !== undefined) {
|
|
@@ -397,22 +746,27 @@ export class DefaultObjectDataAccess {
|
|
|
397
746
|
try {
|
|
398
747
|
if (owned)
|
|
399
748
|
await client.query('BEGIN');
|
|
400
|
-
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)]);
|
|
401
750
|
const { rows } = await runTableQuery(client, objectName, sql, params, ctx.locale);
|
|
402
|
-
const
|
|
403
|
-
if (
|
|
751
|
+
const raw = rows[0];
|
|
752
|
+
if (raw === undefined) {
|
|
404
753
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
405
754
|
}
|
|
755
|
+
const metaKey = String(raw[META_KEY_COL] ?? '');
|
|
756
|
+
const existing = { ...raw };
|
|
757
|
+
delete existing[META_KEY_COL];
|
|
406
758
|
await this.runBeforeHook(SCRIPT_HOOKS.BEFORE_DELETE, objectName, existing, {}, ctx);
|
|
407
759
|
await deleteDetailsChildren(client, def, id, ctx.registry);
|
|
408
|
-
const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope,
|
|
409
|
-
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);
|
|
410
762
|
if (res.rowCount === 0)
|
|
411
763
|
throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
|
|
764
|
+
await deleteRecordMeta(client, def.name, metaKey);
|
|
412
765
|
if (owned)
|
|
413
766
|
await client.query('COMMIT');
|
|
414
767
|
auditWrite(this.audit, ctx, DATA_ACTIONS.DELETE, objectName, id, undefined, undefined, this.replay ? existing : undefined);
|
|
415
768
|
this.events?.publishRecordChange('deleted', objectName, id);
|
|
769
|
+
await this.workflowTimers?.cancel(objectName, id).catch(() => { });
|
|
416
770
|
await this.runAfterHook(SCRIPT_HOOKS.AFTER_DELETE, DATA_ACTIONS.DELETE, objectName, existing, {}, ctx, warnings, id);
|
|
417
771
|
if (warnings.length > 0)
|
|
418
772
|
ctx.onWarnings?.(warnings);
|