@orthacms/content-server 0.0.0-reserve.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/define.d.ts +17 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +28 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/lib/collection/define.d.ts +35 -0
- package/dist/lib/collection/define.d.ts.map +1 -0
- package/dist/lib/collection/define.js +217 -0
- package/dist/lib/collection/table-builder.d.ts +28 -0
- package/dist/lib/collection/table-builder.d.ts.map +1 -0
- package/dist/lib/collection/table-builder.js +306 -0
- package/dist/lib/content-types/controllers/get-content-schema.controller.d.ts +24 -0
- package/dist/lib/content-types/controllers/get-content-schema.controller.d.ts.map +1 -0
- package/dist/lib/content-types/controllers/get-content-schema.controller.js +58 -0
- package/dist/lib/content-types/controllers/get-filter-fields.controller.d.ts +35 -0
- package/dist/lib/content-types/controllers/get-filter-fields.controller.d.ts.map +1 -0
- package/dist/lib/content-types/controllers/get-filter-fields.controller.js +74 -0
- package/dist/lib/content-types/controllers/list-content-schema.controller.d.ts +15 -0
- package/dist/lib/content-types/controllers/list-content-schema.controller.d.ts.map +1 -0
- package/dist/lib/content-types/controllers/list-content-schema.controller.js +38 -0
- package/dist/lib/content-types/queries/workspace-grants.query.d.ts +25 -0
- package/dist/lib/content-types/queries/workspace-grants.query.d.ts.map +1 -0
- package/dist/lib/content-types/queries/workspace-grants.query.js +45 -0
- package/dist/lib/content.module.d.ts +21 -0
- package/dist/lib/content.module.d.ts.map +1 -0
- package/dist/lib/content.module.js +264 -0
- package/dist/lib/content.tokens.d.ts +5 -0
- package/dist/lib/content.tokens.d.ts.map +1 -0
- package/dist/lib/content.tokens.js +9 -0
- package/dist/lib/copilot/content-tool.provider.d.ts +64 -0
- package/dist/lib/copilot/content-tool.provider.d.ts.map +1 -0
- package/dist/lib/copilot/content-tool.provider.js +309 -0
- package/dist/lib/copilot/diff-snapshots.d.ts +42 -0
- package/dist/lib/copilot/diff-snapshots.d.ts.map +1 -0
- package/dist/lib/copilot/diff-snapshots.js +77 -0
- package/dist/lib/copilot/entry-proposal.applier.d.ts +89 -0
- package/dist/lib/copilot/entry-proposal.applier.d.ts.map +1 -0
- package/dist/lib/copilot/entry-proposal.applier.js +245 -0
- package/dist/lib/copilot/entry-proposal.provider.d.ts +157 -0
- package/dist/lib/copilot/entry-proposal.provider.d.ts.map +1 -0
- package/dist/lib/copilot/entry-proposal.provider.js +619 -0
- package/dist/lib/copilot/filter-schema.d.ts +61 -0
- package/dist/lib/copilot/filter-schema.d.ts.map +1 -0
- package/dist/lib/copilot/filter-schema.js +139 -0
- package/dist/lib/copilot/project-entry.d.ts +23 -0
- package/dist/lib/copilot/project-entry.d.ts.map +1 -0
- package/dist/lib/copilot/project-entry.js +36 -0
- package/dist/lib/copilot/proposal-kinds.d.ts +30 -0
- package/dist/lib/copilot/proposal-kinds.d.ts.map +1 -0
- package/dist/lib/copilot/proposal-kinds.js +32 -0
- package/dist/lib/copilot/revision-tool.provider.d.ts +56 -0
- package/dist/lib/copilot/revision-tool.provider.d.ts.map +1 -0
- package/dist/lib/copilot/revision-tool.provider.js +215 -0
- package/dist/lib/docs/content-schemas.d.ts +34 -0
- package/dist/lib/docs/content-schemas.d.ts.map +1 -0
- package/dist/lib/docs/content-schemas.js +617 -0
- package/dist/lib/docs/describe-content-api.d.ts +22 -0
- package/dist/lib/docs/describe-content-api.d.ts.map +1 -0
- package/dist/lib/docs/describe-content-api.js +173 -0
- package/dist/lib/docs/field-schema.d.ts +28 -0
- package/dist/lib/docs/field-schema.d.ts.map +1 -0
- package/dist/lib/docs/field-schema.js +214 -0
- package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.d.ts +23 -0
- package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.d.ts.map +1 -0
- package/dist/lib/entries/application/use-cases/bulk-publish-entries.use-case.js +77 -0
- package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.d.ts +23 -0
- package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.d.ts.map +1 -0
- package/dist/lib/entries/application/use-cases/bulk-unpublish-entries.use-case.js +66 -0
- package/dist/lib/entries/application/use-cases/publish-entry.use-case.d.ts +43 -0
- package/dist/lib/entries/application/use-cases/publish-entry.use-case.d.ts.map +1 -0
- package/dist/lib/entries/application/use-cases/publish-entry.use-case.js +106 -0
- package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.d.ts +30 -0
- package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.d.ts.map +1 -0
- package/dist/lib/entries/application/use-cases/unpublish-entry.use-case.js +70 -0
- package/dist/lib/entries/controllers/bulk-entries.controller.d.ts +26 -0
- package/dist/lib/entries/controllers/bulk-entries.controller.d.ts.map +1 -0
- package/dist/lib/entries/controllers/create-entry.controller.d.ts +20 -0
- package/dist/lib/entries/controllers/create-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/controllers/delete-entry.controller.d.ts +24 -0
- package/dist/lib/entries/controllers/delete-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/controllers/get-entry.controller.d.ts +34 -0
- package/dist/lib/entries/controllers/get-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/controllers/list-entries.controller.d.ts +20 -0
- package/dist/lib/entries/controllers/list-entries.controller.d.ts.map +1 -0
- package/dist/lib/entries/controllers/publish-entry.controller.d.ts +19 -0
- package/dist/lib/entries/controllers/publish-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/controllers/resolve-type.d.ts +9 -0
- package/dist/lib/entries/controllers/resolve-type.d.ts.map +1 -0
- package/dist/lib/entries/controllers/update-entry.controller.d.ts +18 -0
- package/dist/lib/entries/controllers/update-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/domain/entry-publish-blocked.error.d.ts +13 -0
- package/dist/lib/entries/domain/entry-publish-blocked.error.d.ts.map +1 -0
- package/dist/lib/entries/domain/entry-publish-blocked.error.js +19 -0
- package/dist/lib/entries/domain/entry.d.ts +71 -0
- package/dist/lib/entries/domain/entry.d.ts.map +1 -0
- package/dist/lib/entries/domain/entry.js +90 -0
- package/dist/lib/entries/domain/events/entry-events.d.ts +67 -0
- package/dist/lib/entries/domain/events/entry-events.d.ts.map +1 -0
- package/dist/lib/entries/domain/events/entry-events.js +100 -0
- package/dist/lib/entries/dto/bulk-ids.dto.d.ts +11 -0
- package/dist/lib/entries/dto/bulk-ids.dto.d.ts.map +1 -0
- package/dist/lib/entries/dto/list-entries-query.dto.d.ts +46 -0
- package/dist/lib/entries/dto/list-entries-query.dto.d.ts.map +1 -0
- package/dist/lib/entries/dto/relation-delta-map.validator.d.ts +19 -0
- package/dist/lib/entries/dto/relation-delta-map.validator.d.ts.map +1 -0
- package/dist/lib/entries/dto/save-entry.dto.d.ts +46 -0
- package/dist/lib/entries/dto/save-entry.dto.d.ts.map +1 -0
- package/dist/lib/entries/entries.constants.d.ts +19 -0
- package/dist/lib/entries/entries.constants.d.ts.map +1 -0
- package/dist/lib/entries/entries.constants.js +21 -0
- package/dist/lib/entries/http/controllers/bulk-entries.controller.d.ts +33 -0
- package/dist/lib/entries/http/controllers/bulk-entries.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/bulk-entries.controller.js +143 -0
- package/dist/lib/entries/http/controllers/create-entry.controller.d.ts +21 -0
- package/dist/lib/entries/http/controllers/create-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/create-entry.controller.js +52 -0
- package/dist/lib/entries/http/controllers/delete-entry.controller.d.ts +25 -0
- package/dist/lib/entries/http/controllers/delete-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/delete-entry.controller.js +84 -0
- package/dist/lib/entries/http/controllers/get-entry.controller.d.ts +44 -0
- package/dist/lib/entries/http/controllers/get-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/get-entry.controller.js +124 -0
- package/dist/lib/entries/http/controllers/list-entries.controller.d.ts +20 -0
- package/dist/lib/entries/http/controllers/list-entries.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/list-entries.controller.js +52 -0
- package/dist/lib/entries/http/controllers/publish-entry.controller.d.ts +22 -0
- package/dist/lib/entries/http/controllers/publish-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/publish-entry.controller.js +68 -0
- package/dist/lib/entries/http/controllers/resolve-type.d.ts +9 -0
- package/dist/lib/entries/http/controllers/resolve-type.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/resolve-type.js +16 -0
- package/dist/lib/entries/http/controllers/to-actor.d.ts +13 -0
- package/dist/lib/entries/http/controllers/to-actor.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/to-actor.js +15 -0
- package/dist/lib/entries/http/controllers/update-entry.controller.d.ts +19 -0
- package/dist/lib/entries/http/controllers/update-entry.controller.d.ts.map +1 -0
- package/dist/lib/entries/http/controllers/update-entry.controller.js +51 -0
- package/dist/lib/entries/http/dto/bulk-ids.dto.d.ts +11 -0
- package/dist/lib/entries/http/dto/bulk-ids.dto.d.ts.map +1 -0
- package/dist/lib/entries/http/dto/bulk-ids.dto.js +33 -0
- package/dist/lib/entries/http/dto/list-entries-query.dto.d.ts +66 -0
- package/dist/lib/entries/http/dto/list-entries-query.dto.d.ts.map +1 -0
- package/dist/lib/entries/http/dto/list-entries-query.dto.js +192 -0
- package/dist/lib/entries/http/dto/relation-delta-map.validator.d.ts +30 -0
- package/dist/lib/entries/http/dto/relation-delta-map.validator.d.ts.map +1 -0
- package/dist/lib/entries/http/dto/relation-delta-map.validator.js +102 -0
- package/dist/lib/entries/http/dto/save-entry.dto.d.ts +48 -0
- package/dist/lib/entries/http/dto/save-entry.dto.d.ts.map +1 -0
- package/dist/lib/entries/http/dto/save-entry.dto.js +120 -0
- package/dist/lib/entries/http/guards/content-grant.guard.d.ts +37 -0
- package/dist/lib/entries/http/guards/content-grant.guard.d.ts.map +1 -0
- package/dist/lib/entries/http/guards/content-grant.guard.js +67 -0
- package/dist/lib/entries/infrastructure/persistence/bulk-publish-verdicts.d.ts +22 -0
- package/dist/lib/entries/infrastructure/persistence/bulk-publish-verdicts.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/bulk-publish-verdicts.js +81 -0
- package/dist/lib/entries/infrastructure/persistence/entry-counter.service.d.ts +42 -0
- package/dist/lib/entries/infrastructure/persistence/entry-counter.service.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/entry-counter.service.js +73 -0
- package/dist/lib/entries/infrastructure/persistence/entry-row.d.ts +56 -0
- package/dist/lib/entries/infrastructure/persistence/entry-row.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/entry-row.js +185 -0
- package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts +392 -0
- package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/entry-writer.service.js +1223 -0
- package/dist/lib/entries/infrastructure/persistence/field-selection.d.ts +24 -0
- package/dist/lib/entries/infrastructure/persistence/field-selection.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/media-accept.d.ts +23 -0
- package/dist/lib/entries/infrastructure/persistence/media-accept.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/media-accept.js +55 -0
- package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts +327 -0
- package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/persistence/relation-link.service.js +1008 -0
- package/dist/lib/entries/infrastructure/queries/bulk-publish-preview.query.d.ts +19 -0
- package/dist/lib/entries/infrastructure/queries/bulk-publish-preview.query.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/bulk-publish-preview.query.js +39 -0
- package/dist/lib/entries/infrastructure/queries/entries.service.d.ts +64 -0
- package/dist/lib/entries/infrastructure/queries/entries.service.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/entries.service.js +202 -0
- package/dist/lib/entries/infrastructure/queries/entry-filter-schema.d.ts +40 -0
- package/dist/lib/entries/infrastructure/queries/entry-filter-schema.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/entry-filter-surface.d.ts +38 -0
- package/dist/lib/entries/infrastructure/queries/entry-filter-surface.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/entry-filter-surface.js +310 -0
- package/dist/lib/entries/infrastructure/queries/entry-scalar-fields.d.ts +25 -0
- package/dist/lib/entries/infrastructure/queries/entry-scalar-fields.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/entry-scalar-fields.js +51 -0
- package/dist/lib/entries/infrastructure/queries/entry-search.d.ts +19 -0
- package/dist/lib/entries/infrastructure/queries/entry-search.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/entry-search.js +52 -0
- package/dist/lib/entries/infrastructure/queries/media-refs.query.d.ts +21 -0
- package/dist/lib/entries/infrastructure/queries/media-refs.query.d.ts.map +1 -0
- package/dist/lib/entries/infrastructure/queries/media-refs.query.js +117 -0
- package/dist/lib/entries/services/entries.service.d.ts +59 -0
- package/dist/lib/entries/services/entries.service.d.ts.map +1 -0
- package/dist/lib/entries/services/entry-counter.service.d.ts +31 -0
- package/dist/lib/entries/services/entry-counter.service.d.ts.map +1 -0
- package/dist/lib/entries/services/entry-filter-schema.d.ts +32 -0
- package/dist/lib/entries/services/entry-filter-schema.d.ts.map +1 -0
- package/dist/lib/entries/services/entry-row.d.ts +56 -0
- package/dist/lib/entries/services/entry-row.d.ts.map +1 -0
- package/dist/lib/entries/services/entry-writer.service.d.ts +193 -0
- package/dist/lib/entries/services/entry-writer.service.d.ts.map +1 -0
- package/dist/lib/entries/services/relation-link.service.d.ts +115 -0
- package/dist/lib/entries/services/relation-link.service.d.ts.map +1 -0
- package/dist/lib/entries/types/bulk-publish.d.ts +75 -0
- package/dist/lib/entries/types/bulk-publish.d.ts.map +1 -0
- package/dist/lib/entries/types/bulk-publish.js +22 -0
- package/dist/lib/entries/types/entry-list-view.d.ts +205 -0
- package/dist/lib/entries/types/entry-list-view.d.ts.map +1 -0
- package/dist/lib/entries/types/entry-list-view.js +5 -0
- package/dist/lib/entries/types/filter-surface.d.ts +35 -0
- package/dist/lib/entries/types/filter-surface.d.ts.map +1 -0
- package/dist/lib/entries/types/filter-surface.js +2 -0
- package/dist/lib/extension/entry-extension-boot-check.d.ts +16 -0
- package/dist/lib/extension/entry-extension-boot-check.d.ts.map +1 -0
- package/dist/lib/extension/entry-extension-boot-check.js +42 -0
- package/dist/lib/extension/entry-extension.d.ts +225 -0
- package/dist/lib/extension/entry-extension.d.ts.map +1 -0
- package/dist/lib/extension/entry-extension.js +27 -0
- package/dist/lib/extension/media-asset-resolver.d.ts +85 -0
- package/dist/lib/extension/media-asset-resolver.d.ts.map +1 -0
- package/dist/lib/extension/media-asset-resolver.js +26 -0
- package/dist/lib/extension/per-locale-relation.d.ts +18 -0
- package/dist/lib/extension/per-locale-relation.d.ts.map +1 -0
- package/dist/lib/extension/relation-locale-sync.d.ts +62 -0
- package/dist/lib/extension/relation-locale-sync.d.ts.map +1 -0
- package/dist/lib/extension/relation-locale-sync.js +88 -0
- package/dist/lib/fields/index.d.ts +94 -0
- package/dist/lib/fields/index.d.ts.map +1 -0
- package/dist/lib/fields/index.js +203 -0
- package/dist/lib/insights/http/controllers/content-pipeline.controller.d.ts +16 -0
- package/dist/lib/insights/http/controllers/content-pipeline.controller.d.ts.map +1 -0
- package/dist/lib/insights/http/controllers/content-pipeline.controller.js +39 -0
- package/dist/lib/insights/http/controllers/content-punchcard.controller.d.ts +18 -0
- package/dist/lib/insights/http/controllers/content-punchcard.controller.d.ts.map +1 -0
- package/dist/lib/insights/http/controllers/content-punchcard.controller.js +42 -0
- package/dist/lib/insights/http/controllers/content-stale.controller.d.ts +17 -0
- package/dist/lib/insights/http/controllers/content-stale.controller.d.ts.map +1 -0
- package/dist/lib/insights/http/controllers/content-stale.controller.js +40 -0
- package/dist/lib/insights/http/controllers/content-totals.controller.d.ts +18 -0
- package/dist/lib/insights/http/controllers/content-totals.controller.d.ts.map +1 -0
- package/dist/lib/insights/http/controllers/content-totals.controller.js +42 -0
- package/dist/lib/insights/http/controllers/content-unshipped.controller.d.ts +17 -0
- package/dist/lib/insights/http/controllers/content-unshipped.controller.d.ts.map +1 -0
- package/dist/lib/insights/http/controllers/content-unshipped.controller.js +40 -0
- package/dist/lib/insights/http/controllers/content-velocity.controller.d.ts +17 -0
- package/dist/lib/insights/http/controllers/content-velocity.controller.d.ts.map +1 -0
- package/dist/lib/insights/http/controllers/content-velocity.controller.js +41 -0
- package/dist/lib/insights/http/dto/insights-range-query.dto.d.ts +15 -0
- package/dist/lib/insights/http/dto/insights-range-query.dto.d.ts.map +1 -0
- package/dist/lib/insights/http/dto/insights-range-query.dto.js +38 -0
- package/dist/lib/insights/infrastructure/queries/content-insights.query.d.ts +77 -0
- package/dist/lib/insights/infrastructure/queries/content-insights.query.d.ts.map +1 -0
- package/dist/lib/insights/infrastructure/queries/content-insights.query.js +380 -0
- package/dist/lib/insights/types/content-insights-view.d.ts +134 -0
- package/dist/lib/insights/types/content-insights-view.d.ts.map +1 -0
- package/dist/lib/insights/types/content-insights-view.js +10 -0
- package/dist/lib/mcp/content-tools.provider.d.ts +83 -0
- package/dist/lib/mcp/content-tools.provider.d.ts.map +1 -0
- package/dist/lib/mcp/content-tools.provider.js +441 -0
- package/dist/lib/mcp/tool-input.d.ts +43 -0
- package/dist/lib/mcp/tool-input.d.ts.map +1 -0
- package/dist/lib/mcp/tool-input.js +117 -0
- package/dist/lib/mcp/tool-schemas.d.ts +34 -0
- package/dist/lib/mcp/tool-schemas.d.ts.map +1 -0
- package/dist/lib/mcp/tool-schemas.js +282 -0
- package/dist/lib/public/controllers/get-public-entry.controller.d.ts +26 -0
- package/dist/lib/public/controllers/get-public-entry.controller.d.ts.map +1 -0
- package/dist/lib/public/controllers/list-public-entries.controller.d.ts +24 -0
- package/dist/lib/public/controllers/list-public-entries.controller.d.ts.map +1 -0
- package/dist/lib/public/controllers/public-schema.controller.d.ts +18 -0
- package/dist/lib/public/controllers/public-schema.controller.d.ts.map +1 -0
- package/dist/lib/public-api/http/api-token-request.d.ts +41 -0
- package/dist/lib/public-api/http/api-token-request.d.ts.map +1 -0
- package/dist/lib/public-api/http/api-token-request.js +2 -0
- package/dist/lib/public-api/http/controllers/public-content-types.controller.d.ts +31 -0
- package/dist/lib/public-api/http/controllers/public-content-types.controller.d.ts.map +1 -0
- package/dist/lib/public-api/http/controllers/public-content-types.controller.js +93 -0
- package/dist/lib/public-api/http/controllers/public-entries.controller.d.ts +101 -0
- package/dist/lib/public-api/http/controllers/public-entries.controller.d.ts.map +1 -0
- package/dist/lib/public-api/http/controllers/public-entries.controller.js +307 -0
- package/dist/lib/public-api/http/controllers/public-entry-writes.controller.d.ts +76 -0
- package/dist/lib/public-api/http/controllers/public-entry-writes.controller.d.ts.map +1 -0
- package/dist/lib/public-api/http/controllers/public-entry-writes.controller.js +353 -0
- package/dist/lib/public-api/http/controllers/resolve-granted-type.d.ts +42 -0
- package/dist/lib/public-api/http/controllers/resolve-granted-type.d.ts.map +1 -0
- package/dist/lib/public-api/http/controllers/resolve-granted-type.js +25 -0
- package/dist/lib/public-api/http/decorators/current-api-token.decorator.d.ts +8 -0
- package/dist/lib/public-api/http/decorators/current-api-token.decorator.d.ts.map +1 -0
- package/dist/lib/public-api/http/decorators/current-api-token.decorator.js +17 -0
- package/dist/lib/public-api/http/dto/public-bulk.dto.d.ts +58 -0
- package/dist/lib/public-api/http/dto/public-bulk.dto.d.ts.map +1 -0
- package/dist/lib/public-api/http/dto/public-bulk.dto.js +118 -0
- package/dist/lib/public-api/http/dto/public-list-entries-query.dto.d.ts +106 -0
- package/dist/lib/public-api/http/dto/public-list-entries-query.dto.d.ts.map +1 -0
- package/dist/lib/public-api/http/dto/public-list-entries-query.dto.js +297 -0
- package/dist/lib/public-api/http/dto/public-save-entry.dto.d.ts +39 -0
- package/dist/lib/public-api/http/dto/public-save-entry.dto.d.ts.map +1 -0
- package/dist/lib/public-api/http/dto/public-save-entry.dto.js +112 -0
- package/dist/lib/public-api/http/guards/api-token-workspace.guard.d.ts +25 -0
- package/dist/lib/public-api/http/guards/api-token-workspace.guard.d.ts.map +1 -0
- package/dist/lib/public-api/http/guards/api-token-workspace.guard.js +58 -0
- package/dist/lib/public-api/http/guards/api-token.guard.d.ts +32 -0
- package/dist/lib/public-api/http/guards/api-token.guard.d.ts.map +1 -0
- package/dist/lib/public-api/http/guards/api-token.guard.js +92 -0
- package/dist/lib/public-api/http/guards/draft-visibility.guard.d.ts +25 -0
- package/dist/lib/public-api/http/guards/draft-visibility.guard.d.ts.map +1 -0
- package/dist/lib/public-api/http/guards/draft-visibility.guard.js +56 -0
- package/dist/lib/public-api/infrastructure/bulk-save-op.d.ts +55 -0
- package/dist/lib/public-api/infrastructure/bulk-save-op.d.ts.map +1 -0
- package/dist/lib/public-api/infrastructure/bulk-save-op.js +61 -0
- package/dist/lib/public-api/infrastructure/field-selection.d.ts +21 -0
- package/dist/lib/public-api/infrastructure/field-selection.d.ts.map +1 -0
- package/dist/lib/public-api/infrastructure/field-selection.js +72 -0
- package/dist/lib/public-api/infrastructure/public-entries.query.d.ts +248 -0
- package/dist/lib/public-api/infrastructure/public-entries.query.d.ts.map +1 -0
- package/dist/lib/public-api/infrastructure/public-entries.query.js +557 -0
- package/dist/lib/public-api/infrastructure/public-entry-row.d.ts +31 -0
- package/dist/lib/public-api/infrastructure/public-entry-row.d.ts.map +1 -0
- package/dist/lib/public-api/infrastructure/public-entry-row.js +76 -0
- package/dist/lib/public-api/infrastructure/public-entry-writes.service.d.ts +188 -0
- package/dist/lib/public-api/infrastructure/public-entry-writes.service.d.ts.map +1 -0
- package/dist/lib/public-api/infrastructure/public-entry-writes.service.js +321 -0
- package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts +98 -0
- package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts.map +1 -0
- package/dist/lib/public-api/infrastructure/public-expansion.query.js +384 -0
- package/dist/lib/public-api/types/public-bulk.d.ts +77 -0
- package/dist/lib/public-api/types/public-bulk.d.ts.map +1 -0
- package/dist/lib/public-api/types/public-bulk.js +23 -0
- package/dist/lib/public-api/types/public-entry.d.ts +97 -0
- package/dist/lib/public-api/types/public-entry.d.ts.map +1 -0
- package/dist/lib/public-api/types/public-entry.js +8 -0
- package/dist/lib/public-api/types/public-expansion.d.ts +92 -0
- package/dist/lib/public-api/types/public-expansion.d.ts.map +1 -0
- package/dist/lib/public-api/types/public-expansion.js +2 -0
- package/dist/lib/registry/content-type-registry.d.ts +103 -0
- package/dist/lib/registry/content-type-registry.d.ts.map +1 -0
- package/dist/lib/registry/content-type-registry.js +155 -0
- package/dist/lib/revisions/application/ports/revision-store.d.ts +71 -0
- package/dist/lib/revisions/application/ports/revision-store.d.ts.map +1 -0
- package/dist/lib/revisions/application/ports/revision-store.js +9 -0
- package/dist/lib/revisions/application/use-cases/publish-revision.use-case.d.ts +40 -0
- package/dist/lib/revisions/application/use-cases/publish-revision.use-case.d.ts.map +1 -0
- package/dist/lib/revisions/application/use-cases/publish-revision.use-case.js +66 -0
- package/dist/lib/revisions/application/use-cases/restore-revision.use-case.d.ts +36 -0
- package/dist/lib/revisions/application/use-cases/restore-revision.use-case.d.ts.map +1 -0
- package/dist/lib/revisions/application/use-cases/restore-revision.use-case.js +57 -0
- package/dist/lib/revisions/domain/revision-status.d.ts +18 -0
- package/dist/lib/revisions/domain/revision-status.d.ts.map +1 -0
- package/dist/lib/revisions/domain/revision-status.js +18 -0
- package/dist/lib/revisions/domain/revision.d.ts +80 -0
- package/dist/lib/revisions/domain/revision.d.ts.map +1 -0
- package/dist/lib/revisions/domain/revision.js +84 -0
- package/dist/lib/revisions/http/controllers/publish-revision.controller.d.ts +19 -0
- package/dist/lib/revisions/http/controllers/publish-revision.controller.d.ts.map +1 -0
- package/dist/lib/revisions/http/controllers/publish-revision.controller.js +51 -0
- package/dist/lib/revisions/http/controllers/restore-revision.controller.d.ts +17 -0
- package/dist/lib/revisions/http/controllers/restore-revision.controller.d.ts.map +1 -0
- package/dist/lib/revisions/http/controllers/restore-revision.controller.js +49 -0
- package/dist/lib/revisions/http/controllers/revisions.controller.d.ts +20 -0
- package/dist/lib/revisions/http/controllers/revisions.controller.d.ts.map +1 -0
- package/dist/lib/revisions/http/controllers/revisions.controller.js +76 -0
- package/dist/lib/revisions/infrastructure/persistence/drizzle-revision.store.d.ts +33 -0
- package/dist/lib/revisions/infrastructure/persistence/drizzle-revision.store.d.ts.map +1 -0
- package/dist/lib/revisions/infrastructure/persistence/drizzle-revision.store.js +174 -0
- package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts +17 -0
- package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts.map +1 -0
- package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.js +20 -0
- package/dist/lib/revisions/infrastructure/persistence/revision-table.d.ts +228 -0
- package/dist/lib/revisions/infrastructure/persistence/revision-table.d.ts.map +1 -0
- package/dist/lib/revisions/infrastructure/persistence/revision-table.js +57 -0
- package/dist/lib/revisions/infrastructure/queries/revision-refs.query.d.ts +22 -0
- package/dist/lib/revisions/infrastructure/queries/revision-refs.query.d.ts.map +1 -0
- package/dist/lib/revisions/infrastructure/queries/revision-refs.query.js +66 -0
- package/dist/lib/revisions/revisions.constants.d.ts +10 -0
- package/dist/lib/revisions/revisions.constants.d.ts.map +1 -0
- package/dist/lib/revisions/revisions.constants.js +12 -0
- package/dist/lib/revisions/types/revision-view.d.ts +74 -0
- package/dist/lib/revisions/types/revision-view.d.ts.map +1 -0
- package/dist/lib/revisions/types/revision-view.js +2 -0
- package/dist/lib/types/content-type.d.ts +131 -0
- package/dist/lib/types/content-type.d.ts.map +1 -0
- package/dist/lib/types/content-type.js +28 -0
- package/dist/lib/types/fields.d.ts +303 -0
- package/dist/lib/types/fields.d.ts.map +1 -0
- package/dist/lib/types/fields.js +52 -0
- package/dist/lib/utils/content-plugin.d.ts +35 -0
- package/dist/lib/utils/content-plugin.d.ts.map +1 -0
- package/dist/lib/utils/content-plugin.js +35 -0
- package/dist/lib/validation/services/entry-validation.service.d.ts +24 -0
- package/dist/lib/validation/services/entry-validation.service.d.ts.map +1 -0
- package/dist/lib/validation/services/entry-validation.service.js +35 -0
- package/package.json +54 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildEntryFilterSurface = buildEntryFilterSurface;
|
|
4
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
5
|
+
const utils_server_1 = require("@orthacms/utils-server");
|
|
6
|
+
const content_type_1 = require("../../../types/content-type");
|
|
7
|
+
const fields_1 = require("../../../types/fields");
|
|
8
|
+
// `scalarTypeFor` is the single scalar-coercion mapping — shared with the
|
|
9
|
+
// sort whitelist (`isScalarField`), so "filterable" and "sortable" can't
|
|
10
|
+
// disagree on which field types are backed by a comparable column.
|
|
11
|
+
const entry_scalar_fields_1 = require("./entry-scalar-fields");
|
|
12
|
+
/**
|
|
13
|
+
* Relation hops offered by default. 2 hops means `author.company.name` is
|
|
14
|
+
* reachable and `…company.country.name` is not. Each hop is an EXISTS
|
|
15
|
+
* subquery, so this directly bounds worst-case query cost. The engine's
|
|
16
|
+
* `maxDepth` counts path SEGMENTS (hops + 1), so it is derived as
|
|
17
|
+
* `hops + 1` below — raising one without the other would let the picker
|
|
18
|
+
* offer paths the parser rejects with a 400.
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_RELATION_HOPS = 2;
|
|
21
|
+
/** Humanize a field name — mirrors the admin's `fieldLabel` fallback. */
|
|
22
|
+
function humanize(name) {
|
|
23
|
+
return name
|
|
24
|
+
.replace(/[_-]+/g, ' ')
|
|
25
|
+
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
26
|
+
.replace(/^\w/, (c) => c.toUpperCase());
|
|
27
|
+
}
|
|
28
|
+
/** A field's display label — its admin label, else a humanized name. */
|
|
29
|
+
function fieldLabel(name, spec) {
|
|
30
|
+
const label = spec.admin?.label;
|
|
31
|
+
return typeof label === 'string' && label.length > 0
|
|
32
|
+
? label
|
|
33
|
+
: humanize(name);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a column on a generated table by its JS property name.
|
|
37
|
+
*
|
|
38
|
+
* `Object.hasOwn`-guarded, and it throws rather than returning `undefined`.
|
|
39
|
+
* Every caller today passes a literal or a name off `Object.entries(type.fields)`,
|
|
40
|
+
* so nothing request-supplied reaches it — but drizzle's column map is a plain
|
|
41
|
+
* object, an unguarded lookup resolves `constructor`/`valueOf`/`toString` to
|
|
42
|
+
* truthy non-columns, and handing one of those to drizzle as a `Column` emits a
|
|
43
|
+
* broken fragment (a 500) rather than failing here. Its `utils-server`
|
|
44
|
+
* counterpart (`columnOf`) is guarded the same way, so the two helpers can't
|
|
45
|
+
* disagree about what a name means.
|
|
46
|
+
*/
|
|
47
|
+
function col(table, name) {
|
|
48
|
+
const cols = (0, drizzle_orm_1.getTableColumns)(table);
|
|
49
|
+
const column = Object.hasOwn(cols, name) ? cols[name] : undefined;
|
|
50
|
+
if (!column) {
|
|
51
|
+
throw new utils_server_1.FilterSchemaException(`column "${name}" does not exist on the generated table`);
|
|
52
|
+
}
|
|
53
|
+
return column;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The scope predicate for one target type: the workspace boundary plus the
|
|
57
|
+
* soft-delete guard, resolved against whatever table the translator queries
|
|
58
|
+
* (the physical target, or an alias for a self-relation). Without this a
|
|
59
|
+
* relation filter matches rows the root list itself excludes — a
|
|
60
|
+
* soft-deleted author would still match `author.name`.
|
|
61
|
+
*
|
|
62
|
+
* Publish status is deliberately NOT filtered here: an editor filtering
|
|
63
|
+
* articles by author expects to match a draft author, and hiding
|
|
64
|
+
* unpublished targets would silently drop rows. A published-only traversal
|
|
65
|
+
* is expressible as an explicit `author.status` rule instead.
|
|
66
|
+
*/
|
|
67
|
+
function scopeFor(target, workspaceId) {
|
|
68
|
+
return (tbl) => {
|
|
69
|
+
const cols = (0, drizzle_orm_1.getTableColumns)(tbl);
|
|
70
|
+
return (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(cols['workspaceId'], workspaceId), target.paranoid ? (0, drizzle_orm_1.isNull)(cols['deletedAt']) : undefined);
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** The scalar (envelope + field) whitelist for one type at one level. */
|
|
74
|
+
function scalarFieldsOf(type) {
|
|
75
|
+
const fields = {
|
|
76
|
+
// `id` so a relation's record picker (`author.id in (…)`) resolves,
|
|
77
|
+
// and the envelope timestamps so they stay API-filterable.
|
|
78
|
+
id: { type: utils_server_1.ScalarFieldType.Uuid },
|
|
79
|
+
createdAt: { type: utils_server_1.ScalarFieldType.Date },
|
|
80
|
+
updatedAt: { type: utils_server_1.ScalarFieldType.Date }
|
|
81
|
+
};
|
|
82
|
+
if (type.publishable) {
|
|
83
|
+
fields['status'] = {
|
|
84
|
+
type: utils_server_1.ScalarFieldType.Enum,
|
|
85
|
+
enumValues: [content_type_1.ENTRY_STATUS.Draft, content_type_1.ENTRY_STATUS.Published]
|
|
86
|
+
};
|
|
87
|
+
fields['publishedAt'] = { type: utils_server_1.ScalarFieldType.Date };
|
|
88
|
+
}
|
|
89
|
+
if (type.i18n) {
|
|
90
|
+
fields['locale'] = { type: utils_server_1.ScalarFieldType.String };
|
|
91
|
+
// The translation-group key, so a caller holding one row's group can
|
|
92
|
+
// ask for the group's row in another locale (`localeGroupId eq X` +
|
|
93
|
+
// `?locale=de`). Whitelisted for SQL only — `scalarWireOf` below builds
|
|
94
|
+
// the admin's filter *picker*, and this envelope column stays out of
|
|
95
|
+
// it, so the UI is unchanged.
|
|
96
|
+
fields['localeGroupId'] = { type: utils_server_1.ScalarFieldType.Uuid };
|
|
97
|
+
}
|
|
98
|
+
for (const [name, spec] of Object.entries(type.fields)) {
|
|
99
|
+
const scalar = (0, entry_scalar_fields_1.scalarTypeFor)(spec);
|
|
100
|
+
if (scalar)
|
|
101
|
+
fields[name] = scalar;
|
|
102
|
+
}
|
|
103
|
+
return fields;
|
|
104
|
+
}
|
|
105
|
+
/** The wire fields the picker shows at one level: user scalars + status. */
|
|
106
|
+
function scalarWireOf(type, path, group, wire) {
|
|
107
|
+
if (type.publishable) {
|
|
108
|
+
wire.push({
|
|
109
|
+
path: [...path, 'status'].join('.'),
|
|
110
|
+
label: 'Status',
|
|
111
|
+
type: utils_server_1.ScalarFieldType.Enum,
|
|
112
|
+
enumValues: [content_type_1.ENTRY_STATUS.Draft, content_type_1.ENTRY_STATUS.Published],
|
|
113
|
+
group
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
for (const [name, spec] of Object.entries(type.fields)) {
|
|
117
|
+
const scalar = (0, entry_scalar_fields_1.scalarTypeFor)(spec);
|
|
118
|
+
if (!scalar)
|
|
119
|
+
continue;
|
|
120
|
+
wire.push({
|
|
121
|
+
path: [...path, name].join('.'),
|
|
122
|
+
label: fieldLabel(name, spec),
|
|
123
|
+
type: scalar.type,
|
|
124
|
+
enumValues: scalar.enumValues,
|
|
125
|
+
group
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Build one relation's `RelationSchema`, recursing into the target's own
|
|
131
|
+
* relations while hops remain, and pushing the wire fields for the target
|
|
132
|
+
* level as it goes. Returns `null` to omit the relation entirely (ungranted
|
|
133
|
+
* target, a cycle back to an ancestor, or a self-referential shape not yet
|
|
134
|
+
* supported).
|
|
135
|
+
*/
|
|
136
|
+
function relationFor(name, spec, owner, path, group, hopsLeft, visited, ctx) {
|
|
137
|
+
const rel = spec.relation;
|
|
138
|
+
if (!rel)
|
|
139
|
+
return null;
|
|
140
|
+
// `to()` is the target for an owning side, the OWNER of the storage for
|
|
141
|
+
// an inverse — either way, the type this hop traverses to.
|
|
142
|
+
const target = rel.to();
|
|
143
|
+
if (ctx.grantedTypes && !ctx.grantedTypes.has(target.name))
|
|
144
|
+
return null;
|
|
145
|
+
const selfRef = target.name === owner.name;
|
|
146
|
+
// A cycle back to an ANCESTOR is never a filter a user wants. A
|
|
147
|
+
// self-reference is allowed (page trees) and bounded by hops instead.
|
|
148
|
+
if (!selfRef && visited.has(target.name))
|
|
149
|
+
return null;
|
|
150
|
+
const relLabel = fieldLabel(name, spec);
|
|
151
|
+
const nextPath = [...path, name];
|
|
152
|
+
const nextGroup = [...group, relLabel];
|
|
153
|
+
// The relation's record-picker entry: `author.id`, rendered as a picker
|
|
154
|
+
// over `target` rather than a raw uuid input.
|
|
155
|
+
ctx.wire.push({
|
|
156
|
+
path: [...nextPath, 'id'].join('.'),
|
|
157
|
+
label: relLabel,
|
|
158
|
+
type: utils_server_1.ScalarFieldType.Uuid,
|
|
159
|
+
group: nextGroup,
|
|
160
|
+
relationTarget: target.name
|
|
161
|
+
});
|
|
162
|
+
// The target's own scalar fields + (if hops remain) its relations. This
|
|
163
|
+
// is the SAME walk that emits the wire fields, so the SQL whitelist and
|
|
164
|
+
// the picker's field list are one traversal and cannot drift.
|
|
165
|
+
const nested = walk(target, nextPath, nextGroup, hopsLeft - 1, visited, ctx);
|
|
166
|
+
const common = {
|
|
167
|
+
fields: nested.fields,
|
|
168
|
+
relations: nested.relations,
|
|
169
|
+
scope: scopeFor(target, ctx.workspaceId)
|
|
170
|
+
};
|
|
171
|
+
const ownerT = owner.table;
|
|
172
|
+
const targetT = target.table;
|
|
173
|
+
// ---- inverse: storage lives on the owning side, reused swapped ----
|
|
174
|
+
if (rel.inverse) {
|
|
175
|
+
const ownerField = rel.inverse.field;
|
|
176
|
+
const ownerSpec = target.fields[ownerField];
|
|
177
|
+
if (!ownerSpec?.relation)
|
|
178
|
+
return null;
|
|
179
|
+
if (ownerSpec.relation.many) {
|
|
180
|
+
// Inverse of a many-to-many: OUR rows are the join's targets.
|
|
181
|
+
if (selfRef)
|
|
182
|
+
return null; // self many-to-many — not supported yet
|
|
183
|
+
const join = target.joinTables[ownerField];
|
|
184
|
+
if (!join)
|
|
185
|
+
return null;
|
|
186
|
+
return {
|
|
187
|
+
kind: utils_server_1.RelationKind.ManyToMany,
|
|
188
|
+
through: join,
|
|
189
|
+
fk: col(join, 'targetId'),
|
|
190
|
+
targetFk: col(join, 'sourceId'),
|
|
191
|
+
table: target.table,
|
|
192
|
+
parentKey: col(ownerT, 'id'),
|
|
193
|
+
targetKey: col(targetT, 'id'),
|
|
194
|
+
...common
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// Inverse of a single = one-to-many: the owner's FK points at us.
|
|
198
|
+
return {
|
|
199
|
+
kind: utils_server_1.RelationKind.OneToMany,
|
|
200
|
+
table: target.table,
|
|
201
|
+
fk: col(targetT, ownerField),
|
|
202
|
+
parentKey: col(ownerT, 'id'),
|
|
203
|
+
...common
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// ---- owning many-to-many ----
|
|
207
|
+
if (rel.many) {
|
|
208
|
+
if (selfRef)
|
|
209
|
+
return null; // self many-to-many — not supported yet
|
|
210
|
+
const join = owner.joinTables[name];
|
|
211
|
+
if (!join)
|
|
212
|
+
return null;
|
|
213
|
+
return {
|
|
214
|
+
kind: utils_server_1.RelationKind.ManyToMany,
|
|
215
|
+
through: join,
|
|
216
|
+
fk: col(join, 'sourceId'),
|
|
217
|
+
targetFk: col(join, 'targetId'),
|
|
218
|
+
table: target.table,
|
|
219
|
+
parentKey: col(ownerT, 'id'),
|
|
220
|
+
targetKey: col(targetT, 'id'),
|
|
221
|
+
...common
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
// ---- owning single ----
|
|
225
|
+
if (selfRef) {
|
|
226
|
+
return {
|
|
227
|
+
kind: utils_server_1.RelationKind.SelfReferential,
|
|
228
|
+
table: target.table,
|
|
229
|
+
fk: col(ownerT, name),
|
|
230
|
+
// Unique per OCCURRENCE, not per relation: two rules on the same
|
|
231
|
+
// self-relation must not share a correlation name.
|
|
232
|
+
alias: `qb_${nextPath.join('__')}`,
|
|
233
|
+
...common
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
kind: utils_server_1.RelationKind.ManyToOne,
|
|
238
|
+
table: target.table,
|
|
239
|
+
fk: col(ownerT, name),
|
|
240
|
+
targetKey: col(targetT, 'id'),
|
|
241
|
+
...common
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* One node of the surface: the scalar fields filterable at this level and
|
|
246
|
+
* the relations traversable from it. Emits the wire fields for this level
|
|
247
|
+
* as a side effect on `ctx.wire`, so the SQL whitelist (the return value)
|
|
248
|
+
* and the picker's field list (the accumulator) are produced by a single
|
|
249
|
+
* traversal.
|
|
250
|
+
*/
|
|
251
|
+
function walk(type, path, group, hopsLeft, visited, ctx) {
|
|
252
|
+
const fields = scalarFieldsOf(type);
|
|
253
|
+
scalarWireOf(type, path, group, ctx.wire);
|
|
254
|
+
if (hopsLeft <= 0)
|
|
255
|
+
return { fields };
|
|
256
|
+
const nextVisited = new Set([...visited, type.name]);
|
|
257
|
+
const relations = {};
|
|
258
|
+
for (const [name, spec] of Object.entries(type.fields)) {
|
|
259
|
+
if (spec.type !== fields_1.CONTENT_FIELD_TYPE.Relation)
|
|
260
|
+
continue;
|
|
261
|
+
const r = relationFor(name, spec, type, path, group, hopsLeft, nextVisited, ctx);
|
|
262
|
+
if (r)
|
|
263
|
+
relations[name] = r;
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
fields,
|
|
267
|
+
relations: Object.keys(relations).length ? relations : undefined
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* The filterable surface for one content type: the Drizzle `FilterSchema`
|
|
272
|
+
* (the security boundary — only listed paths reach SQL) AND the flat
|
|
273
|
+
* `WireFilterField[]` the admin's query builder renders, produced by a
|
|
274
|
+
* single traversal so they cannot drift.
|
|
275
|
+
*
|
|
276
|
+
* `extensionFields` are virtual fields contributed by the bound
|
|
277
|
+
* `CONTENT_ENTRY_EXTENSION` (locale aggregates, …): they merge into the
|
|
278
|
+
* root `fields` (so the parser can coerce their values) and their names are
|
|
279
|
+
* registered on `extensionFields` (so the translator routes them to the
|
|
280
|
+
* extension's own SQL resolver). A real column always wins a name clash.
|
|
281
|
+
* They are NOT surfaced as wire fields here — a contributing plugin adds
|
|
282
|
+
* those via the admin's `RECORDS_FILTER_FIELDS_SLOT`, as today.
|
|
283
|
+
*/
|
|
284
|
+
function buildEntryFilterSurface(type, opts) {
|
|
285
|
+
const hops = opts.maxRelationHops ?? DEFAULT_RELATION_HOPS;
|
|
286
|
+
const ctx = {
|
|
287
|
+
workspaceId: opts.workspaceId,
|
|
288
|
+
grantedTypes: opts.grantedTypes,
|
|
289
|
+
wire: []
|
|
290
|
+
};
|
|
291
|
+
const root = walk(type, [], [], hops, new Set(), ctx);
|
|
292
|
+
const schema = {
|
|
293
|
+
fields: root.fields,
|
|
294
|
+
relations: root.relations,
|
|
295
|
+
// Path SEGMENTS = hops + 1 (`author.company.name` is 3 at 2 hops),
|
|
296
|
+
// so the engine cap must track the traversal cap or it silently
|
|
297
|
+
// rejects paths the picker offers.
|
|
298
|
+
maxDepth: hops + 1
|
|
299
|
+
};
|
|
300
|
+
if (opts.extensionFields) {
|
|
301
|
+
const merged = schema.fields ?? {};
|
|
302
|
+
const extra = Object.keys(opts.extensionFields).filter((n) => !(n in merged));
|
|
303
|
+
for (const n of extra)
|
|
304
|
+
merged[n] = opts.extensionFields[n];
|
|
305
|
+
schema.fields = merged;
|
|
306
|
+
if (extra.length)
|
|
307
|
+
schema.extensionFields = new Set(extra);
|
|
308
|
+
}
|
|
309
|
+
return { schema, fields: ctx.wire };
|
|
310
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ScalarFieldSchema } from '@orthacms/utils-server';
|
|
2
|
+
import { type AnyFieldSpec } from '../../../types/fields';
|
|
3
|
+
/**
|
|
4
|
+
* The filter scalar type for one content field, or `null` to leave it
|
|
5
|
+
* unfilterable. Mirrors the admin's `filterFieldsFromSchema`: text fields
|
|
6
|
+
* filter as strings, `select` as an enum of its options, numerics as numbers,
|
|
7
|
+
* dates as dates. `json`/`multiselect`/`media` have no scalar editor, and
|
|
8
|
+
* `relation` filtering (by raw FK uuid) has no UI yet — all skipped.
|
|
9
|
+
*
|
|
10
|
+
* `richtext` is skipped too, and deliberately: a body is a **document**, so
|
|
11
|
+
* `equals`/`starts with` over it would be comparing one serialization of a
|
|
12
|
+
* node tree against another rather than comparing prose. Free-text `?search=`
|
|
13
|
+
* still reaches it — see `isTextLike` — which is the question a reader
|
|
14
|
+
* actually asks of a body.
|
|
15
|
+
*/
|
|
16
|
+
export declare function scalarTypeFor(spec: AnyFieldSpec): ScalarFieldSchema | null;
|
|
17
|
+
/**
|
|
18
|
+
* Whether a field is backed by a comparable scalar column — the single source of
|
|
19
|
+
* truth for "can this field be filtered or sorted". `richtext`/`json`/
|
|
20
|
+
* `multiselect` (jsonb) and `relation` (FK uuid / join table) are not: they have
|
|
21
|
+
* no scalar editor and ordering them is meaningless. The sort whitelist and the filter schema both
|
|
22
|
+
* derive from this, so the two can't drift apart.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isScalarField(spec: AnyFieldSpec): boolean;
|
|
25
|
+
//# sourceMappingURL=entry-scalar-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-scalar-fields.d.ts","sourceRoot":"","sources":["../../../../../src/lib/entries/infrastructure/queries/entry-scalar-fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,iBAAiB,EACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE9E;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,iBAAiB,GAAG,IAAI,CAqB1E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAEzD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scalarTypeFor = scalarTypeFor;
|
|
4
|
+
exports.isScalarField = isScalarField;
|
|
5
|
+
const utils_server_1 = require("@orthacms/utils-server");
|
|
6
|
+
const fields_1 = require("../../../types/fields");
|
|
7
|
+
/**
|
|
8
|
+
* The filter scalar type for one content field, or `null` to leave it
|
|
9
|
+
* unfilterable. Mirrors the admin's `filterFieldsFromSchema`: text fields
|
|
10
|
+
* filter as strings, `select` as an enum of its options, numerics as numbers,
|
|
11
|
+
* dates as dates. `json`/`multiselect`/`media` have no scalar editor, and
|
|
12
|
+
* `relation` filtering (by raw FK uuid) has no UI yet — all skipped.
|
|
13
|
+
*
|
|
14
|
+
* `richtext` is skipped too, and deliberately: a body is a **document**, so
|
|
15
|
+
* `equals`/`starts with` over it would be comparing one serialization of a
|
|
16
|
+
* node tree against another rather than comparing prose. Free-text `?search=`
|
|
17
|
+
* still reaches it — see `isTextLike` — which is the question a reader
|
|
18
|
+
* actually asks of a body.
|
|
19
|
+
*/
|
|
20
|
+
function scalarTypeFor(spec) {
|
|
21
|
+
switch (spec.type) {
|
|
22
|
+
case fields_1.CONTENT_FIELD_TYPE.Text:
|
|
23
|
+
return { type: utils_server_1.ScalarFieldType.String };
|
|
24
|
+
case fields_1.CONTENT_FIELD_TYPE.Select:
|
|
25
|
+
return {
|
|
26
|
+
type: utils_server_1.ScalarFieldType.Enum,
|
|
27
|
+
enumValues: spec.options ?? []
|
|
28
|
+
};
|
|
29
|
+
case fields_1.CONTENT_FIELD_TYPE.Number:
|
|
30
|
+
case fields_1.CONTENT_FIELD_TYPE.Money:
|
|
31
|
+
return { type: utils_server_1.ScalarFieldType.Number };
|
|
32
|
+
case fields_1.CONTENT_FIELD_TYPE.Boolean:
|
|
33
|
+
return { type: utils_server_1.ScalarFieldType.Boolean };
|
|
34
|
+
case fields_1.CONTENT_FIELD_TYPE.Date:
|
|
35
|
+
case fields_1.CONTENT_FIELD_TYPE.Datetime:
|
|
36
|
+
return { type: utils_server_1.ScalarFieldType.Date };
|
|
37
|
+
default:
|
|
38
|
+
// richtext / json / multiselect / media / relation
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Whether a field is backed by a comparable scalar column — the single source of
|
|
44
|
+
* truth for "can this field be filtered or sorted". `richtext`/`json`/
|
|
45
|
+
* `multiselect` (jsonb) and `relation` (FK uuid / join table) are not: they have
|
|
46
|
+
* no scalar editor and ordering them is meaningless. The sort whitelist and the filter schema both
|
|
47
|
+
* derive from this, so the two can't drift apart.
|
|
48
|
+
*/
|
|
49
|
+
function isScalarField(spec) {
|
|
50
|
+
return scalarTypeFor(spec) !== null;
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The free-text `?search=` predicate, shared by the admin entries list and the
|
|
3
|
+
* public content API so the two can't drift on which columns are searched or —
|
|
4
|
+
* more importantly — on how the needle is escaped.
|
|
5
|
+
*/
|
|
6
|
+
import { type SQL } from 'drizzle-orm';
|
|
7
|
+
import type { AnyContentType } from '../../../types/content-type';
|
|
8
|
+
import { type AnyFieldSpec } from '../../../types/fields';
|
|
9
|
+
/** Columns the free-text search scans (they hold searchable textual content). */
|
|
10
|
+
export declare function isTextLike(spec: AnyFieldSpec): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Case-insensitive `ILIKE` across the type's text-like columns, OR-ed together;
|
|
13
|
+
* `undefined` when there is no search term (so it collapses out of an `and()`).
|
|
14
|
+
*
|
|
15
|
+
* The needle's LIKE metacharacters are escaped, so a literal `%` or `_`
|
|
16
|
+
* searches literally instead of turning the query into a wildcard scan.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildSearchPredicate(type: AnyContentType, search: string | undefined): SQL | undefined;
|
|
19
|
+
//# sourceMappingURL=entry-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-search.d.ts","sourceRoot":"","sources":["../../../../../src/lib/entries/infrastructure/queries/entry-search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAkC,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAK9E,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAMtD;AAmBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,GAAG,SAAS,GAC3B,GAAG,GAAG,SAAS,CAWjB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The free-text `?search=` predicate, shared by the admin entries list and the
|
|
4
|
+
* public content API so the two can't drift on which columns are searched or —
|
|
5
|
+
* more importantly — on how the needle is escaped.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.isTextLike = isTextLike;
|
|
9
|
+
exports.buildSearchPredicate = buildSearchPredicate;
|
|
10
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
11
|
+
const fields_1 = require("../../../types/fields");
|
|
12
|
+
/** Columns the free-text search scans (they hold searchable textual content). */
|
|
13
|
+
function isTextLike(spec) {
|
|
14
|
+
return (spec.type === fields_1.CONTENT_FIELD_TYPE.Text ||
|
|
15
|
+
spec.type === fields_1.CONTENT_FIELD_TYPE.RichText ||
|
|
16
|
+
spec.type === fields_1.CONTENT_FIELD_TYPE.Select);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The expression a text-like column is matched against.
|
|
20
|
+
*
|
|
21
|
+
* A `richtext` body is a **document** in a `jsonb` column, and `ILIKE` has no
|
|
22
|
+
* meaning against `jsonb` — so it is cast to text and the search runs over the
|
|
23
|
+
* serialized tree. That reaches the words, which is what a reader is looking
|
|
24
|
+
* for; the cost is that a needle spelling one of the tree's own key names
|
|
25
|
+
* (`paragraph`, `heading`) can match a body that never says it. Searching the
|
|
26
|
+
* *text* properly wants a stored, indexed projection of it — worth doing when
|
|
27
|
+
* search is next revisited, and much more than a cast.
|
|
28
|
+
*/
|
|
29
|
+
function searchable(spec, column) {
|
|
30
|
+
return spec.type === fields_1.CONTENT_FIELD_TYPE.RichText
|
|
31
|
+
? (0, drizzle_orm_1.sql) `${column}::text`
|
|
32
|
+
: column;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Case-insensitive `ILIKE` across the type's text-like columns, OR-ed together;
|
|
36
|
+
* `undefined` when there is no search term (so it collapses out of an `and()`).
|
|
37
|
+
*
|
|
38
|
+
* The needle's LIKE metacharacters are escaped, so a literal `%` or `_`
|
|
39
|
+
* searches literally instead of turning the query into a wildcard scan.
|
|
40
|
+
*/
|
|
41
|
+
function buildSearchPredicate(type, search) {
|
|
42
|
+
const needle = search?.trim();
|
|
43
|
+
if (!needle) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const table = type.table;
|
|
47
|
+
const pattern = `%${needle.replace(/[\\%_]/g, '\\$&')}%`;
|
|
48
|
+
const clauses = Object.entries(type.fields)
|
|
49
|
+
.filter(([, spec]) => isTextLike(spec))
|
|
50
|
+
.map(([name, spec]) => (0, drizzle_orm_1.ilike)(searchable(spec, table[name]), pattern));
|
|
51
|
+
return clauses.length ? (0, drizzle_orm_1.or)(...clauses) : undefined;
|
|
52
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AnyContentType } from '../../../types/content-type';
|
|
2
|
+
import { type MediaAssetResolver } from '../../../extension/media-asset-resolver';
|
|
3
|
+
import type { MediaRef } from '../../types/entry-list-view';
|
|
4
|
+
/**
|
|
5
|
+
* Resolves the media fields of a `values` bag to display refs — the assets the
|
|
6
|
+
* admin renders (name / thumbnail url / kind) instead of raw uuids. One batched
|
|
7
|
+
* resolver lookup across every media id; an asset that can't be resolved
|
|
8
|
+
* (deleted / cross-workspace) is kept **in order** as an id-only `missing` ref,
|
|
9
|
+
* so a `multiple` field's list never runs shorter than what was stored.
|
|
10
|
+
*
|
|
11
|
+
* Shared by the entry-editor read (`GET …/:id/media`, against the live row's
|
|
12
|
+
* values) and the revision preview (against a snapshot's values), so the two
|
|
13
|
+
* can't drift. A no-op returning `{}` when no media resolver is bound.
|
|
14
|
+
*/
|
|
15
|
+
export declare class MediaRefsQuery {
|
|
16
|
+
private readonly resolver?;
|
|
17
|
+
constructor(resolver?: MediaAssetResolver | undefined);
|
|
18
|
+
/** Resolve every media field's ids in `values` to ordered {@link MediaRef}s. */
|
|
19
|
+
forValues(type: AnyContentType, values: Record<string, unknown>, workspaceId: string): Promise<Record<string, MediaRef[]>>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=media-refs.query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-refs.query.d.ts","sourceRoot":"","sources":["../../../../../src/lib/entries/infrastructure/queries/media-refs.query.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAEH,KAAK,kBAAkB,EAC1B,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,qBACa,cAAc;IAInB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAT,QAAQ,CAAC,EAAE,kBAAkB,YAAA;IAGlD,gFAAgF;IAC1E,SAAS,CACX,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;CAkEzC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MediaRefsQuery = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const content_domain_1 = require("@orthacms/content-domain");
|
|
7
|
+
const fields_1 = require("../../../types/fields");
|
|
8
|
+
const media_asset_resolver_1 = require("../../../extension/media-asset-resolver");
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the media fields of a `values` bag to display refs — the assets the
|
|
11
|
+
* admin renders (name / thumbnail url / kind) instead of raw uuids. One batched
|
|
12
|
+
* resolver lookup across every media id; an asset that can't be resolved
|
|
13
|
+
* (deleted / cross-workspace) is kept **in order** as an id-only `missing` ref,
|
|
14
|
+
* so a `multiple` field's list never runs shorter than what was stored.
|
|
15
|
+
*
|
|
16
|
+
* Shared by the entry-editor read (`GET …/:id/media`, against the live row's
|
|
17
|
+
* values) and the revision preview (against a snapshot's values), so the two
|
|
18
|
+
* can't drift. A no-op returning `{}` when no media resolver is bound.
|
|
19
|
+
*/
|
|
20
|
+
let MediaRefsQuery = class MediaRefsQuery {
|
|
21
|
+
resolver;
|
|
22
|
+
constructor(resolver) {
|
|
23
|
+
this.resolver = resolver;
|
|
24
|
+
}
|
|
25
|
+
/** Resolve every media field's ids in `values` to ordered {@link MediaRef}s. */
|
|
26
|
+
async forValues(type, values, workspaceId) {
|
|
27
|
+
const out = {};
|
|
28
|
+
if (!this.resolver)
|
|
29
|
+
return out;
|
|
30
|
+
// The **refs**, not just the ids: a media value has carried a
|
|
31
|
+
// per-usage `alt` and a `decorative` flag since `ORT-83`, and the whole
|
|
32
|
+
// point of putting them on the value is that they override the asset
|
|
33
|
+
// row's own description for *this* usage.
|
|
34
|
+
const byField = {};
|
|
35
|
+
const all = new Set();
|
|
36
|
+
for (const [name, spec] of Object.entries(type.fields)) {
|
|
37
|
+
if (spec.type !== fields_1.CONTENT_FIELD_TYPE.Media)
|
|
38
|
+
continue;
|
|
39
|
+
const value = values[name];
|
|
40
|
+
const refs = (Array.isArray(value) ? value : [value])
|
|
41
|
+
.map(content_domain_1.toMediaValueRef)
|
|
42
|
+
.filter((ref) => ref !== null && !!ref.id);
|
|
43
|
+
if (!refs.length)
|
|
44
|
+
continue;
|
|
45
|
+
byField[name] = refs;
|
|
46
|
+
for (const ref of refs)
|
|
47
|
+
all.add(ref.id);
|
|
48
|
+
}
|
|
49
|
+
if (!all.size)
|
|
50
|
+
return out;
|
|
51
|
+
const resolved = await this.resolver.resolve([...all], workspaceId);
|
|
52
|
+
for (const [name, refs] of Object.entries(byField)) {
|
|
53
|
+
out[name] = refs.map((ref) => {
|
|
54
|
+
const id = ref.id;
|
|
55
|
+
const asset = resolved.get(id);
|
|
56
|
+
return asset
|
|
57
|
+
? {
|
|
58
|
+
id: asset.id,
|
|
59
|
+
name: asset.name,
|
|
60
|
+
url: asset.url,
|
|
61
|
+
// Only when the resolver has them — an asset with no
|
|
62
|
+
// derivative keeps the ref clean rather than carrying
|
|
63
|
+
// an undefined the admin has to test twice.
|
|
64
|
+
...(asset.thumbUrl
|
|
65
|
+
? { thumbUrl: asset.thumbUrl }
|
|
66
|
+
: {}),
|
|
67
|
+
...(asset.previewUrl
|
|
68
|
+
? { previewUrl: asset.previewUrl }
|
|
69
|
+
: {}),
|
|
70
|
+
kind: asset.kind,
|
|
71
|
+
mimeType: asset.mimeType,
|
|
72
|
+
// Per-usage wins over the asset's default, and
|
|
73
|
+
// `decorative` beats both: an image the author marked
|
|
74
|
+
// presentational *here* publishes with an empty `alt`
|
|
75
|
+
// however it is described in the library.
|
|
76
|
+
alt: usageAlt(ref, asset.alt),
|
|
77
|
+
...(ref.decorative === true
|
|
78
|
+
? { decorative: true }
|
|
79
|
+
: {})
|
|
80
|
+
}
|
|
81
|
+
: {
|
|
82
|
+
id,
|
|
83
|
+
name: id,
|
|
84
|
+
url: '',
|
|
85
|
+
kind: '',
|
|
86
|
+
mimeType: '',
|
|
87
|
+
missing: true
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
exports.MediaRefsQuery = MediaRefsQuery;
|
|
95
|
+
exports.MediaRefsQuery = MediaRefsQuery = tslib_1.__decorate([
|
|
96
|
+
(0, common_1.Injectable)(),
|
|
97
|
+
tslib_1.__param(0, (0, common_1.Optional)()),
|
|
98
|
+
tslib_1.__param(0, (0, media_asset_resolver_1.InjectMediaAssetResolver)()),
|
|
99
|
+
tslib_1.__metadata("design:paramtypes", [Object])
|
|
100
|
+
], MediaRefsQuery);
|
|
101
|
+
/**
|
|
102
|
+
* The alt text this usage should publish with.
|
|
103
|
+
*
|
|
104
|
+
* `decorative` wins outright and resolves to an empty string — the value an
|
|
105
|
+
* `<img alt="">` needs to be skipped by a screen reader, which is a different
|
|
106
|
+
* claim from having no `alt` attribute at all. Otherwise a per-usage `alt`
|
|
107
|
+
* overrides the asset row's default, and a usage that said nothing falls back to
|
|
108
|
+
* it. Alt text is per usage, not per asset: the same logo is "Acme logo" in a
|
|
109
|
+
* header and decorative in a footer strip (`ORT-83`).
|
|
110
|
+
*/
|
|
111
|
+
function usageAlt(ref, assetAlt) {
|
|
112
|
+
if (ref.decorative === true)
|
|
113
|
+
return '';
|
|
114
|
+
if (typeof ref.alt === 'string' && ref.alt.trim() !== '')
|
|
115
|
+
return ref.alt;
|
|
116
|
+
return assetAlt;
|
|
117
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type Database } from '@ortha-cms/database';
|
|
2
|
+
import { type ContentEntryExtension } from '../../extension/entry-extension';
|
|
3
|
+
import type { AnyContentType } from '../../types/content-type';
|
|
4
|
+
import { type ListEntriesQueryDto } from '../dto/list-entries-query.dto';
|
|
5
|
+
import type { EntryListView } from '../types/entry-list-view';
|
|
6
|
+
/**
|
|
7
|
+
* Reads a collection's entries. Generic over the content type: the physical
|
|
8
|
+
* table, the filterable columns, the searchable columns, and the sort whitelist
|
|
9
|
+
* are all derived from `type` at request time, so one service backs every
|
|
10
|
+
* collection. Owns no schema of its own — it queries the HOST-owned generated
|
|
11
|
+
* `content_<name>` tables through the shared Drizzle client.
|
|
12
|
+
*/
|
|
13
|
+
export declare class EntriesService {
|
|
14
|
+
private readonly db;
|
|
15
|
+
private readonly extension?;
|
|
16
|
+
constructor(db: Database, extension?: ContentEntryExtension | undefined);
|
|
17
|
+
/**
|
|
18
|
+
* One page of a collection's entries: search → filter → sort → paginate, run
|
|
19
|
+
* in SQL against the type's generated table, returned as the
|
|
20
|
+
* `{ items, total, page, pageSize }` envelope the admin records table renders.
|
|
21
|
+
* Scoped to `workspaceId` — only the calling workspace's entries are counted
|
|
22
|
+
* or listed.
|
|
23
|
+
*/
|
|
24
|
+
list(type: AnyContentType, query: ListEntriesQueryDto, workspaceId: string): Promise<EntryListView>;
|
|
25
|
+
/**
|
|
26
|
+
* The full WHERE: the workspace scope AND free-text search AND the
|
|
27
|
+
* query-builder `?filter=` tree AND (for paranoid types) the not-deleted
|
|
28
|
+
* guard. `and(undefined, …)` collapses empties, so an unfiltered list still
|
|
29
|
+
* scans the workspace's whole table. The workspace predicate is always
|
|
30
|
+
* present, so an entry never leaks across workspaces. A malformed filter
|
|
31
|
+
* throws a `FilterException` (HTTP 400).
|
|
32
|
+
*/
|
|
33
|
+
private listWhere;
|
|
34
|
+
/**
|
|
35
|
+
* The soft-delete guard for paranoid types: the default list excludes
|
|
36
|
+
* tombstoned rows (`deleted_at IS NULL`); `?deleted=only` flips to the trash
|
|
37
|
+
* view (`deleted_at IS NOT NULL`). A non-paranoid type has no `deleted_at`,
|
|
38
|
+
* so the predicate collapses to `undefined`.
|
|
39
|
+
*/
|
|
40
|
+
private deletedPredicate;
|
|
41
|
+
/**
|
|
42
|
+
* Case-insensitive `ILIKE` across the type's text-like columns, OR-ed
|
|
43
|
+
* together; `undefined` when there's no search term. The needle's LIKE
|
|
44
|
+
* metacharacters are escaped so a literal `%`/`_` searches literally.
|
|
45
|
+
*/
|
|
46
|
+
private searchPredicate;
|
|
47
|
+
/**
|
|
48
|
+
* Translate the `?sort=` spec (`col` asc, `-col` desc) into an ORDER BY,
|
|
49
|
+
* always with an `id` tiebreaker so pagination is stable across requests.
|
|
50
|
+
* Sortable = the always-present envelope columns + `status` (publishable
|
|
51
|
+
* only) + the type's **scalar** fields. Non-scalar fields (`json`/
|
|
52
|
+
* `multiselect`, single/many `relation`) are excluded — a many-relation has
|
|
53
|
+
* no column on the main table at all, so ordering by it would pass
|
|
54
|
+
* `undefined` to `asc`/`desc`; the others have no meaningful order. An
|
|
55
|
+
* unknown or excluded column falls back to `updatedAt` desc.
|
|
56
|
+
*/
|
|
57
|
+
private orderBy;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=entries.service.d.ts.map
|