@things-factory/figure-service 10.1.74 → 10.1.76

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 (185) hide show
  1. package/README.md +1 -1
  2. package/dist-server/service/figure/figure-format.d.ts +6 -6
  3. package/dist-server/service/figure/figure-format.js +32 -32
  4. package/dist-server/service/figure/figure-format.js.map +1 -1
  5. package/dist-server/service/figure/figure-history.js +1 -1
  6. package/dist-server/service/figure/figure-history.js.map +1 -1
  7. package/dist-server/service/figure/figure-mutation.d.ts +1 -1
  8. package/dist-server/service/figure/figure-mutation.js +12 -12
  9. package/dist-server/service/figure/figure-mutation.js.map +1 -1
  10. package/dist-server/service/figure/{figure-propose-v3.d.ts → figure-propose-steps.d.ts} +16 -16
  11. package/dist-server/service/figure/{figure-propose-v3.js → figure-propose-steps.js} +27 -27
  12. package/dist-server/service/figure/figure-propose-steps.js.map +1 -0
  13. package/dist-server/service/figure/figure-propose-type.js +3 -3
  14. package/dist-server/service/figure/figure-propose-type.js.map +1 -1
  15. package/dist-server/service/figure/figure-query.d.ts +2 -2
  16. package/dist-server/service/figure/figure-query.js +5 -5
  17. package/dist-server/service/figure/figure-query.js.map +1 -1
  18. package/dist-server/service/figure/figure-tools.js +14 -14
  19. package/dist-server/service/figure/figure-tools.js.map +1 -1
  20. package/dist-server/service/figure/figure-type.js +2 -2
  21. package/dist-server/service/figure/figure-type.js.map +1 -1
  22. package/dist-server/service/figure/{figure-v3-write.d.ts → figure-write.d.ts} +3 -3
  23. package/dist-server/service/figure/{figure-v3-write.js → figure-write.js} +10 -10
  24. package/dist-server/service/figure/figure-write.js.map +1 -0
  25. package/dist-server/service/figure/figure.d.ts +2 -2
  26. package/dist-server/service/figure/figure.js +2 -2
  27. package/dist-server/service/figure/figure.js.map +1 -1
  28. package/dist-server/service/figure-recipe/figure-recipe-templates.d.ts +2 -2
  29. package/dist-server/service/figure-recipe/figure-recipe-templates.js +1 -1
  30. package/dist-server/service/figure-recipe/figure-recipe-templates.js.map +1 -1
  31. package/dist-server/service/figure-recipe/figure-recipe-type.js +1 -1
  32. package/dist-server/service/figure-recipe/figure-recipe-type.js.map +1 -1
  33. package/dist-server/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +3 -3
  35. package/recipes/_lib/model.mts +19 -19
  36. package/recipes/air-cylinder/models/default.json +1 -1
  37. package/recipes/air-shower/models/default.json +1 -1
  38. package/recipes/barrier-gate/models/default.json +1 -1
  39. package/recipes/base-frame/models/default.json +1 -1
  40. package/recipes/belt-surface/models/default.json +1 -1
  41. package/recipes/bin-row/models/default.json +1 -1
  42. package/recipes/bollard-row/models/default.json +1 -1
  43. package/recipes/buzzer/models/default.json +1 -1
  44. package/recipes/cabinet-doors/models/default.json +1 -1
  45. package/recipes/cabinet-doors/models/doors=1.json +1 -1
  46. package/recipes/cabinet-doors/models/doors=2.json +1 -1
  47. package/recipes/cable-tray/models/default.json +1 -1
  48. package/recipes/camera-mount/models/default.json +1 -1
  49. package/recipes/canopy/models/default.json +1 -1
  50. package/recipes/cart/models/default.json +1 -1
  51. package/recipes/cart-handle/models/default.json +1 -1
  52. package/recipes/casters-four/models/default.json +1 -1
  53. package/recipes/ceiling-rail-carriage/models/default.json +1 -1
  54. package/recipes/chain-rails/models/default.json +1 -1
  55. package/recipes/charging-station/models/default.json +1 -1
  56. package/recipes/column-row/models/default.json +1 -1
  57. package/recipes/control-cabinet/models/default.json +1 -1
  58. package/recipes/conveyor-skirts/models/default.json +1 -1
  59. package/recipes/counter-display/models/default.json +1 -1
  60. package/recipes/dock-bumpers/models/default.json +1 -1
  61. package/recipes/dock-leveler/models/default.json +1 -1
  62. package/recipes/double-hinged-door/models/default.json +1 -1
  63. package/recipes/drawer-stack/models/default.json +1 -1
  64. package/recipes/drawer-stack/models/drawers=2.json +1 -1
  65. package/recipes/drawer-stack/models/drawers=3.json +1 -1
  66. package/recipes/drawer-stack/models/drawers=4.json +1 -1
  67. package/recipes/drip-tray/models/default.json +1 -1
  68. package/recipes/duct-fan/models/default.json +1 -1
  69. package/recipes/emergency-stop/models/default.json +1 -1
  70. package/recipes/end-covers/models/default.json +1 -1
  71. package/recipes/ffu-row/models/default.json +1 -1
  72. package/recipes/fire-extinguisher/models/default.json +1 -1
  73. package/recipes/first-aid-box/models/default.json +1 -1
  74. package/recipes/floor-zone/models/default.json +1 -1
  75. package/recipes/folding-door/models/default.json +1 -1
  76. package/recipes/fork/models/default.json +1 -1
  77. package/recipes/gantry-frame/models/default.json +1 -1
  78. package/recipes/gripper-2f/models/default.json +1 -1
  79. package/recipes/guard-cover/models/default.json +1 -1
  80. package/recipes/handrail/models/default.json +1 -1
  81. package/recipes/hatch/models/default.json +1 -1
  82. package/recipes/hinged-door/models/default.json +1 -1
  83. package/recipes/hinged-door/models/hinge=left.json +1 -1
  84. package/recipes/hinged-door/models/hinge=right.json +1 -1
  85. package/recipes/hmi-monitor/models/default.json +1 -1
  86. package/recipes/hopper/models/default.json +1 -1
  87. package/recipes/interlock-switch/models/default.json +1 -1
  88. package/recipes/junction-box/models/default.json +1 -1
  89. package/recipes/ladder/models/default.json +1 -1
  90. package/recipes/legs-four/models/default.json +1 -1
  91. package/recipes/leveling-feet/models/default.json +1 -1
  92. package/recipes/lift-updown/models/default.json +1 -1
  93. package/recipes/light-curtain/models/default.json +1 -1
  94. package/recipes/limit-switch/models/default.json +1 -1
  95. package/recipes/linear-guide/models/default.json +1 -1
  96. package/recipes/locker-row/models/default.json +1 -1
  97. package/recipes/motor-box/models/default.json +1 -1
  98. package/recipes/observation-window/models/default.json +1 -1
  99. package/recipes/operator-panel/models/buttons=2.json +1 -1
  100. package/recipes/operator-panel/models/buttons=3.json +1 -1
  101. package/recipes/operator-panel/models/buttons=4.json +1 -1
  102. package/recipes/operator-panel/models/buttons=5.json +1 -1
  103. package/recipes/operator-panel/models/default.json +1 -1
  104. package/recipes/pallet/models/default.json +1 -1
  105. package/recipes/partition-wall/models/default.json +1 -1
  106. package/recipes/pass-box/models/default.json +1 -1
  107. package/recipes/peg-board/models/default.json +1 -1
  108. package/recipes/photo-sensor-pair/models/default.json +1 -1
  109. package/recipes/pipe-run/models/default.json +1 -1
  110. package/recipes/platform/models/default.json +1 -1
  111. package/recipes/power-box/models/default.json +1 -1
  112. package/recipes/pressure-gauge/models/default.json +1 -1
  113. package/recipes/pull-cord/models/default.json +1 -1
  114. package/recipes/pump/models/default.json +1 -1
  115. package/recipes/pusher/models/default.json +1 -1
  116. package/recipes/robot-plinth/models/default.json +1 -1
  117. package/recipes/roll-up-shutter/models/default.json +1 -1
  118. package/recipes/roller-row/models/default.json +1 -1
  119. package/recipes/room-shell/models/default.json +1 -1
  120. package/recipes/rotating-beacon/models/default.json +1 -1
  121. package/recipes/safety-fence/models/default.json +1 -1
  122. package/recipes/safety-mat/models/default.json +1 -1
  123. package/recipes/safety-sign-stand/models/default.json +1 -1
  124. package/recipes/scanner-mount/models/default.json +1 -1
  125. package/recipes/selector-switch/models/default.json +1 -1
  126. package/recipes/shelf-tiers/models/default.json +1 -1
  127. package/recipes/shelf-tiers/models/tiers=2.json +1 -1
  128. package/recipes/shelf-tiers/models/tiers=3.json +1 -1
  129. package/recipes/shelf-tiers/models/tiers=4.json +1 -1
  130. package/recipes/shelf-tiers/models/tiers=5.json +1 -1
  131. package/recipes/side-guides/models/default.json +1 -1
  132. package/recipes/sign-board/models/default.json +1 -1
  133. package/recipes/signal-tower-3/models/default.json +1 -1
  134. package/recipes/sliding-door/models/default.json +1 -1
  135. package/recipes/sliding-door/models/leaves=1,lamp=false.json +1 -1
  136. package/recipes/sliding-door/models/leaves=1,lamp=true.json +1 -1
  137. package/recipes/sliding-door/models/leaves=2,lamp=false.json +1 -1
  138. package/recipes/sliding-door/models/leaves=2,lamp=true.json +1 -1
  139. package/recipes/stairs/models/default.json +1 -1
  140. package/recipes/status-lamp/models/default.json +1 -1
  141. package/recipes/stopper/models/default.json +1 -1
  142. package/recipes/suction-pads/models/default.json +1 -1
  143. package/recipes/tank/models/default.json +1 -1
  144. package/recipes/telescopic-arm/models/default.json +1 -1
  145. package/recipes/toe-board/models/default.json +1 -1
  146. package/recipes/tote/models/default.json +1 -1
  147. package/recipes/traffic-cones/models/default.json +1 -1
  148. package/recipes/transfer-belts/models/default.json +1 -1
  149. package/recipes/tray-stack/models/default.json +1 -1
  150. package/recipes/tray-stack/models/trays=3.json +1 -1
  151. package/recipes/tray-stack/models/trays=4.json +1 -1
  152. package/recipes/tray-stack/models/trays=5.json +1 -1
  153. package/recipes/trough/models/default.json +1 -1
  154. package/recipes/turntable/models/default.json +1 -1
  155. package/recipes/valve-handle/models/default.json +1 -1
  156. package/recipes/waste-bin/models/default.json +1 -1
  157. package/recipes/work-light/models/default.json +1 -1
  158. package/recipes/workbench-top/models/default.json +1 -1
  159. package/scripts/build-templates.mts +7 -7
  160. package/scripts/templates.test.mts +16 -16
  161. package/server/service/figure/figure-blueprint-query.test.ts +3 -3
  162. package/server/service/figure/figure-format.test.ts +57 -57
  163. package/server/service/figure/figure-format.ts +39 -39
  164. package/server/service/figure/figure-history.ts +1 -1
  165. package/server/service/figure/figure-inspect-db.test.ts +14 -14
  166. package/server/service/figure/figure-llm-smoke.test.ts +7 -7
  167. package/server/service/figure/figure-mutation.ts +12 -12
  168. package/server/service/figure/{figure-propose-v3.test.ts → figure-propose-steps.test.ts} +18 -18
  169. package/server/service/figure/{figure-propose-v3.ts → figure-propose-steps.ts} +33 -33
  170. package/server/service/figure/figure-propose-type.ts +3 -3
  171. package/server/service/figure/figure-query.ts +5 -5
  172. package/server/service/figure/figure-rename-db.test.ts +5 -5
  173. package/server/service/figure/figure-rename.test.ts +7 -7
  174. package/server/service/figure/figure-tools.test.ts +22 -22
  175. package/server/service/figure/figure-tools.ts +14 -14
  176. package/server/service/figure/figure-type.ts +2 -2
  177. package/server/service/figure/{figure-v3-write.ts → figure-write.ts} +10 -10
  178. package/server/service/figure/figure.ts +3 -3
  179. package/server/service/figure-recipe/figure-recipe-templates.test.ts +2 -2
  180. package/server/service/figure-recipe/figure-recipe-templates.ts +4 -4
  181. package/server/service/figure-recipe/figure-recipe-type.ts +1 -1
  182. package/translations/en.json +2 -3
  183. package/translations/ko.json +2 -3
  184. package/dist-server/service/figure/figure-propose-v3.js.map +0 -1
  185. package/dist-server/service/figure/figure-v3-write.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"figure.js","sourceRoot":"","sources":["../../../server/service/figure/figure.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, longTextColumn } from '@things-factory/shell'\n\n/**\n * Figure — 저작된 3D 컴포넌트 한 종류.\n *\n * `Board` 를 준용한다. 다른 점만 주석으로 적는다.\n *\n * ## 무엇을 담나 — 도형 자산이다, 씬 모델이 아니다\n *\n * 형식은 `@hatiolab/figure-model` 이 정한다(`figure-v3-asset-1`). 씬 컴포넌트 트리를 담지 않는다.\n * 컴파일한 것도 저장하지 않는다 — 원본에서 파생되므로 소비하는 쪽이 커널로 컴파일한다. 저장하면 원본과 갈린다.\n *\n * 그래서 부품·움직임·자리 같은 것을 컬럼으로 두지 않는다 — 전부 `source` 안에 이미 있다. 두 벌이면 갈린다.\n *\n * 설계: `docs/design/figure-modules.md` §2\n */\n@Entity()\n@Index('ix_figure_1', (figure: Figure) => [figure.domain, figure.type], {\n unique: true,\n where: '\"deleted_at\" IS NULL'\n})\n@Index('ix_figure_2', (figure: Figure) => [figure.domain, figure.category])\n@ObjectType({ description: 'An authored 3D component type — its figure asset plus its metadata.' })\nexport class Figure {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true, description: 'Unique identifier for the figure.' })\n readonly id?: string\n\n /**\n * 발행된 판의 번호 — **발행할 때만 올라간다.**\n *\n * 저장 횟수가 아니다. 저작 중에는 몇 번을 고쳐 저장하든 그대로이고, `draft` 가 `released` 가\n * 되는 순간에만 하나 오른다. 소비처가 「몇 번째 판을 쓰고 있나」를 이 값으로 말한다.\n *\n * 한 번도 발행되지 않았으면 **0** 이다. 1 로 시작하면 아직 아무에게도 약속하지 않은 초안이\n * 첫 판인 것처럼 보인다.\n */\n @Column({ nullable: true, default: 0 })\n @Field(type => Int, {\n nullable: true,\n description: 'Published version. Raised when the figure is released, not when it is saved. 0 means never released.'\n })\n version?: number = 0\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain this figure belongs to.' })\n domain?: Domain\n\n @RelationId((figure: Figure) => figure.domain)\n domainId?: string\n\n /**\n * 컴포넌트 타입 이름. **저장되는 식별자다.**\n *\n * 배치된 도면이 이 이름으로 타입을 찾는다. 바꾸면 그 도면은 타입을 못 찾아\n * **오류 없이 빈 화면**이 된다. 그래서 만들 때 정하고 잠근다 — 고칠 수 있는 것은\n * 표시 이름(`name`)뿐이다. 수정 리졸버가 이 필드를 받지 않는다.\n *\n * `Board.type`(main/sub/popup)과 뜻이 전혀 다르다. 혼동하지 않는다.\n */\n @Column()\n @Field({ description: 'Component type name. A stored identifier — unique per domain and immutable once created.' })\n type?: string\n\n @Column()\n @Field({ description: 'Display name shown to authors. Safe to rename.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A detailed description for the figure.' })\n description?: string\n\n /**\n * 분류 하나. **팔레트에서 묶어 보이는 기준이다.**\n *\n * 도형 하나에 하나뿐이다 — 팔레트는 목록을 한 벌로 나눠 보여 주므로, 한 도형이 두 묶음에\n * 동시에 있으면 저작자가 같은 것을 두 번 만난다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Classification code used to group figures in the palette. One per figure.' })\n category?: string\n\n /**\n * 태그. **여럿 붙는다.**\n *\n * 분류와 다른 일을 한다. 분류는 「이것이 무엇인가」를 한 번 정하는 것이고, 태그는 「어디에\n * 걸리는가」를 여러 갈래로 적는 것이다 — 컨베이어이면서 반출 구역의 것일 수 있다. 그래서\n * 분류로는 못 하는 찾기가 된다.\n *\n * `simple-json` 으로 담는다. 사내 선례가 그것이고(`ops-master` · `organization` ·\n * `personalization`), 드라이버마다 배열 타입이 다른 것을 피한다.\n */\n /* `simple-json` 과 `default: null` 은 사내 선례 그대로다 — board-template · attachment 가 같은 모양이다. */\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => [String], { nullable: true, description: 'Free-form tags. A figure may carry several.' })\n tags?: string[]\n\n @Column({ nullable: true, default: 'draft' })\n @Field({ nullable: true, description: \"Lifecycle state — 'draft' figures do not appear in the board palette.\" })\n state?: 'draft' | 'released'\n\n /**\n * The figure asset JSON (`figure-v3-asset-1`).\n *\n * `Board.model` 자리이지만 이름을 바꿨다 — 「씬 모델이 아니다」를 필드 이름이\n * 드러내야 한다.\n */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The figure asset JSON (figure-v3-asset-1) authored by the modeller.' })\n source?: string\n\n // ── 파생값 — 저장하는 이유가 하나뿐이다 ──────────────────────────────────\n //\n // 셋 다 `source` 에서 계산된다. 그런데도 컬럼으로 두는 이유는 **목록 화면이\n // 정렬·필터를 해야** 하기 때문이다. JSON 을 파싱해 정렬할 수는 없다.\n //\n // 저장할 때 `figure-model` 로 계산해 채운다. **클라이언트가 준 값을 받지 않는다** —\n // 받으면 거짓이 들어오고, 목록이 실물과 다른 것을 보여 준다.\n\n /** 재활용 점수 0~100. `scoreOf()` 가 계산한다. */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Reuse score 0-100, computed from source on save.' })\n score?: number\n\n /** 삼각형 수. `costOf()` 가 계산한다. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Triangle count, computed from source on save.' })\n triangles?: number\n\n /** 재질 묶음 수 — 인스턴스당 draw call 의 근거. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Material group count — the basis of per-instance draw calls.' })\n groups?: number\n\n /** 기준정보 항목 정의. Figure 를 배치할 때 인스턴스가 채우는 자리. */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'JSON definition of the master-data fields an instance of this figure carries.' })\n properties?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image of the figure.' })\n thumbnail?: string\n\n /**\n * 썸네일이 **썸네일로서** 마지막으로 갱신된 시각. `updatedAt` 과는 별개 도메인이다 —\n * 이름·설명만 고쳤을 때는 갱신되지 않는다. `Board` 와 같은 방식.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Timestamp of the last thumbnail generation. Separate lifecycle from updatedAt.' })\n thumbnailUpdatedAt?: Date\n\n @Column({ type: 'float', nullable: true, default: 0 })\n @Field(type => Float, { nullable: true, description: 'Sort order within a listing.' })\n sortOrder?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft-delete timestamp.' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created this figure.' })\n creator?: User\n\n @RelationId((figure: Figure) => figure.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated this figure.' })\n updater?: User\n\n @RelationId((figure: Figure) => figure.updater)\n updaterId?: string\n}\n"]}
