@things-factory/worklist 10.1.25 → 10.1.26

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.
Files changed (48) hide show
  1. package/dist-client/components/activity-approval-ribon.js +3 -2
  2. package/dist-client/components/activity-approval-ribon.js.map +1 -1
  3. package/dist-client/components/activity-starter-form.js +4 -7
  4. package/dist-client/components/activity-starter-form.js.map +1 -1
  5. package/dist-client/components/decision-slots.d.ts +1 -1
  6. package/dist-client/components/decision-slots.js +1 -2
  7. package/dist-client/components/decision-slots.js.map +1 -1
  8. package/dist-client/components/state-ribon.js +2 -1
  9. package/dist-client/components/state-ribon.js.map +1 -1
  10. package/dist-client/pages/activity-approval/activity-approval-page.d.ts +2 -1
  11. package/dist-client/pages/activity-approval/activity-approval-page.js +28 -17
  12. package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
  13. package/dist-client/pages/activity-approval/approval-gate.d.ts +21 -0
  14. package/dist-client/pages/activity-approval/approval-gate.js +9 -0
  15. package/dist-client/pages/activity-approval/approval-gate.js.map +1 -0
  16. package/dist-client/pages/activity-catalog/activity-catalog-page.d.ts +2 -1
  17. package/dist-client/pages/activity-catalog/activity-catalog-page.js +19 -4
  18. package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
  19. package/dist-client/pages/installable-activity/installable-activity-list-page.js +5 -1
  20. package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
  21. package/dist-client/tsconfig.tsbuildinfo +1 -0
  22. package/dist-server/service/activity/activity-decision-key-item-type.d.ts +3 -6
  23. package/dist-server/service/activity/activity-decision-key-item-type.js +3 -6
  24. package/dist-server/service/activity/activity-decision-key-item-type.js.map +1 -1
  25. package/dist-server/service/activity/activity-query.d.ts +2 -0
  26. package/dist-server/service/activity/activity-query.js +12 -0
  27. package/dist-server/service/activity/activity-query.js.map +1 -1
  28. package/dist-server/service/activity/decision-key-declaration.d.ts +34 -2
  29. package/dist-server/service/activity/decision-key-declaration.js +14 -2
  30. package/dist-server/service/activity/decision-key-declaration.js.map +1 -1
  31. package/dist-server/service/activity/index.d.ts +1 -1
  32. package/dist-server/service/activity-instance/index.d.ts +1 -1
  33. package/dist-server/service/activity-template/index.d.ts +1 -1
  34. package/dist-server/service/activity-thread/index.d.ts +1 -1
  35. package/dist-server/service/index.d.ts +3 -3
  36. package/dist-server/service/installable-activity/installable-activity-query.d.ts +4 -0
  37. package/dist-server/service/installable-activity/installable-activity-query.js +23 -0
  38. package/dist-server/service/installable-activity/installable-activity-query.js.map +1 -1
  39. package/dist-server/service/installable-activity/installable-activity.d.ts +3 -2
  40. package/dist-server/service/installable-activity/installable-activity.js +1 -1
  41. package/dist-server/service/installable-activity/installable-activity.js.map +1 -1
  42. package/dist-server/tsconfig.tsbuildinfo +1 -0
  43. package/package.json +12 -11
  44. package/translations/en.json +21 -20
  45. package/translations/ja.json +22 -21
  46. package/translations/ko.json +22 -21
  47. package/translations/ms.json +22 -21
  48. package/translations/zh.json +22 -21
@@ -10,7 +10,6 @@
10
10
  *
11
11
  * subject what this is about
12
12
  * reason what a person wrote
13
- * policy why it came up for approval at all
14
13
  * headline one sentence built from the values
15
14
  * reversibility whether approving can be undone
16
15
  *
