@authup/server-core 1.0.0-beta.54 → 1.0.0-beta.55
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/dist/adapters/database/data-source/options/module.mjs.map +1 -1
- package/dist/adapters/database/domains/client/entity.mjs +2 -2
- package/dist/adapters/database/domains/client/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/client/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/client/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/client-permission/entity.mjs +2 -2
- package/dist/adapters/database/domains/client-permission/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/client-permission/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/client-permission/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/client-role/entity.mjs +2 -2
- package/dist/adapters/database/domains/client-role/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/client-role/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/client-role/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/client-scope/entity.mjs +2 -2
- package/dist/adapters/database/domains/client-scope/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/client-scope/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/client-scope/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/consent/entity.mjs +2 -2
- package/dist/adapters/database/domains/consent/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/consent/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/consent/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/constants.mjs.map +1 -1
- package/dist/adapters/database/domains/event/entity.mjs +2 -2
- package/dist/adapters/database/domains/event/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider/entity.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-account/entity.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-account/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-account/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-account/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute/entity.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-attribute/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute-mapping/entity.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-attribute-mapping/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-permission-mapping/entity.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-permission-mapping/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-role-mapping/entity.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-role-mapping/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-role-mapping/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-role-mapping/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/key/entity.mjs +2 -2
- package/dist/adapters/database/domains/key/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/permission/entity.mjs +2 -2
- package/dist/adapters/database/domains/permission/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/permission/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/permission/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/permission-policy/entity.mjs +2 -2
- package/dist/adapters/database/domains/permission-policy/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/policy/entity.mjs +2 -2
- package/dist/adapters/database/domains/policy/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/policy/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/policy/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/policy-attribute/entity.mjs +2 -2
- package/dist/adapters/database/domains/policy-attribute/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/policy-attribute/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/policy-attribute/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/realm/entity.mjs +2 -2
- package/dist/adapters/database/domains/realm/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/realm/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/realm/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/role/entity.mjs +2 -2
- package/dist/adapters/database/domains/role/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/role/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/role/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/role-attribute/entity.mjs +2 -2
- package/dist/adapters/database/domains/role-attribute/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/role-attribute/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/role-attribute/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/role-permission/entity.mjs +2 -2
- package/dist/adapters/database/domains/role-permission/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/role-permission/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/role-permission/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/scope/entity.mjs +2 -2
- package/dist/adapters/database/domains/scope/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/scope/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/scope/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/session/entity.mjs +2 -2
- package/dist/adapters/database/domains/session/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/session-token/entity.mjs +2 -2
- package/dist/adapters/database/domains/session-token/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/trust-anchor/entity.mjs +2 -2
- package/dist/adapters/database/domains/trust-anchor/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user/entity.mjs +2 -2
- package/dist/adapters/database/domains/user/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/user/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/user-attribute/entity.mjs +2 -2
- package/dist/adapters/database/domains/user-attribute/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user-attribute/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/user-attribute/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/user-authenticator/entity.mjs +2 -2
- package/dist/adapters/database/domains/user-authenticator/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user-permission/entity.mjs +2 -2
- package/dist/adapters/database/domains/user-permission/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user-permission/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/user-permission/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/user-role/entity.mjs +2 -2
- package/dist/adapters/database/domains/user-role/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user-role/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/user-role/subscriber.mjs.map +1 -1
- package/dist/adapters/database/errors/driver.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/adapter.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/adapter.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs.map +1 -1
- package/dist/adapters/database/migrations/mysql/1779267068441-Default.mjs.map +1 -1
- package/dist/adapters/database/migrations/mysql/1779300000000-Default.mjs.map +1 -1
- package/dist/adapters/database/migrations/mysql/1784289540000-CamelCaseAttributes.mjs.map +1 -1
- package/dist/adapters/database/migrations/postgres/1779267068441-Default.mjs.map +1 -1
- package/dist/adapters/database/migrations/postgres/1779300000000-Default.mjs.map +1 -1
- package/dist/adapters/database/migrations/postgres/1784289540000-CamelCaseAttributes.mjs.map +1 -1
- package/dist/adapters/database/subscriber/module.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/authorization/module.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/realm.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/client/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/client/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/client-permission/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/client-permission/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/client-role/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/client-role/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/client-scope/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/client-scope/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/consent/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/consent/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/event/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/event/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provide-role/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/identity-provide-role/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/key/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/key/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/permission/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/permission/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/permission-policy/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/permission-policy/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/policy/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/policy/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/realm/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/realm/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/role/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/role/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/role-attribute/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/role-attribute/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/role-permission/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/role-permission/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/scope/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/scope/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/session/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/session/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/trust-anchor/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/trust-anchor/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/user/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/user-attribute/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user-attribute/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/user-authenticator/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user-authenticator/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/user-permission/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user-permission/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/user-role/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user-role/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/activate/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/jwks/handlers/read.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/jwks/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/jwks/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/logout/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/logout/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/openid/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/password-forgot/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/password-reset/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/register/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/status/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/token/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/token/utils/extract.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/authorization/module.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/cors.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/logger.mjs.map +1 -1
- package/dist/adapters/http/request/constants.mjs.map +1 -1
- package/dist/adapters/http/request/helpers/param-id.mjs.map +1 -1
- package/dist/adapters/http/request/helpers/redirect.mjs.map +1 -1
- package/dist/app/factory.mjs.map +1 -1
- package/dist/app/modules/authentication/module.mjs.map +1 -1
- package/dist/app/modules/authentication/repositories/constants.mjs.map +1 -1
- package/dist/app/modules/authentication/repositories/session.mjs.map +1 -1
- package/dist/app/modules/cache/module.mjs.map +1 -1
- package/dist/app/modules/components/module.mjs.map +1 -1
- package/dist/app/modules/config/constants.mjs.map +1 -1
- package/dist/app/modules/config/origins.mjs.map +1 -1
- package/dist/app/modules/config/read/env.mjs.map +1 -1
- package/dist/app/modules/config/read/fs.mjs.map +1 -1
- package/dist/app/modules/config/validator.mjs.map +1 -1
- package/dist/app/modules/database/module.mjs.map +1 -1
- package/dist/app/modules/database/repositories/bindings.mjs.map +1 -1
- package/dist/app/modules/database/repositories/client/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/event/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/helpers.mjs.map +1 -1
- package/dist/app/modules/database/repositories/permission-provider/module.mjs.map +1 -1
- package/dist/app/modules/database/repositories/user/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/user-attribute/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/user-authenticator/repository.mjs.map +1 -1
- package/dist/app/modules/http/module.mjs.map +1 -1
- package/dist/app/modules/http/modules/controller.mjs.map +1 -1
- package/dist/app/modules/identity/module.mjs.map +1 -1
- package/dist/app/modules/logger/module.mjs.map +1 -1
- package/dist/app/modules/mail/module.mjs.map +1 -1
- package/dist/app/modules/metrics/prom.mjs.map +1 -1
- package/dist/app/modules/oauth2/module.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/consent/repository.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/constants.mjs.map +1 -1
- package/dist/app/modules/provisioning/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/composite/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/file/module.mjs.map +1 -1
- package/dist/app/modules/runtime/module.mjs.map +1 -1
- package/dist/cli/commands/migration.mjs.map +1 -1
- package/dist/components/database/unique-entries/module.mjs.map +1 -1
- package/dist/core/authentication/entities/client/module.mjs.map +1 -1
- package/dist/core/authentication/session/module.mjs.map +1 -1
- package/dist/core/authentication/session/types.mjs.map +1 -1
- package/dist/core/client-certificate/module.mjs.map +1 -1
- package/dist/core/entities/client/schema.mjs.map +1 -1
- package/dist/core/entities/client/service.mjs.map +1 -1
- package/dist/core/entities/client-permission/schema.mjs.map +1 -1
- package/dist/core/entities/client-permission/service.mjs.map +1 -1
- package/dist/core/entities/client-role/schema.mjs.map +1 -1
- package/dist/core/entities/client-role/service.mjs.map +1 -1
- package/dist/core/entities/client-scope/schema.mjs.map +1 -1
- package/dist/core/entities/client-scope/service.mjs.map +1 -1
- package/dist/core/entities/consent/schema.mjs.map +1 -1
- package/dist/core/entities/consent/types.mjs.map +1 -1
- package/dist/core/entities/event/diff.mjs.map +1 -1
- package/dist/core/entities/event/sanitize.mjs.map +1 -1
- package/dist/core/entities/event/schema.mjs.map +1 -1
- package/dist/core/entities/event/service.mjs.map +1 -1
- package/dist/core/entities/identity-provider/schema.mjs.map +1 -1
- package/dist/core/entities/identity-provider-role-mapping/schema.mjs.map +1 -1
- package/dist/core/entities/identity-provider-role-mapping/service.mjs.map +1 -1
- package/dist/core/entities/key/schema.mjs.map +1 -1
- package/dist/core/entities/key/service.mjs.map +1 -1
- package/dist/core/entities/permission/schema.d.ts.map +1 -1
- package/dist/core/entities/permission/schema.mjs +12 -0
- package/dist/core/entities/permission/schema.mjs.map +1 -1
- package/dist/core/entities/permission/service.mjs.map +1 -1
- package/dist/core/entities/permission-policy/schema.mjs.map +1 -1
- package/dist/core/entities/permission-policy/service.mjs.map +1 -1
- package/dist/core/entities/policy/schema.mjs.map +1 -1
- package/dist/core/entities/policy/service.mjs.map +1 -1
- package/dist/core/entities/realm/schema.mjs.map +1 -1
- package/dist/core/entities/role/schema.mjs.map +1 -1
- package/dist/core/entities/role/service.mjs.map +1 -1
- package/dist/core/entities/role-attribute/schema.mjs.map +1 -1
- package/dist/core/entities/role-attribute/service.mjs.map +1 -1
- package/dist/core/entities/role-permission/schema.mjs.map +1 -1
- package/dist/core/entities/role-permission/service.mjs.map +1 -1
- package/dist/core/entities/scope/schema.mjs.map +1 -1
- package/dist/core/entities/scope/service.mjs.map +1 -1
- package/dist/core/entities/session/schema.mjs.map +1 -1
- package/dist/core/entities/session/service.mjs.map +1 -1
- package/dist/core/entities/trust-anchor/schema.mjs.map +1 -1
- package/dist/core/entities/trust-anchor/service.mjs.map +1 -1
- package/dist/core/entities/user/schema.mjs.map +1 -1
- package/dist/core/entities/user/service.mjs.map +1 -1
- package/dist/core/entities/user-attribute/schema.mjs.map +1 -1
- package/dist/core/entities/user-attribute/service.mjs.map +1 -1
- package/dist/core/entities/user-authenticator/schema.mjs.map +1 -1
- package/dist/core/entities/user-authenticator/service.mjs.map +1 -1
- package/dist/core/entities/user-authenticator/types.mjs.map +1 -1
- package/dist/core/entities/user-permission/schema.mjs.map +1 -1
- package/dist/core/entities/user-permission/service.mjs.map +1 -1
- package/dist/core/entities/user-role/schema.mjs.map +1 -1
- package/dist/core/entities/user-role/service.mjs.map +1 -1
- package/dist/core/identity/permission/junction-grant.mjs.map +1 -1
- package/dist/core/identity/permission/module.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/presets/facebook.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/presets/github.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/presets/google.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/presets/instagram.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/presets/paypal.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/protocols/ldap/module.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/module.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/protocols/open-id/module.mjs.map +1 -1
- package/dist/core/identity/provider/constants.mjs.map +1 -1
- package/dist/core/identity/provider/mapper/base.mjs.map +1 -1
- package/dist/core/identity/provider/mapper/constants.mjs.map +1 -1
- package/dist/core/identity/registration/service.mjs.map +1 -1
- package/dist/core/key/provisioner.mjs.map +1 -1
- package/dist/core/key/realm-cipher.mjs.map +1 -1
- package/dist/core/mail/template/templates/mfa-email-otp.mjs.map +1 -1
- package/dist/core/mail/template/templates/password-reset.mjs.map +1 -1
- package/dist/core/mail/template/templates/registration-activation.mjs.map +1 -1
- package/dist/core/mail/template/types.mjs.map +1 -1
- package/dist/core/oauth2/authorization/code/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/module.mjs.map +1 -1
- package/dist/core/oauth2/end-session/service.mjs.map +1 -1
- package/dist/core/oauth2/grant-types/refresh-token.mjs.map +1 -1
- package/dist/core/oauth2/mfa-login/module.mjs.map +1 -1
- package/dist/core/oauth2/openid/claims.mjs.map +1 -1
- package/dist/core/oauth2/scope/resolver.mjs.map +1 -1
- package/dist/core/oauth2/token/issuer/access/module.mjs.map +1 -1
- package/dist/core/oauth2/token/issuer/mfa/module.mjs.map +1 -1
- package/dist/core/oauth2/token/issuer/open-id/module.mjs.map +1 -1
- package/dist/core/oauth2/token/issuer/refresh/module.mjs.map +1 -1
- package/dist/core/oauth2/token/verifier/module.mjs.map +1 -1
- package/dist/core/provisioning/entities/policy/validator.mjs.map +1 -1
- package/dist/core/provisioning/entities/utils.mjs.map +1 -1
- package/dist/core/provisioning/strategy/constants.mjs.map +1 -1
- package/dist/core/provisioning/strategy/validator.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/client/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/role/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/user/module.mjs.map +1 -1
- package/dist/core/query/module.mjs.map +1 -1
- package/dist/core/query/relations.mjs.map +1 -1
- package/dist/core/security/policy/evaluator.mjs.map +1 -1
- package/dist/ui/client/.vite/ssr-manifest.json +218 -218
- package/dist/ui/client/assets/index-CiHrf73J.css +2 -0
- package/dist/ui/client/assets/{index-BmJ2X468.js → index-mtJngmng.js} +1 -1
- package/dist/ui/client/index.html +2 -2
- package/dist/ui/server/server.js +534 -79
- package/package.json +26 -26
- package/dist/ui/client/assets/index-DiOvW76Q.css +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriber.mjs","names":["EntityType","buildRedisKeyPath","EventSubscriber","EntitySubscriber","buildEntityDestinations","UserPermissionEntity","CachePrefix","UserPermissionSubscriber","type","USER_PERMISSION","target","destinations","data","userRealmId","permissionRealmId","cache","onInsert","keys","prefix","USER_OWNED_PERMISSIONS","key","userId"],"sources":["../../../../../src/adapters/database/domains/user-permission/subscriber.ts"],"sourcesContent":["/*\n * Copyright (c) 2022-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { UserPermission } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { buildRedisKeyPath } from '@authup/server-kit';\nimport { EventSubscriber } from 'typeorm';\nimport { EntitySubscriber, buildEntityDestinations } from '../../subscriber/index.ts';\nimport { UserPermissionEntity } from './entity.ts';\nimport { CachePrefix } from '../constants.ts';\n\n@EventSubscriber()\nexport class UserPermissionSubscriber extends EntitySubscriber<UserPermission> {\n constructor() {\n super({\n type: EntityType.USER_PERMISSION,\n target: UserPermissionEntity,\n destinations: buildEntityDestinations(EntityType.USER_PERMISSION, (data) => [\n data.userRealmId,\n data.permissionRealmId,\n ]),\n cache: {\n onInsert: true,\n keys: (data) => [\n buildRedisKeyPath({\n prefix: CachePrefix.USER_OWNED_PERMISSIONS,\n key: data.userId,\n }),\n ],\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAKC,SAAA,aAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;AAWD,IAAaO,2BAAb,cAA8CJ,iBAAAA;CAC1C,cAAc;EACV,MAAM;GACFK,MAAMR,WAAWS;GACjBC,QAAQL;GACRM,cAAcP,wBAAwBJ,WAAWS,kBAAkBG,SAAS,CACxEA,KAAKC,aACLD,KAAKE,
|
|
1
|
+
{"version":3,"file":"subscriber.mjs","names":["EntityType","buildRedisKeyPath","EventSubscriber","EntitySubscriber","buildEntityDestinations","UserPermissionEntity","CachePrefix","UserPermissionSubscriber","type","USER_PERMISSION","target","destinations","data","userRealmId","permissionRealmId","cache","onInsert","keys","prefix","USER_OWNED_PERMISSIONS","key","userId"],"sources":["../../../../../src/adapters/database/domains/user-permission/subscriber.ts"],"sourcesContent":["/*\n * Copyright (c) 2022-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { UserPermission } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { buildRedisKeyPath } from '@authup/server-kit';\nimport { EventSubscriber } from 'typeorm';\nimport { EntitySubscriber, buildEntityDestinations } from '../../subscriber/index.ts';\nimport { UserPermissionEntity } from './entity.ts';\nimport { CachePrefix } from '../constants.ts';\n\n@EventSubscriber()\nexport class UserPermissionSubscriber extends EntitySubscriber<UserPermission> {\n constructor() {\n super({\n type: EntityType.USER_PERMISSION,\n target: UserPermissionEntity,\n destinations: buildEntityDestinations(EntityType.USER_PERMISSION, (data) => [\n data.userRealmId,\n data.permissionRealmId,\n ]),\n cache: {\n onInsert: true,\n keys: (data) => [\n buildRedisKeyPath({\n prefix: CachePrefix.USER_OWNED_PERMISSIONS,\n key: data.userId,\n }),\n ],\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAKC,SAAA,aAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;AAWD,IAAaO,2BAAb,cAA8CJ,iBAAAA;CAC1C,cAAc;EACV,MAAM;GACFK,MAAMR,WAAWS;GACjBC,QAAQL;GACRM,cAAcP,wBAAwBJ,WAAWS,kBAAkBG,SAAS,CACxEA,KAAKC,aACLD,KAAKE,iBACR,CAAA;GACDC,OAAO;IACHC,UAAU;IACVC,OAAOL,SAAS,CACZX,kBAAkB;KACdiB,QAAQZ,YAAYa;KACpBC,KAAKR,KAAKS;IACd,CAAA,CACH;GACL;EACJ,CAAA;CACJ;AACJ"}
|
|
@@ -16,8 +16,8 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
16
16
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
17
17
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
18
18
|
}
|
|
19
|
-
function _ts_metadata(
|
|
20
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(
|
|
19
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
21
21
|
}
|
|
22
22
|
var UserRoleEntity = class {
|
|
23
23
|
id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity.mjs","names":["Column","CreateDateColumn","Entity","Index","JoinColumn","ManyToOne","PrimaryGeneratedColumn","UpdateDateColumn","dateToISOStringTransformer","RoleEntity","UserEntity","RealmEntity","UserRoleEntity","id","roleId","role","roleRealmId","roleRealm","userId","user","userRealmId","userRealm","createdAt","updatedAt","name","onDelete","nullable","transformer","unique"],"sources":["../../../../../src/adapters/database/domains/user-role/entity.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from 'typeorm';\nimport { dateToISOStringTransformer } from '../../helpers/index.ts';\nimport type {\n Realm, \n Role, \n User, \n UserRole,\n} from '@authup/core-kit';\nimport { RoleEntity } from '../role/index.ts';\nimport { UserEntity } from '../user/entity.ts';\nimport { RealmEntity } from '../realm/index.ts';\n\n@Entity({ name: 'auth_user_roles' })\n@Index(['roleId', 'userId'], { unique: true })\nexport class UserRoleEntity implements UserRole {\n @PrimaryGeneratedColumn('uuid')\n id: string;\n\n // ------------------------------------------------------------------\n\n @Column({ name: 'role_id' })\n roleId: string;\n\n @ManyToOne(() => RoleEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'role_id' })\n role: Role;\n\n @Column({ name: 'role_realm_id', nullable: true })\n roleRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'role_realm_id' })\n roleRealm: Realm | null;\n\n @Column({ name: 'user_id' })\n userId: string;\n\n @ManyToOne(() => UserEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'user_id' })\n user: User;\n\n @Column({ name: 'user_realm_id', nullable: true })\n userRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'user_realm_id' })\n userRealm: Realm | null;\n\n // ------------------------------------------------------------------\n\n @CreateDateColumn({ name: 'created_at', transformer: dateToISOStringTransformer })\n createdAt: string;\n\n @UpdateDateColumn({ name: 'updated_at', transformer: dateToISOStringTransformer })\n updatedAt: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8BA,IAAaY,iBAAb,MAAaA;CAETC;CAKAC;CAIAC;CAGAC;CAOAC;CAGAC;CAIAC;CAGAC;CAOAC;CAKAC;CAGAC;AACJ;;
|
|
1
|
+
{"version":3,"file":"entity.mjs","names":["Column","CreateDateColumn","Entity","Index","JoinColumn","ManyToOne","PrimaryGeneratedColumn","UpdateDateColumn","dateToISOStringTransformer","RoleEntity","UserEntity","RealmEntity","UserRoleEntity","id","roleId","role","roleRealmId","roleRealm","userId","user","userRealmId","userRealm","createdAt","updatedAt","name","onDelete","nullable","transformer","unique"],"sources":["../../../../../src/adapters/database/domains/user-role/entity.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from 'typeorm';\nimport { dateToISOStringTransformer } from '../../helpers/index.ts';\nimport type {\n Realm, \n Role, \n User, \n UserRole,\n} from '@authup/core-kit';\nimport { RoleEntity } from '../role/index.ts';\nimport { UserEntity } from '../user/entity.ts';\nimport { RealmEntity } from '../realm/index.ts';\n\n@Entity({ name: 'auth_user_roles' })\n@Index(['roleId', 'userId'], { unique: true })\nexport class UserRoleEntity implements UserRole {\n @PrimaryGeneratedColumn('uuid')\n id: string;\n\n // ------------------------------------------------------------------\n\n @Column({ name: 'role_id' })\n roleId: string;\n\n @ManyToOne(() => RoleEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'role_id' })\n role: Role;\n\n @Column({ name: 'role_realm_id', nullable: true })\n roleRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'role_realm_id' })\n roleRealm: Realm | null;\n\n @Column({ name: 'user_id' })\n userId: string;\n\n @ManyToOne(() => UserEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'user_id' })\n user: User;\n\n @Column({ name: 'user_realm_id', nullable: true })\n userRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'user_realm_id' })\n userRealm: Realm | null;\n\n // ------------------------------------------------------------------\n\n @CreateDateColumn({ name: 'created_at', transformer: dateToISOStringTransformer })\n createdAt: string;\n\n @UpdateDateColumn({ name: 'updated_at', transformer: dateToISOStringTransformer })\n updatedAt: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8BA,IAAaY,iBAAb,MAAaA;CAETC;CAKAC;CAIAC;CAGAC;CAOAC;CAGAC;CAIAC;CAGAC;CAOAC;CAKAC;CAGAC;AACJ;;AAzCcC,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,UAAA,CAAA,GAAA,aAAA,eAAA,MAAA,CAAA,GAAA,eAAA,WAAA,UAAA,KAAA,CAAA;;CAGCf,gBAAAA,YAAAA,EAAcgB,UAAU,UAAA,CAAA;CAC3BD,WAAAA,EAAAA,MAAM,UAAA,CAAA;;;;CAGVA,MAAM;CAAiBE,UAAU;;;CAG1Bf,gBAAAA,aAAAA;EACbc,UAAU;EACVC,UAAU;;CAEAF,WAAAA,EAAAA,MAAM,gBAAA,CAAA;;;AAGVA,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,UAAA,CAAA,GAAA,aAAA,eAAA,MAAA,CAAA,GAAA,eAAA,WAAA,UAAA,KAAA,CAAA;;CAGCd,gBAAAA,YAAAA,EAAce,UAAU,UAAA,CAAA;CAC3BD,WAAAA,EAAAA,MAAM,UAAA,CAAA;;;;CAGVA,MAAM;CAAiBE,UAAU;;;CAG1Bf,gBAAAA,aAAAA;EACbc,UAAU;EACVC,UAAU;;CAEAF,WAAAA,EAAAA,MAAM,gBAAA,CAAA;;;;CAKAA,MAAM;CAAcG,aAAanB;;;CAGjCgB,MAAM;CAAcG,aAAanB;;AA/C/CgB,iBAAAA,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,kBAAA,CAAA,GAAA,MAAA,CACR,UAAU,QAAA,GAAA,EAAaI,QAAQ,KAAA,CAAA,CAAA,GAAA,cAAA"}
|
|
@@ -15,8 +15,8 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
15
15
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
16
16
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
17
17
|
}
|
|
18
|
-
function _ts_metadata(
|
|
19
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(
|
|
18
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
20
20
|
}
|
|
21
21
|
var UserRoleSubscriber = class extends EntitySubscriber {
|
|
22
22
|
constructor() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriber.mjs","names":["EntityType","buildRedisKeyPath","EventSubscriber","EntitySubscriber","buildEntityDestinations","UserRoleEntity","CachePrefix","UserRoleSubscriber","type","USER_ROLE","target","destinations","data","userRealmId","roleRealmId","cache","onInsert","keys","prefix","USER_OWNED_ROLES","key","userId"],"sources":["../../../../../src/adapters/database/domains/user-role/subscriber.ts"],"sourcesContent":["/*\n * Copyright (c) 2022-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { UserRole } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { buildRedisKeyPath } from '@authup/server-kit';\nimport { EventSubscriber } from 'typeorm';\nimport { EntitySubscriber, buildEntityDestinations } from '../../subscriber/index.ts';\nimport { UserRoleEntity } from './entity.ts';\nimport { CachePrefix } from '../constants.ts';\n\n@EventSubscriber()\nexport class UserRoleSubscriber extends EntitySubscriber<UserRole> {\n constructor() {\n super({\n type: EntityType.USER_ROLE,\n target: UserRoleEntity,\n destinations: buildEntityDestinations(EntityType.USER_ROLE, (data) => [\n data.userRealmId,\n data.roleRealmId,\n ]),\n cache: {\n onInsert: true,\n keys: (data) => [\n buildRedisKeyPath({\n prefix: CachePrefix.USER_OWNED_ROLES,\n key: data.userId,\n }),\n ],\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAKC,SAAA,aAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;AAWD,IAAaO,qBAAb,cAAwCJ,iBAAAA;CACpC,cAAc;EACV,MAAM;GACFK,MAAMR,WAAWS;GACjBC,QAAQL;GACRM,cAAcP,wBAAwBJ,WAAWS,YAAYG,SAAS,CAClEA,KAAKC,aACLD,KAAKE,
|
|
1
|
+
{"version":3,"file":"subscriber.mjs","names":["EntityType","buildRedisKeyPath","EventSubscriber","EntitySubscriber","buildEntityDestinations","UserRoleEntity","CachePrefix","UserRoleSubscriber","type","USER_ROLE","target","destinations","data","userRealmId","roleRealmId","cache","onInsert","keys","prefix","USER_OWNED_ROLES","key","userId"],"sources":["../../../../../src/adapters/database/domains/user-role/subscriber.ts"],"sourcesContent":["/*\n * Copyright (c) 2022-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { UserRole } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { buildRedisKeyPath } from '@authup/server-kit';\nimport { EventSubscriber } from 'typeorm';\nimport { EntitySubscriber, buildEntityDestinations } from '../../subscriber/index.ts';\nimport { UserRoleEntity } from './entity.ts';\nimport { CachePrefix } from '../constants.ts';\n\n@EventSubscriber()\nexport class UserRoleSubscriber extends EntitySubscriber<UserRole> {\n constructor() {\n super({\n type: EntityType.USER_ROLE,\n target: UserRoleEntity,\n destinations: buildEntityDestinations(EntityType.USER_ROLE, (data) => [\n data.userRealmId,\n data.roleRealmId,\n ]),\n cache: {\n onInsert: true,\n keys: (data) => [\n buildRedisKeyPath({\n prefix: CachePrefix.USER_OWNED_ROLES,\n key: data.userId,\n }),\n ],\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAKC,SAAA,aAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;AAWD,IAAaO,qBAAb,cAAwCJ,iBAAAA;CACpC,cAAc;EACV,MAAM;GACFK,MAAMR,WAAWS;GACjBC,QAAQL;GACRM,cAAcP,wBAAwBJ,WAAWS,YAAYG,SAAS,CAClEA,KAAKC,aACLD,KAAKE,WACR,CAAA;GACDC,OAAO;IACHC,UAAU;IACVC,OAAOL,SAAS,CACZX,kBAAkB;KACdiB,QAAQZ,YAAYa;KACpBC,KAAKR,KAAKS;IACd,CAAA,CACH;GACL;EACJ,CAAA;CACJ;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.mjs","names":["hasOwnProperty","isObject","getDatabaseDriverErrorCode","input","undefined","code","driverError","UNIQUE_CONSTRAINT_ERROR_CODES","isUniqueConstraintDatabaseError","includes"],"sources":["../../../../src/adapters/database/errors/driver.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasOwnProperty, isObject } from '@authup/kit';\n\n/**\n * Unwrap the vendor error code from a thrown database error. TypeORM wraps the\n * raw driver error in a `QueryFailedError`, exposing the vendor code on the\n * top-level `code` and/or the nested `driverError.code` depending on the\n * driver — this normalizes both shapes to the vendor code string.\n */\nexport function getDatabaseDriverErrorCode(input: unknown): string | undefined {\n if (!isObject(input)) {\n return undefined;\n }\n\n if (\n hasOwnProperty(input, 'code') &&\n typeof input.code === 'string'\n ) {\n return input.code;\n }\n\n if (\n hasOwnProperty(input, 'driverError') &&\n isObject(input.driverError) &&\n hasOwnProperty(input.driverError, 'code') &&\n typeof input.driverError.code === 'string'\n ) {\n return input.driverError.code;\n }\n\n return undefined;\n}\n\nconst UNIQUE_CONSTRAINT_ERROR_CODES = [\n 'ER_DUP_ENTRY', // mysql\n '23505', // postgres\n 'SQLITE_CONSTRAINT_UNIQUE', // sqlite (better-sqlite3)\n];\n\n/**\n * True when the error is a unique-constraint (duplicate key) violation from any\n * supported driver — the benign race outcome when two writers insert the same\n * unique key concurrently.\n */\nexport function isUniqueConstraintDatabaseError(input: unknown): boolean {\n const code = getDatabaseDriverErrorCode(input);\n return typeof code === 'string' && UNIQUE_CONSTRAINT_ERROR_CODES.includes(code);\n}\n"],"mappings":";;;;;;;;;;GAeA,SAAgBE,2BAA2BC,OAAc;CACrD,IAAI,CAACF,SAASE,KAAAA,GACV;CAGJ,IACIH,eAAeG,OAAO,MAAA,KACtB,OAAOA,MAAME,SAAS,UAEtB,OAAOF,MAAME;CAGjB,IACIL,eAAeG,OAAO,aAAA,KACtBF,SAASE,MAAMG,WAAW,KAC1BN,eAAeG,MAAMG,aAAa,MAAA,KAClC,OAAOH,MAAMG,YAAYD,SAAS,UAElC,OAAOF,MAAMG,YAAYD;AAIjC;AAEA,MAAME,gCAAgC;CAClC;CACA;CACA
|
|
1
|
+
{"version":3,"file":"driver.mjs","names":["hasOwnProperty","isObject","getDatabaseDriverErrorCode","input","undefined","code","driverError","UNIQUE_CONSTRAINT_ERROR_CODES","isUniqueConstraintDatabaseError","includes"],"sources":["../../../../src/adapters/database/errors/driver.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasOwnProperty, isObject } from '@authup/kit';\n\n/**\n * Unwrap the vendor error code from a thrown database error. TypeORM wraps the\n * raw driver error in a `QueryFailedError`, exposing the vendor code on the\n * top-level `code` and/or the nested `driverError.code` depending on the\n * driver — this normalizes both shapes to the vendor code string.\n */\nexport function getDatabaseDriverErrorCode(input: unknown): string | undefined {\n if (!isObject(input)) {\n return undefined;\n }\n\n if (\n hasOwnProperty(input, 'code') &&\n typeof input.code === 'string'\n ) {\n return input.code;\n }\n\n if (\n hasOwnProperty(input, 'driverError') &&\n isObject(input.driverError) &&\n hasOwnProperty(input.driverError, 'code') &&\n typeof input.driverError.code === 'string'\n ) {\n return input.driverError.code;\n }\n\n return undefined;\n}\n\nconst UNIQUE_CONSTRAINT_ERROR_CODES = [\n 'ER_DUP_ENTRY', // mysql\n '23505', // postgres\n 'SQLITE_CONSTRAINT_UNIQUE', // sqlite (better-sqlite3)\n];\n\n/**\n * True when the error is a unique-constraint (duplicate key) violation from any\n * supported driver — the benign race outcome when two writers insert the same\n * unique key concurrently.\n */\nexport function isUniqueConstraintDatabaseError(input: unknown): boolean {\n const code = getDatabaseDriverErrorCode(input);\n return typeof code === 'string' && UNIQUE_CONSTRAINT_ERROR_CODES.includes(code);\n}\n"],"mappings":";;;;;;;;;;GAeA,SAAgBE,2BAA2BC,OAAc;CACrD,IAAI,CAACF,SAASE,KAAAA,GACV;CAGJ,IACIH,eAAeG,OAAO,MAAA,KACtB,OAAOA,MAAME,SAAS,UAEtB,OAAOF,MAAME;CAGjB,IACIL,eAAeG,OAAO,aAAA,KACtBF,SAASE,MAAMG,WAAW,KAC1BN,eAAeG,MAAMG,aAAa,MAAA,KAClC,OAAOH,MAAMG,YAAYD,SAAS,UAElC,OAAOF,MAAMG,YAAYD;AAIjC;AAEA,MAAME,gCAAgC;CAClC;CACA;CACA;AACH;;;;;GAOD,SAAgBC,gCAAgCL,OAAc;CAC1D,MAAME,OAAOH,2BAA2BC,KAAAA;CACxC,OAAO,OAAOE,SAAS,YAAYE,8BAA8BE,SAASJ,IAAAA;AAC9E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.mjs","names":["hasOwnProperty","In","ExtraAttributesRepositoryAdapter","repository","primaryColumn","attributeRepository","attributeForeignColumn","cachePrefix","extra","ctx","attributeProperties","input","entityPrimaryColumn","findOneWithEA","options","extraOptions","entity","findOne","undefined","extendWithEA","findWithEA","entities","find","extendManyWithEA","saveWithEA","attributes","columns","i","metadata","length","push","propertyName","relations","keys","Object","key_","key","index","indexOf","save","saveEA","extraKeys","extraKey","findOneWithEAByPrimaryColumn","value","attributesByPrimary","findWithEAByPrimaryColumn","attributeKeys","attributeKey","where","name","output","element","entityAttributes","filter","attribute","reduce","acc","curr","attributesByPrimaryKey","getPrimaryKeyValues","parent","foreignColumn","foreignColumnValue","items","findBy","itemsToDelete","itemsToUpdate","keysProcessed","item","keepAll","remove","itemsToAdd","keyIndex","insert","map"],"sources":["../../../../src/adapters/database/extra-attribute-repository/adapter.ts"],"sourcesContent":["/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@authup/kit';\nimport { hasOwnProperty } from '@authup/kit';\nimport type {\n FindManyOptions,\n FindOneOptions,\n FindOptionsWhere,\n FindOptionsWhereProperty,\n Repository,\n} from 'typeorm';\nimport { In } from 'typeorm';\nimport type {\n EARepositoryAdapterOptions,\n EARepositoryEntityBase,\n EARepositoryFindOptions,\n EARepositoryPropertiesModifyFn,\n EARepositorySaveOptions,\n} from './types.ts';\n\nexport class ExtraAttributesRepositoryAdapter<\n T extends ObjectLiteral = ObjectLiteral,\n A extends EARepositoryEntityBase = EARepositoryEntityBase,\n> {\n protected repository : Repository<T>;\n\n public primaryColumn : keyof T;\n\n protected attributeRepository : Repository<A>;\n\n public attributeForeignColumn : keyof A;\n\n protected cachePrefix?: string;\n\n protected extra : EARepositoryPropertiesModifyFn<T, A>;\n\n // ------------------------------------------------------------------------------\n\n constructor(ctx: EARepositoryAdapterOptions<T, A>) {\n let extra : EARepositoryPropertiesModifyFn<T, A>;\n if (ctx.attributeProperties) {\n extra = ctx.attributeProperties;\n } else {\n extra = (input) => input;\n }\n this.extra = extra;\n\n this.repository = ctx.repository;\n this.primaryColumn = ctx.entityPrimaryColumn;\n this.attributeRepository = ctx.attributeRepository;\n this.attributeForeignColumn = ctx.attributeForeignColumn;\n this.cachePrefix = ctx.cachePrefix;\n }\n\n // ------------------------------------------------------------------------------\n\n async findOneWithEA(\n options: FindOneOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<T | undefined> {\n const entity = await this.repository.findOne(options);\n if (!entity) {\n return undefined;\n }\n\n await this.extendWithEA(entity, extraOptions);\n\n return entity;\n }\n\n async findWithEA<\n E extends Record<string, any>,\n >(\n options: FindManyOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<(T & E)[]> {\n const entities = await this.repository.find(options);\n\n return this.extendManyWithEA(entities, extraOptions);\n }\n\n async saveWithEA<E extends Record<string, any>>(\n input: T & E,\n attributes?: E,\n options?: EARepositorySaveOptions<T>,\n ) : Promise<T & E> {\n const columns : string[] = [];\n\n for (let i = 0; i < this.repository.metadata.columns.length; i++) {\n columns.push(this.repository.metadata.columns[i].propertyName);\n }\n for (let i = 0; i < this.repository.metadata.relations.length; i++) {\n columns.push(this.repository.metadata.relations[i].propertyName);\n }\n\n let extra : Record<string, any> = {};\n if (attributes) {\n extra = { ...attributes };\n }\n\n const keys = Object.keys(input) as (keyof T)[];\n for (const key_ of keys) {\n const key = key_ as string;\n const index = columns.indexOf(key);\n if (index === -1) {\n extra[key] = input[key];\n delete input[key];\n }\n }\n\n await this.repository.save(input);\n\n await this.saveEA(\n input,\n extra,\n options,\n );\n\n const extraKeys = Object.keys(extra);\n for (const extraKey of extraKeys) {\n input[extraKey as keyof T] = extra[extraKey];\n }\n\n return input;\n }\n\n async findOneWithEAByPrimaryColumn<E extends Record<string, any>>(\n value: T[keyof T],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<E> {\n const attributesByPrimary = await this.findWithEAByPrimaryColumn([value], extraOptions);\n return (attributesByPrimary[value as string] || {}) as E;\n }\n\n async extendWithEA<E extends Record<string, any>>(\n entity: T,\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<T & E> {\n const attributes = await this.findOneWithEAByPrimaryColumn(entity[this.primaryColumn], extraOptions);\n const attributeKeys = Object.keys(attributes);\n for (const attributeKey of attributeKeys) {\n entity[attributeKey as keyof T] = attributes[attributeKey] as T[keyof T];\n }\n\n return entity as T & E;\n }\n\n async findWithEAByPrimaryColumn<E extends Record<string, any>>(\n value: (T[keyof T])[],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<Record<string, E>> {\n const where : FindOptionsWhere<A> = {};\n where[this.attributeForeignColumn as keyof FindOptionsWhere<A>] = In(value) as any;\n if (extraOptions.attributes) {\n where.name = In(extraOptions.attributes) as FindOptionsWhereProperty<A['name']>;\n }\n\n const attributes = await this.attributeRepository.find({ where });\n const output : Record<string, E> = {};\n\n for (const element of value) {\n const entityAttributes = attributes.filter(\n (attribute) => attribute[this.attributeForeignColumn] === element as unknown as A[keyof A],\n );\n\n output[element as string] = entityAttributes\n .reduce((acc, curr) => {\n acc[curr.name as keyof E] = curr.value as E[keyof E];\n\n return acc;\n }, {} as E);\n }\n\n return output;\n }\n\n async extendManyWithEA<E extends Record<string, any>>(\n entities: T[],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<(T & E)[]> {\n const attributesByPrimaryKey = await this.findWithEAByPrimaryColumn(\n this.getPrimaryKeyValues(entities),\n extraOptions,\n );\n\n for (const entity of entities) {\n const attributes = attributesByPrimaryKey[entity[this.primaryColumn] as string];\n if (!attributes) {\n continue;\n }\n\n const attributeKeys = Object.keys(attributes);\n for (const attributeKey of attributeKeys) {\n entity[attributeKey as keyof T] = attributes[attributeKey] as T[keyof T];\n }\n }\n\n return entities as (T & E)[];\n }\n\n // ------------------------------------------------------------------------------\n\n private async saveEA(\n parent: T,\n input: Record<string, any>,\n options: EARepositorySaveOptions<T> = {},\n ) {\n const foreignColumn = this.attributeForeignColumn as keyof A;\n const foreignColumnValue = parent[this.primaryColumn] as unknown as A[keyof A];\n\n const where : Partial<A> = {};\n where[foreignColumn] = foreignColumnValue;\n\n const items = await this.attributeRepository.findBy(where);\n\n const itemsToDelete : A[] = [];\n const itemsToUpdate : A[] = [];\n\n const keysProcessed : string[] = [];\n for (const item of items) {\n if (hasOwnProperty(input, item.name)) {\n item.value = input[item.name];\n item[foreignColumn] = foreignColumnValue;\n\n itemsToUpdate.push(this.extra(item, parent));\n\n keysProcessed.push(item.name);\n } else if (!options.keepAll) {\n itemsToDelete.push(item);\n }\n }\n\n if (itemsToUpdate.length > 0) {\n await this.attributeRepository.save(itemsToUpdate);\n }\n\n if (itemsToDelete.length > 0) {\n await this.attributeRepository.remove(itemsToDelete);\n }\n\n const itemsToAdd : A[] = [];\n\n const keys = Object.keys(input);\n let keyIndex : number;\n\n for (const key of keys) {\n keyIndex = keysProcessed.indexOf(key);\n if (keyIndex === -1) {\n itemsToAdd.push(this.extra({\n name: key,\n value: input[key],\n [foreignColumn]: foreignColumnValue,\n } as A, parent));\n }\n }\n\n if (itemsToAdd.length > 0) {\n await this.attributeRepository.insert(itemsToAdd);\n }\n }\n\n getPrimaryKeyValues(entities: T[]) : T[keyof T][] {\n return entities.map((entity) => entity[this.primaryColumn as keyof T]);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapter.mjs","names":["hasOwnProperty","In","ExtraAttributesRepositoryAdapter","repository","primaryColumn","attributeRepository","attributeForeignColumn","cachePrefix","extra","ctx","attributeProperties","input","entityPrimaryColumn","findOneWithEA","options","extraOptions","entity","findOne","undefined","extendWithEA","findWithEA","entities","find","extendManyWithEA","saveWithEA","attributes","columns","i","metadata","length","push","propertyName","relations","keys","Object","key_","key","index","indexOf","save","saveEA","extraKeys","extraKey","findOneWithEAByPrimaryColumn","value","attributesByPrimary","findWithEAByPrimaryColumn","attributeKeys","attributeKey","where","name","output","element","entityAttributes","filter","attribute","reduce","acc","curr","attributesByPrimaryKey","getPrimaryKeyValues","parent","foreignColumn","foreignColumnValue","items","findBy","itemsToDelete","itemsToUpdate","keysProcessed","item","keepAll","remove","itemsToAdd","keyIndex","insert","map"],"sources":["../../../../src/adapters/database/extra-attribute-repository/adapter.ts"],"sourcesContent":["/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@authup/kit';\nimport { hasOwnProperty } from '@authup/kit';\nimport type {\n FindManyOptions,\n FindOneOptions,\n FindOptionsWhere,\n FindOptionsWhereProperty,\n Repository,\n} from 'typeorm';\nimport { In } from 'typeorm';\nimport type {\n EARepositoryAdapterOptions,\n EARepositoryEntityBase,\n EARepositoryFindOptions,\n EARepositoryPropertiesModifyFn,\n EARepositorySaveOptions,\n} from './types.ts';\n\nexport class ExtraAttributesRepositoryAdapter<\n T extends ObjectLiteral = ObjectLiteral,\n A extends EARepositoryEntityBase = EARepositoryEntityBase,\n> {\n protected repository : Repository<T>;\n\n public primaryColumn : keyof T;\n\n protected attributeRepository : Repository<A>;\n\n public attributeForeignColumn : keyof A;\n\n protected cachePrefix?: string;\n\n protected extra : EARepositoryPropertiesModifyFn<T, A>;\n\n // ------------------------------------------------------------------------------\n\n constructor(ctx: EARepositoryAdapterOptions<T, A>) {\n let extra : EARepositoryPropertiesModifyFn<T, A>;\n if (ctx.attributeProperties) {\n extra = ctx.attributeProperties;\n } else {\n extra = (input) => input;\n }\n this.extra = extra;\n\n this.repository = ctx.repository;\n this.primaryColumn = ctx.entityPrimaryColumn;\n this.attributeRepository = ctx.attributeRepository;\n this.attributeForeignColumn = ctx.attributeForeignColumn;\n this.cachePrefix = ctx.cachePrefix;\n }\n\n // ------------------------------------------------------------------------------\n\n async findOneWithEA(\n options: FindOneOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<T | undefined> {\n const entity = await this.repository.findOne(options);\n if (!entity) {\n return undefined;\n }\n\n await this.extendWithEA(entity, extraOptions);\n\n return entity;\n }\n\n async findWithEA<\n E extends Record<string, any>,\n >(\n options: FindManyOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<(T & E)[]> {\n const entities = await this.repository.find(options);\n\n return this.extendManyWithEA(entities, extraOptions);\n }\n\n async saveWithEA<E extends Record<string, any>>(\n input: T & E,\n attributes?: E,\n options?: EARepositorySaveOptions<T>,\n ) : Promise<T & E> {\n const columns : string[] = [];\n\n for (let i = 0; i < this.repository.metadata.columns.length; i++) {\n columns.push(this.repository.metadata.columns[i].propertyName);\n }\n for (let i = 0; i < this.repository.metadata.relations.length; i++) {\n columns.push(this.repository.metadata.relations[i].propertyName);\n }\n\n let extra : Record<string, any> = {};\n if (attributes) {\n extra = { ...attributes };\n }\n\n const keys = Object.keys(input) as (keyof T)[];\n for (const key_ of keys) {\n const key = key_ as string;\n const index = columns.indexOf(key);\n if (index === -1) {\n extra[key] = input[key];\n delete input[key];\n }\n }\n\n await this.repository.save(input);\n\n await this.saveEA(\n input,\n extra,\n options,\n );\n\n const extraKeys = Object.keys(extra);\n for (const extraKey of extraKeys) {\n input[extraKey as keyof T] = extra[extraKey];\n }\n\n return input;\n }\n\n async findOneWithEAByPrimaryColumn<E extends Record<string, any>>(\n value: T[keyof T],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<E> {\n const attributesByPrimary = await this.findWithEAByPrimaryColumn([value], extraOptions);\n return (attributesByPrimary[value as string] || {}) as E;\n }\n\n async extendWithEA<E extends Record<string, any>>(\n entity: T,\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<T & E> {\n const attributes = await this.findOneWithEAByPrimaryColumn(entity[this.primaryColumn], extraOptions);\n const attributeKeys = Object.keys(attributes);\n for (const attributeKey of attributeKeys) {\n entity[attributeKey as keyof T] = attributes[attributeKey] as T[keyof T];\n }\n\n return entity as T & E;\n }\n\n async findWithEAByPrimaryColumn<E extends Record<string, any>>(\n value: (T[keyof T])[],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<Record<string, E>> {\n const where : FindOptionsWhere<A> = {};\n where[this.attributeForeignColumn as keyof FindOptionsWhere<A>] = In(value) as any;\n if (extraOptions.attributes) {\n where.name = In(extraOptions.attributes) as FindOptionsWhereProperty<A['name']>;\n }\n\n const attributes = await this.attributeRepository.find({ where });\n const output : Record<string, E> = {};\n\n for (const element of value) {\n const entityAttributes = attributes.filter(\n (attribute) => attribute[this.attributeForeignColumn] === element as unknown as A[keyof A],\n );\n\n output[element as string] = entityAttributes\n .reduce((acc, curr) => {\n acc[curr.name as keyof E] = curr.value as E[keyof E];\n\n return acc;\n }, {} as E);\n }\n\n return output;\n }\n\n async extendManyWithEA<E extends Record<string, any>>(\n entities: T[],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<(T & E)[]> {\n const attributesByPrimaryKey = await this.findWithEAByPrimaryColumn(\n this.getPrimaryKeyValues(entities),\n extraOptions,\n );\n\n for (const entity of entities) {\n const attributes = attributesByPrimaryKey[entity[this.primaryColumn] as string];\n if (!attributes) {\n continue;\n }\n\n const attributeKeys = Object.keys(attributes);\n for (const attributeKey of attributeKeys) {\n entity[attributeKey as keyof T] = attributes[attributeKey] as T[keyof T];\n }\n }\n\n return entities as (T & E)[];\n }\n\n // ------------------------------------------------------------------------------\n\n private async saveEA(\n parent: T,\n input: Record<string, any>,\n options: EARepositorySaveOptions<T> = {},\n ) {\n const foreignColumn = this.attributeForeignColumn as keyof A;\n const foreignColumnValue = parent[this.primaryColumn] as unknown as A[keyof A];\n\n const where : Partial<A> = {};\n where[foreignColumn] = foreignColumnValue;\n\n const items = await this.attributeRepository.findBy(where);\n\n const itemsToDelete : A[] = [];\n const itemsToUpdate : A[] = [];\n\n const keysProcessed : string[] = [];\n for (const item of items) {\n if (hasOwnProperty(input, item.name)) {\n item.value = input[item.name];\n item[foreignColumn] = foreignColumnValue;\n\n itemsToUpdate.push(this.extra(item, parent));\n\n keysProcessed.push(item.name);\n } else if (!options.keepAll) {\n itemsToDelete.push(item);\n }\n }\n\n if (itemsToUpdate.length > 0) {\n await this.attributeRepository.save(itemsToUpdate);\n }\n\n if (itemsToDelete.length > 0) {\n await this.attributeRepository.remove(itemsToDelete);\n }\n\n const itemsToAdd : A[] = [];\n\n const keys = Object.keys(input);\n let keyIndex : number;\n\n for (const key of keys) {\n keyIndex = keysProcessed.indexOf(key);\n if (keyIndex === -1) {\n itemsToAdd.push(this.extra({\n name: key,\n value: input[key],\n [foreignColumn]: foreignColumnValue,\n } as A, parent));\n }\n }\n\n if (itemsToAdd.length > 0) {\n await this.attributeRepository.insert(itemsToAdd);\n }\n }\n\n getPrimaryKeyValues(entities: T[]) : T[keyof T][] {\n return entities.map((entity) => entity[this.primaryColumn as keyof T]);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.mjs","names":["ExtraAttributesRepositoryAdapter","ExtraAttributesTreeRepositoryAdapter","saveWithEA","input","attributes","options","childColumnName","repository","metadata","treeChildrenRelation","propertyName","parentColumnName","treeParentRelation","children","parent","Array","isArray","child","undefined","extendManyWithEA","entities","extraOptions","flattened","flatten","attributesByPrimaryKey","findWithEAByPrimaryColumn","getPrimaryKeyValues","traverse","entity","value","primaryColumn","keys","Object","key","output","push","fn","data","datum"],"sources":["../../../../../src/adapters/database/extra-attribute-repository/tree/adapter.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@authup/kit';\nimport { ExtraAttributesRepositoryAdapter } from '../adapter.ts';\nimport type { EARepositoryEntityBase, EARepositoryFindOptions, EARepositorySaveOptions } from '../types.ts';\n\nexport class ExtraAttributesTreeRepositoryAdapter<\n T extends ObjectLiteral = ObjectLiteral,\n A extends EARepositoryEntityBase = EARepositoryEntityBase,\n> extends ExtraAttributesRepositoryAdapter<T, A> {\n async saveWithEA<E extends Record<string, any>>(\n input: T & E,\n attributes?: E,\n options?: EARepositorySaveOptions<T>,\n ) : Promise<T & E> {\n const childColumnName = this.repository.metadata.treeChildrenRelation?.propertyName;\n const parentColumnName = this.repository.metadata.treeParentRelation?.propertyName;\n\n let children : T | T[] | undefined;\n\n if (childColumnName && input[childColumnName]) {\n children = input[childColumnName];\n delete input[childColumnName];\n }\n\n if (\n parentColumnName &&\n options &&\n options.parent\n ) {\n input[parentColumnName as keyof T] = options.parent as (T & E)[keyof T];\n }\n\n await super.saveWithEA(input, attributes, options);\n\n if (\n parentColumnName &&\n options &&\n options.parent\n ) {\n delete input[parentColumnName as keyof T];\n }\n\n if (\n childColumnName &&\n parentColumnName &&\n children\n ) {\n if (Array.isArray(children)) {\n for (const child of children) {\n await this.saveWithEA(child, undefined, {\n ...(options || {}),\n parent: input,\n });\n }\n } else {\n await this.saveWithEA(children, undefined, {\n ...(options || {}),\n parent: input,\n });\n }\n\n input[childColumnName as keyof T] = children as (T & E)[keyof T];\n }\n\n return input;\n }\n\n // ------------------------------------------------------------------------------\n\n async extendManyWithEA<E extends Record<string, any>>(\n entities: T[],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<(T & E)[]> {\n const flattened = this.flatten(entities);\n\n const attributesByPrimaryKey = await this.findWithEAByPrimaryColumn(\n this.getPrimaryKeyValues(flattened),\n extraOptions,\n );\n\n this.traverse(entities, (entity) => {\n const value = attributesByPrimaryKey[entity[this.primaryColumn] as string];\n if (!value) {\n return entity;\n }\n\n const keys = Object.keys(value);\n for (const key of keys) {\n entity[key as keyof T] = value[key] as T[keyof T];\n }\n\n return entity;\n });\n\n return entities as (T & E)[];\n }\n\n // ------------------------------------------------------------------------------\n\n protected flatten(entities: T | T[]) : T[] {\n const output : T[] = [];\n\n this.traverse(entities, (entity) => {\n output.push(entity);\n\n return entity;\n });\n\n return output;\n }\n\n protected traverse(entities: T | T[], fn: (entity: T) => T) {\n const data : T[] = Array.isArray(entities) ? entities : [entities];\n\n const childColumnName = this.repository.metadata.treeChildrenRelation?.propertyName;\n for (const datum of data) {\n fn(datum);\n\n if (childColumnName && datum[childColumnName]) {\n if (Array.isArray(datum[childColumnName])) {\n this.traverse(datum[childColumnName], fn);\n } else {\n this.traverse([datum[childColumnName]], fn);\n }\n }\n }\n }\n}\n"],"mappings":";;;;;AAWA,IAAaC,uCAAb,cAGUD,iCAAAA;CACN,MAAME,WACFC,OACAC,YACAC,SACe;EACf,MAAMC,kBAAkB,KAAKC,WAAWC,SAASC,sBAAsBC;EACvE,MAAMC,mBAAmB,KAAKJ,WAAWC,SAASI,oBAAoBF;EAEtE,IAAIG;EAEJ,IAAIP,mBAAmBH,MAAMG,kBAAkB;GAC3CO,WAAWV,MAAMG;GACjB,OAAOH,MAAMG;EACjB;EAEA,IACIK,oBACAN,WACAA,QAAQS,QAERX,MAAMQ,oBAA+BN,QAAQS;EAGjD,MAAM,MAAMZ,WAAWC,OAAOC,YAAYC,OAAAA;EAE1C,IACIM,oBACAN,WACAA,QAAQS,QAER,OAAOX,MAAMQ;EAGjB,IACIL,mBACAK,oBACAE,UACF;GACE,IAAIE,MAAMC,QAAQH,QAAAA,GACd,KAAK,MAAMI,SAASJ,UAChB,MAAM,KAAKX,WAAWe,OAAOC,KAAAA,GAAW;IACpC,GAAIb,WAAW,CAAC;IAChBS,QAAQX;GACZ,CAAA;QAGJ,MAAM,KAAKD,WAAWW,UAAUK,KAAAA,GAAW;IACvC,GAAIb,WAAW,CAAC;IAChBS,QAAQX;GACZ,CAAA;GAGJA,MAAMG,mBAA8BO;EACxC;EAEA,OAAOV;CACX;CAIA,MAAMgB,iBACFC,UACAC,eAAwC,CAAC,GACtB;EACnB,MAAMC,YAAY,KAAKC,QAAQH,QAAAA;EAE/B,MAAMI,yBAAyB,MAAM,KAAKC,0BACtC,KAAKC,oBAAoBJ,SAAAA,GACzBD,YAAAA;EAGJ,KAAKM,SAASP,WAAWQ,WAAAA;GACrB,MAAMC,QAAQL,uBAAuBI,OAAO,KAAKE;GACjD,IAAI,CAACD,OACD,OAAOD;GAGX,MAAMG,OAAOC,OAAOD,KAAKF,KAAAA;GACzB,KAAK,MAAMI,OAAOF,MACdH,OAAOK,OAAkBJ,MAAMI;GAGnC,OAAOL;EACX,CAAA;EAEA,OAAOR;CACX;CAIUG,QAAQH,UAAyB;EACvC,MAAMc,SAAe,CAAA;EAErB,KAAKP,SAASP,WAAWQ,WAAAA;GACrBM,OAAOC,KAAKP,MAAAA;GAEZ,OAAOA;EACX,CAAA;EAEA,OAAOM;CACX;CAEUP,SAASP,UAAmBgB,IAAsB;EACxD,MAAMC,OAAatB,MAAMC,QAAQI,QAAAA,IAAYA,WAAW,CAACA,
|
|
1
|
+
{"version":3,"file":"adapter.mjs","names":["ExtraAttributesRepositoryAdapter","ExtraAttributesTreeRepositoryAdapter","saveWithEA","input","attributes","options","childColumnName","repository","metadata","treeChildrenRelation","propertyName","parentColumnName","treeParentRelation","children","parent","Array","isArray","child","undefined","extendManyWithEA","entities","extraOptions","flattened","flatten","attributesByPrimaryKey","findWithEAByPrimaryColumn","getPrimaryKeyValues","traverse","entity","value","primaryColumn","keys","Object","key","output","push","fn","data","datum"],"sources":["../../../../../src/adapters/database/extra-attribute-repository/tree/adapter.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@authup/kit';\nimport { ExtraAttributesRepositoryAdapter } from '../adapter.ts';\nimport type { EARepositoryEntityBase, EARepositoryFindOptions, EARepositorySaveOptions } from '../types.ts';\n\nexport class ExtraAttributesTreeRepositoryAdapter<\n T extends ObjectLiteral = ObjectLiteral,\n A extends EARepositoryEntityBase = EARepositoryEntityBase,\n> extends ExtraAttributesRepositoryAdapter<T, A> {\n async saveWithEA<E extends Record<string, any>>(\n input: T & E,\n attributes?: E,\n options?: EARepositorySaveOptions<T>,\n ) : Promise<T & E> {\n const childColumnName = this.repository.metadata.treeChildrenRelation?.propertyName;\n const parentColumnName = this.repository.metadata.treeParentRelation?.propertyName;\n\n let children : T | T[] | undefined;\n\n if (childColumnName && input[childColumnName]) {\n children = input[childColumnName];\n delete input[childColumnName];\n }\n\n if (\n parentColumnName &&\n options &&\n options.parent\n ) {\n input[parentColumnName as keyof T] = options.parent as (T & E)[keyof T];\n }\n\n await super.saveWithEA(input, attributes, options);\n\n if (\n parentColumnName &&\n options &&\n options.parent\n ) {\n delete input[parentColumnName as keyof T];\n }\n\n if (\n childColumnName &&\n parentColumnName &&\n children\n ) {\n if (Array.isArray(children)) {\n for (const child of children) {\n await this.saveWithEA(child, undefined, {\n ...(options || {}),\n parent: input,\n });\n }\n } else {\n await this.saveWithEA(children, undefined, {\n ...(options || {}),\n parent: input,\n });\n }\n\n input[childColumnName as keyof T] = children as (T & E)[keyof T];\n }\n\n return input;\n }\n\n // ------------------------------------------------------------------------------\n\n async extendManyWithEA<E extends Record<string, any>>(\n entities: T[],\n extraOptions: EARepositoryFindOptions = {},\n ) : Promise<(T & E)[]> {\n const flattened = this.flatten(entities);\n\n const attributesByPrimaryKey = await this.findWithEAByPrimaryColumn(\n this.getPrimaryKeyValues(flattened),\n extraOptions,\n );\n\n this.traverse(entities, (entity) => {\n const value = attributesByPrimaryKey[entity[this.primaryColumn] as string];\n if (!value) {\n return entity;\n }\n\n const keys = Object.keys(value);\n for (const key of keys) {\n entity[key as keyof T] = value[key] as T[keyof T];\n }\n\n return entity;\n });\n\n return entities as (T & E)[];\n }\n\n // ------------------------------------------------------------------------------\n\n protected flatten(entities: T | T[]) : T[] {\n const output : T[] = [];\n\n this.traverse(entities, (entity) => {\n output.push(entity);\n\n return entity;\n });\n\n return output;\n }\n\n protected traverse(entities: T | T[], fn: (entity: T) => T) {\n const data : T[] = Array.isArray(entities) ? entities : [entities];\n\n const childColumnName = this.repository.metadata.treeChildrenRelation?.propertyName;\n for (const datum of data) {\n fn(datum);\n\n if (childColumnName && datum[childColumnName]) {\n if (Array.isArray(datum[childColumnName])) {\n this.traverse(datum[childColumnName], fn);\n } else {\n this.traverse([datum[childColumnName]], fn);\n }\n }\n }\n }\n}\n"],"mappings":";;;;;AAWA,IAAaC,uCAAb,cAGUD,iCAAAA;CACN,MAAME,WACFC,OACAC,YACAC,SACe;EACf,MAAMC,kBAAkB,KAAKC,WAAWC,SAASC,sBAAsBC;EACvE,MAAMC,mBAAmB,KAAKJ,WAAWC,SAASI,oBAAoBF;EAEtE,IAAIG;EAEJ,IAAIP,mBAAmBH,MAAMG,kBAAkB;GAC3CO,WAAWV,MAAMG;GACjB,OAAOH,MAAMG;EACjB;EAEA,IACIK,oBACAN,WACAA,QAAQS,QAERX,MAAMQ,oBAA+BN,QAAQS;EAGjD,MAAM,MAAMZ,WAAWC,OAAOC,YAAYC,OAAAA;EAE1C,IACIM,oBACAN,WACAA,QAAQS,QAER,OAAOX,MAAMQ;EAGjB,IACIL,mBACAK,oBACAE,UACF;GACE,IAAIE,MAAMC,QAAQH,QAAAA,GACd,KAAK,MAAMI,SAASJ,UAChB,MAAM,KAAKX,WAAWe,OAAOC,KAAAA,GAAW;IACpC,GAAIb,WAAW,CAAC;IAChBS,QAAQX;GACZ,CAAA;QAGJ,MAAM,KAAKD,WAAWW,UAAUK,KAAAA,GAAW;IACvC,GAAIb,WAAW,CAAC;IAChBS,QAAQX;GACZ,CAAA;GAGJA,MAAMG,mBAA8BO;EACxC;EAEA,OAAOV;CACX;CAIA,MAAMgB,iBACFC,UACAC,eAAwC,CAAC,GACtB;EACnB,MAAMC,YAAY,KAAKC,QAAQH,QAAAA;EAE/B,MAAMI,yBAAyB,MAAM,KAAKC,0BACtC,KAAKC,oBAAoBJ,SAAAA,GACzBD,YAAAA;EAGJ,KAAKM,SAASP,WAAWQ,WAAAA;GACrB,MAAMC,QAAQL,uBAAuBI,OAAO,KAAKE;GACjD,IAAI,CAACD,OACD,OAAOD;GAGX,MAAMG,OAAOC,OAAOD,KAAKF,KAAAA;GACzB,KAAK,MAAMI,OAAOF,MACdH,OAAOK,OAAkBJ,MAAMI;GAGnC,OAAOL;EACX,CAAA;EAEA,OAAOR;CACX;CAIUG,QAAQH,UAAyB;EACvC,MAAMc,SAAe,CAAA;EAErB,KAAKP,SAASP,WAAWQ,WAAAA;GACrBM,OAAOC,KAAKP,MAAAA;GAEZ,OAAOA;EACX,CAAA;EAEA,OAAOM;CACX;CAEUP,SAASP,UAAmBgB,IAAsB;EACxD,MAAMC,OAAatB,MAAMC,QAAQI,QAAAA,IAAYA,WAAW,CAACA,QAAS;EAElE,MAAMd,kBAAkB,KAAKC,WAAWC,SAASC,sBAAsBC;EACvE,KAAK,MAAM4B,SAASD,MAAM;GACtBD,GAAGE,KAAAA;GAEH,IAAIhC,mBAAmBgC,MAAMhC,kBACzB,IAAIS,MAAMC,QAAQsB,MAAMhC,gBAAgB,GACpC,KAAKqB,SAASW,MAAMhC,kBAAkB8B,EAAAA;QAEtC,KAAKT,SAAS,CAACW,MAAMhC,gBAAiB,GAAE8B,EAAAA;EAGpD;CACJ;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.mjs","names":["FindOptionsUtils","InstanceChecker","TreeRepository","TreeRepositoryUtils","ExtraAttributesTreeRepositoryAdapter","EATreeRepository","adapter","options","instance","entity","attributeEntity","ctx","isDataSource","manager","repository","attributeRepository","getRepository","create","entityLike","Array","isArray","map","i","preserveExtraAttributes","source","columns","Set","col","metadata","add","propertyName","rel","relations","key","Object","keys","has","saveOneWithEA","input","attributes","saveWithEA","findOneWithEA","extraOptions","findOneWithEAByPrimaryColumn","value","findManyWithEA","findWithEA","extendOneWithEA","output","extendManyWithEA","entities","findRoots","findDescendantsTree","qb","createDescendantsQueryBuilder","applyOptionsToTreeQueryBuilder","getRawAndEntities","relationMaps","createRelationMaps","raw","buildChildrenEntityTree","depth","findAncestors","findAncestorsTree","createAncestorsQueryBuilder","buildParentEntityTree","updateClosureTable","primaryKeyValue","primaryColumns","getEntityValue","closureTable","closureJunctionTable","executeClosureTableUpdate","connection","transaction","tableName","ancestorColumn","ancestorColumns","descendantColumn","descendantColumns","param","index","driver","createParameter","ancestors","query","databasePath","treeParentRelation","parentId","joinColumns","ancestorIds","filter","ancestor","length","descendants","descendantIds","descendant","placeholders","_","join","ancestorsOfDescendants","acc","reduce","curr","push","ancestorsOfDescendent","ancestorId","indexOf","descendantId"],"sources":["../../../../../src/adapters/database/extra-attribute-repository/tree/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2024-2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type {\n DataSource, \n DeepPartial, \n EntityManager, \n FindManyOptions, \n FindOneOptions, \n FindTreeOptions,\n SelectQueryBuilder,\n} from 'typeorm';\nimport {\n FindOptionsUtils,\n InstanceChecker,\n TreeRepository, \n TreeRepositoryUtils,\n} from 'typeorm';\nimport type { ObjectLiteral } from '@authup/kit';\nimport type { ExtraAttributesRepositoryAdapter } from '../adapter.ts';\nimport type {\n EARepositoryEntityBase, \n EARepositoryFindOptions, \n EARepositoryOptions, \n EARepositorySaveOptions, \n IEARepository,\n} from '../types.ts';\nimport { ExtraAttributesTreeRepositoryAdapter } from './adapter.ts';\n\n/**\n * @see https://github.com/typeorm/typeorm/blob/master/src/repository/TreeRepository.ts\n */\nexport class EATreeRepository<\n T extends ObjectLiteral = ObjectLiteral,\n A extends EARepositoryEntityBase = EARepositoryEntityBase,\n> extends TreeRepository<T> implements IEARepository<T> {\n protected adapter: ExtraAttributesRepositoryAdapter<T, A>;\n\n protected options: EARepositoryOptions<T, A>;\n\n constructor(\n instance: DataSource | EntityManager,\n options: EARepositoryOptions<T, A>,\n ) {\n const {\n entity,\n attributeEntity,\n ...ctx\n } = options;\n\n super(\n entity,\n InstanceChecker.isDataSource(instance) ? instance.manager : instance,\n );\n\n this.options = options;\n this.adapter = new ExtraAttributesTreeRepositoryAdapter<T, A>({\n ...ctx,\n repository: this,\n attributeRepository: this.manager.getRepository(attributeEntity),\n });\n }\n\n // ------------------------------------------------------------------------------\n\n override create(): T;\n\n override create(entityLikeArray: DeepPartial<T>[]): T[];\n\n override create(entityLike: DeepPartial<T>): T;\n\n override create(entityLike?: DeepPartial<T> | DeepPartial<T>[]): T | T[] {\n if (!entityLike) {\n return super.create();\n }\n\n if (Array.isArray(entityLike)) {\n return super.create(entityLike).map((entity, i) => {\n this.preserveExtraAttributes(entity, entityLike[i]);\n return entity;\n });\n }\n\n const entity = super.create(entityLike);\n this.preserveExtraAttributes(entity, entityLike);\n return entity;\n }\n\n private preserveExtraAttributes(entity: T, source: DeepPartial<T>): void {\n const columns = new Set<string>();\n for (const col of this.metadata.columns) {\n columns.add(col.propertyName);\n }\n for (const rel of this.metadata.relations) {\n columns.add(rel.propertyName);\n }\n\n for (const key of Object.keys(source)) {\n if (!columns.has(key) && !(key in entity)) {\n (entity as Record<string, any>)[key] = (source as Record<string, any>)[key];\n }\n }\n }\n\n // ------------------------------------------------------------------------------\n\n async saveOneWithEA<E extends Record<string, any>>(\n input: T & E,\n attributes?: E,\n options?: EARepositorySaveOptions<T>,\n ): Promise<T & E> {\n return this.adapter.saveWithEA(input, attributes, options);\n }\n\n // ------------------------------------------------------------------------------\n\n async findOneWithEA(\n options: FindOneOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<T | undefined> {\n return this.adapter.findOneWithEA(options, extraOptions);\n }\n\n async findOneWithEAByPrimaryColumn<E extends Record<string, any>>(\n value: T[keyof T],\n extraOptions?: EARepositoryFindOptions,\n ): Promise<E> {\n return this.adapter.findOneWithEAByPrimaryColumn(value, extraOptions);\n }\n\n async findManyWithEA<\n E extends Record<string, any>,\n >(\n options: FindManyOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<(T & E)[]> {\n return this.adapter.findWithEA(options, extraOptions);\n }\n\n // ------------------------------------------------------------------------------\n\n async extendOneWithEA<E extends Record<string, any>>(\n entity: T,\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<T & E> {\n const [output] = await this.extendManyWithEA([entity], extraOptions);\n\n return output as (T & E);\n }\n\n async extendManyWithEA<E extends Record<string, any>>(\n entities: T[],\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<(T & E)[]> {\n return this.adapter.extendManyWithEA(entities, extraOptions);\n }\n\n // -------------------------------------------------------------------------------\n\n async findRoots(options?: FindTreeOptions): Promise<T[]> {\n const entities = await super.findRoots(options);\n\n await this.extendManyWithEA(entities);\n\n return entities;\n }\n\n async findDescendantsTree(\n entity: T,\n options?: FindTreeOptions,\n ): Promise<T> {\n const qb: SelectQueryBuilder<T> = this.createDescendantsQueryBuilder(\n 'treeEntity',\n 'treeClosure',\n entity,\n );\n FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, options);\n\n const entities = await qb.getRawAndEntities();\n const relationMaps = TreeRepositoryUtils.createRelationMaps(\n this.manager,\n this.metadata,\n 'treeEntity',\n entities.raw,\n );\n\n await this.extendManyWithEA(entities.entities);\n\n TreeRepositoryUtils.buildChildrenEntityTree(\n this.metadata,\n entity,\n entities.entities,\n relationMaps,\n {\n depth: -1,\n ...options,\n },\n );\n\n // The descendants closure may include the root, but `entity` here is a\n // different reference than the one in `entities.entities`, so its own EA\n // fields are not populated. Load them explicitly so leaf-as-root callers\n // (e.g. policies bound directly to permissions/junctions) see EA.\n await this.extendOneWithEA(entity);\n\n return entity;\n }\n\n async findAncestors(\n entity: T,\n options?: FindTreeOptions,\n ): Promise<T[]> {\n const entities = await super.findAncestors(entity, options);\n\n await this.extendManyWithEA(entities);\n\n return entities;\n }\n\n // -------------------------------------------------------------------------------\n\n async findAncestorsTree(\n entity: T,\n options?: FindTreeOptions,\n ): Promise<T> {\n const qb = this.createAncestorsQueryBuilder(\n 'treeEntity',\n 'treeClosure',\n entity,\n );\n FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, options);\n\n const entities = await qb.getRawAndEntities();\n const relationMaps = TreeRepositoryUtils.createRelationMaps(\n this.manager,\n this.metadata,\n 'treeEntity',\n entities.raw,\n );\n\n await this.extendManyWithEA(entities.entities);\n\n TreeRepositoryUtils.buildParentEntityTree(\n this.metadata,\n entity,\n entities.entities,\n relationMaps,\n );\n return entity;\n }\n\n // -------------------------------------------------------------------------------\n\n async updateClosureTable(entity: T, manager?: EntityManager) {\n const primaryKeyValue = this.metadata.primaryColumns[0].getEntityValue(entity);\n if (!primaryKeyValue) {\n return;\n }\n\n const closureTable = this.metadata.closureJunctionTable;\n if (!closureTable) {\n return;\n }\n\n if (manager) {\n await this.executeClosureTableUpdate(entity, manager);\n } else {\n await this.manager.connection.transaction(async (manager) => {\n await this.executeClosureTableUpdate(entity, manager);\n });\n }\n }\n\n private async executeClosureTableUpdate(entity: T, manager: EntityManager) {\n const primaryKeyValue = this.metadata.primaryColumns[0].getEntityValue(entity);\n\n const { tableName } = this.metadata.closureJunctionTable;\n const ancestorColumn = this.metadata.closureJunctionTable.ancestorColumns[0];\n const descendantColumn = this.metadata.closureJunctionTable.descendantColumns[0];\n\n const param = (index: number) => manager.connection.driver.createParameter(`p${index}`, index);\n\n // 1. Get All ancestors of current entity\n const ancestors = await manager.query<Record<string, any>[]>(\n `SELECT *\n FROM ${tableName}\n WHERE ${ancestorColumn.databasePath} != ${descendantColumn.databasePath} AND\n ${descendantColumn.databasePath} = ${param(0)} AND\n ${ancestorColumn.databasePath} != ${param(1)}`,\n [primaryKeyValue, primaryKeyValue],\n );\n\n if (!this.metadata.treeParentRelation) {\n return;\n }\n\n const parentId = this.metadata.treeParentRelation.joinColumns[0].getEntityValue(entity);\n\n let ancestorIds : string[];\n if (parentId) {\n ancestorIds = [\n parentId,\n ...ancestors\n .filter((ancestor) => ancestor[ancestorColumn.databasePath] !== parentId)\n .map((ancestor) => ancestor[ancestorColumn.databasePath]),\n ];\n } else {\n ancestorIds = ancestors.map((ancestor) => ancestor[ancestorColumn.databasePath]);\n }\n\n if (ancestorIds.length === 0) {\n return;\n }\n\n // 2. Get All descendants of current entity.\n const descendants = await manager.query<Record<string, any>[]>(\n `SELECT *\n FROM ${tableName}\n WHERE ${ancestorColumn.databasePath} != ${descendantColumn.databasePath} AND\n ${ancestorColumn.databasePath} = ${param(0)} AND\n ${descendantColumn.databasePath} != ${param(1)}`,\n [primaryKeyValue, primaryKeyValue],\n );\n\n if (parentId) {\n // 3. get all descendant\n const descendantIds = descendants\n .map((descendant) => descendant[descendantColumn.databasePath]);\n\n if (descendantIds.length > 0) {\n // 4. get all ancestors of each descendant\n const placeholders = descendantIds.map((_, i) => param(i + 1)).join(',');\n const ancestorsOfDescendants = await manager.query<Record<string, any>[]>(\n `SELECT *\n FROM ${tableName}\n WHERE\n ${ancestorColumn.databasePath} != ${param(0)} AND\n ${ancestorColumn.databasePath} != ${descendantColumn.databasePath} AND\n ${descendantColumn.databasePath} IN (${placeholders})`,\n [primaryKeyValue, ...descendantIds],\n );\n\n const acc = ancestorsOfDescendants.reduce((acc, curr) => {\n if (!acc[curr[descendantColumn.databasePath]]) {\n acc[curr[descendantColumn.databasePath]] = [];\n }\n\n acc[curr[descendantColumn.databasePath]].push(curr[ancestorColumn.databasePath]);\n return acc;\n }, {} as Record<string, string[]>);\n\n // 5. Check if for each child a relation exists with each ancestor (create if not exist)\n for (const descendant of descendantIds) {\n const ancestorsOfDescendent = acc[descendant] ?? [];\n\n for (const ancestorId of ancestorIds) {\n const index = ancestorsOfDescendent.indexOf(ancestorId);\n if (index === -1) {\n await manager.query(\n `INSERT INTO ${tableName}\n (${ancestorColumn.databasePath}, ${descendantColumn.databasePath})\n VALUES (${param(0)}, ${param(1)})`,\n [ancestorId, descendant],\n );\n }\n }\n }\n }\n } else {\n const descendantIds = [\n primaryKeyValue,\n ...descendants.map((descendant) => descendant[descendantColumn.databasePath]),\n ];\n\n for (const ancestorId of ancestorIds) {\n for (const descendantId of descendantIds) {\n await manager.query(\n `DELETE FROM ${tableName}\n WHERE ${ancestorColumn.databasePath} = ${param(0)}\n AND ${descendantColumn.databasePath} = ${param(1)}`,\n [ancestorId, descendantId],\n );\n }\n }\n }\n }\n}\n"],"mappings":";;;;;;;;GAoCA,IAAaK,mBAAb,cAGUH,eAAAA;CACII;CAEAC;CAEV,YACIC,UACAD,SACF;EACE,MAAM,EACFE,QACAC,iBACA,GAAGC,QACHJ;EAEJ,MACIE,QACAR,gBAAgBW,aAAaJ,QAAAA,IAAYA,SAASK,UAAUL,QAAAA;EAGhE,KAAKD,UAAUA;EACf,KAAKD,UAAU,IAAIF,qCAA2C;GAC1D,GAAGO;GACHG,YAAY;GACZC,qBAAqB,KAAKF,QAAQG,cAAcN,eAAAA;EACpD,CAAA;CACJ;CAUSO,OAAOC,YAAyD;EACrE,IAAI,CAACA,YACD,OAAO,MAAMD,OAAAA;EAGjB,IAAIE,MAAMC,QAAQF,UAAAA,GACd,OAAO,MAAMD,OAAOC,UAAAA,CAAAA,CAAYG,KAAKZ,QAAQa,MAAAA;GACzC,KAAKC,wBAAwBd,QAAQS,WAAWI,EAAE;GAClD,OAAOb;EACX,CAAA;EAGJ,MAAMA,SAAS,MAAMQ,OAAOC,UAAAA;EAC5B,KAAKK,wBAAwBd,QAAQS,UAAAA;EACrC,OAAOT;CACX;CAEQc,wBAAwBd,QAAWe,QAA8B;EACrE,MAAMC,0BAAU,IAAIC,IAAAA;EACpB,KAAK,MAAMC,OAAO,KAAKC,SAASH,SAC5BA,QAAQI,IAAIF,IAAIG,YAAY;EAEhC,KAAK,MAAMC,OAAO,KAAKH,SAASI,WAC5BP,QAAQI,IAAIE,IAAID,YAAY;EAGhC,KAAK,MAAMG,OAAOC,OAAOC,KAAKX,MAAAA,GAC1B,IAAI,CAACC,QAAQW,IAAIH,GAAAA,KAAQ,EAAEA,OAAOxB,SAC7BA,OAA+BwB,OAAO,OAAgCA;CAGnF;CAIA,MAAMI,cACFC,OACAC,YACAhC,SACc;EACd,OAAO,KAAKD,QAAQkC,WAAWF,OAAOC,YAAYhC,OAAAA;CACtD;CAIA,MAAMkC,cACFlC,SACAmC,eAAwC,CAAC,GACnB;EACtB,OAAO,KAAKpC,QAAQmC,cAAclC,SAASmC,YAAAA;CAC/C;CAEA,MAAMC,6BACFC,OACAF,cACU;EACV,OAAO,KAAKpC,QAAQqC,6BAA6BC,OAAOF,YAAAA;CAC5D;CAEA,MAAMG,eAGFtC,SACAmC,eAAwC,CAAC,GACvB;EAClB,OAAO,KAAKpC,QAAQwC,WAAWvC,SAASmC,YAAAA;CAC5C;CAIA,MAAMK,gBACFtC,QACAiC,eAAwC,CAAC,GAC3B;EACd,MAAM,CAACM,UAAU,MAAM,KAAKC,iBAAiB,CAACxC,MAAAA,GAASiC,YAAAA;EAEvD,OAAOM;CACX;CAEA,MAAMC,iBACFC,UACAR,eAAwC,CAAC,GACvB;EAClB,OAAO,KAAKpC,QAAQ2C,iBAAiBC,UAAUR,YAAAA;CACnD;CAIA,MAAMS,UAAU5C,SAAyC;EACrD,MAAM2C,WAAW,MAAM,MAAMC,UAAU5C,OAAAA;EAEvC,MAAM,KAAK0C,iBAAiBC,QAAAA;EAE5B,OAAOA;CACX;CAEA,MAAME,oBACF3C,QACAF,SACU;EACV,MAAM8C,KAA4B,KAAKC,8BACnC,cACA,eACA7C,MAAAA;EAEJT,iBAAiBuD,+BAA+BF,IAAI9C,OAAAA;EAEpD,MAAM2C,WAAW,MAAMG,GAAGG,kBAAiB;EAC3C,MAAMC,eAAetD,oBAAoBuD,mBACrC,KAAK7C,SACL,KAAKe,UACL,cACAsB,SAASS,GAAG;EAGhB,MAAM,KAAKV,iBAAiBC,SAASA,QAAQ;EAE7C/C,oBAAoByD,wBAChB,KAAKhC,UACLnB,QACAyC,SAASA,UACTO,cACA;GACII,OAAO;GACP,GAAGtD;EACP,CAAA;EAOJ,MAAM,KAAKwC,gBAAgBtC,MAAAA;EAE3B,OAAOA;CACX;CAEA,MAAMqD,cACFrD,QACAF,SACY;EACZ,MAAM2C,WAAW,MAAM,MAAMY,cAAcrD,QAAQF,OAAAA;EAEnD,MAAM,KAAK0C,iBAAiBC,QAAAA;EAE5B,OAAOA;CACX;CAIA,MAAMa,kBACFtD,QACAF,SACU;EACV,MAAM8C,KAAK,KAAKW,4BACZ,cACA,eACAvD,MAAAA;EAEJT,iBAAiBuD,+BAA+BF,IAAI9C,OAAAA;EAEpD,MAAM2C,WAAW,MAAMG,GAAGG,kBAAiB;EAC3C,MAAMC,eAAetD,oBAAoBuD,mBACrC,KAAK7C,SACL,KAAKe,UACL,cACAsB,SAASS,GAAG;EAGhB,MAAM,KAAKV,iBAAiBC,SAASA,QAAQ;EAE7C/C,oBAAoB8D,sBAChB,KAAKrC,UACLnB,QACAyC,SAASA,UACTO,YAAAA;EAEJ,OAAOhD;CACX;CAIA,MAAMyD,mBAAmBzD,QAAWI,SAAyB;EAEzD,IAAI,CADoB,KAAKe,SAASwC,eAAe,EAAE,CAACC,eAAe5D,MAClE0D,GACD;EAIJ,IAAI,CADiB,KAAKvC,SAAS2C,sBAE/B;EAGJ,IAAI1D,SACA,MAAM,KAAK2D,0BAA0B/D,QAAQI,OAAAA;OAE7C,MAAM,KAAKA,QAAQ4D,WAAWC,YAAY,OAAO7D,YAAAA;GAC7C,MAAM,KAAK2D,0BAA0B/D,QAAQI,OAAAA;EACjD,CAAA;CAER;CAEA,MAAc2D,0BAA0B/D,QAAWI,SAAwB;EACvE,MAAMsD,kBAAkB,KAAKvC,SAASwC,eAAe,EAAE,CAACC,eAAe5D,MAAAA;EAEvE,MAAM,EAAEkE,cAAc,KAAK/C,SAAS2C;EACpC,MAAMK,iBAAiB,KAAKhD,SAAS2C,qBAAqBM,gBAAgB;EAC1E,MAAMC,mBAAmB,KAAKlD,SAAS2C,qBAAqBQ,kBAAkB;EAE9E,MAAMC,SAASC,UAAkBpE,QAAQ4D,WAAWS,OAAOC,gBAAgB,IAAIF,SAASA,KAAAA;EAGxF,MAAMG,YAAY,MAAMvE,QAAQwE,MAC5B;wBACYV,UAAU;yBACTC,eAAeU,aAAa,MAAMR,iBAAiBQ,aAAa;yBAChER,iBAAiBQ,aAAa,KAAKN,MAAM,CAAA,EAAG;yBAC5CJ,eAAeU,aAAa,MAAMN,MAAM,CAAA,KACrD,CAACb,iBAAiBA,eAAAA,CAAgB;EAGtC,IAAI,CAAC,KAAKvC,SAAS2D,oBACf;EAGJ,MAAMC,WAAW,KAAK5D,SAAS2D,mBAAmBE,YAAY,EAAE,CAACpB,eAAe5D,MAAAA;EAEhF,IAAIiF;EACJ,IAAIF,UACAE,cAAc,CACVF,UAAAA,GACGJ,UACEO,QAAQC,aAAaA,SAAShB,eAAeU,kBAAkBE,QAAAA,CAAAA,CAC/DnE,KAAKuE,aAAaA,SAAShB,eAAeU,aAAa,CAAA;OAGhEI,cAAcN,UAAU/D,KAAKuE,aAAaA,SAAShB,eAAeU,aAAa;EAGnF,IAAII,YAAYG,WAAW,GACvB;EAIJ,MAAMC,cAAc,MAAMjF,QAAQwE,MAC9B;4BACgBV,UAAU;6BACTC,eAAeU,aAAa,MAAMR,iBAAiBQ,aAAa;6BAChEV,eAAeU,aAAa,KAAKN,MAAM,CAAA,EAAG;6BAC1CF,iBAAiBQ,aAAa,MAAMN,MAAM,CAAA,KAC3D,CAACb,iBAAiBA,eAAAA,CAAgB;EAGtC,IAAIqB,UAAU;GAEV,MAAMO,gBAAgBD,YACjBzE,KAAK2E,eAAeA,WAAWlB,iBAAiBQ,aAAa;GAElE,IAAIS,cAAcF,SAAS,GAAG;IAE1B,MAAMI,eAAeF,cAAc1E,KAAK6E,GAAG5E,MAAM0D,MAAM1D,IAAI,CAAA,CAAA,CAAA,CAAI6E,KAAK,GAAA;IAWpE,MAAME,OAAMD,MAVyBvF,QAAQwE,MACzC;gCACYV,UAAU;;+BAEXC,eAAeU,aAAa,MAAMN,MAAM,CAAA,EAAG;+BAC3CJ,eAAeU,aAAa,MAAMR,iBAAiBQ,aAAa;+BAChER,iBAAiBQ,aAAa,OAAOW,aAAa,IAC7D,CAAC9B,iBAAAA,GAAoB4B,aAAAA,CAAc,EAAA,CAGJO,QAAQD,KAAKE,SAAAA;KAC5C,IAAI,CAACF,IAAIE,KAAKzB,iBAAiBQ,gBAC3Be,IAAIE,KAAKzB,iBAAiBQ,iBAAiB,CAAA;KAG/Ce,IAAIE,KAAKzB,iBAAiBQ,cAAc,CAACkB,KAAKD,KAAK3B,eAAeU,aAAa;KAC/E,OAAOe;IACX,GAAG,CAAC,CAAA;IAGJ,KAAK,MAAML,cAAcD,eAAe;KACpC,MAAMU,wBAAwBJ,IAAIL,eAAe,CAAA;KAEjD,KAAK,MAAMU,cAAchB,aAErB,IADce,sBAAsBE,QAAQD,UACxCzB,MAAU,IACV,MAAMpE,QAAQwE,MACV,eAAeV,UAAU;uCAClBC,eAAeU,aAAa,IAAIR,iBAAiBQ,aAAa;8CACvDN,MAAM,CAAA,EAAG,IAAIA,MAAM,CAAA,EAAG,IACpC,CAAC0B,YAAYV,UAAAA,CAAW;IAIxC;GACJ;EACJ,OAAO;GACH,MAAMD,gBAAgB,CAClB5B,iBAAAA,GACG2B,YAAYzE,KAAK2E,eAAeA,WAAWlB,iBAAiBQ,aAAa,CAAA;GAGhF,KAAK,MAAMoB,cAAchB,aACrB,KAAK,MAAMkB,gBAAgBb,eACvB,MAAMlF,QAAQwE,MACV,eAAeV,UAAU;oCACbC,eAAeU,aAAa,KAAKN,MAAM,CAAA,EAAG;oCAC1CF,iBAAiBQ,aAAa,KAAKN,MAAM,CAAA,KACrD,CAAC0B,YAAYE,YAAAA,CAAa;EAI1C;CACJ;AACJ"}
|
|
1
|
+
{"version":3,"file":"repository.mjs","names":["FindOptionsUtils","InstanceChecker","TreeRepository","TreeRepositoryUtils","ExtraAttributesTreeRepositoryAdapter","EATreeRepository","adapter","options","instance","entity","attributeEntity","ctx","isDataSource","manager","repository","attributeRepository","getRepository","create","entityLike","Array","isArray","map","i","preserveExtraAttributes","source","columns","Set","col","metadata","add","propertyName","rel","relations","key","Object","keys","has","saveOneWithEA","input","attributes","saveWithEA","findOneWithEA","extraOptions","findOneWithEAByPrimaryColumn","value","findManyWithEA","findWithEA","extendOneWithEA","output","extendManyWithEA","entities","findRoots","findDescendantsTree","qb","createDescendantsQueryBuilder","applyOptionsToTreeQueryBuilder","getRawAndEntities","relationMaps","createRelationMaps","raw","buildChildrenEntityTree","depth","findAncestors","findAncestorsTree","createAncestorsQueryBuilder","buildParentEntityTree","updateClosureTable","primaryKeyValue","primaryColumns","getEntityValue","closureTable","closureJunctionTable","executeClosureTableUpdate","connection","transaction","tableName","ancestorColumn","ancestorColumns","descendantColumn","descendantColumns","param","index","driver","createParameter","ancestors","query","databasePath","treeParentRelation","parentId","joinColumns","ancestorIds","filter","ancestor","length","descendants","descendantIds","descendant","placeholders","_","join","ancestorsOfDescendants","acc","reduce","curr","push","ancestorsOfDescendent","ancestorId","indexOf","descendantId"],"sources":["../../../../../src/adapters/database/extra-attribute-repository/tree/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2024-2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type {\n DataSource, \n DeepPartial, \n EntityManager, \n FindManyOptions, \n FindOneOptions, \n FindTreeOptions,\n SelectQueryBuilder,\n} from 'typeorm';\nimport {\n FindOptionsUtils,\n InstanceChecker,\n TreeRepository, \n TreeRepositoryUtils,\n} from 'typeorm';\nimport type { ObjectLiteral } from '@authup/kit';\nimport type { ExtraAttributesRepositoryAdapter } from '../adapter.ts';\nimport type {\n EARepositoryEntityBase, \n EARepositoryFindOptions, \n EARepositoryOptions, \n EARepositorySaveOptions, \n IEARepository,\n} from '../types.ts';\nimport { ExtraAttributesTreeRepositoryAdapter } from './adapter.ts';\n\n/**\n * @see https://github.com/typeorm/typeorm/blob/master/src/repository/TreeRepository.ts\n */\nexport class EATreeRepository<\n T extends ObjectLiteral = ObjectLiteral,\n A extends EARepositoryEntityBase = EARepositoryEntityBase,\n> extends TreeRepository<T> implements IEARepository<T> {\n protected adapter: ExtraAttributesRepositoryAdapter<T, A>;\n\n protected options: EARepositoryOptions<T, A>;\n\n constructor(\n instance: DataSource | EntityManager,\n options: EARepositoryOptions<T, A>,\n ) {\n const {\n entity,\n attributeEntity,\n ...ctx\n } = options;\n\n super(\n entity,\n InstanceChecker.isDataSource(instance) ? instance.manager : instance,\n );\n\n this.options = options;\n this.adapter = new ExtraAttributesTreeRepositoryAdapter<T, A>({\n ...ctx,\n repository: this,\n attributeRepository: this.manager.getRepository(attributeEntity),\n });\n }\n\n // ------------------------------------------------------------------------------\n\n override create(): T;\n\n override create(entityLikeArray: DeepPartial<T>[]): T[];\n\n override create(entityLike: DeepPartial<T>): T;\n\n override create(entityLike?: DeepPartial<T> | DeepPartial<T>[]): T | T[] {\n if (!entityLike) {\n return super.create();\n }\n\n if (Array.isArray(entityLike)) {\n return super.create(entityLike).map((entity, i) => {\n this.preserveExtraAttributes(entity, entityLike[i]);\n return entity;\n });\n }\n\n const entity = super.create(entityLike);\n this.preserveExtraAttributes(entity, entityLike);\n return entity;\n }\n\n private preserveExtraAttributes(entity: T, source: DeepPartial<T>): void {\n const columns = new Set<string>();\n for (const col of this.metadata.columns) {\n columns.add(col.propertyName);\n }\n for (const rel of this.metadata.relations) {\n columns.add(rel.propertyName);\n }\n\n for (const key of Object.keys(source)) {\n if (!columns.has(key) && !(key in entity)) {\n (entity as Record<string, any>)[key] = (source as Record<string, any>)[key];\n }\n }\n }\n\n // ------------------------------------------------------------------------------\n\n async saveOneWithEA<E extends Record<string, any>>(\n input: T & E,\n attributes?: E,\n options?: EARepositorySaveOptions<T>,\n ): Promise<T & E> {\n return this.adapter.saveWithEA(input, attributes, options);\n }\n\n // ------------------------------------------------------------------------------\n\n async findOneWithEA(\n options: FindOneOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<T | undefined> {\n return this.adapter.findOneWithEA(options, extraOptions);\n }\n\n async findOneWithEAByPrimaryColumn<E extends Record<string, any>>(\n value: T[keyof T],\n extraOptions?: EARepositoryFindOptions,\n ): Promise<E> {\n return this.adapter.findOneWithEAByPrimaryColumn(value, extraOptions);\n }\n\n async findManyWithEA<\n E extends Record<string, any>,\n >(\n options: FindManyOptions<T>,\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<(T & E)[]> {\n return this.adapter.findWithEA(options, extraOptions);\n }\n\n // ------------------------------------------------------------------------------\n\n async extendOneWithEA<E extends Record<string, any>>(\n entity: T,\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<T & E> {\n const [output] = await this.extendManyWithEA([entity], extraOptions);\n\n return output as (T & E);\n }\n\n async extendManyWithEA<E extends Record<string, any>>(\n entities: T[],\n extraOptions: EARepositoryFindOptions = {},\n ): Promise<(T & E)[]> {\n return this.adapter.extendManyWithEA(entities, extraOptions);\n }\n\n // -------------------------------------------------------------------------------\n\n async findRoots(options?: FindTreeOptions): Promise<T[]> {\n const entities = await super.findRoots(options);\n\n await this.extendManyWithEA(entities);\n\n return entities;\n }\n\n async findDescendantsTree(\n entity: T,\n options?: FindTreeOptions,\n ): Promise<T> {\n const qb: SelectQueryBuilder<T> = this.createDescendantsQueryBuilder(\n 'treeEntity',\n 'treeClosure',\n entity,\n );\n FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, options);\n\n const entities = await qb.getRawAndEntities();\n const relationMaps = TreeRepositoryUtils.createRelationMaps(\n this.manager,\n this.metadata,\n 'treeEntity',\n entities.raw,\n );\n\n await this.extendManyWithEA(entities.entities);\n\n TreeRepositoryUtils.buildChildrenEntityTree(\n this.metadata,\n entity,\n entities.entities,\n relationMaps,\n {\n depth: -1,\n ...options,\n },\n );\n\n // The descendants closure may include the root, but `entity` here is a\n // different reference than the one in `entities.entities`, so its own EA\n // fields are not populated. Load them explicitly so leaf-as-root callers\n // (e.g. policies bound directly to permissions/junctions) see EA.\n await this.extendOneWithEA(entity);\n\n return entity;\n }\n\n async findAncestors(\n entity: T,\n options?: FindTreeOptions,\n ): Promise<T[]> {\n const entities = await super.findAncestors(entity, options);\n\n await this.extendManyWithEA(entities);\n\n return entities;\n }\n\n // -------------------------------------------------------------------------------\n\n async findAncestorsTree(\n entity: T,\n options?: FindTreeOptions,\n ): Promise<T> {\n const qb = this.createAncestorsQueryBuilder(\n 'treeEntity',\n 'treeClosure',\n entity,\n );\n FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, options);\n\n const entities = await qb.getRawAndEntities();\n const relationMaps = TreeRepositoryUtils.createRelationMaps(\n this.manager,\n this.metadata,\n 'treeEntity',\n entities.raw,\n );\n\n await this.extendManyWithEA(entities.entities);\n\n TreeRepositoryUtils.buildParentEntityTree(\n this.metadata,\n entity,\n entities.entities,\n relationMaps,\n );\n return entity;\n }\n\n // -------------------------------------------------------------------------------\n\n async updateClosureTable(entity: T, manager?: EntityManager) {\n const primaryKeyValue = this.metadata.primaryColumns[0].getEntityValue(entity);\n if (!primaryKeyValue) {\n return;\n }\n\n const closureTable = this.metadata.closureJunctionTable;\n if (!closureTable) {\n return;\n }\n\n if (manager) {\n await this.executeClosureTableUpdate(entity, manager);\n } else {\n await this.manager.connection.transaction(async (manager) => {\n await this.executeClosureTableUpdate(entity, manager);\n });\n }\n }\n\n private async executeClosureTableUpdate(entity: T, manager: EntityManager) {\n const primaryKeyValue = this.metadata.primaryColumns[0].getEntityValue(entity);\n\n const { tableName } = this.metadata.closureJunctionTable;\n const ancestorColumn = this.metadata.closureJunctionTable.ancestorColumns[0];\n const descendantColumn = this.metadata.closureJunctionTable.descendantColumns[0];\n\n const param = (index: number) => manager.connection.driver.createParameter(`p${index}`, index);\n\n // 1. Get All ancestors of current entity\n const ancestors = await manager.query<Record<string, any>[]>(\n `SELECT *\n FROM ${tableName}\n WHERE ${ancestorColumn.databasePath} != ${descendantColumn.databasePath} AND\n ${descendantColumn.databasePath} = ${param(0)} AND\n ${ancestorColumn.databasePath} != ${param(1)}`,\n [primaryKeyValue, primaryKeyValue],\n );\n\n if (!this.metadata.treeParentRelation) {\n return;\n }\n\n const parentId = this.metadata.treeParentRelation.joinColumns[0].getEntityValue(entity);\n\n let ancestorIds : string[];\n if (parentId) {\n ancestorIds = [\n parentId,\n ...ancestors\n .filter((ancestor) => ancestor[ancestorColumn.databasePath] !== parentId)\n .map((ancestor) => ancestor[ancestorColumn.databasePath]),\n ];\n } else {\n ancestorIds = ancestors.map((ancestor) => ancestor[ancestorColumn.databasePath]);\n }\n\n if (ancestorIds.length === 0) {\n return;\n }\n\n // 2. Get All descendants of current entity.\n const descendants = await manager.query<Record<string, any>[]>(\n `SELECT *\n FROM ${tableName}\n WHERE ${ancestorColumn.databasePath} != ${descendantColumn.databasePath} AND\n ${ancestorColumn.databasePath} = ${param(0)} AND\n ${descendantColumn.databasePath} != ${param(1)}`,\n [primaryKeyValue, primaryKeyValue],\n );\n\n if (parentId) {\n // 3. get all descendant\n const descendantIds = descendants\n .map((descendant) => descendant[descendantColumn.databasePath]);\n\n if (descendantIds.length > 0) {\n // 4. get all ancestors of each descendant\n const placeholders = descendantIds.map((_, i) => param(i + 1)).join(',');\n const ancestorsOfDescendants = await manager.query<Record<string, any>[]>(\n `SELECT *\n FROM ${tableName}\n WHERE\n ${ancestorColumn.databasePath} != ${param(0)} AND\n ${ancestorColumn.databasePath} != ${descendantColumn.databasePath} AND\n ${descendantColumn.databasePath} IN (${placeholders})`,\n [primaryKeyValue, ...descendantIds],\n );\n\n const acc = ancestorsOfDescendants.reduce((acc, curr) => {\n if (!acc[curr[descendantColumn.databasePath]]) {\n acc[curr[descendantColumn.databasePath]] = [];\n }\n\n acc[curr[descendantColumn.databasePath]].push(curr[ancestorColumn.databasePath]);\n return acc;\n }, {} as Record<string, string[]>);\n\n // 5. Check if for each child a relation exists with each ancestor (create if not exist)\n for (const descendant of descendantIds) {\n const ancestorsOfDescendent = acc[descendant] ?? [];\n\n for (const ancestorId of ancestorIds) {\n const index = ancestorsOfDescendent.indexOf(ancestorId);\n if (index === -1) {\n await manager.query(\n `INSERT INTO ${tableName}\n (${ancestorColumn.databasePath}, ${descendantColumn.databasePath})\n VALUES (${param(0)}, ${param(1)})`,\n [ancestorId, descendant],\n );\n }\n }\n }\n }\n } else {\n const descendantIds = [\n primaryKeyValue,\n ...descendants.map((descendant) => descendant[descendantColumn.databasePath]),\n ];\n\n for (const ancestorId of ancestorIds) {\n for (const descendantId of descendantIds) {\n await manager.query(\n `DELETE FROM ${tableName}\n WHERE ${ancestorColumn.databasePath} = ${param(0)}\n AND ${descendantColumn.databasePath} = ${param(1)}`,\n [ancestorId, descendantId],\n );\n }\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1779267068441-Default.mjs","names":["NAME_COLLISION_CHECKS","table","groupBy","where","NAME_TABLES","map","c","Default1779267068441","name","up","queryRunner","check","join","rows","query","length","Error","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1779267068441-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\ntype CollisionCheck = {\n table: string,\n groupBy: string[],\n where?: string,\n};\n\nconst NAME_COLLISION_CHECKS: CollisionCheck[] = [\n { table: 'auth_clients', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_robots', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_users', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_realms', groupBy: ['LOWER(TRIM(name))'] },\n {\n table: 'auth_roles', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_scopes', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n {\n table: 'auth_permissions', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_policies', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n { table: 'auth_identity_providers', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n];\n\nconst NAME_TABLES = NAME_COLLISION_CHECKS.map((c) => c.table);\n\nexport class Default1779267068441 implements MigrationInterface {\n name = 'Default1779267068441';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n for (const check of NAME_COLLISION_CHECKS) {\n const groupBy = check.groupBy.join(', ');\n const rows = await queryRunner.query(`\n SELECT ${groupBy}\n FROM \\`${check.table}\\`\n ${check.where ? `WHERE ${check.where}` : ''}\n GROUP BY ${groupBy}\n HAVING COUNT(*) > 1\n `);\n if (rows.length > 0) {\n throw new Error(\n `Canonical-name migration aborted: \\`${check.table}\\` has ${rows.length} collision group(s) on ${groupBy}. ` +\n 'Merge the conflicting rows manually before re-running.',\n );\n }\n }\n\n for (const table of NAME_TABLES) {\n await queryRunner.query(`\n UPDATE \\`${table}\\`\n SET \\`name\\` = LOWER(TRIM(\\`name\\`))\n WHERE BINARY \\`name\\` <> LOWER(TRIM(\\`name\\`))\n `);\n }\n\n await queryRunner.query(`\n UPDATE \\`auth_users\\`\n SET \\`email\\` = LOWER(TRIM(\\`email\\`))\n WHERE \\`email\\` IS NOT NULL\n AND BINARY \\`email\\` <> LOWER(TRIM(\\`email\\`))\n `);\n\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\` DROP FOREIGN KEY \\`FK_b1797e07106b4af61280b8edac1\\`\n `);\n await queryRunner.query(`\n DROP INDEX \\`IDX_b1797e07106b4af61280b8edac\\` ON \\`auth_users\\`\n `);\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\` DROP COLUMN \\`client_id\\`\n `);\n }\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\`\n ADD \\`client_id\\` varchar(255) NULL\n `);\n await queryRunner.query(`\n CREATE INDEX \\`IDX_b1797e07106b4af61280b8edac\\` ON \\`auth_users\\` (\\`client_id\\`)\n `);\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\`\n ADD CONSTRAINT \\`FK_b1797e07106b4af61280b8edac1\\` FOREIGN KEY (\\`client_id\\`) REFERENCES \\`auth_clients\\`(\\`id\\`) ON DELETE CASCADE ON UPDATE NO ACTION\n `);\n }\n}\n"],"mappings":";;;;AAQA,MAAMA,wBAA0C;CAC5C;EAAEC,OAAO;EAAgBC,SAAS,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"1779267068441-Default.mjs","names":["NAME_COLLISION_CHECKS","table","groupBy","where","NAME_TABLES","map","c","Default1779267068441","name","up","queryRunner","check","join","rows","query","length","Error","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1779267068441-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\ntype CollisionCheck = {\n table: string,\n groupBy: string[],\n where?: string,\n};\n\nconst NAME_COLLISION_CHECKS: CollisionCheck[] = [\n { table: 'auth_clients', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_robots', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_users', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_realms', groupBy: ['LOWER(TRIM(name))'] },\n {\n table: 'auth_roles', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_scopes', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n {\n table: 'auth_permissions', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_policies', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n { table: 'auth_identity_providers', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n];\n\nconst NAME_TABLES = NAME_COLLISION_CHECKS.map((c) => c.table);\n\nexport class Default1779267068441 implements MigrationInterface {\n name = 'Default1779267068441';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n for (const check of NAME_COLLISION_CHECKS) {\n const groupBy = check.groupBy.join(', ');\n const rows = await queryRunner.query(`\n SELECT ${groupBy}\n FROM \\`${check.table}\\`\n ${check.where ? `WHERE ${check.where}` : ''}\n GROUP BY ${groupBy}\n HAVING COUNT(*) > 1\n `);\n if (rows.length > 0) {\n throw new Error(\n `Canonical-name migration aborted: \\`${check.table}\\` has ${rows.length} collision group(s) on ${groupBy}. ` +\n 'Merge the conflicting rows manually before re-running.',\n );\n }\n }\n\n for (const table of NAME_TABLES) {\n await queryRunner.query(`\n UPDATE \\`${table}\\`\n SET \\`name\\` = LOWER(TRIM(\\`name\\`))\n WHERE BINARY \\`name\\` <> LOWER(TRIM(\\`name\\`))\n `);\n }\n\n await queryRunner.query(`\n UPDATE \\`auth_users\\`\n SET \\`email\\` = LOWER(TRIM(\\`email\\`))\n WHERE \\`email\\` IS NOT NULL\n AND BINARY \\`email\\` <> LOWER(TRIM(\\`email\\`))\n `);\n\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\` DROP FOREIGN KEY \\`FK_b1797e07106b4af61280b8edac1\\`\n `);\n await queryRunner.query(`\n DROP INDEX \\`IDX_b1797e07106b4af61280b8edac\\` ON \\`auth_users\\`\n `);\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\` DROP COLUMN \\`client_id\\`\n `);\n }\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\`\n ADD \\`client_id\\` varchar(255) NULL\n `);\n await queryRunner.query(`\n CREATE INDEX \\`IDX_b1797e07106b4af61280b8edac\\` ON \\`auth_users\\` (\\`client_id\\`)\n `);\n await queryRunner.query(`\n ALTER TABLE \\`auth_users\\`\n ADD CONSTRAINT \\`FK_b1797e07106b4af61280b8edac1\\` FOREIGN KEY (\\`client_id\\`) REFERENCES \\`auth_clients\\`(\\`id\\`) ON DELETE CASCADE ON UPDATE NO ACTION\n `);\n }\n}\n"],"mappings":";;;;AAQA,MAAMA,wBAA0C;CAC5C;EAAEC,OAAO;EAAgBC,SAAS,CAAC,qBAAqB,UAAW;CAAC;CACpE;EAAED,OAAO;EAAeC,SAAS,CAAC,qBAAqB,UAAW;CAAC;CACnE;EAAED,OAAO;EAAcC,SAAS,CAAC,qBAAqB,UAAW;CAAC;CAClE;EAAED,OAAO;EAAeC,SAAS,CAAC,mBAAoB;CAAC;CACvD;EACID,OAAO;EACPC,SAAS;GAAC;GAAqB;GAAa;EAAW;EACvDC,OAAO;CACX;CACA;EACIF,OAAO;EACPC,SAAS,CAAC,qBAAqB,UAAW;EAC1CC,OAAO;CACX;CACA;EACIF,OAAO;EACPC,SAAS;GAAC;GAAqB;GAAa;EAAW;EACvDC,OAAO;CACX;CACA;EACIF,OAAO;EACPC,SAAS,CAAC,qBAAqB,UAAW;EAC1CC,OAAO;CACX;CACA;EAAEF,OAAO;EAA2BC,SAAS,CAAC,qBAAqB,UAAW;CAAC;AAClF;AAED,MAAME,cAAcJ,sBAAsBK,KAAKC,MAAMA,EAAEL,KAAK;AAE5D,IAAaM,uBAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGC,aAAyC;EACrD,KAAK,MAAMC,SAASX,uBAAuB;GACvC,MAAME,UAAUS,MAAMT,QAAQU,KAAK,IAAA;GACnC,MAAMC,OAAO,MAAMH,YAAYI,MAAM;yBACxBZ,QAAQ;yBACRS,MAAMV,MAAM;kBACnBU,MAAMR,QAAQ,SAASQ,MAAMR,UAAU,GAAG;2BACjCD,QAAQ;;aAEtB;GACD,IAAIW,KAAKE,SAAS,GACd,MAAM,IAAIC,MACN,uCAAuCL,MAAMV,MAAM,SAASY,KAAKE,OAAO,yBAAyBb,QAAQ,yDACzG;EAGZ;EAEA,KAAK,MAAMD,SAASG,aAChB,MAAMM,YAAYI,MAAM;2BACTb,MAAM;;;aAGpB;EAGL,MAAMS,YAAYI,MAAM;;;;;SAKvB;EAED,MAAMJ,YAAYI,MAAM;;SAEvB;EACD,MAAMJ,YAAYI,MAAM;;SAEvB;EACD,MAAMJ,YAAYI,MAAM;;SAEvB;CACL;CACA,MAAaG,KAAKP,aAAyC;EACvD,MAAMA,YAAYI,MAAM;;;SAGvB;EACD,MAAMJ,YAAYI,MAAM;;SAEvB;EACD,MAAMJ,YAAYI,MAAM;;;SAGvB;CACL;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1779300000000-Default.mjs","names":["JUNCTION_TABLES","SCOPE_BY_POLICY","policy","scope","Default1779300000000","name","up","queryRunner","table","query","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1779300000000-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * realm_scope enum on the four permission-junction tables (fail-closed realm scoping).\n *\n * Adds the coarse, actor-relative `realm_scope` column (default 'own') and migrates the\n * realm-scoping that previously lived in policies into the column. The redundant system\n * realm policies (`system.realm-match` child of `system.default`,\n * `system.realm-bound`, `system.realm-or-global`) are deleted here as a deterministic\n * safety net; the provisioner ALSO prunes them on boot (cleanupStaleChildren for the\n * realm-match child + the top-level stale-prune), so a fresh install needs no migration.\n *\n * up() ordering is LOAD-BEARING: schema -> convert-by-policy-name -> lift-admin ->\n * delete policy rows (the policy-name joins must resolve before the rows are deleted).\n *\n * BREAKING (existing data): only admin (-> any, matched by role name) and realm_admin\n * (its realm-or-global / realm-bound junction policies -> ownOrNull / own) are converted.\n * Every OTHER pre-existing grant with no realm policy keeps the 'own' default, so a custom\n * role or a direct identity grant that previously reached global (realm_id = null) building\n * blocks via the old system.realm-match baseline is now fail-closed to its own realm. Those\n * grants must be re-widened to ownOrNull/any by hand: there is deliberately no automatic\n * bump, because a policy-less grant that managed global resources is indistinguishable in\n * the data from one that only ever acted on its own realm (auto-widening would fail open).\n *\n * down() is BEST-EFFORT and NOT a true inverse: it drops the column only. The deleted\n * system policies and the nulled junction policy_id pointers are NOT reconstructed, and\n * boot re-provisioning does NOT repair them either -- the junction synchronizer is\n * create-only (it never rewrites realm_scope/policy_id on an already-existing row). So a\n * revert (or revert + re-run) on a POPULATED database permanently pins realm_admin and any\n * converted grant to the fail-closed 'own' default until fixed by hand; a forward-only\n * upgrade is unaffected.\n */\nconst JUNCTION_TABLES = [\n 'auth_role_permissions',\n 'auth_user_permissions',\n 'auth_client_permissions',\n 'auth_robot_permissions',\n];\n\nconst SCOPE_BY_POLICY: { policy: string, scope: string }[] = [\n { policy: 'system.realm-or-global', scope: 'ownOrNull' },\n { policy: 'system.realm-bound', scope: 'own' },\n];\n\nexport class Default1779300000000 implements MigrationInterface {\n name = 'Default1779300000000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n // 1. schema\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \\`${table}\\`\n ADD \\`realm_scope\\` varchar(50) NOT NULL DEFAULT 'own'\n `);\n }\n\n // 2. convert the realm-scoping policies into the enum (clearing only those\n // policy_id pointers; non-realm policies are preserved).\n for (const table of JUNCTION_TABLES) {\n for (const { policy, scope } of SCOPE_BY_POLICY) {\n await queryRunner.query(`\n UPDATE \\`${table}\\` rp\n JOIN \\`auth_policies\\` p ON rp.\\`policy_id\\` = p.\\`id\\`\n SET rp.\\`realm_scope\\` = '${scope}', rp.\\`policy_id\\` = NULL\n WHERE p.\\`name\\` = '${policy}'\n AND p.\\`built_in\\` = 1\n AND p.\\`realm_id\\` IS NULL\n `);\n }\n }\n\n // 3. lift admin-role grants to unrestricted (admin grants carry no policy, so\n // they are unreachable by the policy join above — join by role name instead).\n await queryRunner.query(`\n UPDATE \\`auth_role_permissions\\` rp\n JOIN \\`auth_roles\\` r ON rp.\\`role_id\\` = r.\\`id\\`\n SET rp.\\`realm_scope\\` = 'any'\n WHERE r.\\`name\\` = 'admin'\n AND r.\\`built_in\\` = 1\n `);\n\n // 4. delete the three now-redundant system realm policies (by exact name —\n // never by type, which would wipe user-defined realm-match policies).\n // A cascading closure-tree FK detaches the realm-match child from\n // system.default; the provisioner re-prunes idempotently on boot.\n await queryRunner.query(`\n DELETE FROM \\`auth_policies\\`\n WHERE \\`name\\` IN ('system.realm-match', 'system.realm-bound', 'system.realm-or-global')\n AND \\`built_in\\` = 1\n AND \\`realm_id\\` IS NULL\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \\`${table}\\` DROP COLUMN \\`realm_scope\\`\n `);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCA,MAAMA,kBAAkB;CACpB;CACA;CACA;CACA
|
|
1
|
+
{"version":3,"file":"1779300000000-Default.mjs","names":["JUNCTION_TABLES","SCOPE_BY_POLICY","policy","scope","Default1779300000000","name","up","queryRunner","table","query","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1779300000000-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * realm_scope enum on the four permission-junction tables (fail-closed realm scoping).\n *\n * Adds the coarse, actor-relative `realm_scope` column (default 'own') and migrates the\n * realm-scoping that previously lived in policies into the column. The redundant system\n * realm policies (`system.realm-match` child of `system.default`,\n * `system.realm-bound`, `system.realm-or-global`) are deleted here as a deterministic\n * safety net; the provisioner ALSO prunes them on boot (cleanupStaleChildren for the\n * realm-match child + the top-level stale-prune), so a fresh install needs no migration.\n *\n * up() ordering is LOAD-BEARING: schema -> convert-by-policy-name -> lift-admin ->\n * delete policy rows (the policy-name joins must resolve before the rows are deleted).\n *\n * BREAKING (existing data): only admin (-> any, matched by role name) and realm_admin\n * (its realm-or-global / realm-bound junction policies -> ownOrNull / own) are converted.\n * Every OTHER pre-existing grant with no realm policy keeps the 'own' default, so a custom\n * role or a direct identity grant that previously reached global (realm_id = null) building\n * blocks via the old system.realm-match baseline is now fail-closed to its own realm. Those\n * grants must be re-widened to ownOrNull/any by hand: there is deliberately no automatic\n * bump, because a policy-less grant that managed global resources is indistinguishable in\n * the data from one that only ever acted on its own realm (auto-widening would fail open).\n *\n * down() is BEST-EFFORT and NOT a true inverse: it drops the column only. The deleted\n * system policies and the nulled junction policy_id pointers are NOT reconstructed, and\n * boot re-provisioning does NOT repair them either -- the junction synchronizer is\n * create-only (it never rewrites realm_scope/policy_id on an already-existing row). So a\n * revert (or revert + re-run) on a POPULATED database permanently pins realm_admin and any\n * converted grant to the fail-closed 'own' default until fixed by hand; a forward-only\n * upgrade is unaffected.\n */\nconst JUNCTION_TABLES = [\n 'auth_role_permissions',\n 'auth_user_permissions',\n 'auth_client_permissions',\n 'auth_robot_permissions',\n];\n\nconst SCOPE_BY_POLICY: { policy: string, scope: string }[] = [\n { policy: 'system.realm-or-global', scope: 'ownOrNull' },\n { policy: 'system.realm-bound', scope: 'own' },\n];\n\nexport class Default1779300000000 implements MigrationInterface {\n name = 'Default1779300000000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n // 1. schema\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \\`${table}\\`\n ADD \\`realm_scope\\` varchar(50) NOT NULL DEFAULT 'own'\n `);\n }\n\n // 2. convert the realm-scoping policies into the enum (clearing only those\n // policy_id pointers; non-realm policies are preserved).\n for (const table of JUNCTION_TABLES) {\n for (const { policy, scope } of SCOPE_BY_POLICY) {\n await queryRunner.query(`\n UPDATE \\`${table}\\` rp\n JOIN \\`auth_policies\\` p ON rp.\\`policy_id\\` = p.\\`id\\`\n SET rp.\\`realm_scope\\` = '${scope}', rp.\\`policy_id\\` = NULL\n WHERE p.\\`name\\` = '${policy}'\n AND p.\\`built_in\\` = 1\n AND p.\\`realm_id\\` IS NULL\n `);\n }\n }\n\n // 3. lift admin-role grants to unrestricted (admin grants carry no policy, so\n // they are unreachable by the policy join above — join by role name instead).\n await queryRunner.query(`\n UPDATE \\`auth_role_permissions\\` rp\n JOIN \\`auth_roles\\` r ON rp.\\`role_id\\` = r.\\`id\\`\n SET rp.\\`realm_scope\\` = 'any'\n WHERE r.\\`name\\` = 'admin'\n AND r.\\`built_in\\` = 1\n `);\n\n // 4. delete the three now-redundant system realm policies (by exact name —\n // never by type, which would wipe user-defined realm-match policies).\n // A cascading closure-tree FK detaches the realm-match child from\n // system.default; the provisioner re-prunes idempotently on boot.\n await queryRunner.query(`\n DELETE FROM \\`auth_policies\\`\n WHERE \\`name\\` IN ('system.realm-match', 'system.realm-bound', 'system.realm-or-global')\n AND \\`built_in\\` = 1\n AND \\`realm_id\\` IS NULL\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \\`${table}\\` DROP COLUMN \\`realm_scope\\`\n `);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCA,MAAMA,kBAAkB;CACpB;CACA;CACA;CACA;AACH;AAED,MAAMC,kBAAuD,CACzD;CAAEC,QAAQ;CAA0BC,OAAO;AAAY,GACvD;CAAED,QAAQ;CAAsBC,OAAO;AAAM,CAChD;AAED,IAAaC,uBAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGC,aAAyC;EAErD,KAAK,MAAMC,SAASR,iBAChB,MAAMO,YAAYE,MAAM;gCACJD,MAAM;;aAEzB;EAKL,KAAK,MAAMA,SAASR,iBAChB,KAAK,MAAM,EAAEE,QAAQC,WAAWF,iBAC5B,MAAMM,YAAYE,MAAM;+BACTD,MAAM;;gDAEWL,MAAM;0CACZD,OAAO;;;iBAGhC;EAMT,MAAMK,YAAYE,MAAM;;;;;;SAMvB;EAMD,MAAMF,YAAYE,MAAM;;;;;SAKvB;CACL;CAEA,MAAaC,KAAKH,aAAyC;EACvD,KAAK,MAAMC,SAASR,iBAChB,MAAMO,YAAYE,MAAM;gCACJD,MAAM;aACzB;CAET;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1784289540000-CamelCaseAttributes.mjs","names":["camelCase","snakeCase","renameKeys","queryRunner","table","ownerColumn","valueColumn","transform","rows","query","value","next","CamelCaseAttributes1784289540000","name","up","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1784289540000-CamelCaseAttributes.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { camelCase, snakeCase } from 'change-case';\nimport type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * Rewrite every distinct property-name key in `valueColumn` through `transform`.\n * These columns hold entity property names set by authup (identity-provider\n * attribute keys / targets, user-attribute names), so a blanket transform is\n * correct. The unique `(owner, value)` index means a rename can collide with an\n * already-migrated row; the source duplicate is removed first to keep the\n * update constraint-safe.\n */\nasync function renameKeys(\n queryRunner: QueryRunner,\n table: string,\n ownerColumn: string,\n valueColumn: string,\n transform: (value: string) => string,\n): Promise<void> {\n const rows: { value: string }[] = await queryRunner.query(\n `SELECT DISTINCT \\`${valueColumn}\\` AS \\`value\\` FROM \\`${table}\\` WHERE \\`${valueColumn}\\` IS NOT NULL`,\n );\n\n for (const { value } of rows) {\n const next = transform(value);\n if (next === value) {\n continue;\n }\n\n await queryRunner.query(\n `DELETE \\`source\\` FROM \\`${table}\\` AS \\`source\\` ` +\n `INNER JOIN \\`${table}\\` AS \\`target\\` ON \\`source\\`.\\`${ownerColumn}\\` = \\`target\\`.\\`${ownerColumn}\\` ` +\n `WHERE \\`source\\`.\\`${valueColumn}\\` = ? AND \\`target\\`.\\`${valueColumn}\\` = ?`,\n [value, next],\n );\n\n await queryRunner.query(\n `UPDATE \\`${table}\\` SET \\`${valueColumn}\\` = ? WHERE \\`${valueColumn}\\` = ?`,\n [next, value],\n );\n }\n}\n\n/**\n * Plan 073 data migration. Database identifiers remain snake_case; values which\n * encode management/entity property names move to camelCase. Built-in policy\n * data is intentionally excluded — the provisioner overwrites it on every boot.\n */\nexport class CamelCaseAttributes1784289540000 implements MigrationInterface {\n name = 'CamelCaseAttributes1784289540000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', camelCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', camelCase);\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', camelCase);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', snakeCase);\n }\n}\n"],"mappings":";;;;;;;;;;;;GAkBA,eAAeE,WACXC,aACAC,OACAC,aACAC,aACAC,WAAoC;CAEpC,MAAMC,OAA4B,MAAML,YAAYM,MAChD,qBAAqBH,YAAY,yBAAyBF,MAAM,aAAaE,YAAY,eAAe;CAG5G,KAAK,MAAM,EAAEI,WAAWF,MAAM;EAC1B,MAAMG,OAAOJ,UAAUG,KAAAA;EACvB,IAAIC,SAASD,OACT;EAGJ,MAAMP,YAAYM,MACd,4BAA4BL,MAAM,gCAClBA,MAAM,mCAAmCC,YAAY,oBAAoBA,YAAY,wBAC/EC,YAAY,0BAA0BA,YAAY,SACxE,CAACI,OAAOC,
|
|
1
|
+
{"version":3,"file":"1784289540000-CamelCaseAttributes.mjs","names":["camelCase","snakeCase","renameKeys","queryRunner","table","ownerColumn","valueColumn","transform","rows","query","value","next","CamelCaseAttributes1784289540000","name","up","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1784289540000-CamelCaseAttributes.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { camelCase, snakeCase } from 'change-case';\nimport type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * Rewrite every distinct property-name key in `valueColumn` through `transform`.\n * These columns hold entity property names set by authup (identity-provider\n * attribute keys / targets, user-attribute names), so a blanket transform is\n * correct. The unique `(owner, value)` index means a rename can collide with an\n * already-migrated row; the source duplicate is removed first to keep the\n * update constraint-safe.\n */\nasync function renameKeys(\n queryRunner: QueryRunner,\n table: string,\n ownerColumn: string,\n valueColumn: string,\n transform: (value: string) => string,\n): Promise<void> {\n const rows: { value: string }[] = await queryRunner.query(\n `SELECT DISTINCT \\`${valueColumn}\\` AS \\`value\\` FROM \\`${table}\\` WHERE \\`${valueColumn}\\` IS NOT NULL`,\n );\n\n for (const { value } of rows) {\n const next = transform(value);\n if (next === value) {\n continue;\n }\n\n await queryRunner.query(\n `DELETE \\`source\\` FROM \\`${table}\\` AS \\`source\\` ` +\n `INNER JOIN \\`${table}\\` AS \\`target\\` ON \\`source\\`.\\`${ownerColumn}\\` = \\`target\\`.\\`${ownerColumn}\\` ` +\n `WHERE \\`source\\`.\\`${valueColumn}\\` = ? AND \\`target\\`.\\`${valueColumn}\\` = ?`,\n [value, next],\n );\n\n await queryRunner.query(\n `UPDATE \\`${table}\\` SET \\`${valueColumn}\\` = ? WHERE \\`${valueColumn}\\` = ?`,\n [next, value],\n );\n }\n}\n\n/**\n * Plan 073 data migration. Database identifiers remain snake_case; values which\n * encode management/entity property names move to camelCase. Built-in policy\n * data is intentionally excluded — the provisioner overwrites it on every boot.\n */\nexport class CamelCaseAttributes1784289540000 implements MigrationInterface {\n name = 'CamelCaseAttributes1784289540000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', camelCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', camelCase);\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', camelCase);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', snakeCase);\n }\n}\n"],"mappings":";;;;;;;;;;;;GAkBA,eAAeE,WACXC,aACAC,OACAC,aACAC,aACAC,WAAoC;CAEpC,MAAMC,OAA4B,MAAML,YAAYM,MAChD,qBAAqBH,YAAY,yBAAyBF,MAAM,aAAaE,YAAY,eAAe;CAG5G,KAAK,MAAM,EAAEI,WAAWF,MAAM;EAC1B,MAAMG,OAAOJ,UAAUG,KAAAA;EACvB,IAAIC,SAASD,OACT;EAGJ,MAAMP,YAAYM,MACd,4BAA4BL,MAAM,gCAClBA,MAAM,mCAAmCC,YAAY,oBAAoBA,YAAY,wBAC/EC,YAAY,0BAA0BA,YAAY,SACxE,CAACI,OAAOC,IAAK,CAAA;EAGjB,MAAMR,YAAYM,MACd,YAAYL,MAAM,WAAWE,YAAY,iBAAiBA,YAAY,SACtE,CAACK,MAAMD,KAAM,CAAA;CAErB;AACJ;;;;;GAOA,IAAaE,mCAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGX,aAAyC;EACrD,MAAMD,WAAWC,aAAa,qCAAqC,eAAe,QAAQH,SAAAA;EAC1F,MAAME,WAAWC,aAAa,6CAA6C,eAAe,eAAeH,SAAAA;EACzG,MAAME,WAAWC,aAAa,wBAAwB,WAAW,QAAQH,SAAAA;CAC7E;CAEA,MAAae,KAAKZ,aAAyC;EACvD,MAAMD,WAAWC,aAAa,wBAAwB,WAAW,QAAQF,SAAAA;EACzE,MAAMC,WAAWC,aAAa,6CAA6C,eAAe,eAAeF,SAAAA;EACzG,MAAMC,WAAWC,aAAa,qCAAqC,eAAe,QAAQF,SAAAA;CAC9F;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1779267068441-Default.mjs","names":["NAME_COLLISION_CHECKS","table","groupBy","where","NAME_TABLES","map","c","Default1779267068441","name","up","queryRunner","check","join","rows","query","length","Error","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1779267068441-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\ntype CollisionCheck = {\n table: string,\n groupBy: string[],\n where?: string,\n};\n\nconst NAME_COLLISION_CHECKS: CollisionCheck[] = [\n { table: 'auth_clients', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_robots', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_users', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_realms', groupBy: ['LOWER(TRIM(name))'] },\n {\n table: 'auth_roles', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_scopes', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n {\n table: 'auth_permissions', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_policies', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n { table: 'auth_identity_providers', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n];\n\nconst NAME_TABLES = NAME_COLLISION_CHECKS.map((c) => c.table);\n\nexport class Default1779267068441 implements MigrationInterface {\n name = 'Default1779267068441';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n for (const check of NAME_COLLISION_CHECKS) {\n const groupBy = check.groupBy.join(', ');\n const rows = await queryRunner.query(`\n SELECT ${groupBy}\n FROM \"${check.table}\"\n ${check.where ? `WHERE ${check.where}` : ''}\n GROUP BY ${groupBy}\n HAVING COUNT(*) > 1\n `);\n if (rows.length > 0) {\n throw new Error(\n `Canonical-name migration aborted: \"${check.table}\" has ${rows.length} collision group(s) on ${groupBy}. ` +\n 'Merge the conflicting rows manually before re-running.',\n );\n }\n }\n\n for (const table of NAME_TABLES) {\n await queryRunner.query(`\n UPDATE \"${table}\"\n SET \"name\" = LOWER(TRIM(\"name\"))\n WHERE \"name\" <> LOWER(TRIM(\"name\"))\n `);\n }\n\n await queryRunner.query(`\n UPDATE \"auth_users\"\n SET \"email\" = LOWER(TRIM(\"email\"))\n WHERE \"email\" IS NOT NULL\n AND \"email\" <> LOWER(TRIM(\"email\"))\n `);\n\n await queryRunner.query(`\n ALTER TABLE \"auth_users\" DROP CONSTRAINT \"FK_b1797e07106b4af61280b8edac1\"\n `);\n await queryRunner.query(`\n DROP INDEX \"public\".\"IDX_b1797e07106b4af61280b8edac\"\n `);\n await queryRunner.query(`\n ALTER TABLE \"auth_users\" DROP COLUMN \"client_id\"\n `);\n }\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`\n ALTER TABLE \"auth_users\"\n ADD \"client_id\" uuid\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_b1797e07106b4af61280b8edac\" ON \"auth_users\" (\"client_id\")\n `);\n await queryRunner.query(`\n ALTER TABLE \"auth_users\"\n ADD CONSTRAINT \"FK_b1797e07106b4af61280b8edac1\" FOREIGN KEY (\"client_id\") REFERENCES \"auth_clients\"(\"id\") ON DELETE CASCADE ON UPDATE NO ACTION\n `);\n }\n}\n"],"mappings":";;;;AAQA,MAAMA,wBAA0C;CAC5C;EAAEC,OAAO;EAAgBC,SAAS,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"1779267068441-Default.mjs","names":["NAME_COLLISION_CHECKS","table","groupBy","where","NAME_TABLES","map","c","Default1779267068441","name","up","queryRunner","check","join","rows","query","length","Error","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1779267068441-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\ntype CollisionCheck = {\n table: string,\n groupBy: string[],\n where?: string,\n};\n\nconst NAME_COLLISION_CHECKS: CollisionCheck[] = [\n { table: 'auth_clients', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_robots', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_users', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n { table: 'auth_realms', groupBy: ['LOWER(TRIM(name))'] },\n {\n table: 'auth_roles', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_scopes', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n {\n table: 'auth_permissions', \n groupBy: ['LOWER(TRIM(name))', 'client_id', 'realm_id'], \n where: 'client_id IS NOT NULL AND realm_id IS NOT NULL', \n },\n {\n table: 'auth_policies', \n groupBy: ['LOWER(TRIM(name))', 'realm_id'], \n where: 'realm_id IS NOT NULL', \n },\n { table: 'auth_identity_providers', groupBy: ['LOWER(TRIM(name))', 'realm_id'] },\n];\n\nconst NAME_TABLES = NAME_COLLISION_CHECKS.map((c) => c.table);\n\nexport class Default1779267068441 implements MigrationInterface {\n name = 'Default1779267068441';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n for (const check of NAME_COLLISION_CHECKS) {\n const groupBy = check.groupBy.join(', ');\n const rows = await queryRunner.query(`\n SELECT ${groupBy}\n FROM \"${check.table}\"\n ${check.where ? `WHERE ${check.where}` : ''}\n GROUP BY ${groupBy}\n HAVING COUNT(*) > 1\n `);\n if (rows.length > 0) {\n throw new Error(\n `Canonical-name migration aborted: \"${check.table}\" has ${rows.length} collision group(s) on ${groupBy}. ` +\n 'Merge the conflicting rows manually before re-running.',\n );\n }\n }\n\n for (const table of NAME_TABLES) {\n await queryRunner.query(`\n UPDATE \"${table}\"\n SET \"name\" = LOWER(TRIM(\"name\"))\n WHERE \"name\" <> LOWER(TRIM(\"name\"))\n `);\n }\n\n await queryRunner.query(`\n UPDATE \"auth_users\"\n SET \"email\" = LOWER(TRIM(\"email\"))\n WHERE \"email\" IS NOT NULL\n AND \"email\" <> LOWER(TRIM(\"email\"))\n `);\n\n await queryRunner.query(`\n ALTER TABLE \"auth_users\" DROP CONSTRAINT \"FK_b1797e07106b4af61280b8edac1\"\n `);\n await queryRunner.query(`\n DROP INDEX \"public\".\"IDX_b1797e07106b4af61280b8edac\"\n `);\n await queryRunner.query(`\n ALTER TABLE \"auth_users\" DROP COLUMN \"client_id\"\n `);\n }\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`\n ALTER TABLE \"auth_users\"\n ADD \"client_id\" uuid\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_b1797e07106b4af61280b8edac\" ON \"auth_users\" (\"client_id\")\n `);\n await queryRunner.query(`\n ALTER TABLE \"auth_users\"\n ADD CONSTRAINT \"FK_b1797e07106b4af61280b8edac1\" FOREIGN KEY (\"client_id\") REFERENCES \"auth_clients\"(\"id\") ON DELETE CASCADE ON UPDATE NO ACTION\n `);\n }\n}\n"],"mappings":";;;;AAQA,MAAMA,wBAA0C;CAC5C;EAAEC,OAAO;EAAgBC,SAAS,CAAC,qBAAqB,UAAW;CAAC;CACpE;EAAED,OAAO;EAAeC,SAAS,CAAC,qBAAqB,UAAW;CAAC;CACnE;EAAED,OAAO;EAAcC,SAAS,CAAC,qBAAqB,UAAW;CAAC;CAClE;EAAED,OAAO;EAAeC,SAAS,CAAC,mBAAoB;CAAC;CACvD;EACID,OAAO;EACPC,SAAS;GAAC;GAAqB;GAAa;EAAW;EACvDC,OAAO;CACX;CACA;EACIF,OAAO;EACPC,SAAS,CAAC,qBAAqB,UAAW;EAC1CC,OAAO;CACX;CACA;EACIF,OAAO;EACPC,SAAS;GAAC;GAAqB;GAAa;EAAW;EACvDC,OAAO;CACX;CACA;EACIF,OAAO;EACPC,SAAS,CAAC,qBAAqB,UAAW;EAC1CC,OAAO;CACX;CACA;EAAEF,OAAO;EAA2BC,SAAS,CAAC,qBAAqB,UAAW;CAAC;AAClF;AAED,MAAME,cAAcJ,sBAAsBK,KAAKC,MAAMA,EAAEL,KAAK;AAE5D,IAAaM,uBAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGC,aAAyC;EACrD,KAAK,MAAMC,SAASX,uBAAuB;GACvC,MAAME,UAAUS,MAAMT,QAAQU,KAAK,IAAA;GACnC,MAAMC,OAAO,MAAMH,YAAYI,MAAM;yBACxBZ,QAAQ;wBACTS,MAAMV,MAAM;kBAClBU,MAAMR,QAAQ,SAASQ,MAAMR,UAAU,GAAG;2BACjCD,QAAQ;;aAEtB;GACD,IAAIW,KAAKE,SAAS,GACd,MAAM,IAAIC,MACN,sCAAsCL,MAAMV,MAAM,QAAQY,KAAKE,OAAO,yBAAyBb,QAAQ,yDACvG;EAGZ;EAEA,KAAK,MAAMD,SAASG,aAChB,MAAMM,YAAYI,MAAM;0BACVb,MAAM;;;aAGnB;EAGL,MAAMS,YAAYI,MAAM;;;;;SAKvB;EAED,MAAMJ,YAAYI,MAAM;;SAEvB;EACD,MAAMJ,YAAYI,MAAM;;SAEvB;EACD,MAAMJ,YAAYI,MAAM;;SAEvB;CACL;CACA,MAAaG,KAAKP,aAAyC;EACvD,MAAMA,YAAYI,MAAM;;;SAGvB;EACD,MAAMJ,YAAYI,MAAM;;SAEvB;EACD,MAAMJ,YAAYI,MAAM;;;SAGvB;CACL;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1779300000000-Default.mjs","names":["JUNCTION_TABLES","SCOPE_BY_POLICY","policy","scope","Default1779300000000","name","up","queryRunner","table","query","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1779300000000-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * realm_scope enum on the four permission-junction tables (fail-closed realm scoping).\n *\n * Adds the coarse, actor-relative `realm_scope` column (default 'own') and migrates the\n * realm-scoping that previously lived in policies into the column. The redundant system\n * realm policies (`system.realm-match` child of `system.default`,\n * `system.realm-bound`, `system.realm-or-global`) are deleted here as a deterministic\n * safety net; the provisioner ALSO prunes them on boot (cleanupStaleChildren for the\n * realm-match child + the top-level stale-prune), so a fresh install needs no migration.\n *\n * up() ordering is LOAD-BEARING: schema -> convert-by-policy-name -> lift-admin ->\n * delete policy rows (the policy-name joins must resolve before the rows are deleted).\n *\n * BREAKING (existing data): only admin (-> any, matched by role name) and realm_admin\n * (its realm-or-global / realm-bound junction policies -> ownOrNull / own) are converted.\n * Every OTHER pre-existing grant with no realm policy keeps the 'own' default, so a custom\n * role or a direct identity grant that previously reached global (realm_id = null) building\n * blocks via the old system.realm-match baseline is now fail-closed to its own realm. Those\n * grants must be re-widened to ownOrNull/any by hand: there is deliberately no automatic\n * bump, because a policy-less grant that managed global resources is indistinguishable in\n * the data from one that only ever acted on its own realm (auto-widening would fail open).\n *\n * down() is BEST-EFFORT and NOT a true inverse: it drops the column only. The deleted\n * system policies and the nulled junction policy_id pointers are NOT reconstructed, and\n * boot re-provisioning does NOT repair them either -- the junction synchronizer is\n * create-only (it never rewrites realm_scope/policy_id on an already-existing row). So a\n * revert (or revert + re-run) on a POPULATED database permanently pins realm_admin and any\n * converted grant to the fail-closed 'own' default until fixed by hand; a forward-only\n * upgrade is unaffected.\n */\nconst JUNCTION_TABLES = [\n 'auth_role_permissions',\n 'auth_user_permissions',\n 'auth_client_permissions',\n 'auth_robot_permissions',\n];\n\nconst SCOPE_BY_POLICY: { policy: string, scope: string }[] = [\n { policy: 'system.realm-or-global', scope: 'ownOrNull' },\n { policy: 'system.realm-bound', scope: 'own' },\n];\n\nexport class Default1779300000000 implements MigrationInterface {\n name = 'Default1779300000000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n // 1. schema\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \"${table}\"\n ADD \"realm_scope\" character varying(50) NOT NULL DEFAULT 'own'\n `);\n }\n\n // 2. convert the realm-scoping policies into the enum (clearing only those\n // policy_id pointers; non-realm policies are preserved).\n for (const table of JUNCTION_TABLES) {\n for (const { policy, scope } of SCOPE_BY_POLICY) {\n await queryRunner.query(`\n UPDATE \"${table}\" rp\n SET \"realm_scope\" = '${scope}', \"policy_id\" = NULL\n FROM \"auth_policies\" p\n WHERE rp.\"policy_id\" = p.\"id\"\n AND p.\"name\" = '${policy}'\n AND p.\"built_in\" = true\n AND p.\"realm_id\" IS NULL\n `);\n }\n }\n\n // 3. lift admin-role grants to unrestricted (admin grants carry no policy, so\n // they are unreachable by the policy join above — join by role name instead).\n await queryRunner.query(`\n UPDATE \"auth_role_permissions\" rp\n SET \"realm_scope\" = 'any'\n FROM \"auth_roles\" r\n WHERE rp.\"role_id\" = r.\"id\"\n AND r.\"name\" = 'admin'\n AND r.\"built_in\" = true\n `);\n\n // 4. delete the three now-redundant system realm policies (by exact name —\n // never by type, which would wipe user-defined realm-match policies).\n // A cascading closure-tree FK detaches the realm-match child from\n // system.default; the provisioner re-prunes idempotently on boot.\n await queryRunner.query(`\n DELETE FROM \"auth_policies\"\n WHERE \"name\" IN ('system.realm-match', 'system.realm-bound', 'system.realm-or-global')\n AND \"built_in\" = true\n AND \"realm_id\" IS NULL\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \"${table}\" DROP COLUMN \"realm_scope\"\n `);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCA,MAAMA,kBAAkB;CACpB;CACA;CACA;CACA
|
|
1
|
+
{"version":3,"file":"1779300000000-Default.mjs","names":["JUNCTION_TABLES","SCOPE_BY_POLICY","policy","scope","Default1779300000000","name","up","queryRunner","table","query","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1779300000000-Default.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * realm_scope enum on the four permission-junction tables (fail-closed realm scoping).\n *\n * Adds the coarse, actor-relative `realm_scope` column (default 'own') and migrates the\n * realm-scoping that previously lived in policies into the column. The redundant system\n * realm policies (`system.realm-match` child of `system.default`,\n * `system.realm-bound`, `system.realm-or-global`) are deleted here as a deterministic\n * safety net; the provisioner ALSO prunes them on boot (cleanupStaleChildren for the\n * realm-match child + the top-level stale-prune), so a fresh install needs no migration.\n *\n * up() ordering is LOAD-BEARING: schema -> convert-by-policy-name -> lift-admin ->\n * delete policy rows (the policy-name joins must resolve before the rows are deleted).\n *\n * BREAKING (existing data): only admin (-> any, matched by role name) and realm_admin\n * (its realm-or-global / realm-bound junction policies -> ownOrNull / own) are converted.\n * Every OTHER pre-existing grant with no realm policy keeps the 'own' default, so a custom\n * role or a direct identity grant that previously reached global (realm_id = null) building\n * blocks via the old system.realm-match baseline is now fail-closed to its own realm. Those\n * grants must be re-widened to ownOrNull/any by hand: there is deliberately no automatic\n * bump, because a policy-less grant that managed global resources is indistinguishable in\n * the data from one that only ever acted on its own realm (auto-widening would fail open).\n *\n * down() is BEST-EFFORT and NOT a true inverse: it drops the column only. The deleted\n * system policies and the nulled junction policy_id pointers are NOT reconstructed, and\n * boot re-provisioning does NOT repair them either -- the junction synchronizer is\n * create-only (it never rewrites realm_scope/policy_id on an already-existing row). So a\n * revert (or revert + re-run) on a POPULATED database permanently pins realm_admin and any\n * converted grant to the fail-closed 'own' default until fixed by hand; a forward-only\n * upgrade is unaffected.\n */\nconst JUNCTION_TABLES = [\n 'auth_role_permissions',\n 'auth_user_permissions',\n 'auth_client_permissions',\n 'auth_robot_permissions',\n];\n\nconst SCOPE_BY_POLICY: { policy: string, scope: string }[] = [\n { policy: 'system.realm-or-global', scope: 'ownOrNull' },\n { policy: 'system.realm-bound', scope: 'own' },\n];\n\nexport class Default1779300000000 implements MigrationInterface {\n name = 'Default1779300000000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n // 1. schema\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \"${table}\"\n ADD \"realm_scope\" character varying(50) NOT NULL DEFAULT 'own'\n `);\n }\n\n // 2. convert the realm-scoping policies into the enum (clearing only those\n // policy_id pointers; non-realm policies are preserved).\n for (const table of JUNCTION_TABLES) {\n for (const { policy, scope } of SCOPE_BY_POLICY) {\n await queryRunner.query(`\n UPDATE \"${table}\" rp\n SET \"realm_scope\" = '${scope}', \"policy_id\" = NULL\n FROM \"auth_policies\" p\n WHERE rp.\"policy_id\" = p.\"id\"\n AND p.\"name\" = '${policy}'\n AND p.\"built_in\" = true\n AND p.\"realm_id\" IS NULL\n `);\n }\n }\n\n // 3. lift admin-role grants to unrestricted (admin grants carry no policy, so\n // they are unreachable by the policy join above — join by role name instead).\n await queryRunner.query(`\n UPDATE \"auth_role_permissions\" rp\n SET \"realm_scope\" = 'any'\n FROM \"auth_roles\" r\n WHERE rp.\"role_id\" = r.\"id\"\n AND r.\"name\" = 'admin'\n AND r.\"built_in\" = true\n `);\n\n // 4. delete the three now-redundant system realm policies (by exact name —\n // never by type, which would wipe user-defined realm-match policies).\n // A cascading closure-tree FK detaches the realm-match child from\n // system.default; the provisioner re-prunes idempotently on boot.\n await queryRunner.query(`\n DELETE FROM \"auth_policies\"\n WHERE \"name\" IN ('system.realm-match', 'system.realm-bound', 'system.realm-or-global')\n AND \"built_in\" = true\n AND \"realm_id\" IS NULL\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n for (const table of JUNCTION_TABLES) {\n await queryRunner.query(`\n ALTER TABLE \"${table}\" DROP COLUMN \"realm_scope\"\n `);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCA,MAAMA,kBAAkB;CACpB;CACA;CACA;CACA;AACH;AAED,MAAMC,kBAAuD,CACzD;CAAEC,QAAQ;CAA0BC,OAAO;AAAY,GACvD;CAAED,QAAQ;CAAsBC,OAAO;AAAM,CAChD;AAED,IAAaC,uBAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGC,aAAyC;EAErD,KAAK,MAAMC,SAASR,iBAChB,MAAMO,YAAYE,MAAM;+BACLD,MAAM;;aAExB;EAKL,KAAK,MAAMA,SAASR,iBAChB,KAAK,MAAM,EAAEE,QAAQC,WAAWF,iBAC5B,MAAMM,YAAYE,MAAM;8BACVD,MAAM;2CACOL,MAAM;;;wCAGTD,OAAO;;;iBAG9B;EAMT,MAAMK,YAAYE,MAAM;;;;;;;SAOvB;EAMD,MAAMF,YAAYE,MAAM;;;;;SAKvB;CACL;CAEA,MAAaC,KAAKH,aAAyC;EACvD,KAAK,MAAMC,SAASR,iBAChB,MAAMO,YAAYE,MAAM;+BACLD,MAAM;aACxB;CAET;AACJ"}
|
package/dist/adapters/database/migrations/postgres/1784289540000-CamelCaseAttributes.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1784289540000-CamelCaseAttributes.mjs","names":["camelCase","snakeCase","renameKeys","queryRunner","table","ownerColumn","valueColumn","transform","rows","query","value","next","CamelCaseAttributes1784289540000","name","up","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1784289540000-CamelCaseAttributes.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { camelCase, snakeCase } from 'change-case';\nimport type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * Rewrite every distinct property-name key in `valueColumn` through `transform`.\n * These columns hold entity property names set by authup (identity-provider\n * attribute keys / targets, user-attribute names), so a blanket transform is\n * correct. The unique `(owner, value)` index means a rename can collide with an\n * already-migrated row; the source duplicate is removed first to keep the\n * update constraint-safe.\n */\nasync function renameKeys(\n queryRunner: QueryRunner,\n table: string,\n ownerColumn: string,\n valueColumn: string,\n transform: (value: string) => string,\n): Promise<void> {\n const rows: { value: string }[] = await queryRunner.query(\n `SELECT DISTINCT \"${valueColumn}\" AS \"value\" FROM \"${table}\" WHERE \"${valueColumn}\" IS NOT NULL`,\n );\n\n for (const { value } of rows) {\n const next = transform(value);\n if (next === value) {\n continue;\n }\n\n await queryRunner.query(\n `DELETE FROM \"${table}\" AS \"source\" USING \"${table}\" AS \"target\" ` +\n `WHERE \"source\".\"${ownerColumn}\" = \"target\".\"${ownerColumn}\" ` +\n `AND \"source\".\"${valueColumn}\" = $1 AND \"target\".\"${valueColumn}\" = $2`,\n [value, next],\n );\n\n await queryRunner.query(\n `UPDATE \"${table}\" SET \"${valueColumn}\" = $1 WHERE \"${valueColumn}\" = $2`,\n [next, value],\n );\n }\n}\n\n/**\n * Plan 073 data migration. Database identifiers remain snake_case; values which\n * encode management/entity property names move to camelCase. Built-in policy\n * data is intentionally excluded — the provisioner overwrites it on every boot.\n */\nexport class CamelCaseAttributes1784289540000 implements MigrationInterface {\n name = 'CamelCaseAttributes1784289540000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', camelCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', camelCase);\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', camelCase);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', snakeCase);\n }\n}\n"],"mappings":";;;;;;;;;;;;GAkBA,eAAeE,WACXC,aACAC,OACAC,aACAC,aACAC,WAAoC;CAEpC,MAAMC,OAA4B,MAAML,YAAYM,MAChD,oBAAoBH,YAAY,qBAAqBF,MAAM,WAAWE,YAAY,cAAc;CAGpG,KAAK,MAAM,EAAEI,WAAWF,MAAM;EAC1B,MAAMG,OAAOJ,UAAUG,KAAAA;EACvB,IAAIC,SAASD,OACT;EAGJ,MAAMP,YAAYM,MACd,gBAAgBL,MAAM,uBAAuBA,MAAM,gCAChCC,YAAY,gBAAgBA,YAAY,kBAC1CC,YAAY,uBAAuBA,YAAY,SAChE,CAACI,OAAOC,
|
|
1
|
+
{"version":3,"file":"1784289540000-CamelCaseAttributes.mjs","names":["camelCase","snakeCase","renameKeys","queryRunner","table","ownerColumn","valueColumn","transform","rows","query","value","next","CamelCaseAttributes1784289540000","name","up","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1784289540000-CamelCaseAttributes.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { camelCase, snakeCase } from 'change-case';\nimport type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * Rewrite every distinct property-name key in `valueColumn` through `transform`.\n * These columns hold entity property names set by authup (identity-provider\n * attribute keys / targets, user-attribute names), so a blanket transform is\n * correct. The unique `(owner, value)` index means a rename can collide with an\n * already-migrated row; the source duplicate is removed first to keep the\n * update constraint-safe.\n */\nasync function renameKeys(\n queryRunner: QueryRunner,\n table: string,\n ownerColumn: string,\n valueColumn: string,\n transform: (value: string) => string,\n): Promise<void> {\n const rows: { value: string }[] = await queryRunner.query(\n `SELECT DISTINCT \"${valueColumn}\" AS \"value\" FROM \"${table}\" WHERE \"${valueColumn}\" IS NOT NULL`,\n );\n\n for (const { value } of rows) {\n const next = transform(value);\n if (next === value) {\n continue;\n }\n\n await queryRunner.query(\n `DELETE FROM \"${table}\" AS \"source\" USING \"${table}\" AS \"target\" ` +\n `WHERE \"source\".\"${ownerColumn}\" = \"target\".\"${ownerColumn}\" ` +\n `AND \"source\".\"${valueColumn}\" = $1 AND \"target\".\"${valueColumn}\" = $2`,\n [value, next],\n );\n\n await queryRunner.query(\n `UPDATE \"${table}\" SET \"${valueColumn}\" = $1 WHERE \"${valueColumn}\" = $2`,\n [next, value],\n );\n }\n}\n\n/**\n * Plan 073 data migration. Database identifiers remain snake_case; values which\n * encode management/entity property names move to camelCase. Built-in policy\n * data is intentionally excluded — the provisioner overwrites it on every boot.\n */\nexport class CamelCaseAttributes1784289540000 implements MigrationInterface {\n name = 'CamelCaseAttributes1784289540000';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', camelCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', camelCase);\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', camelCase);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await renameKeys(queryRunner, 'auth_user_attributes', 'user_id', 'name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attribute_mappings', 'provider_id', 'target_name', snakeCase);\n await renameKeys(queryRunner, 'auth_identity_provider_attributes', 'provider_id', 'name', snakeCase);\n }\n}\n"],"mappings":";;;;;;;;;;;;GAkBA,eAAeE,WACXC,aACAC,OACAC,aACAC,aACAC,WAAoC;CAEpC,MAAMC,OAA4B,MAAML,YAAYM,MAChD,oBAAoBH,YAAY,qBAAqBF,MAAM,WAAWE,YAAY,cAAc;CAGpG,KAAK,MAAM,EAAEI,WAAWF,MAAM;EAC1B,MAAMG,OAAOJ,UAAUG,KAAAA;EACvB,IAAIC,SAASD,OACT;EAGJ,MAAMP,YAAYM,MACd,gBAAgBL,MAAM,uBAAuBA,MAAM,gCAChCC,YAAY,gBAAgBA,YAAY,kBAC1CC,YAAY,uBAAuBA,YAAY,SAChE,CAACI,OAAOC,IAAK,CAAA;EAGjB,MAAMR,YAAYM,MACd,WAAWL,MAAM,SAASE,YAAY,gBAAgBA,YAAY,SAClE,CAACK,MAAMD,KAAM,CAAA;CAErB;AACJ;;;;;GAOA,IAAaE,mCAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGX,aAAyC;EACrD,MAAMD,WAAWC,aAAa,qCAAqC,eAAe,QAAQH,SAAAA;EAC1F,MAAME,WAAWC,aAAa,6CAA6C,eAAe,eAAeH,SAAAA;EACzG,MAAME,WAAWC,aAAa,wBAAwB,WAAW,QAAQH,SAAAA;CAC7E;CAEA,MAAae,KAAKZ,aAAyC;EACvD,MAAMD,WAAWC,aAAa,wBAAwB,WAAW,QAAQF,SAAAA;EACzE,MAAMC,WAAWC,aAAa,6CAA6C,eAAe,eAAeF,SAAAA;EACzG,MAAMC,WAAWC,aAAa,qCAAqC,eAAe,QAAQF,SAAAA;CAC9F;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":["EntityDefaultEventName","buildEntityChannelName","buildEntityNamespaceName","buildEntityDestinations","type","realmIds","data","destinations","channel","id","items","seen","Set","realmId","has","add","push","namespace","EntitySubscriber","ctx","publisher","setPublisher","listenTo","target","afterInsert","event","entity","cache","onInsert","dropCacheKeys","connection","publish","CREATED","afterUpdate","UPDATED","databaseEntity","afterRemove","DELETED","queryResultCache","remove","keys","dataPrevious","safePublish","content"],"sources":["../../../../src/adapters/database/subscriber/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { EntityType } from '@authup/core-kit';\nimport {\n EntityDefaultEventName,\n buildEntityChannelName,\n buildEntityNamespaceName,\n} from '@authup/core-kit';\nimport type { DomainEventDestinations, IDomainEventPublisher } from '@authup/server-kit';\nimport type {\n DataSource,\n EntitySubscriberInterface,\n InsertEvent,\n ObjectLiteral,\n RemoveEvent,\n UpdateEvent,\n} from 'typeorm';\nimport type { EntitySubscriberContext } from './types.ts';\n\nexport function buildEntityDestinations<T extends ObjectLiteral>(\n type: `${EntityType}`,\n realmIds?: (data: T) => (string | null | undefined)[],\n) : (data: T) => DomainEventDestinations {\n return (data) => {\n const destinations : DomainEventDestinations = [\n { channel: (id) => buildEntityChannelName(type, id) },\n ];\n\n if (realmIds) {\n const items = realmIds(data);\n const seen = new Set<string>();\n for (const realmId of items) {\n if (realmId && !seen.has(realmId)) {\n seen.add(realmId);\n destinations.push({\n channel: (id) => buildEntityChannelName(type, id),\n namespace: buildEntityNamespaceName(realmId),\n });\n }\n }\n }\n\n return destinations;\n };\n}\n\nexport class EntitySubscriber<T extends ObjectLiteral> implements EntitySubscriberInterface<T> {\n protected ctx : EntitySubscriberContext<T>;\n\n protected publisher? : IDomainEventPublisher;\n\n constructor(ctx: EntitySubscriberContext<T>) {\n this.ctx = ctx;\n this.publisher = ctx.publisher;\n }\n\n setPublisher(publisher: IDomainEventPublisher) : void {\n this.publisher = publisher;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n listenTo() : Function | string {\n return this.ctx.target;\n }\n\n async afterInsert(event: InsertEvent<T>): Promise<any> {\n if (!event.entity) {\n return;\n }\n\n if (this.ctx.cache && this.ctx.cache.onInsert) {\n await this.dropCacheKeys(event.connection, event.entity);\n }\n\n await this.publish(EntityDefaultEventName.CREATED, event.entity);\n }\n\n async afterUpdate(event: UpdateEvent<T>): Promise<any> {\n if (!event.entity) {\n return;\n }\n\n await this.dropCacheKeys(event.connection, event.entity as T);\n\n await this.publish(EntityDefaultEventName.UPDATED, event.entity as T, event.databaseEntity);\n }\n\n async afterRemove(event: RemoveEvent<T>): Promise<any> {\n // remove() strips the primary key from event.entity before the\n // subscriber runs — databaseEntity is the pre-removal row and keeps\n // the id-keyed cache invalidation (and the DELETED payload) intact.\n const entity = event.databaseEntity ?? event.entity;\n if (!entity) {\n return;\n }\n\n await this.dropCacheKeys(event.connection, entity);\n\n await this.publish(EntityDefaultEventName.DELETED, entity);\n }\n\n protected async dropCacheKeys(connection: DataSource, data: T) : Promise<void> {\n if (!this.ctx.cache || !connection.queryResultCache) {\n return;\n }\n\n await connection.queryResultCache.remove(this.ctx.cache.keys(data));\n }\n\n protected async publish(\n event: `${EntityDefaultEventName}`,\n data: T,\n dataPrevious?: T,\n ) : Promise<void> {\n if (!this.publisher) {\n return;\n }\n\n await this.publisher.safePublish({\n content: {\n type: this.ctx.type,\n event,\n data,\n },\n destinations: this.ctx.destinations(data),\n ...(dataPrevious ? { dataPrevious } : {}),\n });\n }\n}\n"],"mappings":";;;;;AAwBA,SAAgBG,wBACZC,MACAC,UAAqD;CAErD,QAAQC,SAAAA;EACJ,MAAMC,eAAyC,CAC3C,EAAEC,UAAUC,OAAOR,uBAAuBG,MAAMK,EAAAA,EAAI,
|
|
1
|
+
{"version":3,"file":"module.mjs","names":["EntityDefaultEventName","buildEntityChannelName","buildEntityNamespaceName","buildEntityDestinations","type","realmIds","data","destinations","channel","id","items","seen","Set","realmId","has","add","push","namespace","EntitySubscriber","ctx","publisher","setPublisher","listenTo","target","afterInsert","event","entity","cache","onInsert","dropCacheKeys","connection","publish","CREATED","afterUpdate","UPDATED","databaseEntity","afterRemove","DELETED","queryResultCache","remove","keys","dataPrevious","safePublish","content"],"sources":["../../../../src/adapters/database/subscriber/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { EntityType } from '@authup/core-kit';\nimport {\n EntityDefaultEventName,\n buildEntityChannelName,\n buildEntityNamespaceName,\n} from '@authup/core-kit';\nimport type { DomainEventDestinations, IDomainEventPublisher } from '@authup/server-kit';\nimport type {\n DataSource,\n EntitySubscriberInterface,\n InsertEvent,\n ObjectLiteral,\n RemoveEvent,\n UpdateEvent,\n} from 'typeorm';\nimport type { EntitySubscriberContext } from './types.ts';\n\nexport function buildEntityDestinations<T extends ObjectLiteral>(\n type: `${EntityType}`,\n realmIds?: (data: T) => (string | null | undefined)[],\n) : (data: T) => DomainEventDestinations {\n return (data) => {\n const destinations : DomainEventDestinations = [\n { channel: (id) => buildEntityChannelName(type, id) },\n ];\n\n if (realmIds) {\n const items = realmIds(data);\n const seen = new Set<string>();\n for (const realmId of items) {\n if (realmId && !seen.has(realmId)) {\n seen.add(realmId);\n destinations.push({\n channel: (id) => buildEntityChannelName(type, id),\n namespace: buildEntityNamespaceName(realmId),\n });\n }\n }\n }\n\n return destinations;\n };\n}\n\nexport class EntitySubscriber<T extends ObjectLiteral> implements EntitySubscriberInterface<T> {\n protected ctx : EntitySubscriberContext<T>;\n\n protected publisher? : IDomainEventPublisher;\n\n constructor(ctx: EntitySubscriberContext<T>) {\n this.ctx = ctx;\n this.publisher = ctx.publisher;\n }\n\n setPublisher(publisher: IDomainEventPublisher) : void {\n this.publisher = publisher;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n listenTo() : Function | string {\n return this.ctx.target;\n }\n\n async afterInsert(event: InsertEvent<T>): Promise<any> {\n if (!event.entity) {\n return;\n }\n\n if (this.ctx.cache && this.ctx.cache.onInsert) {\n await this.dropCacheKeys(event.connection, event.entity);\n }\n\n await this.publish(EntityDefaultEventName.CREATED, event.entity);\n }\n\n async afterUpdate(event: UpdateEvent<T>): Promise<any> {\n if (!event.entity) {\n return;\n }\n\n await this.dropCacheKeys(event.connection, event.entity as T);\n\n await this.publish(EntityDefaultEventName.UPDATED, event.entity as T, event.databaseEntity);\n }\n\n async afterRemove(event: RemoveEvent<T>): Promise<any> {\n // remove() strips the primary key from event.entity before the\n // subscriber runs — databaseEntity is the pre-removal row and keeps\n // the id-keyed cache invalidation (and the DELETED payload) intact.\n const entity = event.databaseEntity ?? event.entity;\n if (!entity) {\n return;\n }\n\n await this.dropCacheKeys(event.connection, entity);\n\n await this.publish(EntityDefaultEventName.DELETED, entity);\n }\n\n protected async dropCacheKeys(connection: DataSource, data: T) : Promise<void> {\n if (!this.ctx.cache || !connection.queryResultCache) {\n return;\n }\n\n await connection.queryResultCache.remove(this.ctx.cache.keys(data));\n }\n\n protected async publish(\n event: `${EntityDefaultEventName}`,\n data: T,\n dataPrevious?: T,\n ) : Promise<void> {\n if (!this.publisher) {\n return;\n }\n\n await this.publisher.safePublish({\n content: {\n type: this.ctx.type,\n event,\n data,\n },\n destinations: this.ctx.destinations(data),\n ...(dataPrevious ? { dataPrevious } : {}),\n });\n }\n}\n"],"mappings":";;;;;AAwBA,SAAgBG,wBACZC,MACAC,UAAqD;CAErD,QAAQC,SAAAA;EACJ,MAAMC,eAAyC,CAC3C,EAAEC,UAAUC,OAAOR,uBAAuBG,MAAMK,EAAAA,EAAI,CACvD;EAED,IAAIJ,UAAU;GACV,MAAMK,QAAQL,SAASC,IAAAA;GACvB,MAAMK,uBAAO,IAAIC,IAAAA;GACjB,KAAK,MAAMC,WAAWH,OAClB,IAAIG,WAAW,CAACF,KAAKG,IAAID,OAAAA,GAAU;IAC/BF,KAAKI,IAAIF,OAAAA;IACTN,aAAaS,KAAK;KACdR,UAAUC,OAAOR,uBAAuBG,MAAMK,EAAAA;KAC9CQ,WAAWf,yBAAyBW,OAAAA;IACxC,CAAA;GACJ;EAER;EAEA,OAAON;CACX;AACJ;AAEA,IAAaW,mBAAb,MAAaA;CACCC;CAEAC;CAEV,YAAYD,KAAiC;EACzC,KAAKA,MAAMA;EACX,KAAKC,YAAYD,IAAIC;CACzB;CAEAC,aAAaD,WAAyC;EAClD,KAAKA,YAAYA;CACrB;CAGAE,WAA+B;EAC3B,OAAO,KAAKH,IAAII;CACpB;CAEA,MAAMC,YAAYC,OAAqC;EACnD,IAAI,CAACA,MAAMC,QACP;EAGJ,IAAI,KAAKP,IAAIQ,SAAS,KAAKR,IAAIQ,MAAMC,UACjC,MAAM,KAAKC,cAAcJ,MAAMK,YAAYL,MAAMC,MAAM;EAG3D,MAAM,KAAKK,QAAQ/B,uBAAuBgC,SAASP,MAAMC,MAAM;CACnE;CAEA,MAAMO,YAAYR,OAAqC;EACnD,IAAI,CAACA,MAAMC,QACP;EAGJ,MAAM,KAAKG,cAAcJ,MAAMK,YAAYL,MAAMC,MAAM;EAEvD,MAAM,KAAKK,QAAQ/B,uBAAuBkC,SAAST,MAAMC,QAAaD,MAAMU,cAAc;CAC9F;CAEA,MAAMC,YAAYX,OAAqC;EAInD,MAAMC,SAASD,MAAMU,kBAAkBV,MAAMC;EAC7C,IAAI,CAACA,QACD;EAGJ,MAAM,KAAKG,cAAcJ,MAAMK,YAAYJ,MAAAA;EAE3C,MAAM,KAAKK,QAAQ/B,uBAAuBqC,SAASX,MAAAA;CACvD;CAEA,MAAgBG,cAAcC,YAAwBxB,MAAyB;EAC3E,IAAI,CAAC,KAAKa,IAAIQ,SAAS,CAACG,WAAWQ,kBAC/B;EAGJ,MAAMR,WAAWQ,iBAAiBC,OAAO,KAAKpB,IAAIQ,MAAMa,KAAKlC,IAAAA,CAAAA;CACjE;CAEA,MAAgByB,QACZN,OACAnB,MACAmC,cACc;EACd,IAAI,CAAC,KAAKrB,WACN;EAGJ,MAAM,KAAKA,UAAUsB,YAAY;GAC7BC,SAAS;IACLvC,MAAM,KAAKe,IAAIf;IACfqB;IACAnB;GACJ;GACAC,cAAc,KAAKY,IAAIZ,aAAaD,IAAAA;GACpC,GAAImC,eAAe,EAAEA,aAAa,IAAI,CAAC;EAC3C,CAAA;CACJ;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":["OAuth2Authorization","OAuth2AuthorizationCodeRequestValidator","readFromLocations","useRequestIdentityOrFail","useRequestSessionId","HTTPOAuth2Authorizer","codeRequestVerifier","requestValidator","consentService","logger","ctx","authorizeWithRequest","event","codeRequestValidated","validateWithRequest","data","client","redirectUriVerified","verify","identity","result","authorize","raw","sessionId","builtIn","record","clientId","id","realmId","owner","sub","subKind","type","scope","e","warn","error","run"],"sources":["../../../../../../src/adapters/http/adapters/oauth2/authorization/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IAppEvent } from 'routup';\nimport type { Logger } from '@authup/server-kit';\nimport type { OAuth2AuthorizationCodeRequest } from '@authup/core-kit';\nimport type { IConsentService, IOAuth2AuthorizationCodeRequestVerifier, OAuth2AuthorizationResult } from '../../../../../core/index.ts';\nimport { OAuth2Authorization, OAuth2AuthorizationCodeRequestValidator } from '../../../../../core/index.ts';\nimport { readFromLocations, useRequestIdentityOrFail, useRequestSessionId } from '../../../request/index.ts';\nimport type { HTTPOAuth2AuthorizationManagerContext } from './types.ts';\n\nexport class HTTPOAuth2Authorizer extends OAuth2Authorization {\n protected codeRequestVerifier : IOAuth2AuthorizationCodeRequestVerifier;\n\n protected requestValidator : OAuth2AuthorizationCodeRequestValidator;\n\n protected consentService? : IConsentService;\n\n protected logger? : Logger;\n\n constructor(ctx: HTTPOAuth2AuthorizationManagerContext) {\n super(ctx);\n\n this.codeRequestVerifier = ctx.codeRequestVerifier;\n this.consentService = ctx.consentService;\n this.logger = ctx.logger;\n\n this.requestValidator = new OAuth2AuthorizationCodeRequestValidator();\n }\n\n async authorizeWithRequest(event: IAppEvent) : Promise<OAuth2AuthorizationResult> {\n const codeRequestValidated = await this.validateWithRequest(event);\n\n const {\n data,\n client,\n redirectUriVerified,\n } = await this.codeRequestVerifier.verify(codeRequestValidated);\n\n const identity = useRequestIdentityOrFail(event);\n\n const result = await this.authorize(data, identity.raw, {\n sessionId: useRequestSessionId(event),\n client,\n redirectUriVerified,\n });\n\n // Persisted per-scope consent (plan 055): recorded only after a\n // successful approval — an access-policy denial throws inside\n // authorize() above, so a denied identity never writes a row.\n // built_in clients keep zero rows (locked); insert-missing makes\n // re-recording idempotent (union/keep).\n if (this.consentService && client && !client.builtIn) {\n try {\n await this.consentService.record({\n clientId: client.id,\n realmId: client.realmId,\n owner: {\n sub: identity.raw.data.id,\n subKind: identity.raw.type,\n },\n scope: data.scope ?? null,\n });\n } catch (e) {\n // never fail an issued code over a consent-write failure\n this.logger?.warn('Recording the OAuth2 consent grant failed.', {\n clientId: client.id,\n error: e,\n });\n }\n }\n\n return result;\n }\n\n /**\n * Validate authorization request.\n *\n * @throws OAuth2Error\n */\n async validateWithRequest(\n event: IAppEvent,\n ) : Promise<OAuth2AuthorizationCodeRequest> {\n const data = await readFromLocations(event, ['body', 'query']);\n return this.requestValidator.run(data);\n }\n}\n"],"mappings":";;;;;;;;;;;AAeA,IAAaK,uBAAb,cAA0CL,oBAAAA;CAC5BM;CAEAC;CAEAC;CAEAC;CAEV,YAAYC,KAA4C;EACpD,MAAMA,GAAAA;EAEN,KAAKJ,sBAAsBI,IAAIJ;EAC/B,KAAKE,iBAAiBE,IAAIF;EAC1B,KAAKC,SAASC,IAAID;EAElB,KAAKF,mBAAmB,IAAIN,wCAAAA;CAChC;CAEA,MAAMU,qBAAqBC,OAAuD;EAC9E,MAAMC,uBAAuB,MAAM,KAAKC,oBAAoBF,KAAAA;EAE5D,MAAM,EACFG,MACAC,QACAC,wBACA,MAAM,KAAKX,oBAAoBY,OAAOL,oBAAAA;EAE1C,MAAMM,WAAWhB,yBAAyBS,KAAAA;EAE1C,MAAMQ,SAAS,MAAM,KAAKC,UAAUN,MAAMI,SAASG,KAAK;GACpDC,WAAWnB,oBAAoBQ,KAAAA;GAC/BI;GACAC;EACJ,CAAA;EAOA,IAAI,KAAKT,kBAAkBQ,UAAU,CAACA,OAAOQ,SACzC,IAAI;GACA,MAAM,KAAKhB,eAAeiB,OAAO;IAC7BC,UAAUV,OAAOW;IACjBC,SAASZ,OAAOY;IAChBC,OAAO;KACHC,KAAKX,SAASG,IAAIP,KAAKY;KACvBI,SAASZ,SAASG,IAAIU;IAC1B;IACAC,OAAOlB,KAAKkB,SAAS;GACzB,CAAA;EACJ,SAASC,GAAG;GAER,KAAKzB,QAAQ0B,KAAK,8CAA8C;IAC5DT,UAAUV,OAAOW;IACjBS,OAAOF;GACX,CAAA;EACJ;EAGJ,OAAOd;CACX;;;;;IAOA,MAAMN,oBACFF,OACwC;EACxC,MAAMG,OAAO,MAAMb,kBAAkBU,OAAO,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"module.mjs","names":["OAuth2Authorization","OAuth2AuthorizationCodeRequestValidator","readFromLocations","useRequestIdentityOrFail","useRequestSessionId","HTTPOAuth2Authorizer","codeRequestVerifier","requestValidator","consentService","logger","ctx","authorizeWithRequest","event","codeRequestValidated","validateWithRequest","data","client","redirectUriVerified","verify","identity","result","authorize","raw","sessionId","builtIn","record","clientId","id","realmId","owner","sub","subKind","type","scope","e","warn","error","run"],"sources":["../../../../../../src/adapters/http/adapters/oauth2/authorization/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IAppEvent } from 'routup';\nimport type { Logger } from '@authup/server-kit';\nimport type { OAuth2AuthorizationCodeRequest } from '@authup/core-kit';\nimport type { IConsentService, IOAuth2AuthorizationCodeRequestVerifier, OAuth2AuthorizationResult } from '../../../../../core/index.ts';\nimport { OAuth2Authorization, OAuth2AuthorizationCodeRequestValidator } from '../../../../../core/index.ts';\nimport { readFromLocations, useRequestIdentityOrFail, useRequestSessionId } from '../../../request/index.ts';\nimport type { HTTPOAuth2AuthorizationManagerContext } from './types.ts';\n\nexport class HTTPOAuth2Authorizer extends OAuth2Authorization {\n protected codeRequestVerifier : IOAuth2AuthorizationCodeRequestVerifier;\n\n protected requestValidator : OAuth2AuthorizationCodeRequestValidator;\n\n protected consentService? : IConsentService;\n\n protected logger? : Logger;\n\n constructor(ctx: HTTPOAuth2AuthorizationManagerContext) {\n super(ctx);\n\n this.codeRequestVerifier = ctx.codeRequestVerifier;\n this.consentService = ctx.consentService;\n this.logger = ctx.logger;\n\n this.requestValidator = new OAuth2AuthorizationCodeRequestValidator();\n }\n\n async authorizeWithRequest(event: IAppEvent) : Promise<OAuth2AuthorizationResult> {\n const codeRequestValidated = await this.validateWithRequest(event);\n\n const {\n data,\n client,\n redirectUriVerified,\n } = await this.codeRequestVerifier.verify(codeRequestValidated);\n\n const identity = useRequestIdentityOrFail(event);\n\n const result = await this.authorize(data, identity.raw, {\n sessionId: useRequestSessionId(event),\n client,\n redirectUriVerified,\n });\n\n // Persisted per-scope consent (plan 055): recorded only after a\n // successful approval — an access-policy denial throws inside\n // authorize() above, so a denied identity never writes a row.\n // built_in clients keep zero rows (locked); insert-missing makes\n // re-recording idempotent (union/keep).\n if (this.consentService && client && !client.builtIn) {\n try {\n await this.consentService.record({\n clientId: client.id,\n realmId: client.realmId,\n owner: {\n sub: identity.raw.data.id,\n subKind: identity.raw.type,\n },\n scope: data.scope ?? null,\n });\n } catch (e) {\n // never fail an issued code over a consent-write failure\n this.logger?.warn('Recording the OAuth2 consent grant failed.', {\n clientId: client.id,\n error: e,\n });\n }\n }\n\n return result;\n }\n\n /**\n * Validate authorization request.\n *\n * @throws OAuth2Error\n */\n async validateWithRequest(\n event: IAppEvent,\n ) : Promise<OAuth2AuthorizationCodeRequest> {\n const data = await readFromLocations(event, ['body', 'query']);\n return this.requestValidator.run(data);\n }\n}\n"],"mappings":";;;;;;;;;;;AAeA,IAAaK,uBAAb,cAA0CL,oBAAAA;CAC5BM;CAEAC;CAEAC;CAEAC;CAEV,YAAYC,KAA4C;EACpD,MAAMA,GAAAA;EAEN,KAAKJ,sBAAsBI,IAAIJ;EAC/B,KAAKE,iBAAiBE,IAAIF;EAC1B,KAAKC,SAASC,IAAID;EAElB,KAAKF,mBAAmB,IAAIN,wCAAAA;CAChC;CAEA,MAAMU,qBAAqBC,OAAuD;EAC9E,MAAMC,uBAAuB,MAAM,KAAKC,oBAAoBF,KAAAA;EAE5D,MAAM,EACFG,MACAC,QACAC,wBACA,MAAM,KAAKX,oBAAoBY,OAAOL,oBAAAA;EAE1C,MAAMM,WAAWhB,yBAAyBS,KAAAA;EAE1C,MAAMQ,SAAS,MAAM,KAAKC,UAAUN,MAAMI,SAASG,KAAK;GACpDC,WAAWnB,oBAAoBQ,KAAAA;GAC/BI;GACAC;EACJ,CAAA;EAOA,IAAI,KAAKT,kBAAkBQ,UAAU,CAACA,OAAOQ,SACzC,IAAI;GACA,MAAM,KAAKhB,eAAeiB,OAAO;IAC7BC,UAAUV,OAAOW;IACjBC,SAASZ,OAAOY;IAChBC,OAAO;KACHC,KAAKX,SAASG,IAAIP,KAAKY;KACvBI,SAASZ,SAASG,IAAIU;IAC1B;IACAC,OAAOlB,KAAKkB,SAAS;GACzB,CAAA;EACJ,SAASC,GAAG;GAER,KAAKzB,QAAQ0B,KAAK,8CAA8C;IAC5DT,UAAUV,OAAOW;IACjBS,OAAOF;GACX,CAAA;EACJ;EAGJ,OAAOd;CACX;;;;;IAOA,MAAMN,oBACFF,OACwC;EACxC,MAAMG,OAAO,MAAMb,kBAAkBU,OAAO,CAAC,QAAQ,OAAQ,CAAA;EAC7D,OAAO,KAAKL,iBAAiB8B,IAAItB,IAAAA;CACrC;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realm.mjs","names":["readStringField","readRealmHint","sources","source","hint","map","value","trim","toLowerCase","find","undefined"],"sources":["../../../../../../../src/adapters/http/adapters/oauth2/grant-types/utils/realm.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { readStringField } from './credentials.ts';\n\n/**\n * Read the realm hint (`realm_id` ?? `realm_name`) from the given request\n * sources (checked in order). Both fields denote the same realm key and each\n * accepts a realm UUID or name. Values are canonicalized at the ingress\n * (`trim().toLowerCase()`, canonical identifier form layer 3) since no\n * validator runs on the token body.\n */\nexport function readRealmHint(...sources: (Record<string, any> | undefined)[]): string | undefined {\n for (const source of sources) {\n const hint = [\n readStringField(source, 'realm_id'),\n readStringField(source, 'realm_name'),\n ]\n .map((value) => value?.trim().toLowerCase())\n .find((value) => !!value);\n\n if (hint) {\n return hint;\n }\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;GAgBA,SAAgBC,cAAc,GAAGC,SAA4C;CACzE,KAAK,MAAMC,UAAUD,SAAS;EAC1B,MAAME,OAAO,CACTJ,gBAAgBG,QAAQ,UAAA,GACxBH,gBAAgBG,QAAQ,YAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"realm.mjs","names":["readStringField","readRealmHint","sources","source","hint","map","value","trim","toLowerCase","find","undefined"],"sources":["../../../../../../../src/adapters/http/adapters/oauth2/grant-types/utils/realm.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { readStringField } from './credentials.ts';\n\n/**\n * Read the realm hint (`realm_id` ?? `realm_name`) from the given request\n * sources (checked in order). Both fields denote the same realm key and each\n * accepts a realm UUID or name. Values are canonicalized at the ingress\n * (`trim().toLowerCase()`, canonical identifier form layer 3) since no\n * validator runs on the token body.\n */\nexport function readRealmHint(...sources: (Record<string, any> | undefined)[]): string | undefined {\n for (const source of sources) {\n const hint = [\n readStringField(source, 'realm_id'),\n readStringField(source, 'realm_name'),\n ]\n .map((value) => value?.trim().toLowerCase())\n .find((value) => !!value);\n\n if (hint) {\n return hint;\n }\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;GAgBA,SAAgBC,cAAc,GAAGC,SAA4C;CACzE,KAAK,MAAMC,UAAUD,SAAS;EAC1B,MAAME,OAAO,CACTJ,gBAAgBG,QAAQ,UAAA,GACxBH,gBAAgBG,QAAQ,YAAA,CAC3B,CAAA,CACIE,KAAKC,UAAUA,OAAOC,KAAAA,CAAAA,CAAOC,YAAAA,CAAAA,CAAAA,CAC7BC,MAAMH,UAAU,CAAC,CAACA,KAAAA;EAEvB,IAAIF,MACA,OAAOA;CAEf;AAGJ"}
|