@things-factory/figure-service 10.1.208 → 10.1.212
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist-server/service/figure/event-subscriber.js +2 -2
- package/dist-server/service/figure/event-subscriber.js.map +1 -1
- package/dist-server/service/figure/figure-context.d.ts +2 -1
- package/dist-server/service/figure/figure-context.js +2 -1
- package/dist-server/service/figure/figure-context.js.map +1 -1
- package/dist-server/service/figure/figure-format.js +1 -1
- package/dist-server/service/figure/figure-format.js.map +1 -1
- package/dist-server/service/figure/figure-mutation.d.ts +5 -5
- package/dist-server/service/figure/figure-mutation.js +6 -6
- package/dist-server/service/figure/figure-mutation.js.map +1 -1
- package/dist-server/service/figure/figure-query.d.ts +3 -3
- package/dist-server/service/figure/figure-query.js +4 -4
- package/dist-server/service/figure/figure-query.js.map +1 -1
- package/dist-server/service/figure/figure-rename.d.ts +4 -4
- package/dist-server/service/figure/figure-rename.js +2 -2
- package/dist-server/service/figure/figure-rename.js.map +1 -1
- package/dist-server/service/figure/figure-tools.js +9 -9
- package/dist-server/service/figure/figure-tools.js.map +1 -1
- package/dist-server/service/figure/figure-type.d.ts +2 -2
- package/dist-server/service/figure/figure-type.js +2 -2
- package/dist-server/service/figure/figure-type.js.map +1 -1
- package/dist-server/service/figure/figure.d.ts +2 -2
- package/dist-server/service/figure/figure.js +1 -1
- package/dist-server/service/figure/figure.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/recipes/_lib/model.mts +12 -8
- package/recipes/air-cylinder/models/default.json +1 -1
- package/recipes/air-cylinder/recipe.json +13 -10
- package/recipes/air-cylinder/spec.json +1 -1
- package/recipes/air-shower/models/default.json +1 -1
- package/recipes/air-shower/recipe.json +11 -8
- package/recipes/barrier-gate/models/default.json +1 -1
- package/recipes/barrier-gate/recipe.json +11 -7
- package/recipes/base-frame/models/default.json +1 -1
- package/recipes/base-frame/recipe.json +0 -4
- package/recipes/belt-surface/guide.ko.md +1 -1
- package/recipes/belt-surface/models/default.json +1 -1
- package/recipes/belt-surface/recipe.json +0 -1
- package/recipes/bin-row/models/default.json +1 -1
- package/recipes/bin-row/recipe.json +0 -1
- package/recipes/bollard-row/models/default.json +1 -1
- package/recipes/bollard-row/recipe.json +0 -1
- package/recipes/buzzer/models/default.json +1 -1
- package/recipes/buzzer/recipe.json +0 -1
- package/recipes/cabinet-doors/build.mts +1 -1
- package/recipes/cabinet-doors/models/default.json +1 -1
- package/recipes/cabinet-doors/models/doors=1.json +1 -1
- package/recipes/cabinet-doors/models/doors=2.json +1 -1
- package/recipes/cabinet-doors/recipe.json +21 -13
- package/recipes/cable-tray/models/default.json +1 -1
- package/recipes/cable-tray/recipe.json +0 -3
- package/recipes/camera-mount/models/default.json +1 -1
- package/recipes/camera-mount/recipe.json +11 -8
- package/recipes/canopy/models/default.json +1 -1
- package/recipes/canopy/recipe.json +0 -5
- package/recipes/cart/models/default.json +1 -1
- package/recipes/cart/recipe.json +0 -12
- package/recipes/cart-handle/models/default.json +1 -1
- package/recipes/cart-handle/recipe.json +0 -3
- package/recipes/casters-four/models/default.json +1 -1
- package/recipes/casters-four/recipe.json +0 -8
- package/recipes/ceiling-rail-carriage/build.mts +1 -1
- package/recipes/ceiling-rail-carriage/models/default.json +1 -1
- package/recipes/ceiling-rail-carriage/recipe.json +19 -16
- package/recipes/chain-rails/models/default.json +1 -1
- package/recipes/chain-rails/recipe.json +0 -2
- package/recipes/charging-station/models/default.json +1 -1
- package/recipes/charging-station/recipe.json +0 -2
- package/recipes/column-row/models/default.json +1 -1
- package/recipes/column-row/recipe.json +0 -1
- package/recipes/control-cabinet/models/default.json +1 -1
- package/recipes/control-cabinet/recipe.json +11 -8
- package/recipes/conveyor-skirts/models/default.json +1 -1
- package/recipes/conveyor-skirts/recipe.json +0 -2
- package/recipes/counter-display/models/default.json +1 -1
- package/recipes/counter-display/recipe.json +0 -2
- package/recipes/dock-bumpers/models/default.json +1 -1
- package/recipes/dock-bumpers/recipe.json +0 -2
- package/recipes/dock-leveler/models/default.json +1 -1
- package/recipes/dock-leveler/recipe.json +11 -7
- package/recipes/double-hinged-door/build.mts +1 -1
- package/recipes/double-hinged-door/models/default.json +1 -1
- package/recipes/double-hinged-door/recipe.json +21 -14
- package/recipes/drawer-stack/models/default.json +1 -1
- package/recipes/drawer-stack/models/drawers=2.json +1 -1
- package/recipes/drawer-stack/models/drawers=3.json +1 -1
- package/recipes/drawer-stack/models/drawers=4.json +1 -1
- package/recipes/drawer-stack/recipe.json +99 -63
- package/recipes/drip-tray/models/default.json +1 -1
- package/recipes/drip-tray/recipe.json +0 -1
- package/recipes/duct-fan/models/default.json +1 -1
- package/recipes/duct-fan/recipe.json +11 -8
- package/recipes/emergency-stop/models/default.json +1 -1
- package/recipes/emergency-stop/recipe.json +11 -8
- package/recipes/end-covers/models/default.json +1 -1
- package/recipes/end-covers/recipe.json +0 -2
- package/recipes/ffu-row/models/default.json +1 -1
- package/recipes/ffu-row/recipe.json +0 -1
- package/recipes/fire-extinguisher/models/default.json +1 -1
- package/recipes/fire-extinguisher/recipe.json +0 -2
- package/recipes/first-aid-box/models/default.json +1 -1
- package/recipes/first-aid-box/recipe.json +0 -2
- package/recipes/floor-zone/models/default.json +1 -1
- package/recipes/floor-zone/recipe.json +0 -4
- package/recipes/folding-door/build.mts +1 -1
- package/recipes/folding-door/models/default.json +1 -1
- package/recipes/folding-door/recipe.json +21 -14
- package/recipes/fork/build.mts +1 -1
- package/recipes/fork/models/default.json +1 -1
- package/recipes/fork/recipe.json +23 -15
- package/recipes/fork/spec.json +1 -1
- package/recipes/gantry-frame/models/default.json +1 -1
- package/recipes/gantry-frame/recipe.json +0 -3
- package/recipes/gripper-2f/build.mts +1 -1
- package/recipes/gripper-2f/models/default.json +1 -1
- package/recipes/gripper-2f/recipe.json +23 -16
- package/recipes/gripper-2f/spec.json +1 -1
- package/recipes/guard-cover/models/default.json +1 -1
- package/recipes/guard-cover/recipe.json +11 -7
- package/recipes/handrail/models/default.json +1 -1
- package/recipes/handrail/recipe.json +0 -2
- package/recipes/hatch/models/default.json +1 -1
- package/recipes/hatch/recipe.json +11 -8
- package/recipes/hinged-door/build.mts +2 -3
- package/recipes/hinged-door/models/default.json +1 -1
- package/recipes/hinged-door/models/hinge=left.json +1 -1
- package/recipes/hinged-door/models/hinge=right.json +1 -1
- package/recipes/hinged-door/recipe.json +22 -15
- package/recipes/hmi-monitor/models/default.json +1 -1
- package/recipes/hmi-monitor/recipe.json +11 -8
- package/recipes/hopper/models/default.json +1 -1
- package/recipes/hopper/recipe.json +0 -2
- package/recipes/interlock-switch/models/default.json +1 -1
- package/recipes/interlock-switch/recipe.json +0 -1
- package/recipes/junction-box/models/default.json +1 -1
- package/recipes/junction-box/recipe.json +0 -1
- package/recipes/ladder/models/default.json +1 -1
- package/recipes/ladder/recipe.json +0 -3
- package/recipes/legs-four/models/default.json +1 -1
- package/recipes/legs-four/recipe.json +0 -4
- package/recipes/leveling-feet/models/default.json +1 -1
- package/recipes/leveling-feet/recipe.json +0 -4
- package/recipes/lift-updown/models/default.json +1 -1
- package/recipes/lift-updown/recipe.json +13 -9
- package/recipes/lift-updown/spec.json +1 -1
- package/recipes/light-curtain/models/default.json +1 -1
- package/recipes/light-curtain/recipe.json +0 -2
- package/recipes/limit-switch/models/default.json +1 -1
- package/recipes/limit-switch/recipe.json +11 -8
- package/recipes/linear-guide/build.mts +1 -1
- package/recipes/linear-guide/models/default.json +1 -1
- package/recipes/linear-guide/recipe.json +19 -16
- package/recipes/locker-row/models/default.json +1 -1
- package/recipes/locker-row/recipe.json +0 -1
- package/recipes/motor-box/models/default.json +1 -1
- package/recipes/motor-box/recipe.json +0 -1
- package/recipes/observation-window/models/default.json +1 -1
- package/recipes/observation-window/recipe.json +0 -2
- package/recipes/operator-panel/models/buttons=2.json +1 -1
- package/recipes/operator-panel/models/buttons=3.json +1 -1
- package/recipes/operator-panel/models/buttons=4.json +1 -1
- package/recipes/operator-panel/models/buttons=5.json +1 -1
- package/recipes/operator-panel/models/default.json +1 -1
- package/recipes/operator-panel/recipe.json +0 -5
- package/recipes/pallet/models/default.json +1 -1
- package/recipes/pallet/recipe.json +0 -4
- package/recipes/partition-wall/models/default.json +1 -1
- package/recipes/partition-wall/recipe.json +0 -3
- package/recipes/pass-box/models/default.json +1 -1
- package/recipes/pass-box/recipe.json +11 -8
- package/recipes/peg-board/models/default.json +1 -1
- package/recipes/peg-board/recipe.json +0 -2
- package/recipes/photo-sensor-pair/models/default.json +1 -1
- package/recipes/photo-sensor-pair/recipe.json +0 -2
- package/recipes/pipe-run/models/default.json +1 -1
- package/recipes/pipe-run/recipe.json +0 -1
- package/recipes/platform/models/default.json +1 -1
- package/recipes/platform/recipe.json +0 -5
- package/recipes/power-box/models/default.json +1 -1
- package/recipes/power-box/recipe.json +0 -1
- package/recipes/pressure-gauge/models/default.json +1 -1
- package/recipes/pressure-gauge/recipe.json +0 -1
- package/recipes/pull-cord/models/default.json +1 -1
- package/recipes/pull-cord/recipe.json +0 -1
- package/recipes/pump/models/default.json +1 -1
- package/recipes/pump/recipe.json +0 -2
- package/recipes/pusher/build.mts +1 -1
- package/recipes/pusher/models/default.json +1 -1
- package/recipes/pusher/recipe.json +19 -15
- package/recipes/robot-plinth/models/default.json +1 -1
- package/recipes/robot-plinth/recipe.json +0 -2
- package/recipes/roll-up-shutter/build.mts +1 -1
- package/recipes/roll-up-shutter/models/default.json +1 -1
- package/recipes/roll-up-shutter/recipe.json +19 -16
- package/recipes/roller-row/facts.md +1 -1
- package/recipes/roller-row/guide.ko.md +1 -1
- package/recipes/roller-row/models/default.json +1 -1
- package/recipes/roller-row/recipe.json +11 -7
- package/recipes/room-shell/models/default.json +1 -1
- package/recipes/room-shell/recipe.json +0 -5
- package/recipes/rotating-beacon/models/default.json +1 -1
- package/recipes/rotating-beacon/recipe.json +11 -9
- package/recipes/safety-fence/models/default.json +1 -1
- package/recipes/safety-fence/recipe.json +0 -2
- package/recipes/safety-mat/models/default.json +1 -1
- package/recipes/safety-mat/recipe.json +0 -1
- package/recipes/safety-sign-stand/models/default.json +1 -1
- package/recipes/safety-sign-stand/recipe.json +0 -3
- package/recipes/scanner-mount/models/default.json +1 -1
- package/recipes/scanner-mount/recipe.json +0 -3
- package/recipes/selector-switch/models/default.json +1 -1
- package/recipes/selector-switch/recipe.json +11 -8
- package/recipes/shelf-tiers/models/default.json +1 -1
- package/recipes/shelf-tiers/models/tiers=2.json +1 -1
- package/recipes/shelf-tiers/models/tiers=3.json +1 -1
- package/recipes/shelf-tiers/models/tiers=4.json +1 -1
- package/recipes/shelf-tiers/models/tiers=5.json +1 -1
- package/recipes/shelf-tiers/recipe.json +0 -4
- package/recipes/side-guides/models/default.json +1 -1
- package/recipes/side-guides/recipe.json +0 -2
- package/recipes/sign-board/models/default.json +1 -1
- package/recipes/sign-board/recipe.json +0 -1
- package/recipes/signal-tower-3/build.mts +1 -1
- package/recipes/signal-tower-3/models/default.json +1 -1
- package/recipes/signal-tower-3/recipe.json +11 -10
- package/recipes/sliding-door/build.mts +4 -7
- package/recipes/sliding-door/facts.md +1 -1
- package/recipes/sliding-door/guide.ko.md +1 -1
- package/recipes/sliding-door/models/default.json +1 -1
- package/recipes/sliding-door/models/leaves=1,lamp=false.json +1 -1
- package/recipes/sliding-door/models/leaves=1,lamp=true.json +1 -1
- package/recipes/sliding-door/models/leaves=2,lamp=false.json +1 -1
- package/recipes/sliding-door/models/leaves=2,lamp=true.json +1 -1
- package/recipes/sliding-door/recipe.json +48 -38
- package/recipes/stairs/models/default.json +1 -1
- package/recipes/stairs/recipe.json +0 -1
- package/recipes/status-lamp/models/default.json +1 -1
- package/recipes/status-lamp/recipe.json +11 -9
- package/recipes/stopper/models/default.json +1 -1
- package/recipes/stopper/recipe.json +11 -7
- package/recipes/suction-pads/models/default.json +1 -1
- package/recipes/suction-pads/recipe.json +0 -1
- package/recipes/tank/models/default.json +1 -1
- package/recipes/tank/recipe.json +0 -1
- package/recipes/telescopic-arm/build.mts +1 -1
- package/recipes/telescopic-arm/models/default.json +1 -1
- package/recipes/telescopic-arm/recipe.json +21 -13
- package/recipes/toe-board/models/default.json +1 -1
- package/recipes/toe-board/recipe.json +0 -1
- package/recipes/tote/models/default.json +1 -1
- package/recipes/tote/recipe.json +0 -1
- package/recipes/traffic-cones/models/default.json +1 -1
- package/recipes/traffic-cones/recipe.json +0 -2
- package/recipes/transfer-belts/build.mts +1 -1
- package/recipes/transfer-belts/models/default.json +1 -1
- package/recipes/transfer-belts/recipe.json +23 -15
- package/recipes/transfer-belts/spec.json +1 -1
- package/recipes/tray-stack/models/default.json +1 -1
- package/recipes/tray-stack/models/trays=3.json +1 -1
- package/recipes/tray-stack/models/trays=4.json +1 -1
- package/recipes/tray-stack/models/trays=5.json +1 -1
- package/recipes/tray-stack/recipe.json +0 -5
- package/recipes/trough/models/default.json +1 -1
- package/recipes/trough/recipe.json +0 -1
- package/recipes/turntable/models/default.json +1 -1
- package/recipes/turntable/recipe.json +11 -8
- package/recipes/valve-handle/models/default.json +1 -1
- package/recipes/valve-handle/recipe.json +11 -9
- package/recipes/waste-bin/models/default.json +1 -1
- package/recipes/waste-bin/recipe.json +0 -1
- package/recipes/work-light/models/default.json +1 -1
- package/recipes/work-light/recipe.json +11 -9
- package/recipes/workbench-top/models/default.json +1 -1
- package/recipes/workbench-top/recipe.json +0 -1
- package/server/service/figure/catalog-db.test.ts +1 -1
- package/server/service/figure/event-subscriber.ts +2 -2
- package/server/service/figure/figure-blueprint-query.test.ts +3 -3
- package/server/service/figure/figure-context.test.ts +3 -3
- package/server/service/figure/figure-context.ts +4 -2
- package/server/service/figure/figure-format.test.ts +7 -7
- package/server/service/figure/figure-format.ts +1 -1
- package/server/service/figure/figure-llm-smoke.test.ts +1 -1
- package/server/service/figure/figure-mutation.ts +6 -6
- package/server/service/figure/figure-propose-clips.test.ts +1 -1
- package/server/service/figure/figure-propose-steps.test.ts +2 -2
- package/server/service/figure/figure-query.ts +4 -4
- package/server/service/figure/figure-release-record-db.test.ts +3 -3
- package/server/service/figure/figure-rename-db.test.ts +2 -2
- package/server/service/figure/figure-rename.test.ts +3 -3
- package/server/service/figure/figure-rename.ts +6 -6
- package/server/service/figure/figure-subject.test.ts +1 -1
- package/server/service/figure/figure-tools.test.ts +19 -19
- package/server/service/figure/figure-tools.ts +9 -9
- package/server/service/figure/figure-type.ts +2 -2
- package/server/service/figure/figure.ts +2 -2
- package/translations/ko.json +31 -31
|
@@ -53,7 +53,7 @@ export class FigureQuery {
|
|
|
53
53
|
|
|
54
54
|
`simple-json` 이라 칸에는 `["반출","자동"]` 이 통째로 들어 있고, LIKE 는 그 글자를
|
|
55
55
|
본다. 「반출」로 찾으면 걸린다. 정확히 그 태그만 걸리는 것은 아니지만(이름에 「반출」이
|
|
56
|
-
든
|
|
56
|
+
든 피규어도 걸린다) 찾기로는 그것이 오히려 낫다.
|
|
57
57
|
*/
|
|
58
58
|
searchables: ['type', 'name', 'description', 'category', 'tags']
|
|
59
59
|
})
|
|
@@ -97,7 +97,7 @@ export class FigureQuery {
|
|
|
97
97
|
* 발행된 판들 — 최근 것부터.
|
|
98
98
|
*
|
|
99
99
|
* 저작 중 저장은 여기 없다. 판본은 발행에서만 생기므로(`releaseFigure`), 이 목록이 곧
|
|
100
|
-
* 「이
|
|
100
|
+
* 「이 피규어가 몇 번 약속되었나」다.
|
|
101
101
|
*/
|
|
102
102
|
@Directive('@privilege(category: "figure", privilege: "query", domainOwnerGranted: true)')
|
|
103
103
|
@Query(returns => [FigureHistory], { description: 'Released versions of a figure, newest first.' })
|
|
@@ -117,7 +117,7 @@ export class FigureQuery {
|
|
|
117
117
|
/**
|
|
118
118
|
* 지금 소비처가 쓰는 판.
|
|
119
119
|
*
|
|
120
|
-
*
|
|
120
|
+
* 피규어의 현재 정본은 저작 중일 수 있다(초안). 배치된 것이 보는 것은 **마지막으로 발행된 판**이고,
|
|
121
121
|
* 그것을 이 자리가 답한다.
|
|
122
122
|
*/
|
|
123
123
|
/** What a kept GLB holds, read again from its bytes (ADR-0129): the modeller asks when it reopens a figure. */
|
|
@@ -254,7 +254,7 @@ export class FigureQuery {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
/**
|
|
257
|
-
* 소비처(operato-board, operato-twin, things-scene)가 발행된
|
|
257
|
+
* 소비처(operato-board, operato-twin, things-scene)가 발행된 피규어를 받아 가는 문.
|
|
258
258
|
*
|
|
259
259
|
* 이름은 보드와의 계약이라 그대로 둔다(바꾸는 일은 따로 한다). 돌려주는 것은 자산이다 —
|
|
260
260
|
* `{ type, asset }`. 그리는 쪽(`registerFigure`)이 커널로 컴파일한다.
|
|
@@ -123,9 +123,9 @@ describe('a release of a figure that moves keeps its joint list', () => {
|
|
|
123
123
|
const { asset } = palletizerRobotFigure()
|
|
124
124
|
if (!j4Axis) return serializeFigureAsset(asset)
|
|
125
125
|
const j4 = asset.joints.find((j: any) => j.id === 'j4')
|
|
126
|
-
return serializeFigureAsset(applyFigureAuthoring(asset, { kind: 'set-joint', joint: { ...j4, axis: j4Axis } }))
|
|
126
|
+
return serializeFigureAsset(applyFigureAuthoring(asset, { kind: 'set-joint', joint: { ...j4, motion: [{ ...j4.motion[0], axis: j4Axis }] } }))
|
|
127
127
|
}
|
|
128
|
-
it('schema
|
|
128
|
+
it('schema 3, the wrist following -(j2 + j3), controls with both units; another axis is refused', async () => {
|
|
129
129
|
const domain = await namespaced(await dataSource!.getRepository(shell.Domain).save({ name: 'release-joints', subdomain: 'release-joints' }))
|
|
130
130
|
const context = { state: { domain, user: undefined, tx: dataSource!.manager } }
|
|
131
131
|
const figure = await dataSource!.getRepository(Figure).save({ namespace: domain.subdomain, type: 'PALLETIZER', name: 'palletizer', source: palletizer(), state: 'draft', version: 0, domain })
|
|
@@ -133,7 +133,7 @@ describe('a release of a figure that moves keeps its joint list', () => {
|
|
|
133
133
|
|
|
134
134
|
const [row] = await dataSource!.getRepository(FigureHistory).find({ where: { originalId: figure.id } })
|
|
135
135
|
const list = JSON.parse(row.metrics).joints
|
|
136
|
-
expect(list.schema).toBe(
|
|
136
|
+
expect(list.schema).toBe(3)
|
|
137
137
|
const byId = new Map(list.joints.map((j: any) => [j.id, j]))
|
|
138
138
|
expect(byId.get('wrist')).toMatchObject({
|
|
139
139
|
type: 'revolute',
|
|
@@ -79,7 +79,7 @@ async function namespaced(domain: any) {
|
|
|
79
79
|
|
|
80
80
|
let DOMAIN: { id: string }
|
|
81
81
|
|
|
82
|
-
/*
|
|
82
|
+
/* 피규어가 도메인을 가리킨다 — 행이 없으면 외래키가 먼저 막는다. */
|
|
83
83
|
async function seedDomain() {
|
|
84
84
|
const saved = await namespaced(await dataSource!.getRepository(shell.Domain).save({ name: 'rename-probe', subdomain: 'rename-probe' }))
|
|
85
85
|
DOMAIN = { id: saved.id }
|
|
@@ -127,7 +127,7 @@ describe('이름을 바꾸기 전에 읽는 사실', () => {
|
|
|
127
127
|
expect((await facts(figure, 'robot-arm')).hasHistory).toBe(true)
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
it('같은 도메인에서 그 이름을 쓰는 다른
|
|
130
|
+
it('같은 도메인에서 그 이름을 쓰는 다른 피규어를 찾는다', async () => {
|
|
131
131
|
const figure = await seedFigure()
|
|
132
132
|
await seedFigure({ type: 'conveyor', name: '컨베이어' })
|
|
133
133
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* 초안의 타입을 고치는 규칙 — ADR-0063 결정 4.
|
|
3
3
|
*
|
|
4
|
-
* 이 규칙이 지키는 것은 하나다: **발행된 이름은 안 바뀐다.** 도면은 그 이름 하나로
|
|
4
|
+
* 이 규칙이 지키는 것은 하나다: **발행된 이름은 안 바뀐다.** 도면은 그 이름 하나로 피규어를
|
|
5
5
|
* 찾으므로, 바뀌면 배치된 자리가 아무 오류 없이 빈다.
|
|
6
6
|
*/
|
|
7
7
|
import { readFileSync } from 'fs'
|
|
@@ -21,7 +21,7 @@ const never = { version: 0, hasHistory: false, takenByAnother: false }
|
|
|
21
21
|
|
|
22
22
|
describe('초안의 type 고치기', () => {
|
|
23
23
|
/*
|
|
24
|
-
자산에는 type 칸이 없고 형식은 모르는 칸을 거절한다. 원본에 이름을 써 넣었더니 그
|
|
24
|
+
자산에는 type 칸이 없고 형식은 모르는 칸을 거절한다. 원본에 이름을 써 넣었더니 그 피규어를 다시 열 수
|
|
25
25
|
없었다(`parseFigureAsset` — "unknown type"). 행만 바뀐다.
|
|
26
26
|
*/
|
|
27
27
|
it('★ 행만 바뀌고, 원본은 그대로 다시 열린다', () => {
|
|
@@ -97,7 +97,7 @@ describe('문이 이 규칙을 지난다', () => {
|
|
|
97
97
|
저장이 임시 이름을 스스로 지었다(`FIGURE_<32 hex>`). 형식의 `isPlaceholderType` 이 그것을 못 알아봐서
|
|
98
98
|
발행 판정이 기계 이름을 통과시켰다. 짓는 쪽과 알아보는 쪽이 한 규칙이어야 한다.
|
|
99
99
|
*/
|
|
100
|
-
/* 새
|
|
100
|
+
/* 새 피규어의 임시 이름이 판정이 알아보는 그 규칙인지는 문을 실제로 불러 본다 — figure-rename-db.test.ts 「이름 없이 부르면」. */
|
|
101
101
|
|
|
102
102
|
it('문이 type 을 받는 칸을 갖는다', () => {
|
|
103
103
|
const type = source('figure-type.ts')
|
|
@@ -6,8 +6,8 @@ import { TYPE_LENGTH, TYPE_PATTERN } from '@hatiolab/figure-model'
|
|
|
6
6
|
* ## 왜 발행 전에만인가
|
|
7
7
|
*
|
|
8
8
|
* `type` 은 도면에 적히는 이름이다. 도면은 `{ type, left, top, width, height }` 만 갖고 늘 최신
|
|
9
|
-
* 발행판을 그리므로, 발행된
|
|
10
|
-
* 된다. 한 번도 발행되지 않은
|
|
9
|
+
* 발행판을 그리므로, 발행된 피규어의 이름을 바꾸면 이미 배치된 도면이 아무 오류 없이 빈 자리가
|
|
10
|
+
* 된다. 한 번도 발행되지 않은 피규어는 그려질 자리가 없으니 가리키는 도면도 있을 수 없다.
|
|
11
11
|
*
|
|
12
12
|
* ## 왜 열어야 했나
|
|
13
13
|
*
|
|
@@ -28,10 +28,10 @@ export interface RenameFacts {
|
|
|
28
28
|
version?: number
|
|
29
29
|
/** 판본이 하나라도 있나. 되돌리기로 판 번호가 도로 낮아져도 이력은 남는다. */
|
|
30
30
|
hasHistory: boolean
|
|
31
|
-
/** 같은 도메인에서 그 이름을 이미 쓰는 **다른**
|
|
31
|
+
/** 같은 도메인에서 그 이름을 이미 쓰는 **다른** 피규어가 있나. */
|
|
32
32
|
takenByAnother: boolean
|
|
33
33
|
/**
|
|
34
|
-
* 같은 도메인에서 그 이름으로 발행한 뒤 지워진
|
|
34
|
+
* 같은 도메인에서 그 이름으로 발행한 뒤 지워진 피규어가 있나. 발행한 피규어를 지울 수 없게 되기(G4) 전에 지워진 것이다.
|
|
35
35
|
* 그 이름을 다시 쓰면 판 번호가 1부터 다시 매겨져 같은 `ns/type@n` 이 다른 내용을 가리킨다.
|
|
36
36
|
*/
|
|
37
37
|
releasedBefore?: boolean
|
|
@@ -57,7 +57,7 @@ export async function typeReleasedBefore(
|
|
|
57
57
|
|
|
58
58
|
/** Said when a type was released and deleted before: a new figure may not take it. */
|
|
59
59
|
export const releasedBeforeMessage = (type: string) =>
|
|
60
|
-
`type 「${type}」 는 이 도메인에서 발행한 뒤 지운
|
|
60
|
+
`type 「${type}」 는 이 도메인에서 발행한 뒤 지운 피규어의 이름이다 — 다시 쓰면 같은 판 번호가 다른 내용을 가리키므로 다른 이름을 고른다`
|
|
61
61
|
|
|
62
62
|
export class FigureRenameRefused extends Error {
|
|
63
63
|
constructor(
|
|
@@ -100,7 +100,7 @@ export function renameDraftType(
|
|
|
100
100
|
if ((facts.version ?? 0) > 0 || facts.hasHistory) {
|
|
101
101
|
throw new FigureRenameRefused(
|
|
102
102
|
'already-released',
|
|
103
|
-
'발행된
|
|
103
|
+
'발행된 피규어의 type 은 바꿀 수 없다 — 이미 배치된 도면이 이 이름을 가리킨다'
|
|
104
104
|
)
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const mockFigures: any[] = [
|
|
5
5
|
{ id: 'f1', domain: 'plant-a', name: '선풍기', type: 'system/fan' },
|
|
6
6
|
{ id: 'f2', domain: 'plant-a', name: '', type: 'system/agv-lift' },
|
|
7
|
-
{ id: 'f3', domain: 'plant-b', name: '남의
|
|
7
|
+
{ id: 'f3', domain: 'plant-b', name: '남의 피규어', type: 'other/one' }
|
|
8
8
|
]
|
|
9
9
|
const mockRegistered: any[] = []
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 나타나는 증상이 실제로 겪은 실패와 1:1 로 대응한다.
|
|
7
7
|
*
|
|
8
8
|
* · guidance → 도구 호출 끊기면 → 「후보를 만들었습니다」라고만 쓰고 화면에는 아무것도 없다
|
|
9
|
-
* · hostContext.figureId → 대상 끊기면 → 화면에
|
|
9
|
+
* · hostContext.figureId → 대상 끊기면 → 화면에 피규어가 떠 있는데 「어느 피규어입니까」를 되묻는다
|
|
10
10
|
* · 도메인 확인 → 대상 끊기면 → 모델이 넘긴 id 로 남의 테넌트를 읽는다
|
|
11
11
|
* · hostContext.context·revision → 제안 끊기면 → 모델러가 모델이 본 판이 아닌 판에 명령을 적용한다
|
|
12
12
|
*
|
|
@@ -301,7 +301,7 @@ describe('모델이 읽는 글은 영어다', () => {
|
|
|
301
301
|
})
|
|
302
302
|
|
|
303
303
|
describe('대화면 문맥에서 대상을 해소한다', () => {
|
|
304
|
-
it('id 를 안 주면 열려 있는
|
|
304
|
+
it('id 를 안 주면 열려 있는 피규어를 읽는다 — 사용자에게 되묻지 않는다', async () => {
|
|
305
305
|
const result = await toolNamed('getFigureSource').builder({}, ctx())
|
|
306
306
|
|
|
307
307
|
expect(result.id).toBe('fig-1')
|
|
@@ -316,7 +316,7 @@ describe('대화면 문맥에서 대상을 해소한다', () => {
|
|
|
316
316
|
expect(result.source).toBeUndefined()
|
|
317
317
|
})
|
|
318
318
|
|
|
319
|
-
it('목록에서 대상을 찾아 다시 호출하면 해당
|
|
319
|
+
it('목록에서 대상을 찾아 다시 호출하면 해당 피규어의 정본을 읽는다', async () => {
|
|
320
320
|
const catalog = await toolNamed('listFigures').builder({}, ctx({}))
|
|
321
321
|
const target = catalog.figures.find((figure: any) => figure.name === '믹서')
|
|
322
322
|
const result = await toolNamed('getFigureSource').builder({ figureId: target.id }, ctx({}))
|
|
@@ -324,7 +324,7 @@ describe('대화면 문맥에서 대상을 해소한다', () => {
|
|
|
324
324
|
expect(result.source.name).toBe('Mixer')
|
|
325
325
|
})
|
|
326
326
|
|
|
327
|
-
it('정본이 없는
|
|
327
|
+
it('정본이 없는 피규어는 없다고 말한다 — 지어내지 않는다', async () => {
|
|
328
328
|
const result = await toolNamed('getFigureSource').builder({ figureId: 'fig-blank' }, ctx())
|
|
329
329
|
|
|
330
330
|
expect(result.source).toBeNull()
|
|
@@ -344,7 +344,7 @@ describe('대화면 문맥에서 대상을 해소한다', () => {
|
|
|
344
344
|
있고, 그것을 그대로 믿으면 남의 테넌트를 읽는다.
|
|
345
345
|
*/
|
|
346
346
|
describe('모델이 넘긴 id 를 믿지 않는다', () => {
|
|
347
|
-
it('다른 도메인의
|
|
347
|
+
it('다른 도메인의 피규어는 못 찾았다고 한다', async () => {
|
|
348
348
|
await expect(toolNamed('getFigureSource').builder({ figureId: 'fig-other' }, ctx())).rejects.toThrow(
|
|
349
349
|
/not found in this tenant/
|
|
350
350
|
)
|
|
@@ -362,7 +362,7 @@ describe('모델이 넘긴 id 를 믿지 않는다', () => {
|
|
|
362
362
|
expect(result.figures.map((one: any) => one.id)).toEqual(['fig-1', 'fig-blank'])
|
|
363
363
|
})
|
|
364
364
|
|
|
365
|
-
it('도구 설명이 저장 전
|
|
365
|
+
it('도구 설명이 저장 전 피규어는 모델러에 열린 것만 읽는다고 말한다', () => {
|
|
366
366
|
const description = toolNamed('getFigureSource').schema.properties.figureId.description
|
|
367
367
|
expect(description).not.toMatch(/never saved is not open/)
|
|
368
368
|
expect(description).toMatch(/not saved yet/)
|
|
@@ -394,7 +394,7 @@ describe('목록이 잘릴 때', () => {
|
|
|
394
394
|
expect(result.note).toMatch(/search/)
|
|
395
395
|
})
|
|
396
396
|
|
|
397
|
-
it('이름이나 타입의 일부로 찾으면 잘린 뒤의
|
|
397
|
+
it('이름이나 타입의 일부로 찾으면 잘린 뒤의 피규어도 나온다 — 대소문자 없이', async () => {
|
|
398
398
|
const byName = await toolNamed('listFigures').builder({ search: 'roll PRESS' }, ctx({}))
|
|
399
399
|
const byType = await toolNamed('listFigures').builder({ search: 'old_press' }, ctx({}))
|
|
400
400
|
expect(byName.figures.map((one: any) => one.id)).toEqual(['fig-old'])
|
|
@@ -411,7 +411,7 @@ describe('목록이 잘릴 때', () => {
|
|
|
411
411
|
|
|
412
412
|
/*
|
|
413
413
|
제안은 모델러의 명령 목록이다(ADR-0094). 고치는 제안은 모델러가 모델이 본 판 위에 한 단계로 적용하므로, 고칠 수
|
|
414
|
-
있는 것은 모델러에 열린
|
|
414
|
+
있는 것은 모델러에 열린 피규어뿐이고 그 판(context · revision)을 문맥이 싣고 와야 한다.
|
|
415
415
|
*/
|
|
416
416
|
const figureDraft = () => {
|
|
417
417
|
const model = require('@hatiolab/figure-model')
|
|
@@ -422,7 +422,7 @@ const figureDraft = () => {
|
|
|
422
422
|
const modeller = (over: any = {}) => ({ figureId: 'fig-1', draftSource: figureDraft(), context: 'ctx-7', revision: 4, ...over })
|
|
423
423
|
|
|
424
424
|
describe('제안을 요청할 때', () => {
|
|
425
|
-
it('열린
|
|
425
|
+
it('열린 피규어를 고치면 그 초안이 제안기에 가고, 모델러가 적용할 판이 함께 돌아온다', async () => {
|
|
426
426
|
const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '다리를 길게' }, ctx(modeller()))
|
|
427
427
|
expect(proposed[0].base.name).toBe('Probe')
|
|
428
428
|
expect(proposed[0].base.version).toBe('figure-asset-1')
|
|
@@ -438,19 +438,19 @@ describe('제안을 요청할 때', () => {
|
|
|
438
438
|
expect(proposed).toHaveLength(0)
|
|
439
439
|
})
|
|
440
440
|
|
|
441
|
-
it('모델러에 열리지 않은
|
|
441
|
+
it('모델러에 열리지 않은 피규어는 고치지 않고, 열라고 말한다', async () => {
|
|
442
442
|
const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '고쳐줘', figureId: 'fig-blank' }, ctx(modeller()))
|
|
443
443
|
expect(out.error).toBe('FIGURE_NOT_OPEN')
|
|
444
444
|
expect(proposed).toHaveLength(0)
|
|
445
445
|
})
|
|
446
446
|
|
|
447
|
-
it('원본이 없는
|
|
447
|
+
it('원본이 없는 피규어는 고치지 않는다 — 빈 것을 제안기에 건네지 않는다', async () => {
|
|
448
448
|
const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '고쳐줘' }, ctx({ figureId: 'fig-blank', context: 'c', revision: 1 }))
|
|
449
449
|
expect(out.error).toBe('FIGURE_NOT_OPEN')
|
|
450
450
|
expect(proposed).toHaveLength(0)
|
|
451
451
|
})
|
|
452
452
|
|
|
453
|
-
it('목록에서 새 제작은 열린
|
|
453
|
+
it('목록에서 새 제작은 열린 피규어를 요구하지 않는다', async () => {
|
|
454
454
|
const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '믹서를 새로 만들어줘', create: true, name: 'Mixer' }, ctx({}))
|
|
455
455
|
expect(out.proposed).toBe(true)
|
|
456
456
|
expect(proposed[0].base).toBeUndefined()
|
|
@@ -464,7 +464,7 @@ describe('제안을 요청할 때', () => {
|
|
|
464
464
|
expect(proposed[0].base).toBeUndefined()
|
|
465
465
|
})
|
|
466
466
|
|
|
467
|
-
it('create 를 켜면 열린
|
|
467
|
+
it('create 를 켜면 열린 피규어가 있어도 새로 만든다 — 열린 것을 덮어쓰는 제안이 오지 않게', async () => {
|
|
468
468
|
const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '새 컨베이어', create: true }, ctx(modeller()))
|
|
469
469
|
expect(proposed[0].base).toBeUndefined()
|
|
470
470
|
expect(out.revision).toBeUndefined()
|
|
@@ -474,7 +474,7 @@ describe('제안을 요청할 때', () => {
|
|
|
474
474
|
await expect(toolNamed('proposeFigureCandidate').builder({ prompt: ' ' }, ctx(modeller()))).rejects.toThrow(/prompt is required/)
|
|
475
475
|
})
|
|
476
476
|
|
|
477
|
-
it('남의
|
|
477
|
+
it('남의 피규어를 고치라고 하면 못 찾았다고 한다', async () => {
|
|
478
478
|
await expect(
|
|
479
479
|
toolNamed('proposeFigureCandidate').builder({ prompt: '고쳐줘', figureId: 'fig-other' }, ctx(modeller()))
|
|
480
480
|
).rejects.toThrow(/not found in this tenant/)
|
|
@@ -600,7 +600,7 @@ describe('사람이 붙인 그림', () => {
|
|
|
600
600
|
})
|
|
601
601
|
})
|
|
602
602
|
|
|
603
|
-
describe('
|
|
603
|
+
describe('피규어가 모델러에 열려 있을 때', () => {
|
|
604
604
|
it('저장 전 초안을 이 모델로 읽고, 셈으로 잰다', async () => {
|
|
605
605
|
const draft = figureDraft()
|
|
606
606
|
const got = await toolNamed('getFigureSource').builder({}, ctx({ figureId: 'fig-1', draftSource: draft, palette: ['palette.primary'] }))
|
|
@@ -639,7 +639,7 @@ describe('도형이 모델러에 열려 있을 때', () => {
|
|
|
639
639
|
expect(got.trying).toEqual({ clips: { open: 1 } })
|
|
640
640
|
})
|
|
641
641
|
|
|
642
|
-
it('저장된 정본을 읽을 때는 화면의 선택을 붙이지 않는다 — 다른
|
|
642
|
+
it('저장된 정본을 읽을 때는 화면의 선택을 붙이지 않는다 — 다른 피규어의 선택일 수 있다', async () => {
|
|
643
643
|
const got = await toolNamed('getFigureSource').builder({ figureId: 'fig-1' }, ctx({ selection: { part: 'body', context: 'c', revision: 1 }, context: 'c', revision: 1 }))
|
|
644
644
|
expect(got.draft).toBe(false)
|
|
645
645
|
expect(got.selection).toBeUndefined()
|
|
@@ -661,7 +661,7 @@ describe('도형이 모델러에 열려 있을 때', () => {
|
|
|
661
661
|
Until then the tools refused any draft over 100,000 characters: a figure that opened and saved got no read, no
|
|
662
662
|
inspection and no proposal, and saving again did not help. Now it is read as an outline and the parts asked for.
|
|
663
663
|
*/
|
|
664
|
-
describe('
|
|
664
|
+
describe('피규어가 한 번에 보일 만큼보다 클 때', () => {
|
|
665
665
|
const { FIGURE_CONTEXT_BUDGET } = require('./figure-context')
|
|
666
666
|
const model = require('@hatiolab/figure-model')
|
|
667
667
|
let under: any
|
|
@@ -770,7 +770,7 @@ describe('도형이 한 번에 보일 만큼보다 클 때', () => {
|
|
|
770
770
|
the screen sent, through the same door a save goes through. Only the figure open on that screen: an id the model passes
|
|
771
771
|
that has no row and is not the open one is still not found.
|
|
772
772
|
*/
|
|
773
|
-
describe('저장 전
|
|
773
|
+
describe('저장 전 피규어', () => {
|
|
774
774
|
const CREATION = '33333333-3333-4333-8333-333333333333'
|
|
775
775
|
const unsaved = (over: any = {}) => modeller({ figureId: CREATION, editorMode: 'new', ...over })
|
|
776
776
|
|
|
@@ -811,7 +811,7 @@ describe('저장 전 도형', () => {
|
|
|
811
811
|
await expect(toolNamed('getFigureSource').builder({}, ctx({ figureId: CREATION, editorMode: 'new' }))).rejects.toThrow(/not found in this tenant/)
|
|
812
812
|
})
|
|
813
813
|
|
|
814
|
-
it('생성 식별자 꼴이 아닌 이름은 저장 전
|
|
814
|
+
it('생성 식별자 꼴이 아닌 이름은 저장 전 피규어로 읽지 않는다', async () => {
|
|
815
815
|
await expect(toolNamed('getFigureSource').builder({}, ctx(unsaved({ figureId: 'fig-unknown' })))).rejects.toThrow(/not found in this tenant/)
|
|
816
816
|
})
|
|
817
817
|
})
|
|
@@ -100,7 +100,7 @@ function requireDomainId(state: any): string {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
* 이
|
|
103
|
+
* 이 피규어가 호출자 도메인 것인가.
|
|
104
104
|
*
|
|
105
105
|
* 모델이 넘긴 id 를 그대로 쓰지 않는다. 없으면 못 찾았다고 말한다 — 「권한이 없다」와 구별해
|
|
106
106
|
* 알려 줄 것이 없다(다른 테넌트에 그 id 가 있다는 사실 자체가 알려 줄 것이 아니다).
|
|
@@ -211,8 +211,8 @@ function focusOf(host: any, source: any): { selection?: { part: string }; trying
|
|
|
211
211
|
/**
|
|
212
212
|
* 무엇을 고치라는 것인지 대화면 문맥에서 해소한다.
|
|
213
213
|
*
|
|
214
|
-
* 모델이 대상을 안 줬으면 **저작면이 지금 열고 있는
|
|
215
|
-
* 않는다 — 화면에 그
|
|
214
|
+
* 모델이 대상을 안 줬으면 **저작면이 지금 열고 있는 피규어**이다. 사용자에게 식별자를 되묻지
|
|
215
|
+
* 않는다 — 화면에 그 피규어가 떠 있는데 「어느 피규어입니까」를 묻는 것은 문맥을 안 읽은 것이다.
|
|
216
216
|
*/
|
|
217
217
|
function figureIdFrom(args: any, host: any): string | undefined {
|
|
218
218
|
const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''
|
|
@@ -303,7 +303,7 @@ function figureToolSpecs(): ToolSpec[] {
|
|
|
303
303
|
{
|
|
304
304
|
kind: 'read',
|
|
305
305
|
name: 'listFigures',
|
|
306
|
-
/* 이 도메인의
|
|
306
|
+
/* 이 도메인의 피규어 목록 — 저장소를 직접 읽지만 같은 일을 하는 문은 이것이다. */
|
|
307
307
|
doors: ['Query.figures'],
|
|
308
308
|
description:
|
|
309
309
|
'Lists the figures in this tenant with their type names, states and part counts. ' +
|
|
@@ -354,8 +354,8 @@ function figureToolSpecs(): ToolSpec[] {
|
|
|
354
354
|
{
|
|
355
355
|
kind: 'read',
|
|
356
356
|
name: 'getFigureSource',
|
|
357
|
-
/* 저장된
|
|
358
|
-
* 그 갈래에는 닿는 문이 없지만 `doors: []` 로 적지 않는다. 그러면 저장된
|
|
357
|
+
/* 저장된 피규어의 원본. **저장 전 초안**을 물으면 저장소에 갈 것이 없어 화면이 보낸 것을 그대로 돌려준다 —
|
|
358
|
+
* 그 갈래에는 닿는 문이 없지만 `doors: []` 로 적지 않는다. 그러면 저장된 피규어를 읽는 권한 검사가 선언에서 사라진다. */
|
|
359
359
|
doors: ['Query.figure'],
|
|
360
360
|
description:
|
|
361
361
|
'Returns the source (the figure asset) of one figure, with its measured cost ' +
|
|
@@ -467,12 +467,12 @@ function figureToolSpecs(): ToolSpec[] {
|
|
|
467
467
|
if (!prompt) throw new Error('prompt is required: there is nothing to ask for')
|
|
468
468
|
|
|
469
469
|
/*
|
|
470
|
-
고치는 것인지 만드는 것인지를 **문맥에서 정한다.** 열린
|
|
471
|
-
모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는
|
|
470
|
+
고치는 것인지 만드는 것인지를 **문맥에서 정한다.** 열린 피규어가 있으면 고치는 것이 기본이고,
|
|
471
|
+
모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는 피규어를 덮어쓰는
|
|
472
472
|
후보가 온다.
|
|
473
473
|
|
|
474
474
|
고치는 제안은 모델러가 **요청 당시의 판(context · revision)** 위에 한 단계로 적용한다(ADR-0094).
|
|
475
|
-
그래서 고칠 수 있는 것은 모델러에 열린
|
|
475
|
+
그래서 고칠 수 있는 것은 모델러에 열린 피규어뿐이고, 그 판을 문맥이 함께 실어 와야 한다.
|
|
476
476
|
*/
|
|
477
477
|
const host = ctx?.host
|
|
478
478
|
const create = args?.create === true || args?.figureId === null
|
|
@@ -48,8 +48,8 @@ export class NewFigure {
|
|
|
48
48
|
*
|
|
49
49
|
* `type` 은 **한 번도 발행되지 않은 초안에서만** 바뀐다(ADR-0063 결정 4). 저장되는 식별자라
|
|
50
50
|
* 발행된 뒤에 바꾸면 이미 배치된 보드가 타입을 못 찾아 오류 없이 빈 화면이 된다. 발행 전에는
|
|
51
|
-
* 그
|
|
52
|
-
*
|
|
51
|
+
* 그 피규어를 가리키는 도면이 있을 수 없다 — 도면은 최신 발행판을 그리므로 발행된 적 없는
|
|
52
|
+
* 피규어는 그려질 자리가 없다.
|
|
53
53
|
*
|
|
54
54
|
* 닫아 두었더니 저작자가 이름을 한 번도 정하지 못했다. 새 Figure 에는 기계가 지은 이름이
|
|
55
55
|
* 붙고(`FIGURE_MU6RJH47`) 칸에 자물쇠가 걸려서, 그 이름이 그대로 도면에 적히는 이름이 됐다.
|
|
@@ -20,7 +20,7 @@ import { Domain, longTextColumn } from '@things-factory/shell'
|
|
|
20
20
|
*
|
|
21
21
|
* `Board` 를 준용한다. 다른 점만 주석으로 적는다.
|
|
22
22
|
*
|
|
23
|
-
* ## 무엇을 담나 —
|
|
23
|
+
* ## 무엇을 담나 — 피규어 자산이다, 씬 모델이 아니다
|
|
24
24
|
*
|
|
25
25
|
* 형식은 `@hatiolab/figure-model` 이 정한다(`figure-asset-1`). 씬 컴포넌트 트리를 담지 않는다.
|
|
26
26
|
* 컴파일한 것도 저장하지 않는다 — 원본에서 파생되므로 소비하는 쪽이 커널로 컴파일한다. 저장하면 원본과 갈린다.
|
|
@@ -124,7 +124,7 @@ export class Figure {
|
|
|
124
124
|
/**
|
|
125
125
|
* 분류 하나. **팔레트에서 묶어 보이는 기준이다.**
|
|
126
126
|
*
|
|
127
|
-
*
|
|
127
|
+
* 피규어 하나에 하나뿐이다 — 팔레트는 목록을 한 벌로 나눠 보여 주므로, 한 피규어가 두 묶음에
|
|
128
128
|
* 동시에 있으면 저작자가 같은 것을 두 번 만난다.
|
|
129
129
|
*/
|
|
130
130
|
@Column({ nullable: true })
|
package/translations/ko.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
"error.figure-proposal-failed": "
|
|
2
|
+
"error.figure-proposal-failed": "피규어를 만들지 못했습니다.",
|
|
3
3
|
"error.figure-release-does-not-compile": "{type} 의 발행판({version})이 지금 컴파일되지 않습니다. 저작 화면에서 열어 수정한 후 다시 발행해야 보드에 나옵니다.",
|
|
4
4
|
"figure.gate.parts-off-placement-face.how": "'{part}' 부품을 Y 로 {mm}mm 옮겨 그 면을 평면에 맞추거나, 장착면을 다른 면으로 다시 정하세요.",
|
|
5
5
|
"figure.gate.parts-off-placement-face.message": "장착면으로 정한 '{part}' 부품의 면이 놓이는 평면에서 {mm}mm 떨어져 있습니다.",
|
|
6
|
-
"figure.gate.parts-off-placement-face.why": "
|
|
6
|
+
"figure.gate.parts-off-placement-face.why": "피규어는 그 면으로 놓인다고 선언돼 있습니다. 닿지 않으면 도면에서 그만큼 떠 보이고, 자리에 놓인 물건도 함께 뜹니다.",
|
|
7
7
|
"figure.gate.parts-split-on-resize.how": "{parts} 부품을 올려 둔 부품의 면에 붙이거나, 반응형 탭의 「위치」에서 「여기에 고정」을 누르면 크기를 바꿔도 제자리에 있습니다.",
|
|
8
8
|
"figure.gate.parts-split-on-resize.message": "크기를 {axes} 로 {factor}배로 하면 {parts} 부품이 나머지에서 떨어집니다.",
|
|
9
|
-
"figure.gate.parts-split-on-resize.why": "다른 크기로 놓으면 그 부품이 공중에 떠 보입니다. 보는 사람에게는 부서진
|
|
10
|
-
"figure.gate.sizing-not-uniform.how": "{parts} 부품이
|
|
11
|
-
"figure.gate.sizing-not-uniform.message": "이
|
|
12
|
-
"figure.gate.sizing-not-uniform.why": "균일한 비율로 확대되는
|
|
9
|
+
"figure.gate.parts-split-on-resize.why": "다른 크기로 놓으면 그 부품이 공중에 떠 보입니다. 보는 사람에게는 부서진 피규어입니다.",
|
|
10
|
+
"figure.gate.sizing-not-uniform.how": "{parts} 부품이 피규어 크기에 비례하도록 반응형 탭의 「위치」에서 「크기에 비례」를 설정해 주세요. 치수가 고정된 부품은 같은 비율로 확대되지 않습니다.",
|
|
11
|
+
"figure.gate.sizing-not-uniform.message": "이 피규어는 한 비율로 커지는데, 크기를 {axes} 로 {factor}배로 하면 {parts} 부품은 같이 커지지 않습니다.",
|
|
12
|
+
"figure.gate.sizing-not-uniform.why": "균일한 비율로 확대되는 피규어는 부품 간 비율이 유지됩니다. 치수나 위치가 고정된 부품은 다른 부품과 정렬이 어긋날 수 있습니다.",
|
|
13
13
|
"figure.gate.placement-face-tilted.how": "평면과 나란한 면을 장착면으로 다시 정하거나, '{part}' 부품을 바로 세우세요.",
|
|
14
14
|
"figure.gate.placement-face-tilted.message": "장착면으로 정한 '{part}' 부품의 면이 놓이는 평면에서 {degrees}° 기울어 있습니다.",
|
|
15
|
-
"figure.gate.placement-face-tilted.why": "기운 면은 평면에 닿을 수 없어서,
|
|
16
|
-
"figure.gate.type-is-placeholder.how": "타입 항목에
|
|
15
|
+
"figure.gate.placement-face-tilted.why": "기운 면은 평면에 닿을 수 없어서, 피규어가 어떤 자세로 놓이는지 정해지지 않습니다.",
|
|
16
|
+
"figure.gate.type-is-placeholder.how": "타입 항목에 피규어 타입을 지정한 후 발행해 주세요.",
|
|
17
17
|
"figure.gate.type-is-placeholder.message": "'{type}' 타입은 처음 저장할 때 붙은 임시 타입입니다.",
|
|
18
|
-
"figure.gate.type-is-placeholder.why": "보드는 이 타입으로
|
|
18
|
+
"figure.gate.type-is-placeholder.why": "보드는 이 타입으로 피규어를 부르고, 발행한 뒤에는 바꿀 수 없습니다.",
|
|
19
19
|
"figure.gate.released-not-compared.message": "직전 발행본과 비교하지 못했습니다. 현재는 발행본 간 비교를 지원하지 않습니다.",
|
|
20
20
|
"figure.gate.released-not-compared.why": "이번 발행이 기존에 배치된 인스턴스와 호환되는지 확인되지 않았습니다.",
|
|
21
|
-
"figure.gate.contract.gone.how": "기존 정의를 복원하거나 새
|
|
21
|
+
"figure.gate.contract.gone.how": "기존 정의를 복원하거나 새 피규어 타입으로 발행해 주세요. 새 타입으로 발행하면 기존에 배치된 피규어는 이전 정의를 유지합니다.",
|
|
22
22
|
"figure.gate.contract.placement-changed.message": "배치 기준이 {before} 에서 {after} 로 바뀌었습니다.",
|
|
23
23
|
"figure.gate.contract.placement-changed.why": "놓인 인스턴스의 높이를 배치 기준이 정합니다. 놓인 것이 모두 함께 옮겨 갑니다.",
|
|
24
|
-
"figure.gate.contract.size-inputs-gone.message": "
|
|
24
|
+
"figure.gate.contract.size-inputs-gone.message": "피규어가 더 이상 도면에서 받은 크기를 따르지 않습니다.",
|
|
25
25
|
"figure.gate.contract.size-inputs-gone.why": "놓인 인스턴스는 도면에서 크기를 맞춰 두었습니다. 이 발행 뒤에는 모두 저작한 크기로 그려집니다.",
|
|
26
|
-
"figure.gate.contract.size-inputs-added.message": "
|
|
26
|
+
"figure.gate.contract.size-inputs-added.message": "피규어가 이제 도면에서 받은 크기를 따릅니다.",
|
|
27
27
|
"figure.gate.contract.size-inputs-added.why": "놓인 인스턴스가 이제 도면의 제 크기를 따릅니다.",
|
|
28
28
|
"figure.gate.contract.size-range-narrowed.message": "{input} 의 크기 범위가 {before} 에서 {after} 로 좁아졌습니다.",
|
|
29
29
|
"figure.gate.contract.size-range-narrowed.why": "새 범위 밖의 크기로 놓인 인스턴스는 그려지지 않습니다. 어떤 크기로 놓였는지는 기록되지 않습니다.",
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
"figure.gate.contract.capability-gone.why": "씬이 이 이름으로 동작을 붙입니다. 놓인 인스턴스가 그 동작을 잃습니다.",
|
|
56
56
|
"figure.gate.contract.capability-added.message": "'{name}' 능력이 새로 생겼습니다.",
|
|
57
57
|
"figure.gate.contract.capability-added.why": "사용 가능한 기능이 추가됩니다. 기존 인스턴스의 상태는 유지됩니다.",
|
|
58
|
-
"figure.gate.contract.size-changed.message": "
|
|
59
|
-
"figure.gate.contract.size-changed.why": "보드는 이 크기의 상자로
|
|
58
|
+
"figure.gate.contract.size-changed.message": "피규어의 크기가 바뀌었습니다: {before} → {after}.",
|
|
59
|
+
"figure.gate.contract.size-changed.why": "보드는 이 크기의 상자로 피규어를 놓습니다. 이 발행본으로 옮기면 상자가 바뀝니다.",
|
|
60
60
|
"figure.gate.contract.motion-range-changed.message": "움직일 때 쓸어 가는 공간이 바뀌었습니다: {before} → {after}.",
|
|
61
|
-
"figure.gate.contract.motion-range-changed.why": "
|
|
62
|
-
"figure.gate.contract.contact-face-changed.message": "
|
|
61
|
+
"figure.gate.contract.motion-range-changed.why": "피규어가 움직이며 닿는 곳입니다. 이 발행본으로 옮기면 닿는 곳이 달라집니다.",
|
|
62
|
+
"figure.gate.contract.contact-face-changed.message": "피규어가 붙는 면이 바뀌었습니다.",
|
|
63
63
|
"figure.gate.contract.contact-face-changed.why": "이 발행본을 적용하면 새로운 접촉면을 기준으로 배치됩니다.",
|
|
64
64
|
"figure.gate.contract.public-input-gone.message": "'{input}' 값은 이제 보드에서 정할 수 없습니다.",
|
|
65
65
|
"figure.gate.contract.public-input-gone.why": "놓인 인스턴스가 준 값은 이 발행본부터 아무 일도 하지 않습니다.",
|
|
@@ -88,25 +88,25 @@
|
|
|
88
88
|
"figure.gate.off-mounting-plane.floor.clear.message": "'{part}' 부품이 바닥에서 {mm}mm 떠 있습니다.",
|
|
89
89
|
"figure.gate.off-mounting-plane.floor.through.message": "'{part}' 부품이 바닥 아래로 {mm}mm 내려가 있습니다.",
|
|
90
90
|
"figure.gate.off-mounting-plane.floor.beyond.message": "모든 부품이 바닥 아래에 있습니다.",
|
|
91
|
-
"figure.gate.off-mounting-plane.floor.why": "보드는 이
|
|
91
|
+
"figure.gate.off-mounting-plane.floor.why": "보드는 이 피규어를 바닥에 세웁니다. 어느 보드에서나 지금 모습 그대로 놓입니다.",
|
|
92
92
|
"figure.gate.off-mounting-plane.floor.beyond.how": "천장에 매다는 설비라면 놓이는 곳을 천장으로 바꿉니다.",
|
|
93
93
|
"figure.gate.off-mounting-plane.ceiling.clear.message": "'{part}' 부품이 천장에서 {mm}mm 아래에 있습니다.",
|
|
94
94
|
"figure.gate.off-mounting-plane.ceiling.through.message": "'{part}' 부품이 천장 위로 {mm}mm 올라가 있습니다.",
|
|
95
95
|
"figure.gate.off-mounting-plane.ceiling.beyond.message": "모든 부품이 천장 위에 있습니다.",
|
|
96
|
-
"figure.gate.off-mounting-plane.ceiling.why": "보드는 이
|
|
96
|
+
"figure.gate.off-mounting-plane.ceiling.why": "보드는 이 피규어를 천장에 매답니다. 어느 보드에서나 지금 모습 그대로 놓입니다.",
|
|
97
97
|
"figure.gate.off-mounting-plane.ceiling.beyond.how": "바닥에 세우는 설비라면 놓이는 곳을 바닥으로 바꿉니다.",
|
|
98
98
|
"figure.gate.off-mounting-plane.wall.clear.message": "'{part}' 부품이 벽에서 {mm}mm 떨어져 있습니다.",
|
|
99
99
|
"figure.gate.off-mounting-plane.wall.through.message": "'{part}' 부품이 벽 안으로 {mm}mm 들어가 있습니다.",
|
|
100
100
|
"figure.gate.off-mounting-plane.wall.beyond.message": "모든 부품이 벽 뒤에 있습니다.",
|
|
101
|
-
"figure.gate.off-mounting-plane.wall.why": "보드는 이
|
|
101
|
+
"figure.gate.off-mounting-plane.wall.why": "보드는 이 피규어를 벽에 붙입니다. 어느 보드에서나 지금 모습 그대로 놓입니다.",
|
|
102
102
|
"figure.gate.off-mounting-plane.wall.beyond.how": "부품을 벽 앞으로 옮기거나 놓이는 곳을 다시 고릅니다.",
|
|
103
103
|
"figure.gate.off-mounting-plane.how": "의도한 것이면 그대로 둡니다. 아니면 그 부품을 장착 평면에 붙이거나, 평면에 닿도록 옮깁니다.",
|
|
104
|
-
"error.figure-namespace-missing": "이 도메인에는 기본
|
|
105
|
-
"error.figure-namespace-invalid": "
|
|
106
|
-
"error.figure-type-malformed": "{type} 은
|
|
104
|
+
"error.figure-namespace-missing": "이 도메인에는 기본 피규어 namespace 가 없습니다. 먼저 namespace 를 추가해 주세요.",
|
|
105
|
+
"error.figure-namespace-invalid": "피규어 namespace 형식이 아닙니다({value}). 영문 소문자·숫자·점·하이픈으로 입력해 주세요. 예: hatiolab.com",
|
|
106
|
+
"error.figure-type-malformed": "{type} 은 피규어 type 이 아닙니다. 소문자로 시작하고 소문자·숫자·하이픈 하나씩만 써서 {min}~{max}자로 정해 주세요.",
|
|
107
107
|
"error.figure-name-malformed": "{type} 은 namespace/type 형식의 정식 이름이 아닙니다.",
|
|
108
108
|
"error.figure-not-released": "이 도메인에 발행판이 없습니다.",
|
|
109
|
-
"error.figure-names-too-many": "
|
|
109
|
+
"error.figure-names-too-many": "피규어 이름은 한 번에 {max}개까지 물을 수 있습니다({count}개).",
|
|
110
110
|
"error.figure-package-size": "패키지에 포함할 수 있는 발행본은 1~{max}개입니다. 현재 {count}개가 지정되어 있습니다.",
|
|
111
111
|
"error.figure-ref-malformed": "{ref} 은 namespace/type@버전 형식의 발행판 참조가 아닙니다.",
|
|
112
112
|
"error.figure-package-release-not-found": "{ref} 은 이 도메인에서 읽을 수 있는 발행판이 아닙니다.",
|
|
@@ -117,20 +117,20 @@
|
|
|
117
117
|
"error.figure-mesh-extension": "보드가 아직 이 파일을 그리지 못합니다: {extensions} 가 필요합니다. 그 압축 없이 내보내 다시 업로드해 주세요.",
|
|
118
118
|
"error.figure-mesh-empty": "파일에 그릴 메시가 없습니다.",
|
|
119
119
|
"error.figure-mesh-too-large": "파일이 {max} MB 보다 큽니다. 보드가 부품 하나에 내려받는 최대 크기입니다. 줄여서 다시 업로드해 주세요.",
|
|
120
|
-
"error.figure-mesh-missing": "이
|
|
120
|
+
"error.figure-mesh-missing": "이 피규어가 쓰는 메시 파일({hash})이 이 도메인에 없습니다. 파일을 다시 업로드해 주세요.",
|
|
121
121
|
"error.figure-package-mesh-missing": "{ref} 가 쓰는 메시 파일({hash})이 이 서버에 없어 묶을 수 없습니다.",
|
|
122
122
|
"figure.gate.contract.data-field-gone.message": "'{id}' 데이터 필드가 없어졌습니다.",
|
|
123
123
|
"figure.gate.contract.data-field-gone.why": "보드는 데이터를 이 ID에 대응합니다. 이 발행 뒤에는 그 데이터가 아무것도 움직이지 않습니다.",
|
|
124
124
|
"figure.gate.contract.data-field-kind-changed.message": "'{id}' 데이터 필드가 {before} 에서 {after} 로 바뀌었습니다.",
|
|
125
125
|
"figure.gate.contract.data-field-kind-changed.why": "대응한 데이터는 이전 종류나 단위로 쓰였습니다. 이 발행 뒤에는 같은 데이터가 거절되거나 다른 뜻이 됩니다.",
|
|
126
126
|
"figure.gate.contract.data-field-narrowed.message": "'{id}' 데이터 필드가 받는 값이 줄었습니다: {before} → {after}.",
|
|
127
|
-
"figure.gate.contract.data-field-narrowed.why": "더 받지 않는 값이 든 데이터는 통째로 거절되고,
|
|
127
|
+
"figure.gate.contract.data-field-narrowed.why": "더 받지 않는 값이 든 데이터는 통째로 거절되고, 피규어는 직전 모습을 유지합니다.",
|
|
128
128
|
"figure.gate.contract.data-field-added.message": "'{id}' 데이터 필드가 새로 생겼습니다.",
|
|
129
129
|
"figure.gate.contract.data-field-added.why": "보드에서 데이터 매핑을 설정하기 전까지 기본값이 적용됩니다.",
|
|
130
130
|
"figure.gate.contract.data-field-label-changed.message": "'{id}' 데이터 필드의 이름이 '{after}' 이름으로 바뀌었습니다.",
|
|
131
131
|
"figure.gate.contract.data-field-label-changed.why": "대응은 ID로 하므로 그대로 동작합니다.",
|
|
132
132
|
"figure.gate.contract.data-field-default-changed.message": "'{id}' 데이터 필드의 기본값이 {before} 에서 {after} 로 바뀌었습니다.",
|
|
133
|
-
"figure.gate.contract.data-field-default-changed.why": "데이터나 저장된 값이 없는
|
|
133
|
+
"figure.gate.contract.data-field-default-changed.why": "데이터나 저장된 값이 없는 피규어는 발행 후 변경된 기본값에 따라 표시됩니다.",
|
|
134
134
|
"figure.gate.contract.data-bindings-changed.message": "데이터가 움직이는 대상(바인딩)이 바뀌었습니다.",
|
|
135
135
|
"figure.gate.contract.data-bindings-changed.why": "이 발행 뒤에는 같은 데이터가 다른 자세, 색, 클립을 만듭니다.",
|
|
136
136
|
"figure.gate.contract.motion-group-gone.message": "'{group}' 동작 그룹이 없어졌습니다.",
|
|
@@ -156,13 +156,13 @@
|
|
|
156
156
|
"figure.proposal.label-create": "{name} 만들기",
|
|
157
157
|
"figure.proposal.label-revise": "{name} 수정",
|
|
158
158
|
"figure.proposal.reason": "명령 {steps}개 · 등급 {grade} · 삼각형 {triangles} · {attempts}번에 만들었다",
|
|
159
|
-
"error.figure-released-not-deletable": "{type} 은 발행한
|
|
160
|
-
"error.figure-namespace-taken": "
|
|
161
|
-
"error.figure-namespace-not-owned": "이 도메인은
|
|
162
|
-
"error.figure-namespace-suspended": "
|
|
159
|
+
"error.figure-released-not-deletable": "{type} 은 발행한 피규어라 지울 수 없습니다.",
|
|
160
|
+
"error.figure-namespace-taken": "피규어 namespace {namespace} 는 이 서버에서 이미 쓰고 있습니다.",
|
|
161
|
+
"error.figure-namespace-not-owned": "이 도메인은 피규어 namespace {namespace} 를 갖고 있지 않습니다.",
|
|
162
|
+
"error.figure-namespace-suspended": "피규어 namespace {namespace} 는 쉬는 중입니다.",
|
|
163
163
|
"error.figure-namespace-default-suspended": "기본 namespace {namespace} 는 쉬게 할 수 없습니다. 먼저 다른 namespace 를 기본으로 정해 주세요.",
|
|
164
164
|
"error.figure-namespace-state": "{state} 는 namespace 상태가 아닙니다. active 나 suspended 를 쓰세요.",
|
|
165
|
-
"error.figure-public-unreleased": "{type} 은 아직 발행하지 않았습니다. 발행한
|
|
165
|
+
"error.figure-public-unreleased": "{type} 은 아직 발행하지 않았습니다. 발행한 피규어만 공개할 수 있습니다.",
|
|
166
166
|
"error.figure-category-fixed": "분류 {category}은(는) 최초 지정 후 변경할 수 없습니다.",
|
|
167
167
|
"error.figure-category-unknown": "{category}은(는) 지원하지 않는 분류입니다. {allowed} 중 하나를 선택해 주세요.",
|
|
168
168
|
"error.figure-category-missing": "{type}의 분류가 지정되지 않았습니다. 발행하기 전에 {allowed} 중 하나를 선택해 주세요."
|