@@ -54,8 +53,6 @@ export declare enum ActivityDecisionRole {
54
53
  * this sense in its stop-reason dialog. (2026-09-10, architect's ruling)
55
54
  */
56
55
  consequence = "consequence",
57
- /** Why this came up for approval at all: 「폐기는 100 이상이면 결재」. */
58
- policy = "policy",
59
56
  /**
60
57
  * What is measured to be true right now — about the world, not about the request.
61
58
  *
@@ -110,8 +107,8 @@ export declare enum ActivityDecisionRole {
110
107
  * ── Why this points at input rather than at a model item ──────────────────
111
108
  * inputPath names a value inside the instance's input and does not go through the activity's model.
112
109
  * That is the whole reason it is a separate array: the values an approver most needs are computed by
113
- * the registering module and put on the input, not declared as model items — plant's `policy` and
114
- * its `shift.passes` / `shift.passedBy` are exactly that. A role hung on a model item could not
110
+ * the registering module and put on the input, not declared as model items — plant's
111
+ * `shift.passes` / `shift.passedBy` are exactly that. A role hung on a model item could not
115
112
  * reach them.
116
113
  *
117
114
  * ── inputPath, not inputKey ───────────────────────────────────────────────
@@ -121,7 +118,7 @@ export declare enum ActivityDecisionRole {
121
118
  * one word with two meanings would make the wrong one silent, and a name that does not exist is
122
119
  * read as a mistake instead. (2026-09-09, architect's ruling)
123
120
  *
124
- * 'policy' → input.policy
121
+ * 'reason' → input.reason
125
122
  * 'shift.passes' → input.shift.passes
126
123
  *
127
124
  * Dots only. No array index — drawing a list is the slot's job, not the path's — and no wildcard. A
@@ -16,7 +16,6 @@ const shell_1 = require("@things-factory/shell");
16
16
  *
17
17
  * subject what this is about
18
18
  * reason what a person wrote
19
- * policy why it came up for approval at all
20
19
  * headline one sentence built from the values
21
20
  * reversibility whether approving can be undone
22
21
  *
@@ -61,8 +60,6 @@ var ActivityDecisionRole;
61
60
  * this sense in its stop-reason dialog. (2026-09-10, architect's ruling)
62
61
  */
63
62
  ActivityDecisionRole["consequence"] = "consequence";
64
- /** Why this came up for approval at all: 「폐기는 100 이상이면 결재」. */
65
- ActivityDecisionRole["policy"] = "policy";
66
63
  /**
67
64
  * What is measured to be true right now — about the world, not about the request.
68
65
  *
@@ -121,8 +118,8 @@ var ActivityDecisionRole;
121
118
  * ── Why this points at input rather than at a model item ──────────────────
122
119
  * inputPath names a value inside the instance's input and does not go through the activity's model.
123
120
  * That is the whole reason it is a separate array: the values an approver most needs are computed by
124
- * the registering module and put on the input, not declared as model items — plant's `policy` and
125
- * its `shift.passes` / `shift.passedBy` are exactly that. A role hung on a model item could not
121
+ * the registering module and put on the input, not declared as model items — plant's
122
+ * `shift.passes` / `shift.passedBy` are exactly that. A role hung on a model item could not
126
123
  * reach them.
127
124
  *
128
125
  * ── inputPath, not inputKey ───────────────────────────────────────────────
@@ -132,7 +129,7 @@ var ActivityDecisionRole;
132
129
  * one word with two meanings would make the wrong one silent, and a name that does not exist is
133
130
  * read as a mistake instead. (2026-09-09, architect's ruling)
134
131
  *
135
- * 'policy' → input.policy
132
+ * 'reason' → input.reason
136
133
  * 'shift.passes' → input.shift.passes
137
134
  *
138
135
  * Dots only. No array index — drawing a list is the slot's job, not the path's — and no wildcard. A
@@ -1 +1 @@
1
- {"version":3,"file":"activity-decision-key-item-type.js","sourceRoot":"","sources":["../../../server/service/activity/activity-decision-key-item-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAkE;AAElE,iDAAoD;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,IAAY,oBAkEX;AAlED,WAAY,oBAAoB;IAC9B,mEAAmE;IACnE,6CAAqB,CAAA;IACrB,mDAAmD;IACnD,2CAAmB,CAAA;IACnB,iGAAiG;IACjG,yCAAiB,CAAA;IACjB;;;;;;;;OAQG;IACH,mDAA2B,CAAA;IAC3B,+DAA+D;IAC/D,yCAAiB,CAAA;IACjB;;;;;;;;;;;;OAYG;IACH,qDAA6B,CAAA;IAC7B;;;;;;;;;;;;;;;;OAgBG;IACH,uDAA+B,CAAA;IAC/B;;;;;;;;;;;;;OAaG;IACH,6CAAqB,CAAA;AACvB,CAAC,EAlEW,oBAAoB,oCAApB,oBAAoB,QAkE/B;AAED,IAAA,+BAAgB,EAAC,oBAAoB,EAAE;IACrC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EAAE,sDAAsD;CACpE,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;CAgFnC,CAAA;AAhFY,0DAAuB;AAElC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC;;qDACV;AAG1B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,2EAA2E,EAAE,CAAC;;0DACnF;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;;qDAC7E;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;;qDAC3F;AAoCb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;;0DACrF;AAelB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;;uDAC9D;AAiBnC;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,iEAAiE,EAAE,CAAC;;qDAC7F;kCA/EF,uBAAuB;IADnC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;GACrD,uBAAuB,CAgFnC","sourcesContent":["import { Field, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\n/**\n * The part an input value plays on the approval screen.\n *\n * ── The shape of the set: three tenses, and five others ───────────────────\n * Three of the eight say something about the subject at a point in time, and the other five do not:\n *\n * past evidence what the decision was made from (may repeat)\n * present currentState how things stand right now\n * future consequence what approving would change (may repeat)\n *\n * subject what this is about\n * reason what a person wrote\n * policy why it came up for approval at all\n * headline one sentence built from the values\n * reversibility whether approving can be undone\n *\n * Every mis-slotting found so far was the same mistake in that column: currentState under\n * consequence read the present as the future, and evidence under currentState read the past as the\n * present. So when a ninth role is asked for, the first question is whether the value is the\n * subject's past, present or future — if it is, one of those three already holds it. If it is not,\n * whoever asks should be able to say what it is instead. (2026-09-10, architect's ruling)\n *\n * ── Why the keys and the values are spelled the same ──────────────────────\n * type-graphql publishes an enum by its **keys** when the field names the enum type, and by its\n * **values** when the field leaves the type off. One word in a @Field decorator therefore decides\n * what a client receives, and a schema-improving edit far away can flip it. That has already cost\n * this repository twice: ApprovalLineItem.participation arrives as `Reference` and was compared\n * against `reference`, false every time; the catalog page read `NotWorklist` where its selector,\n * i18n key and stage list all said `notworklist`.\n *\n * Writing each key as its own value takes the choice away — either spelling produces the same\n * string. ActivityModelItemInoutType and ActivityModelItemType are written the same way.\n *\n * ── The set is closed, and widening it is the architect's call ────────────\n * Left open as a free string, a convention becomes suffix-appending: every lane invents its own\n * word for the same slot and the screen ends up switching on a dozen spellings, printing the\n * unmatched ones. Adding a role here is an architecture decision, not a lane's. (2026-09-09,\n * architect's ruling)\n */\nexport enum ActivityDecisionRole {\n /** One sentence built from the values: 「폐기 30 EA」, 「3에서 1로 올림」. */\n headline = 'headline',\n /** What the decision is about — one identifier. */\n subject = 'subject',\n /** What the person who raised it wrote. Absent, the screen says so rather than leaving a gap. */\n reason = 'reason',\n /**\n * What changes on approval: 「주문 넷이 뒤로 밀린다」. The only role that may appear more than once.\n *\n * Named consequence rather than effect because TwinCommand.effect already means the opposite in\n * time: { status, at, seen }, what the source reported back after the command was dispatched.\n * That one is an observation and past; this one is a prediction and future. Using a real term for\n * the wrong meaning is worse than coining one, and plant already writes .consequence for exactly\n * this sense in its stop-reason dialog. (2026-09-10, architect's ruling)\n */\n consequence = 'consequence',\n /** Why this came up for approval at all: 「폐기는 100 이상이면 결재」. */\n policy = 'policy',\n /**\n * What is measured to be true right now — about the world, not about the request.\n *\n * The other roles all describe what is being asked for. This one does not, and putting it under\n * consequence made the screen say the opposite of the truth: the twin's current readings would\n * have read as things the approval causes.\n *\n * Not named observed: ops-contract already has observedBy for which observation backs a declared\n * property, and TwinCommand.effect is an observation too, so observed would sit in the most\n * confusable spot between them. (2026-09-10, architect's ruling) plant never needed it because the subject's present state\n * went into the headline (「폐기 30 EA」); the twin's instruction and its current state are two\n * separate things, and holding them side by side is what this screen is for.\n */\n currentState = 'currentState',\n /**\n * Whether approving can be undone. Drawn in the frame rather than in the body.\n *\n * Not a separate role for want of a place — it fits consequence well enough — but for want of\n * weight. Listed among the consequences it reads with the same force as \"four orders get pushed\n * back\", and on\n * the twin actuation, where approving moves equipment, it is the heaviest line on the screen.\n *\n * ── Not the same as rejectionIsFinal ──────────────────────────────────\n * Two \"cannot be undone\" facts attach to opposite actions, and the twin actuation carries both,\n * which is what makes them look like one:\n *\n * reversibility whether **approving** can be undone (this role, read from the input)\n * rejectionIsFinal whether **rejecting** ends the case (a column on Activity)\n *\n * Merging them in a screen sentence tells the reader that rejection can be taken back.\n */\n reversibility = 'reversibility',\n /**\n * What the decision was made from — which inspection, against which spec, decided when.\n *\n * Neither consequence nor currentState: consequence is the opposite direction in time, and under\n * currentState a past finding reads as the present state of the subject. plant's disposition\n * approval kept its own screen for exactly these three values, and it survived the comparison not\n * because a slot could not hold them but because no slot existed — those are different reasons,\n * and only the second one means the set is short.\n *\n * plant's case for it: someone approving a concession in a regulated plant who cannot see which\n * inspection produced the finding is approving without grounds.\n *\n * Repeats, because grounds come in several — there were three.\n */\n evidence = 'evidence'\n}\n\nregisterEnumType(ActivityDecisionRole, {\n name: 'ActivityDecisionRole',\n description: 'the part an input value plays on the approval screen'\n})\n\n/**\n * One value the approver reads, and the part it plays.\n *\n * ── Why this points at input rather than at a model item ──────────────────\n * inputPath names a value inside the instance's input and does not go through the activity's model.\n * That is the whole reason it is a separate array: the values an approver most needs are computed by\n * the registering module and put on the input, not declared as model items — plant's `policy` and\n * its `shift.passes` / `shift.passedBy` are exactly that. A role hung on a model item could not\n * reach them.\n *\n * ── inputPath, not inputKey ───────────────────────────────────────────────\n * ActivitySearchKeyItem.inputKey names one top-level key, because its value goes into a searchable\n * column and a path into a list is not something that can be indexed. This field takes a path,\n * because it points at a value to draw. The two do different work, so they carry different names —\n * one word with two meanings would make the wrong one silent, and a name that does not exist is\n * read as a mistake instead. (2026-09-09, architect's ruling)\n *\n * 'policy' → input.policy\n * 'shift.passes' → input.shift.passes\n *\n * Dots only. No array index — drawing a list is the slot's job, not the path's — and no wildcard. A\n * path that leads nowhere resolves to undefined and is not folded into an empty value: a `reason`\n * that is missing and a `reason` someone left blank are different facts, and the screen draws them\n * differently.\n *\n * The two declarations also address different readers. model declares the boxes a performer fills;\n * this declares what an approver reads. Putting both on one item leaves \"is this an input or\n * something to judge by\" unanswerable.\n *\n * Order matters. plant wrote four of these screens by hand and all four laid the slots out in the\n * same order, which makes the order the screen's hierarchy rather than a preference — so this is an\n * ordered array and not an object keyed by role.\n */\n@ObjectType({ description: 'Entity for ActivityDecisionKeyItem' })\nexport class ActivityDecisionKeyItem {\n @Field(type => ActivityDecisionRole)\n role: ActivityDecisionRole\n\n @Field({ description: \"Dotted path to the value inside the instance's input, e.g. 'shift.passes'\" })\n inputPath: string\n\n @Field({ nullable: true, description: 'Developer-facing note. Never shown on a screen.' })\n name?: string\n\n @Field({ nullable: true, description: 'i18n key for the label. Without it the screen shows no label.' })\n tKey?: string\n\n /**\n * i18n key for the **value**, when the value is a sentence the module would otherwise freeze.\n *\n * ── tKey is the label; this is the sentence ───────────────────────────\n * Two different things were being asked of one field. The screen draws a slot as a label and a\n * value, and they come from different places:\n *\n * label declaredLabel(slot) = t(slot.tKey, { defaultValue: name }) 「설비」 「사유」\n * value fieldValue(slot.value) the frozen sentence\n *\n * Putting a sentence key in `tKey` turns the label into a developer's English name and leaves the\n * frozen Korean where it was — the thing this is meant to remove.\n *\n * ── Why the sentence must not freeze ──────────────────────────────────\n * Eighteen doors build a Korean sentence when the request is raised and `issue()` snapshots it\n * whole. The sentence then stands in the language of whoever raised it, not whoever reads it, and\n * an approver on another language never catches up.\n *\n * Values are right to freeze — an approval is a judgment about facts at a moment, so quantities,\n * dates and counts are the record. The prose describing them is not a fact, and freezing it also\n * loses what it described: maintenance deferral carries `impact.times` as a value but `dueAt`\n * only inside the sentence, so editing that wording would leave no way to say which due date the\n * approval was about. (ADR-0054 ④)\n *\n * ── Computed, never invented ──────────────────────────────────────────\n * `approval.<door>.<inputPath>` — `inputPath` is the one thing unique within a door, which `role`\n * is not (a door repeats `consequence`). Nobody writing a new door picks a key, so no table of\n * keys grows, and a test can count every one of them.\n *\n * Leaving it out is how a slot stays as it is. The frozen sentence remains in `value`, so a\n * consumer that knows nothing about this field — the plain card, the timeline, an export — draws\n * exactly what it drew before, and a missing translation never puts English into a Korean screen.\n */\n @Field({ nullable: true, description: \"i18n key for the value sentence: approval.<door>.<inputPath>\" })\n valueTKey?: string\n\n /**\n * What the sentence puts into its blanks: **name in the sentence → where the value lives.**\n *\n * { what: 'equipmentName', days: 'impact.days' } → t(valueTKey, { what: …, days: … })\n *\n * Every value here is an `inputPath`, and that is the point rather than a convention: a sentence\n * may only be built from values that were snapshotted. Wanting a value with no field to read it\n * from means the field is missing, not that params needs another source — so the rule is a shape\n * a declaration cannot write around, and a test counts it.\n *\n * The names on the left belong to the sentence and only have to match the locale files.\n */\n @Field(type => ScalarObject, { nullable: true, description: 'sentence placeholder → inputPath' })\n params?: { [name: string]: string }\n\n /**\n * Unit to print after the value, when the activity fixes the unit.\n *\n * Declared once, so it holds for every instance of the activity — 「30 건」 works, and a unit that\n * varies per record does not: plant's disposition carries the unit alongside the quantity, so the\n * same activity produces 「3 EA」 and 「12.5 KG」. Writing one of them here would attach the wrong\n * unit to the other records, with nothing to catch it.\n *\n * A unit that varies belongs in the headline sentence the module builds, which is what plant did:\n * 「LOT-A 3 EA 를 폐기합니다」. Leave this empty then.\n *\n * Delete this field if no activity ever turns out to fix a unit. A field nobody writes stays\n * forever and the next person reads a meaning into it. (2026-09-10, architect's ruling)\n */\n @Field({ nullable: true, description: 'Unit to print after the value, when the activity fixes the unit' })\n unit?: string\n}\n"]}
1
+ {"version":3,"file":"activity-decision-key-item-type.js","sourceRoot":"","sources":["../../../server/service/activity/activity-decision-key-item-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAkE;AAElE,iDAAoD;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,IAAY,oBAgEX;AAhED,WAAY,oBAAoB;IAC9B,mEAAmE;IACnE,6CAAqB,CAAA;IACrB,mDAAmD;IACnD,2CAAmB,CAAA;IACnB,iGAAiG;IACjG,yCAAiB,CAAA;IACjB;;;;;;;;OAQG;IACH,mDAA2B,CAAA;IAC3B;;;;;;;;;;;;OAYG;IACH,qDAA6B,CAAA;IAC7B;;;;;;;;;;;;;;;;OAgBG;IACH,uDAA+B,CAAA;IAC/B;;;;;;;;;;;;;OAaG;IACH,6CAAqB,CAAA;AACvB,CAAC,EAhEW,oBAAoB,oCAApB,oBAAoB,QAgE/B;AAED,IAAA,+BAAgB,EAAC,oBAAoB,EAAE;IACrC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EAAE,sDAAsD;CACpE,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;CAgFnC,CAAA;AAhFY,0DAAuB;AAElC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC;;qDACV;AAG1B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,2EAA2E,EAAE,CAAC;;0DACnF;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;;qDAC7E;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;;qDAC3F;AAoCb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;;0DACrF;AAelB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;;uDAC9D;AAiBnC;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,iEAAiE,EAAE,CAAC;;qDAC7F;kCA/EF,uBAAuB;IADnC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;GACrD,uBAAuB,CAgFnC","sourcesContent":["import { Field, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\n/**\n * The part an input value plays on the approval screen.\n *\n * ── The shape of the set: three tenses, and five others ───────────────────\n * Three of the eight say something about the subject at a point in time, and the other five do not:\n *\n * past evidence what the decision was made from (may repeat)\n * present currentState how things stand right now\n * future consequence what approving would change (may repeat)\n *\n * subject what this is about\n * reason what a person wrote\n * headline one sentence built from the values\n * reversibility whether approving can be undone\n *\n * Every mis-slotting found so far was the same mistake in that column: currentState under\n * consequence read the present as the future, and evidence under currentState read the past as the\n * present. So when a ninth role is asked for, the first question is whether the value is the\n * subject's past, present or future — if it is, one of those three already holds it. If it is not,\n * whoever asks should be able to say what it is instead. (2026-09-10, architect's ruling)\n *\n * ── Why the keys and the values are spelled the same ──────────────────────\n * type-graphql publishes an enum by its **keys** when the field names the enum type, and by its\n * **values** when the field leaves the type off. One word in a @Field decorator therefore decides\n * what a client receives, and a schema-improving edit far away can flip it. That has already cost\n * this repository twice: ApprovalLineItem.participation arrives as `Reference` and was compared\n * against `reference`, false every time; the catalog page read `NotWorklist` where its selector,\n * i18n key and stage list all said `notworklist`.\n *\n * Writing each key as its own value takes the choice away — either spelling produces the same\n * string. ActivityModelItemInoutType and ActivityModelItemType are written the same way.\n *\n * ── The set is closed, and widening it is the architect's call ────────────\n * Left open as a free string, a convention becomes suffix-appending: every lane invents its own\n * word for the same slot and the screen ends up switching on a dozen spellings, printing the\n * unmatched ones. Adding a role here is an architecture decision, not a lane's. (2026-09-09,\n * architect's ruling)\n */\nexport enum ActivityDecisionRole {\n /** One sentence built from the values: 「폐기 30 EA」, 「3에서 1로 올림」. */\n headline = 'headline',\n /** What the decision is about — one identifier. */\n subject = 'subject',\n /** What the person who raised it wrote. Absent, the screen says so rather than leaving a gap. */\n reason = 'reason',\n /**\n * What changes on approval: 「주문 넷이 뒤로 밀린다」. The only role that may appear more than once.\n *\n * Named consequence rather than effect because TwinCommand.effect already means the opposite in\n * time: { status, at, seen }, what the source reported back after the command was dispatched.\n * That one is an observation and past; this one is a prediction and future. Using a real term for\n * the wrong meaning is worse than coining one, and plant already writes .consequence for exactly\n * this sense in its stop-reason dialog. (2026-09-10, architect's ruling)\n */\n consequence = 'consequence',\n /**\n * What is measured to be true right now — about the world, not about the request.\n *\n * The other roles all describe what is being asked for. This one does not, and putting it under\n * consequence made the screen say the opposite of the truth: the twin's current readings would\n * have read as things the approval causes.\n *\n * Not named observed: ops-contract already has observedBy for which observation backs a declared\n * property, and TwinCommand.effect is an observation too, so observed would sit in the most\n * confusable spot between them. (2026-09-10, architect's ruling) plant never needed it because the subject's present state\n * went into the headline (「폐기 30 EA」); the twin's instruction and its current state are two\n * separate things, and holding them side by side is what this screen is for.\n */\n currentState = 'currentState',\n /**\n * Whether approving can be undone. Drawn in the frame rather than in the body.\n *\n * Not a separate role for want of a place — it fits consequence well enough — but for want of\n * weight. Listed among the consequences it reads with the same force as \"four orders get pushed\n * back\", and on\n * the twin actuation, where approving moves equipment, it is the heaviest line on the screen.\n *\n * ── Not the same as rejectionIsFinal ──────────────────────────────────\n * Two \"cannot be undone\" facts attach to opposite actions, and the twin actuation carries both,\n * which is what makes them look like one:\n *\n * reversibility whether **approving** can be undone (this role, read from the input)\n * rejectionIsFinal whether **rejecting** ends the case (a column on Activity)\n *\n * Merging them in a screen sentence tells the reader that rejection can be taken back.\n */\n reversibility = 'reversibility',\n /**\n * What the decision was made from — which inspection, against which spec, decided when.\n *\n * Neither consequence nor currentState: consequence is the opposite direction in time, and under\n * currentState a past finding reads as the present state of the subject. plant's disposition\n * approval kept its own screen for exactly these three values, and it survived the comparison not\n * because a slot could not hold them but because no slot existed — those are different reasons,\n * and only the second one means the set is short.\n *\n * plant's case for it: someone approving a concession in a regulated plant who cannot see which\n * inspection produced the finding is approving without grounds.\n *\n * Repeats, because grounds come in several — there were three.\n */\n evidence = 'evidence'\n}\n\nregisterEnumType(ActivityDecisionRole, {\n name: 'ActivityDecisionRole',\n description: 'the part an input value plays on the approval screen'\n})\n\n/**\n * One value the approver reads, and the part it plays.\n *\n * ── Why this points at input rather than at a model item ──────────────────\n * inputPath names a value inside the instance's input and does not go through the activity's model.\n * That is the whole reason it is a separate array: the values an approver most needs are computed by\n * the registering module and put on the input, not declared as model items — plant's\n * `shift.passes` / `shift.passedBy` are exactly that. A role hung on a model item could not\n * reach them.\n *\n * ── inputPath, not inputKey ───────────────────────────────────────────────\n * ActivitySearchKeyItem.inputKey names one top-level key, because its value goes into a searchable\n * column and a path into a list is not something that can be indexed. This field takes a path,\n * because it points at a value to draw. The two do different work, so they carry different names —\n * one word with two meanings would make the wrong one silent, and a name that does not exist is\n * read as a mistake instead. (2026-09-09, architect's ruling)\n *\n * 'reason' → input.reason\n * 'shift.passes' → input.shift.passes\n *\n * Dots only. No array index — drawing a list is the slot's job, not the path's — and no wildcard. A\n * path that leads nowhere resolves to undefined and is not folded into an empty value: a `reason`\n * that is missing and a `reason` someone left blank are different facts, and the screen draws them\n * differently.\n *\n * The two declarations also address different readers. model declares the boxes a performer fills;\n * this declares what an approver reads. Putting both on one item leaves \"is this an input or\n * something to judge by\" unanswerable.\n *\n * Order matters. plant wrote four of these screens by hand and all four laid the slots out in the\n * same order, which makes the order the screen's hierarchy rather than a preference — so this is an\n * ordered array and not an object keyed by role.\n */\n@ObjectType({ description: 'Entity for ActivityDecisionKeyItem' })\nexport class ActivityDecisionKeyItem {\n @Field(type => ActivityDecisionRole)\n role: ActivityDecisionRole\n\n @Field({ description: \"Dotted path to the value inside the instance's input, e.g. 'shift.passes'\" })\n inputPath: string\n\n @Field({ nullable: true, description: 'Developer-facing note. Never shown on a screen.' })\n name?: string\n\n @Field({ nullable: true, description: 'i18n key for the label. Without it the screen shows no label.' })\n tKey?: string\n\n /**\n * i18n key for the **value**, when the value is a sentence the module would otherwise freeze.\n *\n * ── tKey is the label; this is the sentence ───────────────────────────\n * Two different things were being asked of one field. The screen draws a slot as a label and a\n * value, and they come from different places:\n *\n * label declaredLabel(slot) = t(slot.tKey, { defaultValue: name }) 「설비」 「사유」\n * value fieldValue(slot.value) the frozen sentence\n *\n * Putting a sentence key in `tKey` turns the label into a developer's English name and leaves the\n * frozen Korean where it was — the thing this is meant to remove.\n *\n * ── Why the sentence must not freeze ──────────────────────────────────\n * Eighteen doors build a Korean sentence when the request is raised and `issue()` snapshots it\n * whole. The sentence then stands in the language of whoever raised it, not whoever reads it, and\n * an approver on another language never catches up.\n *\n * Values are right to freeze — an approval is a judgment about facts at a moment, so quantities,\n * dates and counts are the record. The prose describing them is not a fact, and freezing it also\n * loses what it described: maintenance deferral carries `impact.times` as a value but `dueAt`\n * only inside the sentence, so editing that wording would leave no way to say which due date the\n * approval was about. (ADR-0054 ④)\n *\n * ── Computed, never invented ──────────────────────────────────────────\n * `approval.<door>.<inputPath>` — `inputPath` is the one thing unique within a door, which `role`\n * is not (a door repeats `consequence`). Nobody writing a new door picks a key, so no table of\n * keys grows, and a test can count every one of them.\n *\n * Leaving it out is how a slot stays as it is. The frozen sentence remains in `value`, so a\n * consumer that knows nothing about this field — the plain card, the timeline, an export — draws\n * exactly what it drew before, and a missing translation never puts English into a Korean screen.\n */\n @Field({ nullable: true, description: \"i18n key for the value sentence: approval.<door>.<inputPath>\" })\n valueTKey?: string\n\n /**\n * What the sentence puts into its blanks: **name in the sentence → where the value lives.**\n *\n * { what: 'equipmentName', days: 'impact.days' } → t(valueTKey, { what: …, days: … })\n *\n * Every value here is an `inputPath`, and that is the point rather than a convention: a sentence\n * may only be built from values that were snapshotted. Wanting a value with no field to read it\n * from means the field is missing, not that params needs another source — so the rule is a shape\n * a declaration cannot write around, and a test counts it.\n *\n * The names on the left belong to the sentence and only have to match the locale files.\n */\n @Field(type => ScalarObject, { nullable: true, description: 'sentence placeholder → inputPath' })\n params?: { [name: string]: string }\n\n /**\n * Unit to print after the value, when the activity fixes the unit.\n *\n * Declared once, so it holds for every instance of the activity — 「30 건」 works, and a unit that\n * varies per record does not: plant's disposition carries the unit alongside the quantity, so the\n * same activity produces 「3 EA」 and 「12.5 KG」. Writing one of them here would attach the wrong\n * unit to the other records, with nothing to catch it.\n *\n * A unit that varies belongs in the headline sentence the module builds, which is what plant did:\n * 「LOT-A 3 EA 를 폐기합니다」. Leave this empty then.\n *\n * Delete this field if no activity ever turns out to fix a unit. A field nobody writes stays\n * forever and the next person reads a meaning into it. (2026-09-10, architect's ruling)\n */\n @Field({ nullable: true, description: 'Unit to print after the value, when the activity fixes the unit' })\n unit?: string\n}\n"]}
@@ -9,6 +9,8 @@ export declare class ActivityQuery {
9
9
  activities(params: ListParam, context: ResolverContext): Promise<ActivityList>;
10
10
  startableActivities(params: ListParam, context: ResolverContext): Promise<ActivityList>;
11
11
  supervisableActivities(params: ListParam, context: ResolverContext): Promise<ActivityList>;
12
+ /** The key `label` is translated from. Computed from `name`, never stored — see activityTKey. */
13
+ labelTKey(activity: Activity): string;
12
14
  issuerRole(activity: Activity): Promise<Role>;
13
15
  assigneeRole(activity: Activity): Promise<Role>;
14
16
  assignees(activity: Activity, context: ResolverContext): Promise<AssigneeItem[]>;
@@ -11,6 +11,7 @@ const shell_1 = require("@things-factory/shell");
11
11
  const organization_1 = require("@things-factory/organization");
12
12
  const activity_js_1 = require("./activity.js");
13
13
  const activity_type_js_1 = require("./activity-type.js");
14
+ const decision_key_declaration_js_1 = require("./decision-key-declaration.js");
14
15
  let ActivityQuery = class ActivityQuery {
15
16
  async activity(id, context) {
16
17
  const { domain } = context.state;
@@ -86,6 +87,10 @@ let ActivityQuery = class ActivityQuery {
86
87
  .getManyAndCount();
87
88
  return { items, total };
88
89
  }
90
+ /** The key `label` is translated from. Computed from `name`, never stored — see activityTKey. */
91
+ labelTKey(activity) {
92
+ return (0, decision_key_declaration_js_1.activityTKey)(activity.name, 'label');
93
+ }
89
94
  async issuerRole(activity) {
90
95
  return (activity.issuerRole ||
91
96
  (activity.issuerRoleId &&
@@ -235,6 +240,13 @@ tslib_1.__decorate([
235
240
  tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
236
241
  tslib_1.__metadata("design:returntype", Promise)
237
242
  ], ActivityQuery.prototype, "supervisableActivities", null);
243
+ tslib_1.__decorate([
244
+ (0, type_graphql_1.FieldResolver)(type => String, { description: 'i18n key the label is translated from, computed from name' }),
245
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
246
+ tslib_1.__metadata("design:type", Function),
247
+ tslib_1.__metadata("design:paramtypes", [activity_js_1.Activity]),
248
+ tslib_1.__metadata("design:returntype", String)
249
+ ], ActivityQuery.prototype, "labelTKey", null);
238
250
  tslib_1.__decorate([
239
251
  (0, type_graphql_1.FieldResolver)(type => auth_base_1.Role),
240
252
  tslib_1.__param(0, (0, type_graphql_1.Root)()),
@@ -1 +1 @@
1
- {"version":3,"file":"activity-query.js","sourceRoot":"","sources":["../../../server/service/activity/activity-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { Brackets } from 'typeorm'\n\nimport { Attachment } from '@things-factory/attachment-base'\nimport { Role, User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { ApprovalLineItem } from '@things-factory/organization'\n\nimport { Activity, ActivityStartingType, ActivityStatus, AssigneeItem } from './activity.js'\nimport { ActivityList } from './activity-type.js'\n\n@Resolver(Activity)\nexport class ActivityQuery {\n @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity' })\n async activity(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Activity> {\n const { domain } = context.state\n\n return await getRepository(Activity).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n }\n\n @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity by name' })\n async activityByName(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Activity> {\n const { domain } = context.state\n\n return await getRepository(Activity).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, name }\n })\n }\n\n @Query(returns => ActivityList, { description: 'To fetch multiple Activities' })\n async activities(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ActivityList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(Activity),\n alias: 'activity',\n searchables: ['name', 'description', 'issuerRole', 'assigneeRole', 'supervisoryRole']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityList, { description: 'To fetch the list of activities I can start' })\n async startableActivities(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityList> {\n var { domain, user } = context.state\n\n /* 조회한 사용자가 assigner 역할을 가진 activity-instance 리스트만 반환 */\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(Activity),\n params,\n domain,\n alias: 'activity',\n searchables: ['name', 'description']\n })\n .andWhere(`activity.startingType IN (:...startingTypes)`, {\n startingTypes: [ActivityStartingType.Issue, ActivityStartingType.Post]\n })\n .andWhere(`activity.state = :state`, { state: ActivityStatus.Released })\n .andWhere(\n roles.length > 0\n ? new Brackets(qb => {\n qb.orWhere(`activity.issuerRole IN (:...roles)`, { roles })\n qb.orWhere(`activity.issuerRole IS NULL`)\n })\n : `activity.issuerRole IS NULL`\n )\n .getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityList, { description: 'To fetch the list of activities that I can report on' })\n async supervisableActivities(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityList> {\n var { domain, user } = context.state\n\n /* 조회한 사용자가 assigner 역할을 가진 activity-instance 리스트만 반환 */\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n if (!roles.length) {\n return { items: [], total: 0 }\n }\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(Activity),\n params,\n domain,\n alias: 'activity',\n searchables: ['name', 'description']\n })\n .andWhere(`activity.supervisoryRole IN (:...roles)`, { roles })\n .getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => Role)\n async issuerRole(@Root() activity: Activity): Promise<Role> {\n return (\n activity.issuerRole ||\n (activity.issuerRoleId &&\n (await getRepository(Role).findOneBy({\n id: activity.issuerRoleId\n })))\n )\n }\n\n @FieldResolver(type => Role)\n async assigneeRole(@Root() activity: Activity): Promise<Role> {\n return (\n activity.assigneeRole ||\n (activity.assigneeRoleId &&\n (await getRepository(Role).findOneBy({\n id: activity.assigneeRoleId\n })))\n )\n }\n\n @FieldResolver(type => [AssigneeItem])\n async assignees(@Root() activity: Activity, @Ctx() context: ResolverContext): Promise<AssigneeItem[]> {\n const { domain, user } = context.state\n const { assignees } = activity\n\n if (!assignees || !(assignees instanceof Array)) {\n return null\n }\n\n var assigneeItemList = []\n\n for (let item of assignees) {\n // \"value\" deprecated. to be removed\n var { type, assignee, value } = item\n var id = assignee?.id || id\n\n switch (type) {\n case 'Employee':\n assignee = id && (await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Department':\n assignee = id && (await getRepository('Department').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Role':\n assignee = id && (await getRepository('Role').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Myself':\n assignee = user\n break\n case 'MyDepartment':\n case 'MySupervisor':\n break\n default:\n }\n\n id ? assigneeItemList.push({ type, assignee }) : assigneeItemList.push({ type })\n }\n\n return assigneeItemList\n }\n\n @FieldResolver(type => [ApprovalLineItem])\n async approvalLine(@Root() activity: Activity, @Ctx() context: ResolverContext): Promise<ApprovalLineItem[]> {\n const { domain, user } = context.state\n const { approvalLine } = activity\n\n if (!approvalLine || !(approvalLine instanceof Array)) {\n return null\n }\n\n var approvalLineItems = []\n\n for (let item of approvalLine) {\n // \"value\" deprecated. to be removed\n var { type, approver, value } = item\n var id = approver?.id || value\n approver = null\n\n switch (type) {\n case 'Employee':\n approver = id && (await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Department':\n approver = id && (await getRepository('Department').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Role':\n approver = id && (await getRepository('Role').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Myself':\n approver = user\n break\n case 'MyDepartment':\n case 'MySupervisor':\n break\n default:\n }\n\n id ? approvalLineItems.push({ type, approver }) : approvalLineItems.push({ type })\n }\n\n return approvalLineItems\n }\n\n @FieldResolver(type => Role)\n async supervisoryRole(@Root() activity: Activity): Promise<Role> {\n return (\n activity.supervisoryRole ||\n (activity.supervisoryRoleId &&\n (await getRepository(Role).findOneBy({\n id: activity.supervisoryRoleId\n })))\n )\n }\n\n @FieldResolver(type => String)\n async thumbnail(@Root() activity: Activity): Promise<string | undefined> {\n const attachment: Attachment = await getRepository(Attachment).findOne({\n where: {\n domain: { id: activity.domainId },\n refType: Activity.name,\n refBy: activity.id\n }\n })\n\n return attachment?.fullpath\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() activity: Activity): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: activity.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() activity: Activity): Promise<User> {\n return await getRepository(User).findOneBy({ id: activity.updaterId })\n }\n\n @FieldResolver(type => User)\n async creator(@Root() activity: Activity): Promise<User> {\n return await getRepository(User).findOneBy({ id: activity.creatorId })\n }\n}\n"]}
1
+ {"version":3,"file":"activity-query.js","sourceRoot":"","sources":["../../../server/service/activity/activity-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { Brackets } from 'typeorm'\n\nimport { Attachment } from '@things-factory/attachment-base'\nimport { Role, User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { ApprovalLineItem } from '@things-factory/organization'\n\nimport { Activity, ActivityStartingType, ActivityStatus, AssigneeItem } from './activity.js'\nimport { ActivityList } from './activity-type.js'\nimport { activityTKey } from './decision-key-declaration.js'\n\n@Resolver(Activity)\nexport class ActivityQuery {\n @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity' })\n async activity(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Activity> {\n const { domain } = context.state\n\n return await getRepository(Activity).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n }\n\n @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity by name' })\n async activityByName(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Activity> {\n const { domain } = context.state\n\n return await getRepository(Activity).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, name }\n })\n }\n\n @Query(returns => ActivityList, { description: 'To fetch multiple Activities' })\n async activities(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ActivityList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(Activity),\n alias: 'activity',\n searchables: ['name', 'description', 'issuerRole', 'assigneeRole', 'supervisoryRole']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityList, { description: 'To fetch the list of activities I can start' })\n async startableActivities(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityList> {\n var { domain, user } = context.state\n\n /* 조회한 사용자가 assigner 역할을 가진 activity-instance 리스트만 반환 */\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(Activity),\n params,\n domain,\n alias: 'activity',\n searchables: ['name', 'description']\n })\n .andWhere(`activity.startingType IN (:...startingTypes)`, {\n startingTypes: [ActivityStartingType.Issue, ActivityStartingType.Post]\n })\n .andWhere(`activity.state = :state`, { state: ActivityStatus.Released })\n .andWhere(\n roles.length > 0\n ? new Brackets(qb => {\n qb.orWhere(`activity.issuerRole IN (:...roles)`, { roles })\n qb.orWhere(`activity.issuerRole IS NULL`)\n })\n : `activity.issuerRole IS NULL`\n )\n .getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityList, { description: 'To fetch the list of activities that I can report on' })\n async supervisableActivities(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityList> {\n var { domain, user } = context.state\n\n /* 조회한 사용자가 assigner 역할을 가진 activity-instance 리스트만 반환 */\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n if (!roles.length) {\n return { items: [], total: 0 }\n }\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(Activity),\n params,\n domain,\n alias: 'activity',\n searchables: ['name', 'description']\n })\n .andWhere(`activity.supervisoryRole IN (:...roles)`, { roles })\n .getManyAndCount()\n\n return { items, total }\n }\n\n /** The key `label` is translated from. Computed from `name`, never stored — see activityTKey. */\n @FieldResolver(type => String, { description: 'i18n key the label is translated from, computed from name' })\n labelTKey(@Root() activity: Activity): string {\n return activityTKey(activity.name, 'label')\n }\n\n @FieldResolver(type => Role)\n async issuerRole(@Root() activity: Activity): Promise<Role> {\n return (\n activity.issuerRole ||\n (activity.issuerRoleId &&\n (await getRepository(Role).findOneBy({\n id: activity.issuerRoleId\n })))\n )\n }\n\n @FieldResolver(type => Role)\n async assigneeRole(@Root() activity: Activity): Promise<Role> {\n return (\n activity.assigneeRole ||\n (activity.assigneeRoleId &&\n (await getRepository(Role).findOneBy({\n id: activity.assigneeRoleId\n })))\n )\n }\n\n @FieldResolver(type => [AssigneeItem])\n async assignees(@Root() activity: Activity, @Ctx() context: ResolverContext): Promise<AssigneeItem[]> {\n const { domain, user } = context.state\n const { assignees } = activity\n\n if (!assignees || !(assignees instanceof Array)) {\n return null\n }\n\n var assigneeItemList = []\n\n for (let item of assignees) {\n // \"value\" deprecated. to be removed\n var { type, assignee, value } = item\n var id = assignee?.id || id\n\n switch (type) {\n case 'Employee':\n assignee = id && (await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Department':\n assignee = id && (await getRepository('Department').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Role':\n assignee = id && (await getRepository('Role').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Myself':\n assignee = user\n break\n case 'MyDepartment':\n case 'MySupervisor':\n break\n default:\n }\n\n id ? assigneeItemList.push({ type, assignee }) : assigneeItemList.push({ type })\n }\n\n return assigneeItemList\n }\n\n @FieldResolver(type => [ApprovalLineItem])\n async approvalLine(@Root() activity: Activity, @Ctx() context: ResolverContext): Promise<ApprovalLineItem[]> {\n const { domain, user } = context.state\n const { approvalLine } = activity\n\n if (!approvalLine || !(approvalLine instanceof Array)) {\n return null\n }\n\n var approvalLineItems = []\n\n for (let item of approvalLine) {\n // \"value\" deprecated. to be removed\n var { type, approver, value } = item\n var id = approver?.id || value\n approver = null\n\n switch (type) {\n case 'Employee':\n approver = id && (await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Department':\n approver = id && (await getRepository('Department').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Role':\n approver = id && (await getRepository('Role').findOneBy({ domain: { id: domain.id }, id }))\n break\n case 'Myself':\n approver = user\n break\n case 'MyDepartment':\n case 'MySupervisor':\n break\n default:\n }\n\n id ? approvalLineItems.push({ type, approver }) : approvalLineItems.push({ type })\n }\n\n return approvalLineItems\n }\n\n @FieldResolver(type => Role)\n async supervisoryRole(@Root() activity: Activity): Promise<Role> {\n return (\n activity.supervisoryRole ||\n (activity.supervisoryRoleId &&\n (await getRepository(Role).findOneBy({\n id: activity.supervisoryRoleId\n })))\n )\n }\n\n @FieldResolver(type => String)\n async thumbnail(@Root() activity: Activity): Promise<string | undefined> {\n const attachment: Attachment = await getRepository(Attachment).findOne({\n where: {\n domain: { id: activity.domainId },\n refType: Activity.name,\n refBy: activity.id\n }\n })\n\n return attachment?.fullpath\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() activity: Activity): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: activity.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() activity: Activity): Promise<User> {\n return await getRepository(User).findOneBy({ id: activity.updaterId })\n }\n\n @FieldResolver(type => User)\n async creator(@Root() activity: Activity): Promise<User> {\n return await getRepository(User).findOneBy({ id: activity.creatorId })\n }\n}\n"]}
@@ -1,5 +1,14 @@
1
1
  /**
2
- * Refuses a decisionKeys declaration that cannot draw.
2
+ * Refuses a decisionKeys declaration that cannot draw, and computes the i18n keys an activity's
3
+ * sentences are read from.
4
+ *
5
+ * ── This path is read from outside ────────────────────────────────────────
6
+ * operato-plant's tests import this file by its built path,
7
+ * `@things-factory/worklist/dist-server/service/activity/decision-key-declaration.js`, for
8
+ * DECISION_ROLES, doorSlug and activityTKey. Moving or renaming it breaks those tests, so treat the
9
+ * path as public.
10
+ *
11
+ * Refusing a declaration that cannot draw:
3
12
  *
4
13
  * Same reasoning as search keys: a declaration that does not work should fail where it arrives, not
5
14
  * where someone opens an approval. The difference is what "not working" means here — nothing is
@@ -18,7 +27,7 @@ type DecisionKeyDeclaration = {
18
27
  };
19
28
  };
20
29
  /** Roles a screen knows how to draw. Widening this is an architecture decision, not a lane's. */
21
- export declare const DECISION_ROLES: readonly ["headline", "subject", "reversibility", "reason", "evidence", "currentState", "consequence", "policy"];
30
+ export declare const DECISION_ROLES: readonly ["headline", "subject", "reversibility", "reason", "evidence", "currentState", "consequence"];
22
31
  /**
23
32
  * The roles that may appear more than once.
24
33
  *
@@ -61,5 +70,28 @@ export declare function doorSlug(activityName: string): string;
61
70
  * thing already unique within a door, and it is already written in the declaration.
62
71
  */
63
72
  export declare function decisionValueKey(activityName: string, inputPath: string): string;
73
+ /**
74
+ * The i18n key for an activity's own sentences — `activity.<door>.label`, `activity.<door>.guide.<n>`.
75
+ *
76
+ * Computed from `name` for the reason decisionValueKey is: nobody picks the key, so none is picked
77
+ * wrong, and an app's test can walk its declarations and count every key that must exist.
78
+ *
79
+ * The server sends the result (Activity.labelTKey, InstallableActivity.labelTKey and guideTKeys);
80
+ * screens draw `t(labelTKey, { defaultValue: label })` and never rebuild the slug. A client file that
81
+ * imported this one would move the whole client build under dist-client/client/.
82
+ *
83
+ * `description` has no key. It is the developers' English line and is not shown to the person
84
+ * doing the work.
85
+ *
86
+ * Guide lines are keyed by position. Inserting a line shifts every later translation by one, and a
87
+ * count of keys does not notice — change guide and its translations in the same edit.
88
+ */
89
+ export declare function activityTKey(activityName: string, part: 'label'): string;
90
+ export declare function activityTKey(activityName: string, part: 'guide', index: number): string;
91
+ /**
92
+ * One key per guide line, **always as many as there are lines.** The screen pairs the two arrays
93
+ * by position; a shorter key list would send the last lines out untranslated with nothing to show it.
94
+ */
95
+ export declare function activityGuideTKeys(activityName: string, guide: string[] | undefined | null): string[];
64
96
  export declare function assertDecisionKeysAreUsable(decisionKeys: DecisionKeyDeclaration[] | undefined, activityName?: string): void;
65
97
  export {};
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.REPEATABLE_ROLES = exports.DECISION_ROLES = void 0;
4
4
  exports.doorSlug = doorSlug;
5
5
  exports.decisionValueKey = decisionValueKey;
6
+ exports.activityTKey = activityTKey;
7
+ exports.activityGuideTKeys = activityGuideTKeys;
6
8
  exports.assertDecisionKeysAreUsable = assertDecisionKeysAreUsable;
7
9
  /** Roles a screen knows how to draw. Widening this is an architecture decision, not a lane's. */
8
10
  exports.DECISION_ROLES = [
@@ -12,8 +14,7 @@ exports.DECISION_ROLES = [
12
14
  'reason',
13
15
  'evidence',
14
16
  'currentState',
15
- 'consequence',
16
- 'policy'
17
+ 'consequence'
17
18
  ];
18
19
  /**
19
20
  * The roles that may appear more than once.
@@ -66,6 +67,17 @@ function doorSlug(activityName) {
66
67
  function decisionValueKey(activityName, inputPath) {
67
68
  return `approval.${doorSlug(activityName)}.${inputPath}`;
68
69
  }
70
+ function activityTKey(activityName, part, index) {
71
+ const door = `activity.${doorSlug(activityName)}`;
72
+ return part === 'guide' ? `${door}.guide.${index}` : `${door}.label`;
73
+ }
74
+ /**
75
+ * One key per guide line, **always as many as there are lines.** The screen pairs the two arrays
76
+ * by position; a shorter key list would send the last lines out untranslated with nothing to show it.
77
+ */
78
+ function activityGuideTKeys(activityName, guide) {
79
+ return (guide || []).map((_, index) => activityTKey(activityName, 'guide', index));
80
+ }
69
81
  function assertDecisionKeysAreUsable(decisionKeys, activityName) {
70
82
  if (!decisionKeys?.length) {
71
83
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"decision-key-declaration.js","sourceRoot":"","sources":["../../../server/service/activity/decision-key-declaration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Refuses a decisionKeys declaration that cannot draw.\n *\n * Same reasoning as search keys: a declaration that does not work should fail where it arrives, not\n * where someone opens an approval. The difference is what \"not working\" means here — nothing is\n * dropped by a save, so the failure would be a screen that quietly draws less than it was told to.\n *\n * The shape is spelled out rather than imported. ActivityDecisionKeyItem carries type-graphql\n * decorators and the test runner strips types without reading them, so importing the declared class\n * pulls type-graphql in and the test file fails to load.\n */\ntype DecisionKeyDeclaration = {\n role?: string\n inputPath?: string\n valueTKey?: string\n params?: { [name: string]: string }\n}\n\n/** Roles a screen knows how to draw. Widening this is an architecture decision, not a lane's. */\nexport const DECISION_ROLES = [\n 'headline',\n 'subject',\n 'reversibility',\n 'reason',\n 'evidence',\n 'currentState',\n 'consequence',\n 'policy'\n] as const\n\n/**\n * The roles that may appear more than once.\n *\n * An approval can change several things at once — plant's priority change pushes some orders back\n * and moves others ahead — and those are separate consequences, not one merged sentence. Grounds\n * come in several the same way: which inspection, against which spec, decided when.\n *\n * Every other role names a single value. Two headlines would leave the screen picking one with\n * nothing to say why.\n *\n * Named consequence, not effect: TwinCommand.effect is what the source reported back after dispatch\n * — an observation, and past — while this is a prediction, and future.\n */\nexport const REPEATABLE_ROLES = ['consequence', 'evidence'] as const\n\n/**\n * The door's part of a value key — the activity's name, kebab-cased.\n *\n * ── Why computed and not declared ─────────────────────────────────────────\n * A declared key is a key table, and a key table is what a computed key exists to avoid: nobody\n * writing a new door picks a key, so none of them can be picked wrong, and a test can count every\n * key that exists rather than every key somebody remembered to register.\n *\n * It is safe to hang this on `name` because `name` cannot move — it is the key the callback is\n * found by, and renaming it makes an approval finish with nothing happening. A key derived from a\n * fixed name is fixed.\n *\n * ── The boundary rule ─────────────────────────────────────────────────────\n * Activity names come in two shapes and this repository has both: 'MES Disposition Approval' and\n * 'BatchRelease'. Splitting only on spaces would leave `batchrelease` beside `mes-disposition-\n * approval`; splitting on every capital would turn 'MES' into `m-e-s`. So the split is between a\n * lowercase or digit and a capital, and between a run of capitals and a capitalised word — the same\n * rule `secretEnvName` uses, written after HOOKSECRET and HOOK_SECRET drifted apart.\n */\nexport function doorSlug(activityName: string): string {\n return String(activityName ?? '')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .replace(/[^A-Za-z0-9]+/g, '-')\n .toLowerCase()\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * The i18n key for one slot's **value sentence** — `approval.<door>.<inputPath>`.\n *\n * `inputPath` and not `role`: a door repeats `consequence`, so two slots in one door would collide\n * on role and the later sentence would silently take the earlier one's key. `inputPath` is the one\n * thing already unique within a door, and it is already written in the declaration.\n */\nexport function decisionValueKey(activityName: string, inputPath: string): string {\n return `approval.${doorSlug(activityName)}.${inputPath}`\n}\n\nexport function assertDecisionKeysAreUsable(\n decisionKeys: DecisionKeyDeclaration[] | undefined,\n activityName?: string\n): void {\n if (!decisionKeys?.length) {\n return\n }\n\n const named = activityName ? `activity \"${activityName}\"` : 'this activity'\n\n const unknown = decisionKeys.filter(key => !(DECISION_ROLES as readonly string[]).includes(String(key?.role ?? '')))\n\n if (unknown.length) {\n throw new Error(\n `${named} declares decision keys with a role the approval screen does not know: ` +\n `${unknown.map(key => `\"${key?.role ?? ''}\"`).join(', ')}. ` +\n `Known roles are ${DECISION_ROLES.join(', ')}. A role outside that set draws nothing.`\n )\n }\n\n const pathless = decisionKeys.filter(key => !String(key?.inputPath ?? '').trim())\n\n if (pathless.length) {\n throw new Error(\n `${named} declares ${pathless.length} decision key(s) with no inputPath. ` +\n `A decision key names the value it draws; without a path there is nothing to read.`\n )\n }\n\n /*\n * An index or a wildcard resolves to nothing at draw time and the slot would report \"the path led\n * nowhere\" — which reads as a payload that disagrees with the declaration, when the truth is that\n * the declaration used a path language that does not exist. Refusing here says which it was.\n */\n const notPaths = decisionKeys.filter(key => /[[\\]*]/.test(String(key?.inputPath ?? '')))\n\n if (notPaths.length) {\n throw new Error(\n `${named} declares decision keys whose inputPath is not a plain dotted path: ` +\n `${notPaths.map(key => `\"${key?.inputPath ?? ''}\"`).join(', ')}. ` +\n `Dots only — no array index and no wildcard. Point at the list itself; drawing its items is ` +\n `the slot's work.`\n )\n }\n\n const repeated = DECISION_ROLES.filter(\n role =>\n !(REPEATABLE_ROLES as readonly string[]).includes(role) &&\n decisionKeys.filter(key => key?.role === role).length > 1\n )\n\n if (repeated.length) {\n throw new Error(\n `${named} declares more than one \"${repeated.join('\", \"')}\" decision key. ` +\n `Only ${REPEATABLE_ROLES.map(role => `\"${role}\"`).join(' and ')} may repeat — an approval can ` +\n `change several things at once, and grounds come in several. The screen would draw one of the ` +\n `others and could not say which.`\n )\n }\n\n /*\n * A sentence may only be built from values that were snapshotted, so every params value is an\n * inputPath and reads by the same rules. Wanting a value with no field behind it means the field\n * is missing, not that params needs a second source — the two hold each other up: without the\n * value the sentence cannot be rebuilt, and a value a sentence uses is guaranteed to stay.\n *\n * Only the right side has a rule. The names on the left belong to the sentence and are the\n * locale file's business.\n */\n const badParams: string[] = []\n\n for (const key of decisionKeys) {\n for (const [name, path] of Object.entries(key?.params || {})) {\n const said = String(path ?? '')\n\n if (!said.trim()) {\n badParams.push(`\"${name}\" (empty)`)\n } else if (/[[\\]*]/.test(said)) {\n badParams.push(`\"${name}\": \"${said}\"`)\n }\n }\n }\n\n if (badParams.length) {\n throw new Error(\n `${named} declares sentence params that are not plain dotted paths into the input: ` +\n `${badParams.join(', ')}. Every params value is an inputPath — a sentence is built only from ` +\n `values the request froze, so a value with nowhere to read it from is a missing field.`\n )\n }\n\n if (!activityName) {\n return\n }\n\n /*\n * The key is computed, so a declared one that disagrees is a typo that would draw `approval.…` on\n * the card. Checking it here rather than trusting the writer is the whole reason it is computed.\n */\n const wrongKey = decisionKeys.filter(\n key => key?.valueTKey && key.valueTKey !== decisionValueKey(activityName, String(key?.inputPath ?? ''))\n )\n\n if (wrongKey.length) {\n throw new Error(\n `${named} declares value keys that are not the computed ones: ` +\n `${wrongKey\n .map(key => `\"${key?.valueTKey}\" (expected \"${decisionValueKey(activityName, String(key?.inputPath ?? ''))}\")`)\n .join(', ')}. ` +\n `The key is approval.<door>.<inputPath> and nobody picks it — a key nobody can pick is a key ` +\n `nobody can pick wrong.`\n )\n }\n}\n"]}
1
+ {"version":3,"file":"decision-key-declaration.js","sourceRoot":"","sources":["../../../server/service/activity/decision-key-declaration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Refuses a decisionKeys declaration that cannot draw, and computes the i18n keys an activity's\n * sentences are read from.\n *\n * ── This path is read from outside ────────────────────────────────────────\n * operato-plant's tests import this file by its built path,\n * `@things-factory/worklist/dist-server/service/activity/decision-key-declaration.js`, for\n * DECISION_ROLES, doorSlug and activityTKey. Moving or renaming it breaks those tests, so treat the\n * path as public.\n *\n * Refusing a declaration that cannot draw:\n *\n * Same reasoning as search keys: a declaration that does not work should fail where it arrives, not\n * where someone opens an approval. The difference is what \"not working\" means here — nothing is\n * dropped by a save, so the failure would be a screen that quietly draws less than it was told to.\n *\n * The shape is spelled out rather than imported. ActivityDecisionKeyItem carries type-graphql\n * decorators and the test runner strips types without reading them, so importing the declared class\n * pulls type-graphql in and the test file fails to load.\n */\ntype DecisionKeyDeclaration = {\n role?: string\n inputPath?: string\n valueTKey?: string\n params?: { [name: string]: string }\n}\n\n/** Roles a screen knows how to draw. Widening this is an architecture decision, not a lane's. */\nexport const DECISION_ROLES = [\n 'headline',\n 'subject',\n 'reversibility',\n 'reason',\n 'evidence',\n 'currentState',\n 'consequence'\n] as const\n\n/**\n * The roles that may appear more than once.\n *\n * An approval can change several things at once — plant's priority change pushes some orders back\n * and moves others ahead — and those are separate consequences, not one merged sentence. Grounds\n * come in several the same way: which inspection, against which spec, decided when.\n *\n * Every other role names a single value. Two headlines would leave the screen picking one with\n * nothing to say why.\n *\n * Named consequence, not effect: TwinCommand.effect is what the source reported back after dispatch\n * — an observation, and past — while this is a prediction, and future.\n */\nexport const REPEATABLE_ROLES = ['consequence', 'evidence'] as const\n\n/**\n * The door's part of a value key — the activity's name, kebab-cased.\n *\n * ── Why computed and not declared ─────────────────────────────────────────\n * A declared key is a key table, and a key table is what a computed key exists to avoid: nobody\n * writing a new door picks a key, so none of them can be picked wrong, and a test can count every\n * key that exists rather than every key somebody remembered to register.\n *\n * It is safe to hang this on `name` because `name` cannot move — it is the key the callback is\n * found by, and renaming it makes an approval finish with nothing happening. A key derived from a\n * fixed name is fixed.\n *\n * ── The boundary rule ─────────────────────────────────────────────────────\n * Activity names come in two shapes and this repository has both: 'MES Disposition Approval' and\n * 'BatchRelease'. Splitting only on spaces would leave `batchrelease` beside `mes-disposition-\n * approval`; splitting on every capital would turn 'MES' into `m-e-s`. So the split is between a\n * lowercase or digit and a capital, and between a run of capitals and a capitalised word — the same\n * rule `secretEnvName` uses, written after HOOKSECRET and HOOK_SECRET drifted apart.\n */\nexport function doorSlug(activityName: string): string {\n return String(activityName ?? '')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .replace(/[^A-Za-z0-9]+/g, '-')\n .toLowerCase()\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * The i18n key for one slot's **value sentence** — `approval.<door>.<inputPath>`.\n *\n * `inputPath` and not `role`: a door repeats `consequence`, so two slots in one door would collide\n * on role and the later sentence would silently take the earlier one's key. `inputPath` is the one\n * thing already unique within a door, and it is already written in the declaration.\n */\nexport function decisionValueKey(activityName: string, inputPath: string): string {\n return `approval.${doorSlug(activityName)}.${inputPath}`\n}\n\n/**\n * The i18n key for an activity's own sentences — `activity.<door>.label`, `activity.<door>.guide.<n>`.\n *\n * Computed from `name` for the reason decisionValueKey is: nobody picks the key, so none is picked\n * wrong, and an app's test can walk its declarations and count every key that must exist.\n *\n * The server sends the result (Activity.labelTKey, InstallableActivity.labelTKey and guideTKeys);\n * screens draw `t(labelTKey, { defaultValue: label })` and never rebuild the slug. A client file that\n * imported this one would move the whole client build under dist-client/client/.\n *\n * `description` has no key. It is the developers' English line and is not shown to the person\n * doing the work.\n *\n * Guide lines are keyed by position. Inserting a line shifts every later translation by one, and a\n * count of keys does not notice — change guide and its translations in the same edit.\n */\nexport function activityTKey(activityName: string, part: 'label'): string\nexport function activityTKey(activityName: string, part: 'guide', index: number): string\nexport function activityTKey(activityName: string, part: 'label' | 'guide', index?: number): string {\n const door = `activity.${doorSlug(activityName)}`\n return part === 'guide' ? `${door}.guide.${index}` : `${door}.label`\n}\n\n/**\n * One key per guide line, **always as many as there are lines.** The screen pairs the two arrays\n * by position; a shorter key list would send the last lines out untranslated with nothing to show it.\n */\nexport function activityGuideTKeys(activityName: string, guide: string[] | undefined | null): string[] {\n return (guide || []).map((_, index) => activityTKey(activityName, 'guide', index))\n}\n\nexport function assertDecisionKeysAreUsable(\n decisionKeys: DecisionKeyDeclaration[] | undefined,\n activityName?: string\n): void {\n if (!decisionKeys?.length) {\n return\n }\n\n const named = activityName ? `activity \"${activityName}\"` : 'this activity'\n\n const unknown = decisionKeys.filter(key => !(DECISION_ROLES as readonly string[]).includes(String(key?.role ?? '')))\n\n if (unknown.length) {\n throw new Error(\n `${named} declares decision keys with a role the approval screen does not know: ` +\n `${unknown.map(key => `\"${key?.role ?? ''}\"`).join(', ')}. ` +\n `Known roles are ${DECISION_ROLES.join(', ')}. A role outside that set draws nothing.`\n )\n }\n\n const pathless = decisionKeys.filter(key => !String(key?.inputPath ?? '').trim())\n\n if (pathless.length) {\n throw new Error(\n `${named} declares ${pathless.length} decision key(s) with no inputPath. ` +\n `A decision key names the value it draws; without a path there is nothing to read.`\n )\n }\n\n /*\n * An index or a wildcard resolves to nothing at draw time and the slot would report \"the path led\n * nowhere\" — which reads as a payload that disagrees with the declaration, when the truth is that\n * the declaration used a path language that does not exist. Refusing here says which it was.\n */\n const notPaths = decisionKeys.filter(key => /[[\\]*]/.test(String(key?.inputPath ?? '')))\n\n if (notPaths.length) {\n throw new Error(\n `${named} declares decision keys whose inputPath is not a plain dotted path: ` +\n `${notPaths.map(key => `\"${key?.inputPath ?? ''}\"`).join(', ')}. ` +\n `Dots only — no array index and no wildcard. Point at the list itself; drawing its items is ` +\n `the slot's work.`\n )\n }\n\n const repeated = DECISION_ROLES.filter(\n role =>\n !(REPEATABLE_ROLES as readonly string[]).includes(role) &&\n decisionKeys.filter(key => key?.role === role).length > 1\n )\n\n if (repeated.length) {\n throw new Error(\n `${named} declares more than one \"${repeated.join('\", \"')}\" decision key. ` +\n `Only ${REPEATABLE_ROLES.map(role => `\"${role}\"`).join(' and ')} may repeat — an approval can ` +\n `change several things at once, and grounds come in several. The screen would draw one of the ` +\n `others and could not say which.`\n )\n }\n\n /*\n * A sentence may only be built from values that were snapshotted, so every params value is an\n * inputPath and reads by the same rules. Wanting a value with no field behind it means the field\n * is missing, not that params needs a second source — the two hold each other up: without the\n * value the sentence cannot be rebuilt, and a value a sentence uses is guaranteed to stay.\n *\n * Only the right side has a rule. The names on the left belong to the sentence and are the\n * locale file's business.\n */\n const badParams: string[] = []\n\n for (const key of decisionKeys) {\n for (const [name, path] of Object.entries(key?.params || {})) {\n const said = String(path ?? '')\n\n if (!said.trim()) {\n badParams.push(`\"${name}\" (empty)`)\n } else if (/[[\\]*]/.test(said)) {\n badParams.push(`\"${name}\": \"${said}\"`)\n }\n }\n }\n\n if (badParams.length) {\n throw new Error(\n `${named} declares sentence params that are not plain dotted paths into the input: ` +\n `${badParams.join(', ')}. Every params value is an inputPath — a sentence is built only from ` +\n `values the request froze, so a value with nowhere to read it from is a missing field.`\n )\n }\n\n if (!activityName) {\n return\n }\n\n /*\n * The key is computed, so a declared one that disagrees is a typo that would draw `approval.…` on\n * the card. Checking it here rather than trusting the writer is the whole reason it is computed.\n */\n const wrongKey = decisionKeys.filter(\n key => key?.valueTKey && key.valueTKey !== decisionValueKey(activityName, String(key?.inputPath ?? ''))\n )\n\n if (wrongKey.length) {\n throw new Error(\n `${named} declares value keys that are not the computed ones: ` +\n `${wrongKey\n .map(key => `\"${key?.valueTKey}\" (expected \"${decisionValueKey(activityName, String(key?.inputPath ?? ''))}\")`)\n .join(', ')}. ` +\n `The key is approval.<door>.<inputPath> and nobody picks it — a key nobody can pick is a key ` +\n `nobody can pick wrong.`\n )\n }\n}\n"]}
@@ -5,5 +5,5 @@ import { ActivityQuery } from "./activity-query.js";
5
5
  import { ActivityHistoryEntitySubscriber } from "./event-subscriber.js";
6
6
  import { ActivityDeclarationGuardSubscriber } from "./declaration-guard-subscriber.js";
7
7
  export declare const entities: (typeof Activity | typeof ActivityHistory)[];
8
- export declare const resolvers: (typeof ActivityQuery | typeof ActivityMutation)[];
8
+ export declare const resolvers: (typeof ActivityMutation | typeof ActivityQuery)[];
9
9
  export declare const subscribers: (typeof ActivityHistoryEntitySubscriber | typeof ActivityDeclarationGuardSubscriber)[];
@@ -6,5 +6,5 @@ import { ActivityInstanceHistoryQuery } from "./activity-instance-history-query.
6
6
  import { ActivityInstanceSubscription } from "./activity-instance-subscription.js";
7
7
  import { ActivityInstanceHistoryEntitySubscriber, ActivityInstanceSubscriber } from "./event-subscriber.js";
8
8
  export declare const entities: (typeof ActivityInstance | typeof ActivityInstanceHistory)[];
9
- export declare const resolvers: (typeof ActivityInstanceQuery | typeof ActivityInstanceMutation | typeof ActivityInstanceSubscription | typeof ActivityInstanceHistoryQuery)[];
9
+ export declare const resolvers: (typeof ActivityInstanceMutation | typeof ActivityInstanceQuery | typeof ActivityInstanceHistoryQuery | typeof ActivityInstanceSubscription)[];
10
10
  export declare const subscribers: (typeof ActivityInstanceSubscriber | typeof ActivityInstanceHistoryEntitySubscriber)[];
@@ -4,5 +4,5 @@ import { ActivityTemplateMutation } from "./activity-template-mutation.js";
4
4
  import { ActivityTemplateQuery } from "./activity-template-query.js";
5
5
  import { ActivityTemplateHistoryEntitySubscriber } from "./event-subscriber.js";
6
6
  export declare const entities: (typeof ActivityTemplate | typeof ActivityTemplateHistory)[];
7
- export declare const resolvers: (typeof ActivityTemplateQuery | typeof ActivityTemplateMutation)[];
7
+ export declare const resolvers: (typeof ActivityTemplateMutation | typeof ActivityTemplateQuery)[];
8
8
  export declare const subscribers: (typeof ActivityTemplateHistoryEntitySubscriber)[];
@@ -6,5 +6,5 @@ import { ActivityThreadHistoryQuery } from "./activity-thread-history-query.js";
6
6
  import { ActivityThreadSubscription } from "./activity-thread-subscription.js";
7
7
  import { ActivityThreadHistoryEntitySubscriber, ActivityThreadSubscriber } from "./event-subscriber.js";
8
8
  export declare const entities: (typeof ActivityThread | typeof ActivityThreadHistory)[];
9
- export declare const resolvers: (typeof ActivityThreadQuery | typeof ActivityThreadHistoryQuery | typeof ActivityThreadMutation | typeof ActivityThreadSubscription)[];
9
+ export declare const resolvers: (typeof ActivityThreadMutation | typeof ActivityThreadQuery | typeof ActivityThreadHistoryQuery | typeof ActivityThreadSubscription)[];
10
10
  export declare const subscribers: (typeof ActivityThreadSubscriber | typeof ActivityThreadHistoryEntitySubscriber)[];
@@ -5,8 +5,8 @@ export * from './activity-instance/activity-instance.js';
5
5
  export * from './activity/activity.js';
6
6
  export * from './installable-activity/installable-activity.js';
7
7
  export * from './activity-summary/activity-summary.js';
8
- export declare const entities: (typeof import("./activity-summary/activity-summary.js").ActivitySummary | typeof import("./activity-approval/activity-approval.js").ActivityApproval | typeof import("./activity/activity.js").Activity | typeof import("./activity/activity-history.js").ActivityHistory | typeof import("./activity-instance/activity-instance.js").ActivityInstance | typeof import("./activity-instance/activity-instance-history.js").ActivityInstanceHistory | typeof import("./activity-template/activity-template.js").ActivityTemplate | typeof import("./activity-template/activity-template-history.js").ActivityTemplateHistory | typeof import("./activity-thread/activity-thread.js").ActivityThread | typeof import("./activity-thread/activity-thread-history.js").ActivityThreadHistory | typeof import("./installable-activity/installable-activity.js").InstallableActivity)[];
9
- export declare const subscribers: (typeof import("./activity-approval/event-subscriber.js").ActivityApprovalSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceHistoryEntitySubscriber | typeof import("./activity/event-subscriber.js").ActivityHistoryEntitySubscriber | typeof import("./activity/declaration-guard-subscriber.js").ActivityDeclarationGuardSubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadSubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadHistoryEntitySubscriber)[];
8
+ export declare const entities: (typeof import("./activity/activity.js").Activity | typeof import("./activity-approval/activity-approval.js").ActivityApproval | typeof import("./activity-thread/activity-thread.js").ActivityThread | typeof import("./activity-instance/activity-instance.js").ActivityInstance | typeof import("./installable-activity/installable-activity.js").InstallableActivity | typeof import("./activity-template/activity-template.js").ActivityTemplate | typeof import("./activity-summary/activity-summary.js").ActivitySummary | typeof import("./activity/activity-history.js").ActivityHistory | typeof import("./activity-instance/activity-instance-history.js").ActivityInstanceHistory | typeof import("./activity-template/activity-template-history.js").ActivityTemplateHistory | typeof import("./activity-thread/activity-thread-history.js").ActivityThreadHistory)[];
9
+ export declare const subscribers: (typeof import("./activity-approval/event-subscriber.js").ActivityApprovalSubscriber | typeof import("./activity/event-subscriber.js").ActivityHistoryEntitySubscriber | typeof import("./activity/declaration-guard-subscriber.js").ActivityDeclarationGuardSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceHistoryEntitySubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadSubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadHistoryEntitySubscriber)[];
10
10
  export declare const schema: {
11
- resolverClasses: (typeof import("./activity-summary/activity-summary-query.js").ActivitySummaryQuery | typeof import("./activity-stats/activity-stats-query.js").ActivityStatsQuery | typeof import("./activity-approval/activity-approval-query.js").ActivityApprovalQuery | typeof import("./activity-approval/activity-approval-mutation.js").ActivityApprovalMutation | typeof import("./activity-approval/activity-approval-subscription.js").ActivityApprovalSubscription | typeof import("./activity/activity-query.js").ActivityQuery | typeof import("./activity/activity-mutation.js").ActivityMutation | typeof import("./activity-instance/activity-instance-query.js").ActivityInstanceQuery | typeof import("./activity-instance/activity-instance-mutation.js").ActivityInstanceMutation | typeof import("./activity-instance/activity-instance-subscription.js").ActivityInstanceSubscription | typeof import("./activity-instance/activity-instance-history-query.js").ActivityInstanceHistoryQuery | typeof import("./activity-template/activity-template-query.js").ActivityTemplateQuery | typeof import("./activity-template/activity-template-mutation.js").ActivityTemplateMutation | typeof import("./activity-thread/activity-thread-query.js").ActivityThreadQuery | typeof import("./activity-thread/activity-thread-history-query.js").ActivityThreadHistoryQuery | typeof import("./activity-thread/activity-thread-mutation.js").ActivityThreadMutation | typeof import("./activity-thread/activity-thread-subscription.js").ActivityThreadSubscription | typeof import("./installable-activity/installable-activity-query.js").InstallableActivityQuery | typeof import("./installable-activity/installable-activity-mutation.js").InstallableActivityMutation)[];
11
+ resolverClasses: (typeof import("./activity-stats/activity-stats-query.js").ActivityStatsQuery | typeof import("./activity-approval/activity-approval-query.js").ActivityApprovalQuery | typeof import("./activity-approval/activity-approval-mutation.js").ActivityApprovalMutation | typeof import("./activity-approval/activity-approval-subscription.js").ActivityApprovalSubscription | typeof import("./activity/activity-mutation.js").ActivityMutation | typeof import("./activity/activity-query.js").ActivityQuery | typeof import("./activity-instance/activity-instance-mutation.js").ActivityInstanceMutation | typeof import("./activity-instance/activity-instance-query.js").ActivityInstanceQuery | typeof import("./activity-instance/activity-instance-history-query.js").ActivityInstanceHistoryQuery | typeof import("./activity-instance/activity-instance-subscription.js").ActivityInstanceSubscription | typeof import("./activity-template/activity-template-mutation.js").ActivityTemplateMutation | typeof import("./activity-template/activity-template-query.js").ActivityTemplateQuery | typeof import("./activity-thread/activity-thread-mutation.js").ActivityThreadMutation | typeof import("./activity-thread/activity-thread-query.js").ActivityThreadQuery | typeof import("./activity-thread/activity-thread-history-query.js").ActivityThreadHistoryQuery | typeof import("./activity-thread/activity-thread-subscription.js").ActivityThreadSubscription | typeof import("./installable-activity/installable-activity-query.js").InstallableActivityQuery | typeof import("./installable-activity/installable-activity-mutation.js").InstallableActivityMutation | typeof import("./activity-summary/activity-summary-query.js").ActivitySummaryQuery)[];
12
12
  };
@@ -4,4 +4,8 @@ import { InstallableActivityList } from './installable-activity-type.js';
4
4
  export declare class InstallableActivityQuery {
5
5
  installableActivity(name: string, context: ResolverContext): Promise<InstallableActivity>;
6
6
  installableActivities(params: ListParam, context: ResolverContext): Promise<InstallableActivityList>;
7
+ /** The key `label` is translated from. Computed from `name`, never stored — see activityTKey. */
8
+ labelTKey(one: InstallableActivity): string;
9
+ /** One key per `guide` line, in the same order and always the same length. */
10
+ guideTKeys(one: InstallableActivity): string[];
7
11
  }
@@ -9,6 +9,7 @@ const activity_js_1 = require("../activity/activity.js");
9
9
  const installable_activity_js_1 = require("./installable-activity.js");
10
10
  const approval_line_js_1 = require("../../controllers/activity-approval/approval-line.js");
11
11
  const installable_activity_type_js_1 = require("./installable-activity-type.js");
12
+ const decision_key_declaration_js_1 = require("../activity/decision-key-declaration.js");
12
13
  let InstallableActivityQuery = class InstallableActivityQuery {
13
14
  async installableActivity(name, context) {
14
15
  return await activity_installation_controller_js_1.ActivityInstallations.get(name);
@@ -49,6 +50,14 @@ let InstallableActivityQuery = class InstallableActivityQuery {
49
50
  const merged = [...items, ...intended];
50
51
  return { items: merged, total: merged.length };
51
52
  }
53
+ /** The key `label` is translated from. Computed from `name`, never stored — see activityTKey. */
54
+ labelTKey(one) {
55
+ return (0, decision_key_declaration_js_1.activityTKey)(one.name, 'label');
56
+ }
57
+ /** One key per `guide` line, in the same order and always the same length. */
58
+ guideTKeys(one) {
59
+ return (0, decision_key_declaration_js_1.activityGuideTKeys)(one.name, one.guide);
60
+ }
52
61
  };
53
62
  exports.InstallableActivityQuery = InstallableActivityQuery;
54
63
  tslib_1.__decorate([
@@ -67,6 +76,20 @@ tslib_1.__decorate([
67
76
  tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
68
77
  tslib_1.__metadata("design:returntype", Promise)
69
78
  ], InstallableActivityQuery.prototype, "installableActivities", null);
79
+ tslib_1.__decorate([
80
+ (0, type_graphql_1.FieldResolver)(type => String, { description: 'i18n key the label is translated from, computed from name' }),
81
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
82
+ tslib_1.__metadata("design:type", Function),
83
+ tslib_1.__metadata("design:paramtypes", [installable_activity_js_1.InstallableActivity]),
84
+ tslib_1.__metadata("design:returntype", String)
85
+ ], InstallableActivityQuery.prototype, "labelTKey", null);
86
+ tslib_1.__decorate([
87
+ (0, type_graphql_1.FieldResolver)(type => [String], { description: 'One i18n key per guide line, in order, computed from name' }),
88
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
89
+ tslib_1.__metadata("design:type", Function),
90
+ tslib_1.__metadata("design:paramtypes", [installable_activity_js_1.InstallableActivity]),
91
+ tslib_1.__metadata("design:returntype", Array)
92
+ ], InstallableActivityQuery.prototype, "guideTKeys", null);
70
93
  exports.InstallableActivityQuery = InstallableActivityQuery = tslib_1.__decorate([
71
94
  (0, type_graphql_1.Resolver)(installable_activity_js_1.InstallableActivity)
72
95
  ], InstallableActivityQuery);
@@ -1 +1 @@
1
- {"version":3,"file":"installable-activity-query.js","sourceRoot":"","sources":["../../../server/service/installable-activity/installable-activity-query.ts"],"names":[],"mappings":";;;;AAAA,+CAAmF;AACnF,iDAAwE;AAExE,qIAAmH;AACnH,yDAAkD;AAClD,uEAA+D;AAC/D,2FAAqF;AACrF,iFAAwE;AAGjE,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAE7B,AAAN,KAAK,CAAC,mBAAmB,CAAc,IAAY,EAAS,OAAwB;QAClF,OAAO,MAAM,2DAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC9C,CAAC;IAGK,AAAN,KAAK,CAAC,qBAAqB,CACA,MAAiB,EACnC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,KAAK,GAAG,2DAAqB,CAAC,IAAI,EAAE,CAAA;QAE1C,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,sBAAQ,CAAC,CAAC,SAAS,CAAC;gBACtD,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBACzB,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAA;YAEF;;;;;eAKG;YACH,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,iCAAc,CAAC,CAAC,MAAM,CAAA;QACxF,CAAC;QAED;;;;;;;;WAQG;QACH,MAAM,QAAQ,GAA0B,2DAAqB,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvF,IAAI,EAAE,GAAG,CAAC,GAAG;YACb,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC,CAAA;QAEH,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAA;QAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;IAChD,CAAC;CACF,CAAA;AApDY,4DAAwB;AAE7B;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,6CAAoB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;IAC/E,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;mEAE1D;AAGK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,sDAAuB,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;IAElG,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;qEA2C3C;mCAnDU,wBAAwB;IADpC,IAAA,uBAAQ,EAAC,6CAAmB,CAAC;GACjB,wBAAwB,CAoDpC","sourcesContent":["import { Arg, Args, Ctx, Query, Resolver, FieldResolver, Root } from 'type-graphql'\nimport { Domain, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ActivityInstallations } from '../../controllers/activity-installation/activity-installation-controller.js'\nimport { Activity } from '../activity/activity.js'\nimport { InstallableActivity } from './installable-activity.js'\nimport { isApprovalStep } from '../../controllers/activity-approval/approval-line.js'\nimport { InstallableActivityList } from './installable-activity-type.js'\n\n@Resolver(InstallableActivity)\nexport class InstallableActivityQuery {\n @Query(returns => InstallableActivity!, { nullable: true, description: 'To fetch a InstallableActivity' })\n async installableActivity(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<InstallableActivity> {\n return await ActivityInstallations.get(name)\n }\n\n @Query(returns => InstallableActivityList, { description: 'To fetch multiple InstallableActivitys' })\n async installableActivities(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<InstallableActivityList> {\n const { domain } = context.state\n\n const items = ActivityInstallations.list()\n\n for (var item of items) {\n item.activity = await getRepository(Activity).findOneBy({\n domain: { id: domain.id },\n name: item.name\n })\n\n /*\n * 「이 도메인이 이 단계를 쓰나」를 값으로 낸다 — 판단은 여기서 다시 짜지 않는다.\n *\n * `isApprovalStep` 이 참조를 걸러 내는 그 자리다. 화면이 길이를 세면 참조만 있는 결재선을\n * 「결재자 있음」으로 그리고, 실제로는 그냥 지나간다.\n */\n item.approvalSteps = (item.activity?.approvalLine || []).filter(isApprovalStep).length\n }\n\n /*\n * Identified-but-unbuilt work comes out of this query too, because the catalog is the plan of\n * record — \"what is left\" has to be answerable on the screen.\n *\n * Shaped to look like an installable activity so the screen has one list to draw, but it\n * carries no `activity` (nothing is installed) and no callback. Its stage says planned or\n * not-worklist, and the screen keeps those apart from the built ones: a decision must not read\n * as a promise.\n */\n const intended: InstallableActivity[] = ActivityInstallations.listIntended().map(one => ({\n name: one.key,\n label: one.label,\n description: undefined,\n guide: one.guide,\n category: one.category,\n readiness: one.readiness\n }))\n\n const merged = [...items, ...intended]\n\n return { items: merged, total: merged.length }\n }\n}\n"]}
1
+ {"version":3,"file":"installable-activity-query.js","sourceRoot":"","sources":["../../../server/service/installable-activity/installable-activity-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Query, Resolver, FieldResolver, Root } from 'type-graphql'\nimport { Domain, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ActivityInstallations } from '../../controllers/activity-installation/activity-installation-controller.js'\nimport { Activity } from '../activity/activity.js'\nimport { InstallableActivity } from './installable-activity.js'\nimport { isApprovalStep } from '../../controllers/activity-approval/approval-line.js'\nimport { InstallableActivityList } from './installable-activity-type.js'\nimport { activityGuideTKeys, activityTKey } from '../activity/decision-key-declaration.js'\n\n@Resolver(InstallableActivity)\nexport class InstallableActivityQuery {\n @Query(returns => InstallableActivity!, { nullable: true, description: 'To fetch a InstallableActivity' })\n async installableActivity(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<InstallableActivity> {\n return await ActivityInstallations.get(name)\n }\n\n @Query(returns => InstallableActivityList, { description: 'To fetch multiple InstallableActivitys' })\n async installableActivities(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<InstallableActivityList> {\n const { domain } = context.state\n\n const items = ActivityInstallations.list()\n\n for (var item of items) {\n item.activity = await getRepository(Activity).findOneBy({\n domain: { id: domain.id },\n name: item.name\n })\n\n /*\n * 「이 도메인이 이 단계를 쓰나」를 값으로 낸다 — 판단은 여기서 다시 짜지 않는다.\n *\n * `isApprovalStep` 이 참조를 걸러 내는 그 자리다. 화면이 길이를 세면 참조만 있는 결재선을\n * 「결재자 있음」으로 그리고, 실제로는 그냥 지나간다.\n */\n item.approvalSteps = (item.activity?.approvalLine || []).filter(isApprovalStep).length\n }\n\n /*\n * Identified-but-unbuilt work comes out of this query too, because the catalog is the plan of\n * record — \"what is left\" has to be answerable on the screen.\n *\n * Shaped to look like an installable activity so the screen has one list to draw, but it\n * carries no `activity` (nothing is installed) and no callback. Its stage says planned or\n * not-worklist, and the screen keeps those apart from the built ones: a decision must not read\n * as a promise.\n */\n const intended: InstallableActivity[] = ActivityInstallations.listIntended().map(one => ({\n name: one.key,\n label: one.label,\n description: undefined,\n guide: one.guide,\n category: one.category,\n readiness: one.readiness\n }))\n\n const merged = [...items, ...intended]\n\n return { items: merged, total: merged.length }\n }\n\n /** The key `label` is translated from. Computed from `name`, never stored — see activityTKey. */\n @FieldResolver(type => String, { description: 'i18n key the label is translated from, computed from name' })\n labelTKey(@Root() one: InstallableActivity): string {\n return activityTKey(one.name, 'label')\n }\n\n /** One key per `guide` line, in the same order and always the same length. */\n @FieldResolver(type => [String], { description: 'One i18n key per guide line, in order, computed from name' })\n guideTKeys(@Root() one: InstallableActivity): string[] {\n return activityGuideTKeys(one.name, one.guide)\n }\n}\n"]}