1
+ {"version":3,"file":"figure.js","sourceRoot":"","sources":["../../../server/service/figure/figure.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, longTextColumn } from '@things-factory/shell'\n\n/**\n * Figure — 저작된 3D 컴포넌트 한 종류.\n *\n * `Board` 를 준용한다. 다른 점만 주석으로 적는다.\n *\n * ## 무엇을 담나 — 도형 자산이다, 씬 모델이 아니다\n *\n * 형식은 `@hatiolab/figure-model` 이 정한다(`figure-asset-1`). 씬 컴포넌트 트리를 담지 않는다.\n * 컴파일한 것도 저장하지 않는다 — 원본에서 파생되므로 소비하는 쪽이 커널로 컴파일한다. 저장하면 원본과 갈린다.\n *\n * 그래서 부품·움직임·자리 같은 것을 컬럼으로 두지 않는다 — 전부 `source` 안에 이미 있다. 두 벌이면 갈린다.\n *\n * 설계: `docs/design/figure-modules.md` §2\n */\n@Entity()\n@Index('ix_figure_1', (figure: Figure) => [figure.domain, figure.type], {\n unique: true,\n where: '\"deleted_at\" IS NULL'\n})\n@Index('ix_figure_2', (figure: Figure) => [figure.domain, figure.category])\n@ObjectType({ description: 'An authored 3D component type — its figure asset plus its metadata.' })\nexport class Figure {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true, description: 'Unique identifier for the figure.' })\n readonly id?: string\n\n /**\n * 발행된 판의 번호 — **발행할 때만 올라간다.**\n *\n * 저장 횟수가 아니다. 저작 중에는 몇 번을 고쳐 저장하든 그대로이고, `draft` 가 `released` 가\n * 되는 순간에만 하나 오른다. 소비처가 「몇 번째 판을 쓰고 있나」를 이 값으로 말한다.\n *\n * 한 번도 발행되지 않았으면 **0** 이다. 1 로 시작하면 아직 아무에게도 약속하지 않은 초안이\n * 첫 판인 것처럼 보인다.\n */\n @Column({ nullable: true, default: 0 })\n @Field(type => Int, {\n nullable: true,\n description: 'Published version. Raised when the figure is released, not when it is saved. 0 means never released.'\n })\n version?: number = 0\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain this figure belongs to.' })\n domain?: Domain\n\n @RelationId((figure: Figure) => figure.domain)\n domainId?: string\n\n /**\n * 컴포넌트 타입 이름. **저장되는 식별자다.**\n *\n * 배치된 도면이 이 이름으로 타입을 찾는다. 바꾸면 그 도면은 타입을 못 찾아\n * **오류 없이 빈 화면**이 된다. 그래서 만들 때 정하고 잠근다 — 고칠 수 있는 것은\n * 표시 이름(`name`)뿐이다. 수정 리졸버가 이 필드를 받지 않는다.\n *\n * `Board.type`(main/sub/popup)과 뜻이 전혀 다르다. 혼동하지 않는다.\n */\n @Column()\n @Field({ description: 'Component type name. A stored identifier — unique per domain and immutable once created.' })\n type?: string\n\n @Column()\n @Field({ description: 'Display name shown to authors. Safe to rename.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A detailed description for the figure.' })\n description?: string\n\n /**\n * 분류 하나. **팔레트에서 묶어 보이는 기준이다.**\n *\n * 도형 하나에 하나뿐이다 — 팔레트는 목록을 한 벌로 나눠 보여 주므로, 한 도형이 두 묶음에\n * 동시에 있으면 저작자가 같은 것을 두 번 만난다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Classification code used to group figures in the palette. One per figure.' })\n category?: string\n\n /**\n * 태그. **여럿 붙는다.**\n *\n * 분류와 다른 일을 한다. 분류는 「이것이 무엇인가」를 한 번 정하는 것이고, 태그는 「어디에\n * 걸리는가」를 여러 갈래로 적는 것이다 — 컨베이어이면서 반출 구역의 것일 수 있다. 그래서\n * 분류로는 못 하는 찾기가 된다.\n *\n * `simple-json` 으로 담는다. 사내 선례가 그것이고(`ops-master` · `organization` ·\n * `personalization`), 드라이버마다 배열 타입이 다른 것을 피한다.\n */\n /* `simple-json` 과 `default: null` 은 사내 선례 그대로다 — board-template · attachment 가 같은 모양이다. */\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => [String], { nullable: true, description: 'Free-form tags. A figure may carry several.' })\n tags?: string[]\n\n @Column({ nullable: true, default: 'draft' })\n @Field({ nullable: true, description: \"Lifecycle state — 'draft' figures do not appear in the board palette.\" })\n state?: 'draft' | 'released'\n\n /**\n * The figure asset JSON (`figure-asset-1`).\n *\n * `Board.model` 자리이지만 이름을 바꿨다 — 「씬 모델이 아니다」를 필드 이름이\n * 드러내야 한다.\n */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The figure asset JSON (figure-asset-1) authored by the modeller.' })\n source?: string\n\n // ── 파생값 — 저장하는 이유가 하나뿐이다 ──────────────────────────────────\n //\n // 셋 다 `source` 에서 계산된다. 그런데도 컬럼으로 두는 이유는 **목록 화면이\n // 정렬·필터를 해야** 하기 때문이다. JSON 을 파싱해 정렬할 수는 없다.\n //\n // 저장할 때 `figure-model` 로 계산해 채운다. **클라이언트가 준 값을 받지 않는다** —\n // 받으면 거짓이 들어오고, 목록이 실물과 다른 것을 보여 준다.\n\n /** 재활용 점수 0~100. `scoreOf()` 가 계산한다. */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Reuse score 0-100, computed from source on save.' })\n score?: number\n\n /** 삼각형 수. `costOf()` 가 계산한다. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Triangle count, computed from source on save.' })\n triangles?: number\n\n /** 재질 묶음 수 — 인스턴스당 draw call 의 근거. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Material group count — the basis of per-instance draw calls.' })\n groups?: number\n\n /** 기준정보 항목 정의. Figure 를 배치할 때 인스턴스가 채우는 자리. */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'JSON definition of the master-data fields an instance of this figure carries.' })\n properties?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image of the figure.' })\n thumbnail?: string\n\n /**\n * 썸네일이 **썸네일로서** 마지막으로 갱신된 시각. `updatedAt` 과는 별개 도메인이다 —\n * 이름·설명만 고쳤을 때는 갱신되지 않는다. `Board` 와 같은 방식.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Timestamp of the last thumbnail generation. Separate lifecycle from updatedAt.' })\n thumbnailUpdatedAt?: Date\n\n @Column({ type: 'float', nullable: true, default: 0 })\n @Field(type => Float, { nullable: true, description: 'Sort order within a listing.' })\n sortOrder?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft-delete timestamp.' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created this figure.' })\n creator?: User\n\n @RelationId((figure: Figure) => figure.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated this figure.' })\n updater?: User\n\n @RelationId((figure: Figure) => figure.updater)\n updaterId?: string\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { V3Recipe } from '@hatiolab/figure-model';
1
+ import type { FigureRecipe } from '@hatiolab/figure-model';
2
2
  /**
3
3
  * The recipe templates the product ships (ADR-0095, amended 2026-09-26): static files, served, not managed.
4
4
  *
@@ -10,7 +10,7 @@ import type { V3Recipe } from '@hatiolab/figure-model';
10
10
  * start reads their form only; putting each into the test room is the tests' work (`figure-recipe-templates.test.ts`).
11
11
  */
12
12
  export interface RecipeTemplate {
13
- recipe: V3Recipe;
13
+ recipe: FigureRecipe;
14
14
  category: string;
15
15
  tags: string[];
16
16
  /** Guides by language code, as written. */
@@ -21,7 +21,7 @@ function recipeTemplates(dir = exports.RECIPE_DIR) {
21
21
  const at = (0, path_1.join)(dir, folder);
22
22
  try {
23
23
  const raw = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(at, 'recipe.json'), 'utf-8'));
24
- const recipe = (0, figure_model_1.parseV3Recipe)(raw);
24
+ const recipe = (0, figure_model_1.parseFigureRecipe)(raw);
25
25
  if (recipe.name !== folder)
26
26
  throw new Error(`the recipe is named ${recipe.name}, its folder ${folder}`);
27
27
  const guides = {};
@@ -1 +1 @@
1
- {"version":3,"file":"figure-recipe-templates.js","sourceRoot":"","sources":["../../../server/service/figure-recipe/figure-recipe-templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'fs'\nimport { join, resolve } from 'path'\n\nimport { parseV3Recipe } from '@hatiolab/figure-model'\nimport type { V3Recipe } from '@hatiolab/figure-model'\n\n/**\n * The recipe templates the product ships (ADR-0095, amended 2026-09-26): static files, served, not managed.\n *\n * recipes/<name>/recipe.json the command list, its parameters, category, tags, titles\n * recipes/<name>/guide.<lang>.md how to use it, per language (English stands in for a missing one)\n * recipes/<name>/thumbnail.png drawn by a script from the recipe put into the test room\n *\n * There is no table and no screen that changes them: a template is added or changed as a file, with the code. The\n * start reads their form only; putting each into the test room is the tests' work (`figure-recipe-templates.test.ts`).\n */\nexport interface RecipeTemplate {\n recipe: V3Recipe\n category: string\n tags: string[]\n /** Guides by language code, as written. */\n guides: Record<string, string>\n thumbnail: string | null\n}\n\n/** The folder the templates are in: `recipes/` at the package root, beside `server/` and `dist-server/`. */\nexport const RECIPE_DIR = resolve(__dirname, '..', '..', '..', 'recipes')\n\nlet loaded: { templates: RecipeTemplate[]; refused: string[] } | null = null\n\n/** Every template, read once. One whose form is wrong is left out and named, not half served. */\nexport function recipeTemplates(dir: string = RECIPE_DIR): { templates: RecipeTemplate[]; refused: string[] } {\n if (loaded && dir === RECIPE_DIR) return loaded\n const templates: RecipeTemplate[] = []\n const refused: string[] = []\n /* A folder starting with _ holds what the models are built with, not a template. */\n const folders = existsSync(dir) ? readdirSync(dir, { withFileTypes: true }).filter(e => e.isDirectory() && !e.name.startsWith('_')).map(e => e.name).sort() : []\n for (const folder of folders) {\n const at = join(dir, folder)\n try {\n const raw = JSON.parse(readFileSync(join(at, 'recipe.json'), 'utf-8'))\n const recipe = parseV3Recipe(raw)\n if (recipe.name !== folder) throw new Error(`the recipe is named ${recipe.name}, its folder ${folder}`)\n const guides: Record<string, string> = {}\n for (const file of readdirSync(at)) {\n const lang = /^guide\\.([a-zA-Z-]+)\\.md$/.exec(file)?.[1]\n if (lang) guides[lang] = readFileSync(join(at, file), 'utf-8')\n }\n templates.push({\n recipe,\n category: typeof raw.category === 'string' ? raw.category : 'other',\n tags: Array.isArray(raw.tags) ? raw.tags.filter((t: unknown) => typeof t === 'string') : [],\n guides,\n thumbnail: existsSync(join(at, 'thumbnail.png')) ? join(at, 'thumbnail.png') : null\n })\n } catch (error) {\n refused.push(`${folder}: ${error instanceof Error ? error.message : String(error)}`)\n }\n }\n const result = { templates, refused }\n if (dir === RECIPE_DIR) loaded = result\n return result\n}\n\n/** A word in the language asked: that language, its base (`ko` for `ko-KR`), English, then the first there is. */\nexport function inLanguage(words: Record<string, string> | undefined, lang: string | undefined): string {\n if (!words) return ''\n const asked = lang || 'en'\n return words[asked] ?? words[asked.split('-')[0]!] ?? words.en ?? Object.values(words)[0] ?? ''\n}\n"]}
1
+ {"version":3,"file":"figure-recipe-templates.js","sourceRoot":"","sources":["../../../server/service/figure-recipe/figure-recipe-templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'fs'\nimport { join, resolve } from 'path'\n\nimport { parseFigureRecipe } from '@hatiolab/figure-model'\nimport type { FigureRecipe } from '@hatiolab/figure-model'\n\n/**\n * The recipe templates the product ships (ADR-0095, amended 2026-09-26): static files, served, not managed.\n *\n * recipes/<name>/recipe.json the command list, its parameters, category, tags, titles\n * recipes/<name>/guide.<lang>.md how to use it, per language (English stands in for a missing one)\n * recipes/<name>/thumbnail.png drawn by a script from the recipe put into the test room\n *\n * There is no table and no screen that changes them: a template is added or changed as a file, with the code. The\n * start reads their form only; putting each into the test room is the tests' work (`figure-recipe-templates.test.ts`).\n */\nexport interface RecipeTemplate {\n recipe: FigureRecipe\n category: string\n tags: string[]\n /** Guides by language code, as written. */\n guides: Record<string, string>\n thumbnail: string | null\n}\n\n/** The folder the templates are in: `recipes/` at the package root, beside `server/` and `dist-server/`. */\nexport const RECIPE_DIR = resolve(__dirname, '..', '..', '..', 'recipes')\n\nlet loaded: { templates: RecipeTemplate[]; refused: string[] } | null = null\n\n/** Every template, read once. One whose form is wrong is left out and named, not half served. */\nexport function recipeTemplates(dir: string = RECIPE_DIR): { templates: RecipeTemplate[]; refused: string[] } {\n if (loaded && dir === RECIPE_DIR) return loaded\n const templates: RecipeTemplate[] = []\n const refused: string[] = []\n /* A folder starting with _ holds what the models are built with, not a template. */\n const folders = existsSync(dir) ? readdirSync(dir, { withFileTypes: true }).filter(e => e.isDirectory() && !e.name.startsWith('_')).map(e => e.name).sort() : []\n for (const folder of folders) {\n const at = join(dir, folder)\n try {\n const raw = JSON.parse(readFileSync(join(at, 'recipe.json'), 'utf-8'))\n const recipe = parseFigureRecipe(raw)\n if (recipe.name !== folder) throw new Error(`the recipe is named ${recipe.name}, its folder ${folder}`)\n const guides: Record<string, string> = {}\n for (const file of readdirSync(at)) {\n const lang = /^guide\\.([a-zA-Z-]+)\\.md$/.exec(file)?.[1]\n if (lang) guides[lang] = readFileSync(join(at, file), 'utf-8')\n }\n templates.push({\n recipe,\n category: typeof raw.category === 'string' ? raw.category : 'other',\n tags: Array.isArray(raw.tags) ? raw.tags.filter((t: unknown) => typeof t === 'string') : [],\n guides,\n thumbnail: existsSync(join(at, 'thumbnail.png')) ? join(at, 'thumbnail.png') : null\n })\n } catch (error) {\n refused.push(`${folder}: ${error instanceof Error ? error.message : String(error)}`)\n }\n }\n const result = { templates, refused }\n if (dir === RECIPE_DIR) loaded = result\n return result\n}\n\n/** A word in the language asked: that language, its base (`ko` for `ko-KR`), English, then the first there is. */\nexport function inLanguage(words: Record<string, string> | undefined, lang: string | undefined): string {\n if (!words) return ''\n const asked = lang || 'en'\n return words[asked] ?? words[asked.split('-')[0]!] ?? words.en ?? Object.values(words)[0] ?? ''\n}\n"]}
@@ -31,7 +31,7 @@ tslib_1.__decorate([
31
31
  tslib_1.__metadata("design:type", String)
32
32
  ], FigureRecipeTemplate.prototype, "description", void 0);
33
33
  tslib_1.__decorate([
34
- (0, type_graphql_1.Field)({ description: 'The recipe JSON (figure-model V3Recipe), as the modeller applies it.' }),
34
+ (0, type_graphql_1.Field)({ description: 'The recipe JSON (figure-model FigureRecipe), as the modeller applies it.' }),
35
35
  tslib_1.__metadata("design:type", String)
36
36
  ], FigureRecipeTemplate.prototype, "source", void 0);
37
37
  tslib_1.__decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"figure-recipe-type.js","sourceRoot":"","sources":["../../../server/service/figure-recipe/figure-recipe-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAgD;AAGzC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CA2BhC,CAAA;AA3BY,oDAAoB;AAE/B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;;kDACjE;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;sDAC/D;AAGhB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;;kDACpD;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,gFAAgF,EAAE,CAAC;;oDAC3F;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;mDAClE;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,qEAAqE,EAAE,CAAC;;yDAC3E;AAGnB;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sEAAsE,EAAE,CAAC;;oDACjF;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6GAA6G,EAAE,CAAC;;mDACxI;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;;0DACvC;+BA1BV,oBAAoB;IADhC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,kHAAkH,EAAE,CAAC;GACnI,oBAAoB,CA2BhC","sourcesContent":["import { Field, ObjectType } from 'type-graphql'\n\n@ObjectType({ description: 'A recipe template the product ships: parts, their fastenings and motion, put onto a part in one step (ADR-0095).' })\nexport class FigureRecipeTemplate {\n @Field({ description: 'The template name: lower case, digits and hyphens.' })\n name: string\n\n @Field({ description: 'The category it is listed under (door, conveyor, …).' })\n category: string\n\n @Field(type => [String], { description: 'Words it is found by.' })\n tags: string[]\n\n @Field({ description: \"'part' when it is put onto a chosen part, 'figure' when onto the whole figure.\" })\n target: string\n\n @Field({ description: 'Its title in the language asked (English stands in).' })\n title: string\n\n @Field({ description: 'Its one-line description in the language asked (English stands in).' })\n description: string\n\n @Field({ description: 'The recipe JSON (figure-model V3Recipe), as the modeller applies it.' })\n source: string\n\n @Field({ nullable: true, description: 'How to use it, as Markdown, in the language asked (English stands in). Only when one template is asked for.' })\n guide?: string\n\n @Field({ description: 'Whether it has a thumbnail image.' })\n hasThumbnail: boolean\n}\n"]}
1
+ {"version":3,"file":"figure-recipe-type.js","sourceRoot":"","sources":["../../../server/service/figure-recipe/figure-recipe-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAgD;AAGzC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CA2BhC,CAAA;AA3BY,oDAAoB;AAE/B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;;kDACjE;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;sDAC/D;AAGhB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;;kDACpD;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,gFAAgF,EAAE,CAAC;;oDAC3F;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;mDAClE;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,qEAAqE,EAAE,CAAC;;yDAC3E;AAGnB;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,0EAA0E,EAAE,CAAC;;oDACrF;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6GAA6G,EAAE,CAAC;;mDACxI;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;;0DACvC;+BA1BV,oBAAoB;IADhC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,kHAAkH,EAAE,CAAC;GACnI,oBAAoB,CA2BhC","sourcesContent":["import { Field, ObjectType } from 'type-graphql'\n\n@ObjectType({ description: 'A recipe template the product ships: parts, their fastenings and motion, put onto a part in one step (ADR-0095).' })\nexport class FigureRecipeTemplate {\n @Field({ description: 'The template name: lower case, digits and hyphens.' })\n name: string\n\n @Field({ description: 'The category it is listed under (door, conveyor, …).' })\n category: string\n\n @Field(type => [String], { description: 'Words it is found by.' })\n tags: string[]\n\n @Field({ description: \"'part' when it is put onto a chosen part, 'figure' when onto the whole figure.\" })\n target: string\n\n @Field({ description: 'Its title in the language asked (English stands in).' })\n title: string\n\n @Field({ description: 'Its one-line description in the language asked (English stands in).' })\n description: string\n\n @Field({ description: 'The recipe JSON (figure-model FigureRecipe), as the modeller applies it.' })\n source: string\n\n @Field({ nullable: true, description: 'How to use it, as Markdown, in the language asked (English stands in). Only when one template is asked for.' })\n guide?: string\n\n @Field({ description: 'Whether it has a thumbnail image.' })\n hasThumbnail: boolean\n}\n"]}