@things-factory/ops-master 10.1.248 → 10.1.250
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-client/bootstrap.d.ts +19 -0
- package/dist-client/bootstrap.js +66 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/index.d.ts +17 -0
- package/dist-client/index.js +21 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/master-change-approval.d.ts +14 -0
- package/dist-client/master-change-approval.js +36 -0
- package/dist-client/master-change-approval.js.map +1 -0
- package/dist-client/master-change-policy-axes.d.ts +37 -0
- package/dist-client/master-change-policy-axes.js +29 -0
- package/dist-client/master-change-policy-axes.js.map +1 -0
- package/dist-client/master-change-policy-panel.d.ts +59 -0
- package/dist-client/master-change-policy-panel.js +454 -0
- package/dist-client/master-change-policy-panel.js.map +1 -0
- package/dist-client/master-change-providers.d.ts +4 -0
- package/dist-client/master-change-providers.js +91 -0
- package/dist-client/master-change-providers.js.map +1 -0
- package/dist-client/pages/master/applied-when-dialog.d.ts +48 -0
- package/dist-client/pages/master/applied-when-dialog.js +137 -0
- package/dist-client/pages/master/applied-when-dialog.js.map +1 -0
- package/dist-client/pages/master/assignment-fields.d.ts +27 -0
- package/dist-client/pages/master/assignment-fields.js +62 -0
- package/dist-client/pages/master/assignment-fields.js.map +1 -0
- package/dist-client/pages/master/equipment-class.d.ts +12 -0
- package/dist-client/pages/master/equipment-class.js +42 -0
- package/dist-client/pages/master/equipment-class.js.map +1 -0
- package/dist-client/pages/master/equipment.d.ts +12 -0
- package/dist-client/pages/master/equipment.js +58 -0
- package/dist-client/pages/master/equipment.js.map +1 -0
- package/dist-client/pages/master/grist-iso-duration.d.ts +20 -0
- package/dist-client/pages/master/grist-iso-duration.js +70 -0
- package/dist-client/pages/master/grist-iso-duration.js.map +1 -0
- package/dist-client/pages/master/grist-reference.d.ts +91 -0
- package/dist-client/pages/master/grist-reference.js +419 -0
- package/dist-client/pages/master/grist-reference.js.map +1 -0
- package/dist-client/pages/master/import-rows.d.ts +35 -0
- package/dist-client/pages/master/import-rows.js +66 -0
- package/dist-client/pages/master/import-rows.js.map +1 -0
- package/dist-client/pages/master/iso-duration.d.ts +34 -0
- package/dist-client/pages/master/iso-duration.js +76 -0
- package/dist-client/pages/master/iso-duration.js.map +1 -0
- package/dist-client/pages/master/master-options.d.ts +40 -0
- package/dist-client/pages/master/master-options.js +54 -0
- package/dist-client/pages/master/master-options.js.map +1 -0
- package/dist-client/pages/master/master-page-base.d.ts +369 -0
- package/dist-client/pages/master/master-page-base.js +657 -0
- package/dist-client/pages/master/master-page-base.js.map +1 -0
- package/dist-client/pages/master/material-class.d.ts +12 -0
- package/dist-client/pages/master/material-class.js +42 -0
- package/dist-client/pages/master/material-class.js.map +1 -0
- package/dist-client/pages/master/material-definition.d.ts +5 -0
- package/dist-client/pages/master/material-definition.js +14 -0
- package/dist-client/pages/master/material-definition.js.map +1 -0
- package/dist-client/pages/master/material-revision-fields.d.ts +2 -0
- package/dist-client/pages/master/material-revision-fields.js +43 -0
- package/dist-client/pages/master/material-revision-fields.js.map +1 -0
- package/dist-client/pages/master/operation-definition.d.ts +12 -0
- package/dist-client/pages/master/operation-definition.js +49 -0
- package/dist-client/pages/master/operation-definition.js.map +1 -0
- package/dist-client/pages/master/operational-location.d.ts +84 -0
- package/dist-client/pages/master/operational-location.js +432 -0
- package/dist-client/pages/master/operational-location.js.map +1 -0
- package/dist-client/pages/master/person.d.ts +12 -0
- package/dist-client/pages/master/person.js +41 -0
- package/dist-client/pages/master/person.js.map +1 -0
- package/dist-client/pages/master/personnel-class.d.ts +12 -0
- package/dist-client/pages/master/personnel-class.js +43 -0
- package/dist-client/pages/master/personnel-class.js.map +1 -0
- package/dist-client/pages/master/physical-asset-class.d.ts +12 -0
- package/dist-client/pages/master/physical-asset-class.js +40 -0
- package/dist-client/pages/master/physical-asset-class.js.map +1 -0
- package/dist-client/pages/master/physical-asset.d.ts +12 -0
- package/dist-client/pages/master/physical-asset.js +41 -0
- package/dist-client/pages/master/physical-asset.js.map +1 -0
- package/dist-client/pages/master/recipe-definition.d.ts +5 -0
- package/dist-client/pages/master/recipe-definition.js +14 -0
- package/dist-client/pages/master/recipe-definition.js.map +1 -0
- package/dist-client/pages/master/reference-targets.d.ts +42 -0
- package/dist-client/pages/master/reference-targets.js +82 -0
- package/dist-client/pages/master/reference-targets.js.map +1 -0
- package/dist-client/pages/master/revision-comparison.d.ts +49 -0
- package/dist-client/pages/master/revision-comparison.js +560 -0
- package/dist-client/pages/master/revision-comparison.js.map +1 -0
- package/dist-client/pages/master/revision-view.d.ts +34 -0
- package/dist-client/pages/master/revision-view.js +145 -0
- package/dist-client/pages/master/revision-view.js.map +1 -0
- package/dist-client/pages/master/revision-workspace.d.ts +50 -0
- package/dist-client/pages/master/revision-workspace.js +763 -0
- package/dist-client/pages/master/revision-workspace.js.map +1 -0
- package/dist-client/pages/master/route-definition.d.ts +19 -0
- package/dist-client/pages/master/route-definition.js +40 -0
- package/dist-client/pages/master/route-definition.js.map +1 -0
- package/dist-client/pages/master/stop-reason.d.ts +12 -0
- package/dist-client/pages/master/stop-reason.js +48 -0
- package/dist-client/pages/master/stop-reason.js.map +1 -0
- package/dist-client/pages/master/test-specification.d.ts +5 -0
- package/dist-client/pages/master/test-specification.js +14 -0
- package/dist-client/pages/master/test-specification.js.map +1 -0
- package/dist-client/pages/master-axes.d.ts +24 -0
- package/dist-client/pages/master-axes.js +39 -0
- package/dist-client/pages/master-axes.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +81 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +19 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/service/ai-entry/master-entry-rules.d.ts +175 -0
- package/dist-server/service/ai-entry/master-entry-rules.js +302 -0
- package/dist-server/service/ai-entry/master-entry-rules.js.map +1 -0
- package/dist-server/service/ai-entry/master-entry-targets.d.ts +23 -0
- package/dist-server/service/ai-entry/master-entry-targets.js +293 -0
- package/dist-server/service/ai-entry/master-entry-targets.js.map +1 -0
- package/dist-server/service/approval-route.d.ts +37 -0
- package/dist-server/service/approval-route.js +34 -0
- package/dist-server/service/approval-route.js.map +1 -0
- package/dist-server/service/asset/asset-lifecycle.d.ts +106 -0
- package/dist-server/service/asset/asset-lifecycle.js +126 -0
- package/dist-server/service/asset/asset-lifecycle.js.map +1 -0
- package/dist-server/service/asset/asset-master-resolver.d.ts +53 -0
- package/dist-server/service/asset/asset-master-resolver.js +185 -0
- package/dist-server/service/asset/asset-master-resolver.js.map +1 -0
- package/dist-server/service/asset/asset-master.d.ts +21 -0
- package/dist-server/service/asset/asset-master.js +25 -0
- package/dist-server/service/asset/asset-master.js.map +1 -0
- package/dist-server/service/asset/asset-query.d.ts +16 -0
- package/dist-server/service/asset/asset-query.js +72 -0
- package/dist-server/service/asset/asset-query.js.map +1 -0
- package/dist-server/service/asset/index.d.ts +6 -0
- package/dist-server/service/asset/index.js +10 -0
- package/dist-server/service/asset/index.js.map +1 -0
- package/dist-server/service/asset/physical-asset-class.d.ts +34 -0
- package/dist-server/service/asset/physical-asset-class.js +104 -0
- package/dist-server/service/asset/physical-asset-class.js.map +1 -0
- package/dist-server/service/asset/physical-asset.d.ts +66 -0
- package/dist-server/service/asset/physical-asset.js +123 -0
- package/dist-server/service/asset/physical-asset.js.map +1 -0
- package/dist-server/service/assignment/applied-when.d.ts +24 -0
- package/dist-server/service/assignment/applied-when.js +16 -0
- package/dist-server/service/assignment/applied-when.js.map +1 -0
- package/dist-server/service/assignment/assignment-history.d.ts +92 -0
- package/dist-server/service/assignment/assignment-history.js +289 -0
- package/dist-server/service/assignment/assignment-history.js.map +1 -0
- package/dist-server/service/assignment/assignment-write.d.ts +42 -0
- package/dist-server/service/assignment/assignment-write.js +101 -0
- package/dist-server/service/assignment/assignment-write.js.map +1 -0
- package/dist-server/service/assignment/master-value-claim.d.ts +135 -0
- package/dist-server/service/assignment/master-value-claim.js +174 -0
- package/dist-server/service/assignment/master-value-claim.js.map +1 -0
- package/dist-server/service/equipment/equipment-class.d.ts +34 -0
- package/dist-server/service/equipment/equipment-class.js +104 -0
- package/dist-server/service/equipment/equipment-class.js.map +1 -0
- package/dist-server/service/equipment/equipment-master-resolver.d.ts +77 -0
- package/dist-server/service/equipment/equipment-master-resolver.js +266 -0
- package/dist-server/service/equipment/equipment-master-resolver.js.map +1 -0
- package/dist-server/service/equipment/equipment-master.d.ts +30 -0
- package/dist-server/service/equipment/equipment-master.js +53 -0
- package/dist-server/service/equipment/equipment-master.js.map +1 -0
- package/dist-server/service/equipment/equipment-query.d.ts +16 -0
- package/dist-server/service/equipment/equipment-query.js +72 -0
- package/dist-server/service/equipment/equipment-query.js.map +1 -0
- package/dist-server/service/equipment/equipment.d.ts +71 -0
- package/dist-server/service/equipment/equipment.js +138 -0
- package/dist-server/service/equipment/equipment.js.map +1 -0
- package/dist-server/service/equipment/index.d.ts +8 -0
- package/dist-server/service/equipment/index.js +12 -0
- package/dist-server/service/equipment/index.js.map +1 -0
- package/dist-server/service/equipment/state-period-rules.d.ts +95 -0
- package/dist-server/service/equipment/state-period-rules.js +122 -0
- package/dist-server/service/equipment/state-period-rules.js.map +1 -0
- package/dist-server/service/equipment/stop-reason-query.d.ts +11 -0
- package/dist-server/service/equipment/stop-reason-query.js +39 -0
- package/dist-server/service/equipment/stop-reason-query.js.map +1 -0
- package/dist-server/service/equipment/stop-reason.d.ts +58 -0
- package/dist-server/service/equipment/stop-reason.js +114 -0
- package/dist-server/service/equipment/stop-reason.js.map +1 -0
- package/dist-server/service/index.d.ts +82 -0
- package/dist-server/service/index.js +145 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/location/index.d.ts +5 -0
- package/dist-server/service/location/index.js +9 -0
- package/dist-server/service/location/index.js.map +1 -0
- package/dist-server/service/location/location-master-resolver.d.ts +60 -0
- package/dist-server/service/location/location-master-resolver.js +313 -0
- package/dist-server/service/location/location-master-resolver.js.map +1 -0
- package/dist-server/service/location/location-master.d.ts +26 -0
- package/dist-server/service/location/location-master.js +28 -0
- package/dist-server/service/location/location-master.js.map +1 -0
- package/dist-server/service/location/location-query.d.ts +15 -0
- package/dist-server/service/location/location-query.js +56 -0
- package/dist-server/service/location/location-query.js.map +1 -0
- package/dist-server/service/location/operational-location.d.ts +116 -0
- package/dist-server/service/location/operational-location.js +157 -0
- package/dist-server/service/location/operational-location.js.map +1 -0
- package/dist-server/service/master-axis.d.ts +40 -0
- package/dist-server/service/master-axis.js +57 -0
- package/dist-server/service/master-axis.js.map +1 -0
- package/dist-server/service/master-change-approval/approval-input.d.ts +17 -0
- package/dist-server/service/master-change-approval/approval-input.js +35 -0
- package/dist-server/service/master-change-approval/approval-input.js.map +1 -0
- package/dist-server/service/master-change-approval/builtin-axes.d.ts +4 -0
- package/dist-server/service/master-change-approval/builtin-axes.js +96 -0
- package/dist-server/service/master-change-approval/builtin-axes.js.map +1 -0
- package/dist-server/service/master-change-approval/index.d.ts +14 -0
- package/dist-server/service/master-change-approval/index.js +37 -0
- package/dist-server/service/master-change-approval/index.js.map +1 -0
- package/dist-server/service/master-change-approval/master-change-axis.d.ts +54 -0
- package/dist-server/service/master-change-approval/master-change-axis.js +17 -0
- package/dist-server/service/master-change-approval/master-change-axis.js.map +1 -0
- package/dist-server/service/master-change-approval/master-change-flow.d.ts +65 -0
- package/dist-server/service/master-change-approval/master-change-flow.js +125 -0
- package/dist-server/service/master-change-approval/master-change-flow.js.map +1 -0
- package/dist-server/service/master-change-approval/master-change-resolver.d.ts +18 -0
- package/dist-server/service/master-change-approval/master-change-resolver.js +58 -0
- package/dist-server/service/master-change-approval/master-change-resolver.js.map +1 -0
- package/dist-server/service/master-change-policy.d.ts +122 -0
- package/dist-server/service/master-change-policy.js +304 -0
- package/dist-server/service/master-change-policy.js.map +1 -0
- package/dist-server/service/master-conformance-resolver.d.ts +34 -0
- package/dist-server/service/master-conformance-resolver.js +153 -0
- package/dist-server/service/master-conformance-resolver.js.map +1 -0
- package/dist-server/service/master-conformance.d.ts +80 -0
- package/dist-server/service/master-conformance.js +266 -0
- package/dist-server/service/master-conformance.js.map +1 -0
- package/dist-server/service/master-crud.d.ts +55 -0
- package/dist-server/service/master-crud.js +93 -0
- package/dist-server/service/master-crud.js.map +1 -0
- package/dist-server/service/master-list.d.ts +12 -0
- package/dist-server/service/master-list.js +30 -0
- package/dist-server/service/master-list.js.map +1 -0
- package/dist-server/service/master-page-query.d.ts +33 -0
- package/dist-server/service/master-page-query.js +55 -0
- package/dist-server/service/master-page-query.js.map +1 -0
- package/dist-server/service/master-page.d.ts +85 -0
- package/dist-server/service/master-page.js +104 -0
- package/dist-server/service/master-page.js.map +1 -0
- package/dist-server/service/material/index.d.ts +7 -0
- package/dist-server/service/material/index.js +12 -0
- package/dist-server/service/material/index.js.map +1 -0
- package/dist-server/service/material/material-axis-status.d.ts +8 -0
- package/dist-server/service/material/material-axis-status.js +19 -0
- package/dist-server/service/material/material-axis-status.js.map +1 -0
- package/dist-server/service/material/material-class.d.ts +34 -0
- package/dist-server/service/material/material-class.js +104 -0
- package/dist-server/service/material/material-class.js.map +1 -0
- package/dist-server/service/material/material-definition.d.ts +45 -0
- package/dist-server/service/material/material-definition.js +125 -0
- package/dist-server/service/material/material-definition.js.map +1 -0
- package/dist-server/service/material/material-effective-list.d.ts +39 -0
- package/dist-server/service/material/material-effective-list.js +54 -0
- package/dist-server/service/material/material-effective-list.js.map +1 -0
- package/dist-server/service/material/material-master-resolver.d.ts +106 -0
- package/dist-server/service/material/material-master-resolver.js +351 -0
- package/dist-server/service/material/material-master-resolver.js.map +1 -0
- package/dist-server/service/material/material-master.d.ts +9 -0
- package/dist-server/service/material/material-master.js +24 -0
- package/dist-server/service/material/material-master.js.map +1 -0
- package/dist-server/service/material/material-query.d.ts +16 -0
- package/dist-server/service/material/material-query.js +79 -0
- package/dist-server/service/material/material-query.js.map +1 -0
- package/dist-server/service/material/material-revision-content.d.ts +10 -0
- package/dist-server/service/material/material-revision-content.js +92 -0
- package/dist-server/service/material/material-revision-content.js.map +1 -0
- package/dist-server/service/material/material-revision-resolver.d.ts +60 -0
- package/dist-server/service/material/material-revision-resolver.js +96 -0
- package/dist-server/service/material/material-revision-resolver.js.map +1 -0
- package/dist-server/service/material/material-revision-service.d.ts +179 -0
- package/dist-server/service/material/material-revision-service.js +687 -0
- package/dist-server/service/material/material-revision-service.js.map +1 -0
- package/dist-server/service/material/material-revision.d.ts +86 -0
- package/dist-server/service/material/material-revision.js +339 -0
- package/dist-server/service/material/material-revision.js.map +1 -0
- package/dist-server/service/material/recipe-index.d.ts +23 -0
- package/dist-server/service/material/recipe-index.js +44 -0
- package/dist-server/service/material/recipe-index.js.map +1 -0
- package/dist-server/service/operation/index.d.ts +6 -0
- package/dist-server/service/operation/index.js +10 -0
- package/dist-server/service/operation/index.js.map +1 -0
- package/dist-server/service/operation/operation-definition.d.ts +52 -0
- package/dist-server/service/operation/operation-definition.js +143 -0
- package/dist-server/service/operation/operation-definition.js.map +1 -0
- package/dist-server/service/operation/operation-master-resolver.d.ts +52 -0
- package/dist-server/service/operation/operation-master-resolver.js +187 -0
- package/dist-server/service/operation/operation-master-resolver.js.map +1 -0
- package/dist-server/service/operation/operation-master.d.ts +21 -0
- package/dist-server/service/operation/operation-master.js +28 -0
- package/dist-server/service/operation/operation-master.js.map +1 -0
- package/dist-server/service/operation/operation-query.d.ts +15 -0
- package/dist-server/service/operation/operation-query.js +56 -0
- package/dist-server/service/operation/operation-query.js.map +1 -0
- package/dist-server/service/operation/operation-readiness-resolver.d.ts +39 -0
- package/dist-server/service/operation/operation-readiness-resolver.js +111 -0
- package/dist-server/service/operation/operation-readiness-resolver.js.map +1 -0
- package/dist-server/service/operation/operation-readiness.d.ts +34 -0
- package/dist-server/service/operation/operation-readiness.js +133 -0
- package/dist-server/service/operation/operation-readiness.js.map +1 -0
- package/dist-server/service/personnel/index.d.ts +6 -0
- package/dist-server/service/personnel/index.js +10 -0
- package/dist-server/service/personnel/index.js.map +1 -0
- package/dist-server/service/personnel/person.d.ts +51 -0
- package/dist-server/service/personnel/person.js +119 -0
- package/dist-server/service/personnel/person.js.map +1 -0
- package/dist-server/service/personnel/personnel-class-readiness.d.ts +22 -0
- package/dist-server/service/personnel/personnel-class-readiness.js +98 -0
- package/dist-server/service/personnel/personnel-class-readiness.js.map +1 -0
- package/dist-server/service/personnel/personnel-class.d.ts +54 -0
- package/dist-server/service/personnel/personnel-class.js +114 -0
- package/dist-server/service/personnel/personnel-class.js.map +1 -0
- package/dist-server/service/personnel/personnel-master-resolver.d.ts +53 -0
- package/dist-server/service/personnel/personnel-master-resolver.js +187 -0
- package/dist-server/service/personnel/personnel-master-resolver.js.map +1 -0
- package/dist-server/service/personnel/personnel-master.d.ts +39 -0
- package/dist-server/service/personnel/personnel-master.js +34 -0
- package/dist-server/service/personnel/personnel-master.js.map +1 -0
- package/dist-server/service/personnel/personnel-query.d.ts +29 -0
- package/dist-server/service/personnel/personnel-query.js +79 -0
- package/dist-server/service/personnel/personnel-query.js.map +1 -0
- package/dist-server/service/personnel/qualification.d.ts +104 -0
- package/dist-server/service/personnel/qualification.js +147 -0
- package/dist-server/service/personnel/qualification.js.map +1 -0
- package/dist-server/service/quality/index.d.ts +4 -0
- package/dist-server/service/quality/index.js +8 -0
- package/dist-server/service/quality/index.js.map +1 -0
- package/dist-server/service/quality/nonconformance-cause-resolver.d.ts +12 -0
- package/dist-server/service/quality/nonconformance-cause-resolver.js +60 -0
- package/dist-server/service/quality/nonconformance-cause-resolver.js.map +1 -0
- package/dist-server/service/quality/nonconformance-cause.d.ts +20 -0
- package/dist-server/service/quality/nonconformance-cause.js +90 -0
- package/dist-server/service/quality/nonconformance-cause.js.map +1 -0
- package/dist-server/service/recipe/index.d.ts +10 -0
- package/dist-server/service/recipe/index.js +16 -0
- package/dist-server/service/recipe/index.js.map +1 -0
- package/dist-server/service/recipe/recipe-definition.d.ts +75 -0
- package/dist-server/service/recipe/recipe-definition.js +143 -0
- package/dist-server/service/recipe/recipe-definition.js.map +1 -0
- package/dist-server/service/recipe/recipe-effective-list.d.ts +49 -0
- package/dist-server/service/recipe/recipe-effective-list.js +96 -0
- package/dist-server/service/recipe/recipe-effective-list.js.map +1 -0
- package/dist-server/service/recipe/recipe-master-resolver.d.ts +28 -0
- package/dist-server/service/recipe/recipe-master-resolver.js +128 -0
- package/dist-server/service/recipe/recipe-master-resolver.js.map +1 -0
- package/dist-server/service/recipe/recipe-master.d.ts +37 -0
- package/dist-server/service/recipe/recipe-master.js +47 -0
- package/dist-server/service/recipe/recipe-master.js.map +1 -0
- package/dist-server/service/recipe/recipe-query.d.ts +21 -0
- package/dist-server/service/recipe/recipe-query.js +82 -0
- package/dist-server/service/recipe/recipe-query.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-content.d.ts +32 -0
- package/dist-server/service/recipe/recipe-revision-content.js +70 -0
- package/dist-server/service/recipe/recipe-revision-content.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-line.d.ts +30 -0
- package/dist-server/service/recipe/recipe-revision-line.js +95 -0
- package/dist-server/service/recipe/recipe-revision-line.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-resolver.d.ts +65 -0
- package/dist-server/service/recipe/recipe-revision-resolver.js +96 -0
- package/dist-server/service/recipe/recipe-revision-resolver.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-service.d.ts +183 -0
- package/dist-server/service/recipe/recipe-revision-service.js +754 -0
- package/dist-server/service/recipe/recipe-revision-service.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision.d.ts +102 -0
- package/dist-server/service/recipe/recipe-revision.js +373 -0
- package/dist-server/service/recipe/recipe-revision.js.map +1 -0
- package/dist-server/service/recipe/route-definition.d.ts +51 -0
- package/dist-server/service/recipe/route-definition.js +114 -0
- package/dist-server/service/recipe/route-definition.js.map +1 -0
- package/dist-server/service/resource/class-lineage.d.ts +46 -0
- package/dist-server/service/resource/class-lineage.js +80 -0
- package/dist-server/service/resource/class-lineage.js.map +1 -0
- package/dist-server/service/resource/class-members.d.ts +36 -0
- package/dist-server/service/resource/class-members.js +59 -0
- package/dist-server/service/resource/class-members.js.map +1 -0
- package/dist-server/service/resource/referrers.d.ts +54 -0
- package/dist-server/service/resource/referrers.js +99 -0
- package/dist-server/service/resource/referrers.js.map +1 -0
- package/dist-server/service/resource/resource-class.d.ts +25 -0
- package/dist-server/service/resource/resource-class.js +29 -0
- package/dist-server/service/resource/resource-class.js.map +1 -0
- package/dist-server/service/revision-baseline.d.ts +71 -0
- package/dist-server/service/revision-baseline.js +87 -0
- package/dist-server/service/revision-baseline.js.map +1 -0
- package/dist-server/service/row-lock.d.ts +22 -0
- package/dist-server/service/row-lock.js +31 -0
- package/dist-server/service/row-lock.js.map +1 -0
- package/dist-server/service/status/axis-stamp.d.ts +16 -0
- package/dist-server/service/status/axis-stamp.js +22 -0
- package/dist-server/service/status/axis-stamp.js.map +1 -0
- package/dist-server/service/status/index.d.ts +3 -0
- package/dist-server/service/status/index.js +7 -0
- package/dist-server/service/status/index.js.map +1 -0
- package/dist-server/service/status/master-status.d.ts +38 -0
- package/dist-server/service/status/master-status.js +129 -0
- package/dist-server/service/status/master-status.js.map +1 -0
- package/dist-server/service/test-spec/criteria-check.d.ts +53 -0
- package/dist-server/service/test-spec/criteria-check.js +142 -0
- package/dist-server/service/test-spec/criteria-check.js.map +1 -0
- package/dist-server/service/test-spec/criteria-rows.d.ts +89 -0
- package/dist-server/service/test-spec/criteria-rows.js +139 -0
- package/dist-server/service/test-spec/criteria-rows.js.map +1 -0
- package/dist-server/service/test-spec/index.d.ts +6 -0
- package/dist-server/service/test-spec/index.js +11 -0
- package/dist-server/service/test-spec/index.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-effective-list.d.ts +34 -0
- package/dist-server/service/test-spec/test-spec-effective-list.js +42 -0
- package/dist-server/service/test-spec/test-spec-effective-list.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.d.ts +44 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.js +144 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-master.d.ts +6 -0
- package/dist-server/service/test-spec/test-spec-master.js +18 -0
- package/dist-server/service/test-spec/test-spec-master.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-query.d.ts +15 -0
- package/dist-server/service/test-spec/test-spec-query.js +61 -0
- package/dist-server/service/test-spec/test-spec-query.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-revision-resolver.d.ts +59 -0
- package/dist-server/service/test-spec/test-spec-revision-resolver.js +96 -0
- package/dist-server/service/test-spec/test-spec-revision-resolver.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-revision-service.d.ts +178 -0
- package/dist-server/service/test-spec/test-spec-revision-service.js +685 -0
- package/dist-server/service/test-spec/test-spec-revision-service.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-revision.d.ts +86 -0
- package/dist-server/service/test-spec/test-spec-revision.js +334 -0
- package/dist-server/service/test-spec/test-spec-revision.js.map +1 -0
- package/dist-server/service/test-spec/test-specification.d.ts +47 -0
- package/dist-server/service/test-spec/test-specification.js +119 -0
- package/dist-server/service/test-spec/test-specification.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BASELINE_AXES = void 0;
|
|
4
|
+
exports.baselineEdition = baselineEdition;
|
|
5
|
+
exports.baselineFailureText = baselineFailureText;
|
|
6
|
+
exports.standMasterBaselines = standMasterBaselines;
|
|
7
|
+
exports.standMasterBaselinesAtBoot = standMasterBaselinesAtBoot;
|
|
8
|
+
const shell_1 = require("@things-factory/shell");
|
|
9
|
+
const material_revision_service_1 = require("./material/material-revision-service");
|
|
10
|
+
const recipe_revision_service_1 = require("./recipe/recipe-revision-service");
|
|
11
|
+
const test_spec_revision_service_1 = require("./test-spec/test-spec-revision-service");
|
|
12
|
+
/** 차례가 있다 — 품목이 검사 명세를, 제조법이 품목을 이름으로 가리킨다(이름은 기준선과 무관하게 있다). */
|
|
13
|
+
exports.BASELINE_AXES = [
|
|
14
|
+
{ axis: 'testSpecification', stand: test_spec_revision_service_1.standTestSpecificationBaselines },
|
|
15
|
+
{ axis: 'materialDefinition', stand: material_revision_service_1.standMaterialDefinitionBaselines },
|
|
16
|
+
{ axis: 'recipeDefinition', stand: recipe_revision_service_1.standRecipeBaselines }
|
|
17
|
+
];
|
|
18
|
+
/** 이 버전의 이름 — 기준선의 사유에 남는다. */
|
|
19
|
+
function baselineEdition() {
|
|
20
|
+
try {
|
|
21
|
+
return `@things-factory/ops-master ${require('../../package.json').version}`;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return '@things-factory/ops-master';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 기준선이 실패한 까닭을 **사람이 읽을 수 있게** — 코드만이 아니라 본문을 싣는다.
|
|
29
|
+
*
|
|
30
|
+
* 앞서는 `error.code` 가 있으면 그것만 적었다. SQLite 의 실패는 코드가 늘 `SQLITE_ERROR` 라 기동 로그에
|
|
31
|
+
* 「MIRATEK · SYSTEM: SQLITE_ERROR」만 남았고, 무엇이 실패했는지(「transaction within a transaction」)는 어디에도
|
|
32
|
+
* 없었다(2026-09-24). 교대 기준선도 이 함수로 적는다.
|
|
33
|
+
*/
|
|
34
|
+
function baselineFailureText(error) {
|
|
35
|
+
const message = error?.message ? String(error.message) : '';
|
|
36
|
+
const code = error?.code ? String(error.code) : '';
|
|
37
|
+
if (message && code && !message.includes(code))
|
|
38
|
+
return `${code}: ${message}`;
|
|
39
|
+
return message || code || String(error);
|
|
40
|
+
}
|
|
41
|
+
async function standMasterBaselines(dataSource, options = {}) {
|
|
42
|
+
const edition = options.edition ?? baselineEdition();
|
|
43
|
+
const domains = options.domains ?? (await dataSource.getRepository(shell_1.Domain).find());
|
|
44
|
+
const axes = options.axes ?? exports.BASELINE_AXES;
|
|
45
|
+
const reports = [];
|
|
46
|
+
for (const domain of domains) {
|
|
47
|
+
const at = new Date();
|
|
48
|
+
for (const { axis, stand } of axes) {
|
|
49
|
+
try {
|
|
50
|
+
const outcome = await dataSource.transaction(manager => stand(manager, domain.id, at, edition));
|
|
51
|
+
reports.push({ domain: domain.name, axis, ...outcome });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
reports.push({ domain: domain.name, axis, stood: 0, unreadable: [], failed: baselineFailureText(error) });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return reports;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 기동 때 부른다. **서버를 반쯤 뜬 채로 두지 않는다** — 여기서 무엇이 실패해도 던지지 않고 말한다.
|
|
62
|
+
* 한 도메인의 실패는 그 도메인만의 것이다.
|
|
63
|
+
*/
|
|
64
|
+
async function standMasterBaselinesAtBoot(dataSource) {
|
|
65
|
+
let reports;
|
|
66
|
+
try {
|
|
67
|
+
reports = await standMasterBaselines(dataSource);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error(`[ops-master] 기준선을 세우지 못했습니다 — 도메인을 읽지 못함: ${error?.message ?? error}`);
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
for (const report of reports) {
|
|
74
|
+
const where = `${report.domain} · ${report.axis}`;
|
|
75
|
+
if (report.failed) {
|
|
76
|
+
console.error(`[ops-master] ⚠ 기준선을 세우지 못했습니다 — ${where}: ${report.failed}. 이 사업장의 이 기준정보는 새 업무가 고를 것이 없습니다.`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (report.stood)
|
|
80
|
+
console.info(`[ops-master] 기준선 ${where}: ${report.stood} 건을 첫 개정본으로 세웠습니다`);
|
|
81
|
+
for (const one of report.unreadable) {
|
|
82
|
+
console.warn(`[ops-master] ⚠ 기준선을 못 세운 행 — ${where} · ${one.name}: ${one.problem}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return reports;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=revision-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-baseline.js","sourceRoot":"","sources":["../../server/service/revision-baseline.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataSource, EntityManager } from 'typeorm'\nimport { Domain } from '@things-factory/shell'\n\nimport { standMaterialDefinitionBaselines } from './material/material-revision-service'\nimport { standRecipeBaselines } from './recipe/recipe-revision-service'\nimport { standTestSpecificationBaselines } from './test-spec/test-spec-revision-service'\n\n/**\n * **버전을 올린 설치본의 기준정보에 첫 개정본을 세운다** — 기준선(2026-09-24, 수석 아키텍트 판정).\n *\n * ── 왜 필요한가 ────────────────────────────────────────────────────────────\n * 개정 체계(10.1.35)는 새로 만드는 기준정보만 개정본으로 받았고, **그 전부터 있던 행을 들이는 길이\n * 없었다.** 그래서 버전을 올린 설치본은 레시피 · 품목 · 검사 명세의 개정본이 0 이고, 새 지시가 레시피를\n * 못 고르고 품목 근거를 못 찍어 **새 생산이 한 건도 안 섰다.**\n *\n * ── 왜 결재 없이, 왜 기동 때인가 ───────────────────────────────────────────\n * 첫 개정본이 단정하는 것은 「지금 이 값으로 돌고 있다」뿐이고, 시스템이 이미 그렇게 돌고 있다. 누를\n * 사람이 판단할 것이 없다. 그리고 **유효 시작이 이를수록 「모른다」 구간이 좁다** — 처음 쓰일 때 세우면\n * 버전 올린 뒤부터 첫 사용까지가 모르는 구간이 된다. 규제 축도 같다 — 통제하는 것은 **바꾸는 일**이고\n * 기준선은 아무것도 안 바꾼다. 대신 자기 성격을 이름으로 댄다(발행 종류 `baseline`, 결재자 없음).\n *\n * ── 지키는 것 ──────────────────────────────────────────────────────────────\n * - 개정본이 0 인 루트만. 찾는 것은 축마다 질의 하나다.\n * - 두 번 돌아도, 서버 둘이 동시에 떠도 하나만 선다 — 개정 번호 유니크와 루트의 세대 조건부 갱신이 막는다.\n * - **도메인 × 축마다 트랜잭션 하나.** 하나가 실패해도 나머지는 선다. 실패한 도메인과 축을 크게 말한다.\n * - 세운 시각은 서버가 정한다 — 도메인마다 한 순간.\n * - 읽는 길에서 쓰지 않는다. 이 자리 하나만 세운다.\n */\n\nexport type BaselineAxis = 'testSpecification' | 'materialDefinition' | 'recipeDefinition'\n\ntype Stand = (manager: EntityManager, domainId: string, at: Date, edition: string) => Promise<{\n stood: number\n unreadable: { name: string; problem: string }[]\n}>\n\n/** 차례가 있다 — 품목이 검사 명세를, 제조법이 품목을 이름으로 가리킨다(이름은 기준선과 무관하게 있다). */\nexport const BASELINE_AXES: readonly { axis: BaselineAxis; stand: Stand }[] = [\n { axis: 'testSpecification', stand: standTestSpecificationBaselines },\n { axis: 'materialDefinition', stand: standMaterialDefinitionBaselines },\n { axis: 'recipeDefinition', stand: standRecipeBaselines }\n]\n\nexport interface BaselineReport {\n domain: string\n axis: BaselineAxis\n stood: number\n unreadable: { name: string; problem: string }[]\n /** 이 축의 트랜잭션이 통째로 실패했다 — 그 도메인의 그 축은 아무것도 안 섰다. */\n failed?: string\n}\n\n/** 이 버전의 이름 — 기준선의 사유에 남는다. */\nexport function baselineEdition(): string {\n try {\n return `@things-factory/ops-master ${require('../../package.json').version}`\n } catch {\n return '@things-factory/ops-master'\n }\n}\n\n/**\n * 기준선이 실패한 까닭을 **사람이 읽을 수 있게** — 코드만이 아니라 본문을 싣는다.\n *\n * 앞서는 `error.code` 가 있으면 그것만 적었다. SQLite 의 실패는 코드가 늘 `SQLITE_ERROR` 라 기동 로그에\n * 「MIRATEK · SYSTEM: SQLITE_ERROR」만 남았고, 무엇이 실패했는지(「transaction within a transaction」)는 어디에도\n * 없었다(2026-09-24). 교대 기준선도 이 함수로 적는다.\n */\nexport function baselineFailureText(error: any): string {\n const message = error?.message ? String(error.message) : ''\n const code = error?.code ? String(error.code) : ''\n\n if (message && code && !message.includes(code)) return `${code}: ${message}`\n\n return message || code || String(error)\n}\n\nexport async function standMasterBaselines(\n dataSource: DataSource,\n options: { edition?: string; domains?: Domain[]; axes?: readonly { axis: BaselineAxis; stand: Stand }[] } = {}\n): Promise<BaselineReport[]> {\n const edition = options.edition ?? baselineEdition()\n const domains = options.domains ?? (await dataSource.getRepository(Domain).find())\n const axes = options.axes ?? BASELINE_AXES\n const reports: BaselineReport[] = []\n\n for (const domain of domains) {\n const at = new Date()\n for (const { axis, stand } of axes) {\n try {\n const outcome = await dataSource.transaction(manager => stand(manager, domain.id, at, edition))\n reports.push({ domain: domain.name, axis, ...outcome })\n } catch (error: any) {\n reports.push({ domain: domain.name, axis, stood: 0, unreadable: [], failed: baselineFailureText(error) })\n }\n }\n }\n return reports\n}\n\n/**\n * 기동 때 부른다. **서버를 반쯤 뜬 채로 두지 않는다** — 여기서 무엇이 실패해도 던지지 않고 말한다.\n * 한 도메인의 실패는 그 도메인만의 것이다.\n */\nexport async function standMasterBaselinesAtBoot(dataSource: DataSource) {\n let reports: BaselineReport[]\n try {\n reports = await standMasterBaselines(dataSource)\n } catch (error: any) {\n console.error(`[ops-master] 기준선을 세우지 못했습니다 — 도메인을 읽지 못함: ${error?.message ?? error}`)\n return []\n }\n for (const report of reports) {\n const where = `${report.domain} · ${report.axis}`\n if (report.failed) {\n console.error(`[ops-master] ⚠ 기준선을 세우지 못했습니다 — ${where}: ${report.failed}. 이 사업장의 이 기준정보는 새 업무가 고를 것이 없습니다.`)\n continue\n }\n if (report.stood) console.info(`[ops-master] 기준선 ${where}: ${report.stood} 건을 첫 개정본으로 세웠습니다`)\n for (const one of report.unreadable) {\n console.warn(`[ops-master] ⚠ 기준선을 못 세운 행 — ${where} · ${one.name}: ${one.problem}`)\n }\n }\n return reports\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type EntityManager, type EntityTarget, type SelectQueryBuilder } from 'typeorm';
|
|
2
|
+
/**
|
|
3
|
+
* **A write lock on the rows of one table only** - what every locking read of a revision service takes.
|
|
4
|
+
*
|
|
5
|
+
* Current reads are required after waiting for the subject lock, including MySQL REPEATABLE READ, so these reads lock.
|
|
6
|
+
* But a plain `FOR UPDATE` locks every row the query reads: a read filtered by its domain joins the domain row, and a
|
|
7
|
+
* read that loads a revision with its lines LEFT JOINs them - and postgres refuses `FOR UPDATE` on the nullable side of
|
|
8
|
+
* an outer join outright (`0A000`). Publishing a recipe failed that way on postgres (found 2026-10-23, the warehouse's
|
|
9
|
+
* kitting tests); test specifications and materials read their revisions the same way. Postgres names the table to lock
|
|
10
|
+
* (`FOR UPDATE OF`); the other drivers that lock are left as they were. The operato warehouse took the same turn for
|
|
11
|
+
* its stock rows (`writeLockOn`, `fb055e0d`).
|
|
12
|
+
*/
|
|
13
|
+
export declare function writeLockOn(manager: EntityManager, entity: EntityTarget<any>): {
|
|
14
|
+
lock?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
lock: {
|
|
17
|
+
tables?: string[];
|
|
18
|
+
mode: "pessimistic_write";
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/** The same lock on a query builder's own alias - `setLock` takes the alias as written into the SQL. */
|
|
22
|
+
export declare function lockRowsOf<T extends object>(manager: EntityManager, query: SelectQueryBuilder<T>): SelectQueryBuilder<T>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeLockOn = writeLockOn;
|
|
4
|
+
exports.lockRowsOf = lockRowsOf;
|
|
5
|
+
const shell_1 = require("@things-factory/shell");
|
|
6
|
+
/**
|
|
7
|
+
* **A write lock on the rows of one table only** - what every locking read of a revision service takes.
|
|
8
|
+
*
|
|
9
|
+
* Current reads are required after waiting for the subject lock, including MySQL REPEATABLE READ, so these reads lock.
|
|
10
|
+
* But a plain `FOR UPDATE` locks every row the query reads: a read filtered by its domain joins the domain row, and a
|
|
11
|
+
* read that loads a revision with its lines LEFT JOINs them - and postgres refuses `FOR UPDATE` on the nullable side of
|
|
12
|
+
* an outer join outright (`0A000`). Publishing a recipe failed that way on postgres (found 2026-10-23, the warehouse's
|
|
13
|
+
* kitting tests); test specifications and materials read their revisions the same way. Postgres names the table to lock
|
|
14
|
+
* (`FOR UPDATE OF`); the other drivers that lock are left as they were. The operato warehouse took the same turn for
|
|
15
|
+
* its stock rows (`writeLockOn`, `fb055e0d`).
|
|
16
|
+
*/
|
|
17
|
+
function writeLockOn(manager, entity) {
|
|
18
|
+
if (!(0, shell_1.writeLockSupported)(manager))
|
|
19
|
+
return {};
|
|
20
|
+
return { lock: { mode: 'pessimistic_write', ...(isPostgres(manager) ? { tables: [manager.connection.getMetadata(entity).tableNameWithoutPrefix] } : {}) } };
|
|
21
|
+
}
|
|
22
|
+
/** The same lock on a query builder's own alias - `setLock` takes the alias as written into the SQL. */
|
|
23
|
+
function lockRowsOf(manager, query) {
|
|
24
|
+
if (!(0, shell_1.writeLockSupported)(manager))
|
|
25
|
+
return query;
|
|
26
|
+
return query.setLock('pessimistic_write', undefined, isPostgres(manager) ? [query.escape(query.alias)] : undefined);
|
|
27
|
+
}
|
|
28
|
+
function isPostgres(manager) {
|
|
29
|
+
return manager.connection?.options?.type === 'postgres';
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=row-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-lock.js","sourceRoot":"","sources":["../../server/service/row-lock.ts"],"names":[],"mappings":";;AAeA,kCAGC;AAGD,gCAGC;AAtBD,iDAA0D;AAE1D;;;;;;;;;;GAUG;AACH,SAAgB,WAAW,CAAC,OAAsB,EAAE,MAAyB;IAC3E,IAAI,CAAC,IAAA,0BAAkB,EAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAA;IAC3C,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,mBAA4B,EAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAA;AACtK,CAAC;AAED,wGAAwG;AACxG,SAAgB,UAAU,CAAmB,OAAsB,EAAE,KAA4B;IAC/F,IAAI,CAAC,IAAA,0BAAkB,EAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9C,OAAO,KAAK,CAAC,OAAO,CAAC,mBAAmB,EAAE,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;AACrH,CAAC;AAED,SAAS,UAAU,CAAC,OAAsB;IACxC,OAAO,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,KAAK,UAAU,CAAA;AACzD,CAAC","sourcesContent":["import { type EntityManager, type EntityTarget, type SelectQueryBuilder } from 'typeorm'\n\nimport { writeLockSupported } from '@things-factory/shell'\n\n/**\n * **A write lock on the rows of one table only** - what every locking read of a revision service takes.\n *\n * Current reads are required after waiting for the subject lock, including MySQL REPEATABLE READ, so these reads lock.\n * But a plain `FOR UPDATE` locks every row the query reads: a read filtered by its domain joins the domain row, and a\n * read that loads a revision with its lines LEFT JOINs them - and postgres refuses `FOR UPDATE` on the nullable side of\n * an outer join outright (`0A000`). Publishing a recipe failed that way on postgres (found 2026-10-23, the warehouse's\n * kitting tests); test specifications and materials read their revisions the same way. Postgres names the table to lock\n * (`FOR UPDATE OF`); the other drivers that lock are left as they were. The operato warehouse took the same turn for\n * its stock rows (`writeLockOn`, `fb055e0d`).\n */\nexport function writeLockOn(manager: EntityManager, entity: EntityTarget<any>) {\n if (!writeLockSupported(manager)) return {}\n return { lock: { mode: 'pessimistic_write' as const, ...(isPostgres(manager) ? { tables: [manager.connection.getMetadata(entity).tableNameWithoutPrefix] } : {}) } }\n}\n\n/** The same lock on a query builder's own alias - `setLock` takes the alias as written into the SQL. */\nexport function lockRowsOf<T extends object>(manager: EntityManager, query: SelectQueryBuilder<T>): SelectQueryBuilder<T> {\n if (!writeLockSupported(manager)) return query\n return query.setLock('pessimistic_write', undefined, isPostgres(manager) ? [query.escape(query.alias)] : undefined)\n}\n\nfunction isPostgres(manager: EntityManager): boolean {\n return manager.connection?.options?.type === 'postgres'\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 축의 상태를 한 값으로 — **크기로 비교하지 말고 같은지만 본다.**
|
|
3
|
+
*
|
|
4
|
+
* 시각을 크기로 비교하면 안 된다. 시계가 되감기면(백업 복원 · 시각 보정) 바뀐 것을 놓치고, 원천이
|
|
5
|
+
* 내림차순으로 주면 커서가 뒤로 처진다.
|
|
6
|
+
*
|
|
7
|
+
* 시각만으로는 같은 초에 두 번 바뀐 것을 놓치고, 개수만으로는 내용이 고쳐진 것을 놓친다. 둘을 함께 두면
|
|
8
|
+
* 어느 쪽이 바뀌어도 표시값은 달라진다.
|
|
9
|
+
*
|
|
10
|
+
* **뜻을 읽는 것이 아니다.** 모양에 기대지 말고 같은지만 볼 것.
|
|
11
|
+
*
|
|
12
|
+
* ── 왜 따로 두나 ────────────────────────────────────────────────────────────
|
|
13
|
+
* 데코레이터가 붙은 모듈은 소스를 그대로 실행하는 테스트에서 실행되지 않는다. 순수한 부분을 갈라 두면
|
|
14
|
+
* 그 부분은 테스트가 볼 수 있다 — 이 저장소에서 계약과 엔진을 나눈 것과 같은 규칙이다.
|
|
15
|
+
*/
|
|
16
|
+
export declare function axisStamp(count: number, changedAt: Date | undefined): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.axisStamp = axisStamp;
|
|
4
|
+
/**
|
|
5
|
+
* 축의 상태를 한 값으로 — **크기로 비교하지 말고 같은지만 본다.**
|
|
6
|
+
*
|
|
7
|
+
* 시각을 크기로 비교하면 안 된다. 시계가 되감기면(백업 복원 · 시각 보정) 바뀐 것을 놓치고, 원천이
|
|
8
|
+
* 내림차순으로 주면 커서가 뒤로 처진다.
|
|
9
|
+
*
|
|
10
|
+
* 시각만으로는 같은 초에 두 번 바뀐 것을 놓치고, 개수만으로는 내용이 고쳐진 것을 놓친다. 둘을 함께 두면
|
|
11
|
+
* 어느 쪽이 바뀌어도 표시값은 달라진다.
|
|
12
|
+
*
|
|
13
|
+
* **뜻을 읽는 것이 아니다.** 모양에 기대지 말고 같은지만 볼 것.
|
|
14
|
+
*
|
|
15
|
+
* ── 왜 따로 두나 ────────────────────────────────────────────────────────────
|
|
16
|
+
* 데코레이터가 붙은 모듈은 소스를 그대로 실행하는 테스트에서 실행되지 않는다. 순수한 부분을 갈라 두면
|
|
17
|
+
* 그 부분은 테스트가 볼 수 있다 — 이 저장소에서 계약과 엔진을 나눈 것과 같은 규칙이다.
|
|
18
|
+
*/
|
|
19
|
+
function axisStamp(count, changedAt) {
|
|
20
|
+
return `${count}:${changedAt ? changedAt.toISOString() : '-'}`;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=axis-stamp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axis-stamp.js","sourceRoot":"","sources":["../../../server/service/status/axis-stamp.ts"],"names":[],"mappings":";;AAeA,8BAEC;AAjBD;;;;;;;;;;;;;;GAcG;AACH,SAAgB,SAAS,CAAC,KAAa,EAAE,SAA2B;IAClE,OAAO,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAA;AAChE,CAAC","sourcesContent":["/**\n * 축의 상태를 한 값으로 — **크기로 비교하지 말고 같은지만 본다.**\n *\n * 시각을 크기로 비교하면 안 된다. 시계가 되감기면(백업 복원 · 시각 보정) 바뀐 것을 놓치고, 원천이\n * 내림차순으로 주면 커서가 뒤로 처진다.\n *\n * 시각만으로는 같은 초에 두 번 바뀐 것을 놓치고, 개수만으로는 내용이 고쳐진 것을 놓친다. 둘을 함께 두면\n * 어느 쪽이 바뀌어도 표시값은 달라진다.\n *\n * **뜻을 읽는 것이 아니다.** 모양에 기대지 말고 같은지만 볼 것.\n *\n * ── 왜 따로 두나 ────────────────────────────────────────────────────────────\n * 데코레이터가 붙은 모듈은 소스를 그대로 실행하는 테스트에서 실행되지 않는다. 순수한 부분을 갈라 두면\n * 그 부분은 테스트가 볼 수 있다 — 이 저장소에서 계약과 엔진을 나눈 것과 같은 규칙이다.\n */\nexport function axisStamp(count: number, changedAt: Date | undefined): string {\n return `${count}:${changedAt ? changedAt.toISOString() : '-'}`\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolvers = exports.entities = void 0;
|
|
4
|
+
const master_status_1 = require("./master-status");
|
|
5
|
+
exports.entities = [];
|
|
6
|
+
exports.resolvers = [master_status_1.OpsMasterStatusQuery];
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/status/index.ts"],"names":[],"mappings":";;;AAAA,mDAAsD;AAEzC,QAAA,QAAQ,GAAG,EAAE,CAAA;AACb,QAAA,SAAS,GAAG,CAAC,oCAAoB,CAAC,CAAA","sourcesContent":["import { OpsMasterStatusQuery } from './master-status'\n\nexport const entities = []\nexport const resolvers = [OpsMasterStatusQuery]\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 축이 언제 바뀌었나 — **당길지 말지를 싸게 판단하는 자리.**
|
|
3
|
+
*
|
|
4
|
+
* ── 왜 필요한가 ─────────────────────────────────────────────────────────────
|
|
5
|
+
* 트윈은 마스터를 주기적으로 당긴다. 그런데 인원 마스터가 수천 건이면 바뀐 것이 없어도 매번 그만큼을
|
|
6
|
+
* 옮기게 된다. 이 질의는 **축마다 마지막으로 바뀐 시각과 건수만** 내므로, 트윈이 자기가 마지막으로 본
|
|
7
|
+
* 값과 비교해 바뀐 축만 당길 수 있다.
|
|
8
|
+
*
|
|
9
|
+
* ── 왜 지우지 않는가 ────────────────────────────────────────────────────────
|
|
10
|
+
* 건수가 줄지 않는 것을 전제로 한다. 마스터에서 무엇을 「없앨」 때 행을 지우지 않고 유효 기간으로
|
|
11
|
+
* 끝내기 때문이다(§`effectiveEnd`). 지우면 그 개체를 가리키는 지난 기록이 가리킬 것을 잃는다.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MasterAxisStatus {
|
|
14
|
+
axis: string;
|
|
15
|
+
count: number;
|
|
16
|
+
/** 마지막으로 바뀐 시각. 축이 비어 있으면 없다 — 「비어 있다」와 「바뀐 적 없다」를 섞지 않는다. */
|
|
17
|
+
changedAt?: Date;
|
|
18
|
+
/**
|
|
19
|
+
* 이 축의 상태를 대표하는 값 하나 — **크기로 비교하지 말고 같은지만 본다.**
|
|
20
|
+
*
|
|
21
|
+
* 시각을 크기로 비교하면 시계가 되감길 때(백업 복원 · 시각 보정) 바뀐 것을 놓친다. 개수를 함께 담아
|
|
22
|
+
* 두므로 같은 초에 두 번 바뀌어도 표시가 달라진다. 읽는 쪽은 자기가 마지막으로 본 표시와 **다르면**
|
|
23
|
+
* 당기면 된다.
|
|
24
|
+
*/
|
|
25
|
+
stamp: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class OpsMasterStatus {
|
|
28
|
+
axes: MasterAxisStatus[];
|
|
29
|
+
}
|
|
30
|
+
export declare class OpsMasterStatusQuery {
|
|
31
|
+
/**
|
|
32
|
+
* 모든 축의 변경 상태 — 트윈이 주기적으로 부르는 자리.
|
|
33
|
+
*
|
|
34
|
+
* 한 번에 낸다. 축마다 따로 물으면 일곱 번 오가고, 그 사이에 마스터가 바뀌면 축들이 서로 다른 시점을
|
|
35
|
+
* 보게 된다.
|
|
36
|
+
*/
|
|
37
|
+
opsMasterStatus(context: ResolverContext): Promise<OpsMasterStatus>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpsMasterStatusQuery = exports.OpsMasterStatus = exports.MasterAxisStatus = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const shell_1 = require("@things-factory/shell");
|
|
7
|
+
const physical_asset_1 = require("../asset/physical-asset");
|
|
8
|
+
const physical_asset_class_1 = require("../asset/physical-asset-class");
|
|
9
|
+
const equipment_1 = require("../equipment/equipment");
|
|
10
|
+
const equipment_class_1 = require("../equipment/equipment-class");
|
|
11
|
+
const operational_location_1 = require("../location/operational-location");
|
|
12
|
+
const material_class_1 = require("../material/material-class");
|
|
13
|
+
const material_definition_1 = require("../material/material-definition");
|
|
14
|
+
const material_axis_status_1 = require("../material/material-axis-status");
|
|
15
|
+
const operation_definition_1 = require("../operation/operation-definition");
|
|
16
|
+
const person_1 = require("../personnel/person");
|
|
17
|
+
const personnel_class_1 = require("../personnel/personnel-class");
|
|
18
|
+
const recipe_definition_1 = require("../recipe/recipe-definition");
|
|
19
|
+
const route_definition_1 = require("../recipe/route-definition");
|
|
20
|
+
const test_specification_1 = require("../test-spec/test-specification");
|
|
21
|
+
const axis_stamp_1 = require("./axis-stamp");
|
|
22
|
+
/**
|
|
23
|
+
* 축이 언제 바뀌었나 — **당길지 말지를 싸게 판단하는 자리.**
|
|
24
|
+
*
|
|
25
|
+
* ── 왜 필요한가 ─────────────────────────────────────────────────────────────
|
|
26
|
+
* 트윈은 마스터를 주기적으로 당긴다. 그런데 인원 마스터가 수천 건이면 바뀐 것이 없어도 매번 그만큼을
|
|
27
|
+
* 옮기게 된다. 이 질의는 **축마다 마지막으로 바뀐 시각과 건수만** 내므로, 트윈이 자기가 마지막으로 본
|
|
28
|
+
* 값과 비교해 바뀐 축만 당길 수 있다.
|
|
29
|
+
*
|
|
30
|
+
* ── 왜 지우지 않는가 ────────────────────────────────────────────────────────
|
|
31
|
+
* 건수가 줄지 않는 것을 전제로 한다. 마스터에서 무엇을 「없앨」 때 행을 지우지 않고 유효 기간으로
|
|
32
|
+
* 끝내기 때문이다(§`effectiveEnd`). 지우면 그 개체를 가리키는 지난 기록이 가리킬 것을 잃는다.
|
|
33
|
+
*/
|
|
34
|
+
let MasterAxisStatus = class MasterAxisStatus {
|
|
35
|
+
};
|
|
36
|
+
exports.MasterAxisStatus = MasterAxisStatus;
|
|
37
|
+
tslib_1.__decorate([
|
|
38
|
+
(0, type_graphql_1.Field)({ description: 'axis name, matching the pull query' }),
|
|
39
|
+
tslib_1.__metadata("design:type", String)
|
|
40
|
+
], MasterAxisStatus.prototype, "axis", void 0);
|
|
41
|
+
tslib_1.__decorate([
|
|
42
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'number of rows in this axis' }),
|
|
43
|
+
tslib_1.__metadata("design:type", Number)
|
|
44
|
+
], MasterAxisStatus.prototype, "count", void 0);
|
|
45
|
+
tslib_1.__decorate([
|
|
46
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'last change time, absent when the axis is empty' }),
|
|
47
|
+
tslib_1.__metadata("design:type", Date
|
|
48
|
+
/**
|
|
49
|
+
* 이 축의 상태를 대표하는 값 하나 — **크기로 비교하지 말고 같은지만 본다.**
|
|
50
|
+
*
|
|
51
|
+
* 시각을 크기로 비교하면 시계가 되감길 때(백업 복원 · 시각 보정) 바뀐 것을 놓친다. 개수를 함께 담아
|
|
52
|
+
* 두므로 같은 초에 두 번 바뀌어도 표시가 달라진다. 읽는 쪽은 자기가 마지막으로 본 표시와 **다르면**
|
|
53
|
+
* 당기면 된다.
|
|
54
|
+
*/
|
|
55
|
+
)
|
|
56
|
+
], MasterAxisStatus.prototype, "changedAt", void 0);
|
|
57
|
+
tslib_1.__decorate([
|
|
58
|
+
(0, type_graphql_1.Field)({ description: 'opaque value — compare for equality, never for order' }),
|
|
59
|
+
tslib_1.__metadata("design:type", String)
|
|
60
|
+
], MasterAxisStatus.prototype, "stamp", void 0);
|
|
61
|
+
exports.MasterAxisStatus = MasterAxisStatus = tslib_1.__decorate([
|
|
62
|
+
(0, type_graphql_1.ObjectType)({ description: 'When one master axis last changed' })
|
|
63
|
+
], MasterAxisStatus);
|
|
64
|
+
let OpsMasterStatus = class OpsMasterStatus {
|
|
65
|
+
};
|
|
66
|
+
exports.OpsMasterStatus = OpsMasterStatus;
|
|
67
|
+
tslib_1.__decorate([
|
|
68
|
+
(0, type_graphql_1.Field)(type => [MasterAxisStatus]),
|
|
69
|
+
tslib_1.__metadata("design:type", Array)
|
|
70
|
+
], OpsMasterStatus.prototype, "axes", void 0);
|
|
71
|
+
exports.OpsMasterStatus = OpsMasterStatus = tslib_1.__decorate([
|
|
72
|
+
(0, type_graphql_1.ObjectType)({ description: 'Change status of every master axis' })
|
|
73
|
+
], OpsMasterStatus);
|
|
74
|
+
/** 축 하나의 건수와 마지막 변경 시각. 두 값을 한 질의로 읽는다. */
|
|
75
|
+
async function axisStatus(axis, repository, domainId) {
|
|
76
|
+
const row = await repository
|
|
77
|
+
.createQueryBuilder('row')
|
|
78
|
+
.select('COUNT(1)', 'count')
|
|
79
|
+
.addSelect('MAX(row.updatedAt)', 'changedAt')
|
|
80
|
+
.where('row.domain = :domainId', { domainId })
|
|
81
|
+
.getRawOne();
|
|
82
|
+
const count = Number(row?.count ?? 0);
|
|
83
|
+
const changedAt = row?.changedAt ? new Date(row.changedAt) : undefined;
|
|
84
|
+
return {
|
|
85
|
+
axis,
|
|
86
|
+
count,
|
|
87
|
+
stamp: (0, axis_stamp_1.axisStamp)(count, changedAt),
|
|
88
|
+
...(changedAt ? { changedAt } : {})
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
let OpsMasterStatusQuery = class OpsMasterStatusQuery {
|
|
92
|
+
/**
|
|
93
|
+
* 모든 축의 변경 상태 — 트윈이 주기적으로 부르는 자리.
|
|
94
|
+
*
|
|
95
|
+
* 한 번에 낸다. 축마다 따로 물으면 일곱 번 오가고, 그 사이에 마스터가 바뀌면 축들이 서로 다른 시점을
|
|
96
|
+
* 보게 된다.
|
|
97
|
+
*/
|
|
98
|
+
async opsMasterStatus(context) {
|
|
99
|
+
const { domain } = context.state;
|
|
100
|
+
const axes = await Promise.all([
|
|
101
|
+
axisStatus('personnelClasses', (0, shell_1.getRepository)(personnel_class_1.PersonnelClass), domain.id),
|
|
102
|
+
axisStatus('persons', (0, shell_1.getRepository)(person_1.Person), domain.id),
|
|
103
|
+
axisStatus('equipmentClasses', (0, shell_1.getRepository)(equipment_class_1.EquipmentClass), domain.id),
|
|
104
|
+
axisStatus('equipment', (0, shell_1.getRepository)(equipment_1.Equipment), domain.id),
|
|
105
|
+
axisStatus('assetClasses', (0, shell_1.getRepository)(physical_asset_class_1.PhysicalAssetClass), domain.id),
|
|
106
|
+
axisStatus('assets', (0, shell_1.getRepository)(physical_asset_1.PhysicalAsset), domain.id),
|
|
107
|
+
axisStatus('locations', (0, shell_1.getRepository)(operational_location_1.OperationalLocation), domain.id),
|
|
108
|
+
axisStatus('materialClasses', (0, shell_1.getRepository)(material_class_1.MaterialClass), domain.id),
|
|
109
|
+
(0, material_axis_status_1.materialAxisStatus)((0, shell_1.getRepository)(material_definition_1.MaterialDefinition).manager, domain.id),
|
|
110
|
+
axisStatus('operations', (0, shell_1.getRepository)(operation_definition_1.OperationDefinition), domain.id),
|
|
111
|
+
axisStatus('recipes', (0, shell_1.getRepository)(recipe_definition_1.RecipeDefinition), domain.id),
|
|
112
|
+
axisStatus('routes', (0, shell_1.getRepository)(route_definition_1.RouteDefinition), domain.id),
|
|
113
|
+
axisStatus('testSpecifications', (0, shell_1.getRepository)(test_specification_1.TestSpecification), domain.id)
|
|
114
|
+
]);
|
|
115
|
+
return { axes };
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
exports.OpsMasterStatusQuery = OpsMasterStatusQuery;
|
|
119
|
+
tslib_1.__decorate([
|
|
120
|
+
(0, type_graphql_1.Query)(returns => OpsMasterStatus, { description: 'Change status of every master axis' }),
|
|
121
|
+
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
122
|
+
tslib_1.__metadata("design:type", Function),
|
|
123
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
124
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
125
|
+
], OpsMasterStatusQuery.prototype, "opsMasterStatus", null);
|
|
126
|
+
exports.OpsMasterStatusQuery = OpsMasterStatusQuery = tslib_1.__decorate([
|
|
127
|
+
(0, type_graphql_1.Resolver)(OpsMasterStatus)
|
|
128
|
+
], OpsMasterStatusQuery);
|
|
129
|
+
//# sourceMappingURL=master-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"master-status.js","sourceRoot":"","sources":["../../../server/service/status/master-status.ts"],"names":[],"mappings":"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","sourcesContent":["import { Ctx, Field, Int, ObjectType, Query, Resolver } from 'type-graphql'\nimport type { ObjectLiteral, Repository } from 'typeorm'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { PhysicalAsset } from '../asset/physical-asset'\nimport { PhysicalAssetClass } from '../asset/physical-asset-class'\nimport { Equipment } from '../equipment/equipment'\nimport { EquipmentClass } from '../equipment/equipment-class'\nimport { OperationalLocation } from '../location/operational-location'\nimport { MaterialClass } from '../material/material-class'\nimport { MaterialDefinition } from '../material/material-definition'\nimport { materialAxisStatus } from '../material/material-axis-status'\nimport { OperationDefinition } from '../operation/operation-definition'\nimport { Person } from '../personnel/person'\nimport { PersonnelClass } from '../personnel/personnel-class'\nimport { RecipeDefinition } from '../recipe/recipe-definition'\nimport { RouteDefinition } from '../recipe/route-definition'\nimport { TestSpecification } from '../test-spec/test-specification'\n\nimport { axisStamp } from './axis-stamp'\n\n/**\n * 축이 언제 바뀌었나 — **당길지 말지를 싸게 판단하는 자리.**\n *\n * ── 왜 필요한가 ─────────────────────────────────────────────────────────────\n * 트윈은 마스터를 주기적으로 당긴다. 그런데 인원 마스터가 수천 건이면 바뀐 것이 없어도 매번 그만큼을\n * 옮기게 된다. 이 질의는 **축마다 마지막으로 바뀐 시각과 건수만** 내므로, 트윈이 자기가 마지막으로 본\n * 값과 비교해 바뀐 축만 당길 수 있다.\n *\n * ── 왜 지우지 않는가 ────────────────────────────────────────────────────────\n * 건수가 줄지 않는 것을 전제로 한다. 마스터에서 무엇을 「없앨」 때 행을 지우지 않고 유효 기간으로\n * 끝내기 때문이다(§`effectiveEnd`). 지우면 그 개체를 가리키는 지난 기록이 가리킬 것을 잃는다.\n */\n@ObjectType({ description: 'When one master axis last changed' })\nexport class MasterAxisStatus {\n @Field({ description: 'axis name, matching the pull query' })\n axis: string\n\n @Field(type => Int, { description: 'number of rows in this axis' })\n count: number\n\n /** 마지막으로 바뀐 시각. 축이 비어 있으면 없다 — 「비어 있다」와 「바뀐 적 없다」를 섞지 않는다. */\n @Field({ nullable: true, description: 'last change time, absent when the axis is empty' })\n changedAt?: Date\n\n /**\n * 이 축의 상태를 대표하는 값 하나 — **크기로 비교하지 말고 같은지만 본다.**\n *\n * 시각을 크기로 비교하면 시계가 되감길 때(백업 복원 · 시각 보정) 바뀐 것을 놓친다. 개수를 함께 담아\n * 두므로 같은 초에 두 번 바뀌어도 표시가 달라진다. 읽는 쪽은 자기가 마지막으로 본 표시와 **다르면**\n * 당기면 된다.\n */\n @Field({ description: 'opaque value — compare for equality, never for order' })\n stamp: string\n}\n\n@ObjectType({ description: 'Change status of every master axis' })\nexport class OpsMasterStatus {\n @Field(type => [MasterAxisStatus])\n axes: MasterAxisStatus[]\n\n}\n\n/** 축 하나의 건수와 마지막 변경 시각. 두 값을 한 질의로 읽는다. */\nasync function axisStatus<T extends ObjectLiteral>(\n axis: string,\n repository: Repository<T>,\n domainId: string\n): Promise<MasterAxisStatus> {\n const row = await repository\n .createQueryBuilder('row')\n .select('COUNT(1)', 'count')\n .addSelect('MAX(row.updatedAt)', 'changedAt')\n .where('row.domain = :domainId', { domainId })\n .getRawOne<{ count: string | number; changedAt: Date | string | null }>()\n\n const count = Number(row?.count ?? 0)\n const changedAt = row?.changedAt ? new Date(row.changedAt) : undefined\n\n return {\n axis,\n count,\n stamp: axisStamp(count, changedAt),\n ...(changedAt ? { changedAt } : {})\n }\n}\n\n\n@Resolver(OpsMasterStatus)\nexport class OpsMasterStatusQuery {\n /**\n * 모든 축의 변경 상태 — 트윈이 주기적으로 부르는 자리.\n *\n * 한 번에 낸다. 축마다 따로 물으면 일곱 번 오가고, 그 사이에 마스터가 바뀌면 축들이 서로 다른 시점을\n * 보게 된다.\n */\n @Query(returns => OpsMasterStatus, { description: 'Change status of every master axis' })\n async opsMasterStatus(@Ctx() context: ResolverContext): Promise<OpsMasterStatus> {\n const { domain } = context.state\n\n const axes = await Promise.all([\n axisStatus('personnelClasses', getRepository(PersonnelClass), domain.id),\n axisStatus('persons', getRepository(Person), domain.id),\n axisStatus('equipmentClasses', getRepository(EquipmentClass), domain.id),\n axisStatus('equipment', getRepository(Equipment), domain.id),\n axisStatus('assetClasses', getRepository(PhysicalAssetClass), domain.id),\n axisStatus('assets', getRepository(PhysicalAsset), domain.id),\n axisStatus('locations', getRepository(OperationalLocation), domain.id),\n axisStatus('materialClasses', getRepository(MaterialClass), domain.id),\n materialAxisStatus(getRepository(MaterialDefinition).manager, domain.id),\n axisStatus('operations', getRepository(OperationDefinition), domain.id),\n axisStatus('recipes', getRepository(RecipeDefinition), domain.id),\n axisStatus('routes', getRepository(RouteDefinition), domain.id),\n axisStatus('testSpecifications', getRepository(TestSpecification), domain.id)\n ])\n\n return { axes }\n }\n}\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 검사 기준이 **판정에 쓸 수 있는 모양인가** — 순수 판단.
|
|
3
|
+
*
|
|
4
|
+
* ── 왜 저장하기 전에 보나 ──────────────────────────────────────────────────
|
|
5
|
+
* 기준을 저장하는 자리와 그 기준으로 판정하는 자리가 다르다. 판정하는 쪽(`measurement-judge`)은
|
|
6
|
+
* **모르는 것을 통과로 읽지 않도록** 만들어져 있어서, 망가진 기준이 들어와도 오류를 내지 않고 조용히
|
|
7
|
+
* 「판정하지 않음」이 된다. 그 조용함이 여기서는 위험하다 — 기준을 적은 사람은 적었다고 믿고,
|
|
8
|
+
* 검사원은 통과했다고 읽는다.
|
|
9
|
+
*
|
|
10
|
+
* 세 가지가 특히 조용하다.
|
|
11
|
+
*
|
|
12
|
+
* 한계가 숫자가 아니다 그리드 칸에서 온 `"39.7"` 은 글자다. `값 < "39.7"` 은 견주기가 되긴 하지만
|
|
13
|
+
* `"약 40"` 같은 것이 들어오면 어느 쪽 비교도 참이 아니어서 **모든 값이
|
|
14
|
+
* 한계 안**으로 읽힌다. 그 기준은 아무것도 막지 않는다.
|
|
15
|
+
* 한계에 단위가 없다 관측이 단위를 말해도 견줄 단위가 없으면 단위 검사를 건너뛴다. 화씨 관측이
|
|
16
|
+
* 섭씨 한계와 견주어지고 아무도 모른다.
|
|
17
|
+
* 기준 이름이 비었다 잰 값은 이름으로 기준을 찾는다. 이름이 없으면 영원히 「안 쟀음」이 된다.
|
|
18
|
+
*
|
|
19
|
+
* ── 막지 않는 것 ───────────────────────────────────────────────────────────
|
|
20
|
+
* **숫자 한계가 없는 기준은 정상이다.** 「표면에 흠이 없을 것」처럼 사람이 보고 판단하는 기준이 있고,
|
|
21
|
+
* 그때는 `expression` 만 있다. 그것까지 막으면 현장의 사실을 담을 수 없다.
|
|
22
|
+
*
|
|
23
|
+
* 다만 `limit` 을 **적다 만 것**과 애초에 안 적은 것은 다르다. 앞은 막고 뒤는 통과시킨다.
|
|
24
|
+
*/
|
|
25
|
+
/** 저장하려는 기준 하나 — 무엇이 들어올지 모르므로 열어 둔다. */
|
|
26
|
+
export type CriterionInput = Record<string, unknown>;
|
|
27
|
+
export interface CriteriaVerdict {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
/** 무엇이 왜 막혔는지. 한 줄에 하나씩, 고칠 자리를 가리킨다. */
|
|
30
|
+
problems: string[];
|
|
31
|
+
}
|
|
32
|
+
export declare function judgeCriteria(criteria: readonly CriterionInput[]): CriteriaVerdict;
|
|
33
|
+
export declare function criteriaRejected(verdict: CriteriaVerdict): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* 그리드가 보낸 값을 기준 목록으로 읽는다.
|
|
36
|
+
*
|
|
37
|
+
* 화면은 JSON 글자로 보내고 저장 칸은 배열이다. **읽지 못한 것을 빈 목록으로 바꾸지 않는다** —
|
|
38
|
+
* 그러면 사람이 적은 기준이 통째로 사라지고 명세는 기준 없는 명세가 된다.
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* 읽음 · 못 읽음을 **글자로** 가른다.
|
|
42
|
+
*
|
|
43
|
+
* `ok: boolean` 으로 두면 이 저장소의 설정(`strict: false`)에서 `if (!read.ok)` 가 갈래를 좁히지 못해
|
|
44
|
+
* 못 읽은 쪽의 칸을 꺼낼 수 없다. 글자 표식은 어느 설정에서나 좁혀진다.
|
|
45
|
+
*/
|
|
46
|
+
export type CriteriaRead = {
|
|
47
|
+
read: 'ok';
|
|
48
|
+
criteria: CriterionInput[];
|
|
49
|
+
} | {
|
|
50
|
+
read: 'failed';
|
|
51
|
+
detail: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function readCriteria(value: unknown): CriteriaRead;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 검사 기준이 **판정에 쓸 수 있는 모양인가** — 순수 판단.
|
|
4
|
+
*
|
|
5
|
+
* ── 왜 저장하기 전에 보나 ──────────────────────────────────────────────────
|
|
6
|
+
* 기준을 저장하는 자리와 그 기준으로 판정하는 자리가 다르다. 판정하는 쪽(`measurement-judge`)은
|
|
7
|
+
* **모르는 것을 통과로 읽지 않도록** 만들어져 있어서, 망가진 기준이 들어와도 오류를 내지 않고 조용히
|
|
8
|
+
* 「판정하지 않음」이 된다. 그 조용함이 여기서는 위험하다 — 기준을 적은 사람은 적었다고 믿고,
|
|
9
|
+
* 검사원은 통과했다고 읽는다.
|
|
10
|
+
*
|
|
11
|
+
* 세 가지가 특히 조용하다.
|
|
12
|
+
*
|
|
13
|
+
* 한계가 숫자가 아니다 그리드 칸에서 온 `"39.7"` 은 글자다. `값 < "39.7"` 은 견주기가 되긴 하지만
|
|
14
|
+
* `"약 40"` 같은 것이 들어오면 어느 쪽 비교도 참이 아니어서 **모든 값이
|
|
15
|
+
* 한계 안**으로 읽힌다. 그 기준은 아무것도 막지 않는다.
|
|
16
|
+
* 한계에 단위가 없다 관측이 단위를 말해도 견줄 단위가 없으면 단위 검사를 건너뛴다. 화씨 관측이
|
|
17
|
+
* 섭씨 한계와 견주어지고 아무도 모른다.
|
|
18
|
+
* 기준 이름이 비었다 잰 값은 이름으로 기준을 찾는다. 이름이 없으면 영원히 「안 쟀음」이 된다.
|
|
19
|
+
*
|
|
20
|
+
* ── 막지 않는 것 ───────────────────────────────────────────────────────────
|
|
21
|
+
* **숫자 한계가 없는 기준은 정상이다.** 「표면에 흠이 없을 것」처럼 사람이 보고 판단하는 기준이 있고,
|
|
22
|
+
* 그때는 `expression` 만 있다. 그것까지 막으면 현장의 사실을 담을 수 없다.
|
|
23
|
+
*
|
|
24
|
+
* 다만 `limit` 을 **적다 만 것**과 애초에 안 적은 것은 다르다. 앞은 막고 뒤는 통과시킨다.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.judgeCriteria = judgeCriteria;
|
|
28
|
+
exports.criteriaRejected = criteriaRejected;
|
|
29
|
+
exports.readCriteria = readCriteria;
|
|
30
|
+
/** 이름을 붙일 자리 — 오류 문구가 몇 번째 기준인지 말해야 고칠 수 있다. */
|
|
31
|
+
function nameOf(criterion, index) {
|
|
32
|
+
const id = typeof criterion.id === 'string' ? criterion.id.trim() : '';
|
|
33
|
+
return id ? `"${id}"` : `${index + 1}번째 기준`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 한계값 하나를 본다.
|
|
37
|
+
*
|
|
38
|
+
* `undefined` 와 `null` 은 「없다」이고 정상이다. 그 밖의 것은 **숫자여야 한다** — 글자를 그대로 두면
|
|
39
|
+
* 판정이 조용히 무너진다.
|
|
40
|
+
*/
|
|
41
|
+
function limitNumberProblem(where, field, value) {
|
|
42
|
+
if (value === undefined || value === null || value === '') {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
if (typeof value === 'number') {
|
|
46
|
+
return Number.isFinite(value)
|
|
47
|
+
? undefined
|
|
48
|
+
: `${where}의 ${field} 이(가) 숫자가 아닙니다. 견줄 수 없는 값입니다`;
|
|
49
|
+
}
|
|
50
|
+
return (`${where}의 ${field} 에 "${String(value)}" 이(가) 들어 있습니다 — 숫자여야 합니다. ` +
|
|
51
|
+
'글자로 두면 견주기가 늘 참이 되어 모든 값이 한계 안으로 읽힙니다');
|
|
52
|
+
}
|
|
53
|
+
function judgeCriteria(criteria) {
|
|
54
|
+
const problems = [];
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
criteria.forEach((criterion, index) => {
|
|
57
|
+
const where = nameOf(criterion, index);
|
|
58
|
+
const id = typeof criterion.id === 'string' ? criterion.id.trim() : '';
|
|
59
|
+
if (!id) {
|
|
60
|
+
problems.push(`${where}에 이름이 없습니다. 잰 값은 이름으로 기준을 찾으므로, ` +
|
|
61
|
+
'이름이 없으면 무엇을 재도 「안 쟀음」으로 남습니다');
|
|
62
|
+
}
|
|
63
|
+
else if (seen.has(id)) {
|
|
64
|
+
problems.push(`기준 이름 "${id}" 이(가) 두 번 나옵니다. 잰 값 하나가 어느 쪽 것인지 정할 수 없습니다`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
seen.add(id);
|
|
68
|
+
}
|
|
69
|
+
const limit = criterion.limit;
|
|
70
|
+
if (limit === undefined || limit === null) {
|
|
71
|
+
/* 숫자 한계 없이 사람이 보고 판단하는 기준이다. 정상이다. */
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (typeof limit !== 'object' || Array.isArray(limit)) {
|
|
75
|
+
problems.push(`${where}의 한계가 { minimum, maximum, uom } 모양이 아닙니다`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const minimumProblem = limitNumberProblem(where, 'minimum', limit.minimum);
|
|
79
|
+
const maximumProblem = limitNumberProblem(where, 'maximum', limit.maximum);
|
|
80
|
+
if (minimumProblem)
|
|
81
|
+
problems.push(minimumProblem);
|
|
82
|
+
if (maximumProblem)
|
|
83
|
+
problems.push(maximumProblem);
|
|
84
|
+
const hasMinimum = typeof limit.minimum === 'number' && Number.isFinite(limit.minimum);
|
|
85
|
+
const hasMaximum = typeof limit.maximum === 'number' && Number.isFinite(limit.maximum);
|
|
86
|
+
if (!hasMinimum && !hasMaximum && !minimumProblem && !maximumProblem) {
|
|
87
|
+
/*
|
|
88
|
+
* `limit` 을 적기 시작했는데 상한도 하한도 없다. 안 적은 것과 다르다 — 적으려다 만 것이고,
|
|
89
|
+
* 그대로 두면 「한계를 정했다」고 믿은 채 아무 값이나 지나간다.
|
|
90
|
+
*/
|
|
91
|
+
problems.push(`${where}에 한계가 열려 있으나 상한도 하한도 없습니다. ` +
|
|
92
|
+
'값을 채우거나, 사람이 보고 판단하는 기준이면 한계를 비우십시오');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (hasMinimum && hasMaximum && limit.minimum > limit.maximum) {
|
|
96
|
+
problems.push(`${where}의 하한 ${limit.minimum} 이(가) 상한 ${limit.maximum} 보다 큽니다. ` +
|
|
97
|
+
'어떤 값도 이 한계 안에 들어올 수 없습니다');
|
|
98
|
+
}
|
|
99
|
+
const uom = limit.uom;
|
|
100
|
+
if (uom === undefined || uom === null || String(uom).trim() === '') {
|
|
101
|
+
/*
|
|
102
|
+
* **단위 없는 한계는 막는다.** 판정하는 쪽은 한계에 단위가 없으면 단위 검사를 건너뛴다 —
|
|
103
|
+
* 화씨로 잰 값이 섭씨 한계와 견주어지고 아무도 모른다. 여기가 그것을 막을 수 있는 유일한 자리다.
|
|
104
|
+
*/
|
|
105
|
+
problems.push(`${where}에 단위가 없습니다. 단위가 없으면 다른 단위로 잰 값이 그대로 견주어져 ` +
|
|
106
|
+
'틀린 판정이 오류 보고 없이 나옵니다');
|
|
107
|
+
}
|
|
108
|
+
else if (typeof uom !== 'string') {
|
|
109
|
+
problems.push(`${where}의 단위가 글자가 아닙니다`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return { ok: problems.length === 0, problems };
|
|
113
|
+
}
|
|
114
|
+
function criteriaRejected(verdict) {
|
|
115
|
+
return !verdict.ok;
|
|
116
|
+
}
|
|
117
|
+
function readCriteria(value) {
|
|
118
|
+
if (value === undefined || value === null || value === '') {
|
|
119
|
+
return { read: 'ok', criteria: [] };
|
|
120
|
+
}
|
|
121
|
+
let parsed = value;
|
|
122
|
+
if (typeof value === 'string') {
|
|
123
|
+
try {
|
|
124
|
+
parsed = JSON.parse(value);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return {
|
|
128
|
+
read: 'failed',
|
|
129
|
+
detail: `기준을 읽지 못했습니다 — JSON 이 아닙니다: ${error.message}`
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (!Array.isArray(parsed)) {
|
|
134
|
+
return { read: 'failed', detail: '기준은 목록이어야 합니다. 기준 하나여도 [ ] 로 감쌉니다' };
|
|
135
|
+
}
|
|
136
|
+
const notObjects = parsed.filter(one => typeof one !== 'object' || one === null || Array.isArray(one));
|
|
137
|
+
if (notObjects.length) {
|
|
138
|
+
return { read: 'failed', detail: '기준 목록 안에 { } 모양이 아닌 것이 있습니다' };
|
|
139
|
+
}
|
|
140
|
+
return { read: 'ok', criteria: parsed };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=criteria-check.js.map
|