@operato/board 10.29.0 → 10.29.2

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.
@@ -1,10 +1,9 @@
1
1
  /**
2
- * What the server hands over for one released type: the figure asset under a `format` tag. The board does not read
3
- * the asset; the scene's own registration compiles it with the kernel (ADR-0087 decision 5). V1 and V2 are gone
4
- * (2026-09-26), so a payload that does not say `format: 'v3'` is not a figure this board can draw.
2
+ * What the server hands over for one released type: the figure asset. The board does not read the asset; the scene's
3
+ * own registration compiles it with the kernel (ADR-0087 decision 5), which refuses an asset of any other format by
4
+ * its version. A payload without an asset is not a figure this board can draw.
5
5
  */
6
6
  export type FigurePayload = {
7
- format: 'v3';
8
7
  type: string;
9
8
  asset: any;
10
9
  };
@@ -2,7 +2,7 @@
2
2
  * Copyright © HatioLab Inc. All rights reserved.
3
3
  */
4
4
  import gql from 'graphql-tag';
5
- import { Component, registerFigureV3, registerTypeResolver } from '@hatiolab/things-scene';
5
+ import { Component, registerFigure, registerTypeResolver } from '@hatiolab/things-scene';
6
6
  import { client, gqlContext } from '@operato/graphql';
7
7
  /*
8
8
  * Where a board gets the figures somebody authored.
@@ -31,9 +31,9 @@ const FIGURE_TYPE = /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/;
31
31
  /** Registers one released figure with the scene. Anything but a figure asset is refused by name. */
32
32
  export function registerFigurePayload(type, payload) {
33
33
  var _a;
34
- if ((payload === null || payload === void 0 ? void 0 : payload.format) !== 'v3')
34
+ if (!(payload === null || payload === void 0 ? void 0 : payload.asset) || typeof payload.asset !== 'object')
35
35
  throw new Error(`not a figure asset: ${type}`);
36
- registerFigureV3((_a = payload.type) !== null && _a !== void 0 ? _a : type, payload.asset);
36
+ registerFigure((_a = payload.type) !== null && _a !== void 0 ? _a : type, payload.asset);
37
37
  }
38
38
  const FETCH_FIGURE_BLUEPRINT = gql `
39
39
  query FetchFigureBlueprint($type: String!) {
@@ -1 +1 @@
1
- {"version":3,"file":"figure-provider.js","sourceRoot":"","sources":["../../src/figure-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport gql from 'graphql-tag'\n\nimport { Component, registerFigureV3, registerTypeResolver } from '@hatiolab/things-scene'\nimport { client, gqlContext } from '@operato/graphql'\n\n/*\n * Where a board gets the figures somebody authored.\n *\n * ── Why the seat is filled here ─────────────────────────────────────────────\n * things-scene keeps the seat (`registerTypeResolver`) and knows nothing about figures, GraphQL or\n * who published what. The board package is where a saved model already gets its values from the\n * server — `board-provider.ts` reads a board by id the same way — so this is where the types a\n * model names, and nobody has registered, get fetched. Putting it in the authoring package would\n * make every consumer drag the modeller along, and putting it in each app would make every app\n * build the same thing (ADR-0063 결정 2 · ADR-0045).\n *\n * ── What it asks for, and what it does not ──────────────────────────────────\n * Uppercase names are the figure namespace, so those are the only ones asked about: a model that\n * names `rect` or a mistyped `Conveyor` never reaches the server. A type that is already\n * registered is left alone — a figure never replaces a component that is already drawing.\n *\n * ── An answer of \"nobody published this\" is not a failure ───────────────────\n * `figureBlueprint` returns null for a type that has no released figure, and that type stays\n * unregistered on purpose: the scene draws it as a stand-in and saves it back untouched\n * (ADR-0063 결정 1). Being unable to ask at all is a different fact, so a transport or server\n * error rejects — `resolveUnknownTypes` reports those in `failed` and the board still opens.\n */\n\n/** The figure namespace: `EQ_MIXER`, `CONVEYOR`, `VEH_AGV_01`. */\nconst FIGURE_TYPE = /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/\n\n/**\n * What the server hands over for one released type: the figure asset under a `format` tag. The board does not read\n * the asset; the scene's own registration compiles it with the kernel (ADR-0087 decision 5). V1 and V2 are gone\n * (2026-09-26), so a payload that does not say `format: 'v3'` is not a figure this board can draw.\n */\nexport type FigurePayload = { format: 'v3'; type: string; asset: any }\n\n/** Asks for one type's payload. Null when no released figure carries that name. */\nexport type BlueprintFetch = (type: string) => Promise<FigurePayload | null>\n\n/** Registers one released figure with the scene. Anything but a figure asset is refused by name. */\nexport function registerFigurePayload(type: string, payload: FigurePayload): void {\n if ((payload as { format?: unknown })?.format !== 'v3') throw new Error(`not a figure asset: ${type}`)\n registerFigureV3(payload.type ?? type, payload.asset)\n}\n\nconst FETCH_FIGURE_BLUEPRINT = gql`\n query FetchFigureBlueprint($type: String!) {\n figureBlueprint(type: $type)\n }\n`\n\nexport const fetchFigureBlueprint: BlueprintFetch = async (type: string) => {\n const response = await client.query({\n query: FETCH_FIGURE_BLUEPRINT,\n variables: { type },\n context: gqlContext()\n })\n\n /*\n The client runs with errorPolicy 'all', so a rejected query comes back as a resolved response\n carrying `errors` and a null field. Without this the caller cannot tell \"no such figure\" from\n \"the door said no\".\n */\n const errors = (response as { errors?: readonly { message?: string }[] }).errors\n if (errors?.length) {\n throw new Error(errors.map(e => e?.message ?? String(e)).join('\\n'))\n }\n\n return response.data?.figureBlueprint ?? null\n}\n\n/**\n * Builds the resolver that fills things-scene's seat.\n *\n * `fetch` is a seam for tests — the default one talks to the server.\n */\nexport function createFigureResolver(fetch: BlueprintFetch = fetchFigureBlueprint) {\n return async function resolveFigureTypes(types: readonly string[]): Promise<void> {\n const asking = types.filter(type => FIGURE_TYPE.test(type) && !Component.register(type))\n if (asking.length === 0) {\n return\n }\n\n const failures: { type: string; error: unknown }[] = []\n\n await Promise.all(\n asking.map(async type => {\n try {\n const payload = await fetch(type)\n if (!payload) {\n /* Nobody published this type. It stays a stand-in. */\n return\n }\n\n registerFigurePayload(type, payload)\n } catch (error) {\n failures.push({ type, error })\n }\n })\n )\n\n if (failures.length > 0) {\n /*\n What did register stays registered — the seat reads the registry back, not what this says.\n The throw is how \"could not ask\" reaches `TypeResolution.failed`.\n */\n throw new Error(\n `Figure 를 가져오지 못했다:\\n${failures\n .map(({ type, error }) => ` - ${type}: ${error instanceof Error ? error.message : String(error)}`)\n .join('\\n')}`\n )\n }\n }\n}\n\n/**\n * Takes the seat. The package entry (`index.ts`) calls this, so an app that has `@operato/board`\n * gets published figures on its boards without registering anything itself. Returns the function\n * that takes the seat back.\n */\nexport function installFigureResolver(fetch: BlueprintFetch = fetchFigureBlueprint): () => void {\n return registerTypeResolver(createFigureResolver(fetch))\n}\n"]}
1
+ {"version":3,"file":"figure-provider.js","sourceRoot":"","sources":["../../src/figure-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport gql from 'graphql-tag'\n\nimport { Component, registerFigure, registerTypeResolver } from '@hatiolab/things-scene'\nimport { client, gqlContext } from '@operato/graphql'\n\n/*\n * Where a board gets the figures somebody authored.\n *\n * ── Why the seat is filled here ─────────────────────────────────────────────\n * things-scene keeps the seat (`registerTypeResolver`) and knows nothing about figures, GraphQL or\n * who published what. The board package is where a saved model already gets its values from the\n * server — `board-provider.ts` reads a board by id the same way — so this is where the types a\n * model names, and nobody has registered, get fetched. Putting it in the authoring package would\n * make every consumer drag the modeller along, and putting it in each app would make every app\n * build the same thing (ADR-0063 결정 2 · ADR-0045).\n *\n * ── What it asks for, and what it does not ──────────────────────────────────\n * Uppercase names are the figure namespace, so those are the only ones asked about: a model that\n * names `rect` or a mistyped `Conveyor` never reaches the server. A type that is already\n * registered is left alone — a figure never replaces a component that is already drawing.\n *\n * ── An answer of \"nobody published this\" is not a failure ───────────────────\n * `figureBlueprint` returns null for a type that has no released figure, and that type stays\n * unregistered on purpose: the scene draws it as a stand-in and saves it back untouched\n * (ADR-0063 결정 1). Being unable to ask at all is a different fact, so a transport or server\n * error rejects — `resolveUnknownTypes` reports those in `failed` and the board still opens.\n */\n\n/** The figure namespace: `EQ_MIXER`, `CONVEYOR`, `VEH_AGV_01`. */\nconst FIGURE_TYPE = /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/\n\n/**\n * What the server hands over for one released type: the figure asset. The board does not read the asset; the scene's\n * own registration compiles it with the kernel (ADR-0087 decision 5), which refuses an asset of any other format by\n * its version. A payload without an asset is not a figure this board can draw.\n */\nexport type FigurePayload = { type: string; asset: any }\n\n/** Asks for one type's payload. Null when no released figure carries that name. */\nexport type BlueprintFetch = (type: string) => Promise<FigurePayload | null>\n\n/** Registers one released figure with the scene. Anything but a figure asset is refused by name. */\nexport function registerFigurePayload(type: string, payload: FigurePayload): void {\n if (!(payload as { asset?: unknown })?.asset || typeof payload.asset !== 'object') throw new Error(`not a figure asset: ${type}`)\n registerFigure(payload.type ?? type, payload.asset)\n}\n\nconst FETCH_FIGURE_BLUEPRINT = gql`\n query FetchFigureBlueprint($type: String!) {\n figureBlueprint(type: $type)\n }\n`\n\nexport const fetchFigureBlueprint: BlueprintFetch = async (type: string) => {\n const response = await client.query({\n query: FETCH_FIGURE_BLUEPRINT,\n variables: { type },\n context: gqlContext()\n })\n\n /*\n The client runs with errorPolicy 'all', so a rejected query comes back as a resolved response\n carrying `errors` and a null field. Without this the caller cannot tell \"no such figure\" from\n \"the door said no\".\n */\n const errors = (response as { errors?: readonly { message?: string }[] }).errors\n if (errors?.length) {\n throw new Error(errors.map(e => e?.message ?? String(e)).join('\\n'))\n }\n\n return response.data?.figureBlueprint ?? null\n}\n\n/**\n * Builds the resolver that fills things-scene's seat.\n *\n * `fetch` is a seam for tests — the default one talks to the server.\n */\nexport function createFigureResolver(fetch: BlueprintFetch = fetchFigureBlueprint) {\n return async function resolveFigureTypes(types: readonly string[]): Promise<void> {\n const asking = types.filter(type => FIGURE_TYPE.test(type) && !Component.register(type))\n if (asking.length === 0) {\n return\n }\n\n const failures: { type: string; error: unknown }[] = []\n\n await Promise.all(\n asking.map(async type => {\n try {\n const payload = await fetch(type)\n if (!payload) {\n /* Nobody published this type. It stays a stand-in. */\n return\n }\n\n registerFigurePayload(type, payload)\n } catch (error) {\n failures.push({ type, error })\n }\n })\n )\n\n if (failures.length > 0) {\n /*\n What did register stays registered — the seat reads the registry back, not what this says.\n The throw is how \"could not ask\" reaches `TypeResolution.failed`.\n */\n throw new Error(\n `Figure 를 가져오지 못했다:\\n${failures\n .map(({ type, error }) => ` - ${type}: ${error instanceof Error ? error.message : String(error)}`)\n .join('\\n')}`\n )\n }\n }\n}\n\n/**\n * Takes the seat. The package entry (`index.ts`) calls this, so an app that has `@operato/board`\n * gets published figures on its boards without registering anything itself. Returns the function\n * that takes the seat back.\n */\nexport function installFigureResolver(fetch: BlueprintFetch = fetchFigureBlueprint): () => void {\n return registerTypeResolver(createFigureResolver(fetch))\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { expect } from '@open-wc/testing';
2
- import { Component, hasFigureV3, registerTypeResolver, resetFiguresV3, resolveUnknownTypes } from '@hatiolab/things-scene';
2
+ import { Component, hasFigure, registerTypeResolver, resetFigures, resolveUnknownTypes } from '@hatiolab/things-scene';
3
3
  import { createFigureResolver } from '../src/figure-provider.js';
4
4
  /**
5
5
  * The path a published figure takes to a board (ADR-0063 결정 2).
@@ -12,12 +12,12 @@ import { createFigureResolver } from '../src/figure-provider.js';
12
12
  * to the scene's own registration, and a fixture that drifts from the format should fail loudly here rather than
13
13
  * draw nothing at runtime.
14
14
  */
15
- /** What the door hands over: a figure asset under a `format` tag. One box standing on the floor, its room declared. */
16
- const v3AssetOf = (type) => ({
17
- version: 'figure-v3-asset-1',
15
+ /** What the door hands over: a figure asset. One box standing on the floor, its room declared. */
16
+ const figureAssetOf = (type) => ({
17
+ version: 'figure-asset-1',
18
18
  name: type,
19
19
  document: {
20
- version: 'figure-v3-prototype-1',
20
+ version: 'figure-prototype-1',
21
21
  model: {
22
22
  version: 'r3-spatial-1',
23
23
  inputs: [],
@@ -51,7 +51,7 @@ const v3AssetOf = (type) => ({
51
51
  placement: 'floor'
52
52
  }
53
53
  });
54
- const v3PayloadOf = (type) => ({ format: 'v3', type, asset: v3AssetOf(type) });
54
+ const figurePayloadOf = (type) => ({ type, asset: figureAssetOf(type) });
55
55
  /** Records what was asked for, and answers from a table. */
56
56
  function fetcherOf(published, failing = []) {
57
57
  const asked = [];
@@ -69,38 +69,38 @@ function fetcherOf(published, failing = []) {
69
69
  }
70
70
  describe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () => {
71
71
  afterEach(() => {
72
- resetFiguresV3();
72
+ resetFigures();
73
73
  });
74
74
  it('대문자 이름만 서버에 묻는다 — 씬의 기본 type 과 오타는 문을 지나지 않는다', async () => {
75
- const { asked, fetch } = fetcherOf({ EQ_MIXER: v3PayloadOf('EQ_MIXER') });
75
+ const { asked, fetch } = fetcherOf({ EQ_MIXER: figurePayloadOf('EQ_MIXER') });
76
76
  await createFigureResolver(fetch)(['EQ_MIXER', 'rect', 'Conveyor', 'text', 'VEH_AGV_01']);
77
77
  expect(asked).to.deep.equal(['EQ_MIXER', 'VEH_AGV_01']);
78
78
  });
79
79
  it('이미 등록된 type 은 묻지 않는다 — 그리고 있는 컴포넌트를 figure 가 덮지 않는다', async () => {
80
- const { asked, fetch } = fetcherOf({ EQ_TAKEN: v3PayloadOf('EQ_TAKEN') });
80
+ const { asked, fetch } = fetcherOf({ EQ_TAKEN: figurePayloadOf('EQ_TAKEN') });
81
81
  /* Somebody else already draws this name — a plugin, an app's own component. */
82
82
  Component.register('EQ_TAKEN', class Taken extends Component {
83
83
  });
84
84
  await createFigureResolver(fetch)(['EQ_TAKEN']);
85
85
  expect(asked).to.deep.equal([]);
86
- expect(hasFigureV3('EQ_TAKEN')).to.equal(false);
86
+ expect(hasFigure('EQ_TAKEN')).to.equal(false);
87
87
  });
88
88
  it('받은 자산을 등록한다 — 도면은 type 만 적으면 된다', async () => {
89
- const { fetch } = fetcherOf({ EQ_REGISTERED: v3PayloadOf('EQ_REGISTERED') });
89
+ const { fetch } = fetcherOf({ EQ_REGISTERED: figurePayloadOf('EQ_REGISTERED') });
90
90
  await createFigureResolver(fetch)(['EQ_REGISTERED']);
91
- expect(hasFigureV3('EQ_REGISTERED')).to.equal(true);
91
+ expect(hasFigure('EQ_REGISTERED')).to.equal(true);
92
92
  /* The component type is registered with it — the model writes `type` and nothing else. */
93
93
  expect(Component.register('EQ_REGISTERED')).to.not.equal(undefined);
94
94
  });
95
95
  it('자산은 씬의 문으로 등록한다 — 보드는 그것을 읽지 않고 씬에 넘긴다', async () => {
96
- const { fetch } = fetcherOf({ EQ_V3: v3PayloadOf('EQ_V3') });
97
- await createFigureResolver(fetch)(['EQ_V3']);
98
- expect(hasFigureV3('EQ_V3')).to.equal(true);
96
+ const { fetch } = fetcherOf({ EQ: figurePayloadOf('EQ') });
97
+ await createFigureResolver(fetch)(['EQ']);
98
+ expect(hasFigure('EQ')).to.equal(true);
99
99
  /* 도면은 type 하나만 적으면 그려진다. */
100
- expect(Component.register('EQ_V3')).to.not.equal(undefined);
100
+ expect(Component.register('EQ')).to.not.equal(undefined);
101
101
  });
102
- it('자산이 아닌 것(format 이 v3 가 아닌 답)은 그 type 만 실패로 남는다 — 옛 청사진을 그리지 않는다', async () => {
103
- const { fetch } = fetcherOf({ EQ_NEW: v3PayloadOf('EQ_NEW'), EQ_OLD: { version: 1, type: 'EQ_OLD', groups: [] } });
102
+ it('자산이 없는 답은 그 type 만 실패로 남는다 — 옛 청사진을 그리지 않는다', async () => {
103
+ const { fetch } = fetcherOf({ EQ_NEW: figurePayloadOf('EQ_NEW'), EQ_OLD: { version: 1, type: 'EQ_OLD', groups: [] } });
104
104
  let message = '';
105
105
  try {
106
106
  await createFigureResolver(fetch)(['EQ_NEW', 'EQ_OLD']);
@@ -109,23 +109,23 @@ describe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () =>
109
109
  message = error instanceof Error ? error.message : String(error);
110
110
  }
111
111
  expect(message).to.contain('not a figure asset: EQ_OLD');
112
- expect(hasFigureV3('EQ_NEW')).to.equal(true);
113
- expect(hasFigureV3('EQ_OLD')).to.equal(false);
112
+ expect(hasFigure('EQ_NEW')).to.equal(true);
113
+ expect(hasFigure('EQ_OLD')).to.equal(false);
114
114
  });
115
- it('읽을 수 없는 V3 자산은 그 type 만 실패로 남는다', async () => {
116
- const broken = v3PayloadOf('EQ_V3_BROKEN');
115
+ it('읽을 수 없는 자산은 그 type 만 실패로 남는다', async () => {
116
+ const broken = figurePayloadOf('EQ_ASSET_BROKEN');
117
117
  broken.asset.appearance = [];
118
- const { fetch } = fetcherOf({ EQ_BESIDE_V3: v3PayloadOf('EQ_BESIDE_V3'), EQ_V3_BROKEN: broken });
118
+ const { fetch } = fetcherOf({ EQ_BESIDE: figurePayloadOf('EQ_BESIDE'), EQ_ASSET_BROKEN: broken });
119
119
  let message = '';
120
120
  try {
121
- await createFigureResolver(fetch)(['EQ_BESIDE_V3', 'EQ_V3_BROKEN']);
121
+ await createFigureResolver(fetch)(['EQ_BESIDE', 'EQ_ASSET_BROKEN']);
122
122
  }
123
123
  catch (error) {
124
124
  message = error instanceof Error ? error.message : String(error);
125
125
  }
126
- expect(message).to.contain('EQ_V3_BROKEN');
127
- expect(hasFigureV3('EQ_BESIDE_V3')).to.equal(true);
128
- expect(hasFigureV3('EQ_V3_BROKEN')).to.equal(false);
126
+ expect(message).to.contain('EQ_ASSET_BROKEN');
127
+ expect(hasFigure('EQ_BESIDE')).to.equal(true);
128
+ expect(hasFigure('EQ_ASSET_BROKEN')).to.equal(false);
129
129
  });
130
130
  it('발행된 것이 없으면 조용히 자리표시로 남는다 — 거절이 아니다', async () => {
131
131
  const { fetch } = fetcherOf({});
@@ -137,10 +137,10 @@ describe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () =>
137
137
  rejected = true;
138
138
  }
139
139
  expect(rejected).to.equal(false);
140
- expect(hasFigureV3('EQ_NOT_PUBLISHED')).to.equal(false);
140
+ expect(hasFigure('EQ_NOT_PUBLISHED')).to.equal(false);
141
141
  });
142
142
  it('물을 수 없으면 거절한다. 그때도 답을 받은 것은 등록된다', async () => {
143
- const { fetch } = fetcherOf({ EQ_BESIDE_BROKEN: v3PayloadOf('EQ_BESIDE_BROKEN') }, ['EQ_BROKEN']);
143
+ const { fetch } = fetcherOf({ EQ_BESIDE_BROKEN: figurePayloadOf('EQ_BESIDE_BROKEN') }, ['EQ_BROKEN']);
144
144
  let message = '';
145
145
  try {
146
146
  await createFigureResolver(fetch)(['EQ_BESIDE_BROKEN', 'EQ_BROKEN']);
@@ -150,12 +150,12 @@ describe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () =>
150
150
  }
151
151
  expect(message).to.contain('EQ_BROKEN');
152
152
  expect(message).to.not.contain('EQ_BESIDE_BROKEN');
153
- expect(hasFigureV3('EQ_BESIDE_BROKEN')).to.equal(true);
153
+ expect(hasFigure('EQ_BESIDE_BROKEN')).to.equal(true);
154
154
  });
155
155
  it('읽을 수 없는 자산은 그 type 만 실패로 남는다 — 다른 type 을 막지 않는다', async () => {
156
156
  const { fetch } = fetcherOf({
157
- EQ_BESIDE_MALFORMED: v3PayloadOf('EQ_BESIDE_MALFORMED'),
158
- EQ_MALFORMED: { format: 'v3', type: 'EQ_MALFORMED', asset: { version: 'figure-v3-asset-1' } }
157
+ EQ_BESIDE_MALFORMED: figurePayloadOf('EQ_BESIDE_MALFORMED'),
158
+ EQ_MALFORMED: { type: 'EQ_MALFORMED', asset: { version: 'figure-asset-1' } }
159
159
  });
160
160
  let message = '';
161
161
  try {
@@ -165,11 +165,11 @@ describe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () =>
165
165
  message = error instanceof Error ? error.message : String(error);
166
166
  }
167
167
  expect(message).to.contain('EQ_MALFORMED');
168
- expect(hasFigureV3('EQ_BESIDE_MALFORMED')).to.equal(true);
169
- expect(hasFigureV3('EQ_MALFORMED')).to.equal(false);
168
+ expect(hasFigure('EQ_BESIDE_MALFORMED')).to.equal(true);
169
+ expect(hasFigure('EQ_MALFORMED')).to.equal(false);
170
170
  });
171
171
  it('씬의 자리에 앉아 동작한다 — 모델의 모르는 type 이 해석 뒤에 남지 않는다', async () => {
172
- const { fetch } = fetcherOf({ EQ_ON_A_BOARD: v3PayloadOf('EQ_ON_A_BOARD') });
172
+ const { fetch } = fetcherOf({ EQ_ON_A_BOARD: figurePayloadOf('EQ_ON_A_BOARD') });
173
173
  const takeBack = registerTypeResolver(createFigureResolver(fetch));
174
174
  try {
175
175
  const model = {
@@ -182,7 +182,7 @@ describe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () =>
182
182
  const resolution = await resolveUnknownTypes(model);
183
183
  expect(resolution.unresolved).to.deep.equal(['EQ_NEVER_PUBLISHED']);
184
184
  expect(resolution.failed).to.deep.equal([]);
185
- expect(hasFigureV3('EQ_ON_A_BOARD')).to.equal(true);
185
+ expect(hasFigure('EQ_ON_A_BOARD')).to.equal(true);
186
186
  }
187
187
  finally {
188
188
  takeBack();
@@ -1 +1 @@
1
- {"version":3,"file":"figure-provider.test.js","sourceRoot":"","sources":["../../test/figure-provider.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing'\n\nimport { Component, hasFigureV3, registerTypeResolver, resetFiguresV3, resolveUnknownTypes } from '@hatiolab/things-scene'\n\nimport { createFigureResolver } from '../src/figure-provider.js'\n\n/**\n * The path a published figure takes to a board (ADR-0063 결정 2).\n *\n * things-scene holds the seat and knows nothing about figures; this package fills it. What is\n * checked here is the part that belongs to the board: which names are asked about, what happens to\n * the answer, and how \"nobody published this\" stays apart from \"could not ask\".\n *\n * The payload below is written out rather than built with figure-model: this package does not read it, it passes it\n * to the scene's own registration, and a fixture that drifts from the format should fail loudly here rather than\n * draw nothing at runtime.\n */\n\n/** What the door hands over: a figure asset under a `format` tag. One box standing on the floor, its room declared. */\nconst v3AssetOf = (type: string) => ({\n version: 'figure-v3-asset-1',\n name: type,\n document: {\n version: 'figure-v3-prototype-1',\n model: {\n version: 'r3-spatial-1',\n inputs: [],\n constants: [\n { id: 'w', unit: 'mm', value: 100 },\n { id: 'half', unit: 'mm', value: 50 },\n { id: 'minusHalf', unit: 'mm', value: -50 },\n { id: 'zero', unit: 'mm', value: 0 },\n { id: 'a0', unit: 'deg', value: 0 }\n ],\n nodes: [\n { id: 'body.shape', op: 'box-shape@1', args: ['w', 'w', 'w'], outputs: { shape: 'body.s' }, params: { frame: 'body.local' } },\n {\n id: 'body.pose',\n op: 'rigid@1',\n args: ['zero', 'half', 'zero', 'a0', 'a0', 'a0'],\n outputs: { pose: 'body.p' },\n params: { from: 'body.local', to: 'asset' }\n },\n { id: 'body', op: 'place@1', args: ['body.s', 'body.p'], outputs: { placed: 'body.placed' } }\n ]\n },\n capabilities: { version: 'r3-capability-3', assetFrame: 'asset', bindings: [] }\n },\n designInputs: {},\n stateDefaults: {},\n palette: { 'palette.primary': '#477b9e' },\n appearance: [{ target: 'body', material: { token: 'palette.primary' } }],\n occupancy: {\n bounds: { x: { min: 'minusHalf', max: 'half' }, y: { min: 'zero', max: 'w' }, z: { min: 'minusHalf', max: 'half' } },\n placement: 'floor'\n }\n})\n\nconst v3PayloadOf = (type: string) => ({ format: 'v3' as const, type, asset: v3AssetOf(type) })\n\n/** Records what was asked for, and answers from a table. */\nfunction fetcherOf(published: Record<string, unknown>, failing: string[] = []) {\n const asked: string[] = []\n\n return {\n asked,\n fetch: async (type: string) => {\n asked.push(type)\n if (failing.includes(type)) {\n throw new Error(`no route to the door (${type})`)\n }\n return (published[type] ?? null) as never\n }\n }\n}\n\ndescribe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () => {\n afterEach(() => {\n resetFiguresV3()\n })\n\n it('대문자 이름만 서버에 묻는다 — 씬의 기본 type 과 오타는 문을 지나지 않는다', async () => {\n const { asked, fetch } = fetcherOf({ EQ_MIXER: v3PayloadOf('EQ_MIXER') })\n\n await createFigureResolver(fetch)(['EQ_MIXER', 'rect', 'Conveyor', 'text', 'VEH_AGV_01'])\n\n expect(asked).to.deep.equal(['EQ_MIXER', 'VEH_AGV_01'])\n })\n\n it('이미 등록된 type 은 묻지 않는다 — 그리고 있는 컴포넌트를 figure 가 덮지 않는다', async () => {\n const { asked, fetch } = fetcherOf({ EQ_TAKEN: v3PayloadOf('EQ_TAKEN') })\n\n /* Somebody else already draws this name — a plugin, an app's own component. */\n Component.register('EQ_TAKEN', class Taken extends Component {} as never)\n\n await createFigureResolver(fetch)(['EQ_TAKEN'])\n\n expect(asked).to.deep.equal([])\n expect(hasFigureV3('EQ_TAKEN')).to.equal(false)\n })\n\n it('받은 자산을 등록한다 — 도면은 type 만 적으면 된다', async () => {\n const { fetch } = fetcherOf({ EQ_REGISTERED: v3PayloadOf('EQ_REGISTERED') })\n\n await createFigureResolver(fetch)(['EQ_REGISTERED'])\n\n expect(hasFigureV3('EQ_REGISTERED')).to.equal(true)\n /* The component type is registered with it — the model writes `type` and nothing else. */\n expect(Component.register('EQ_REGISTERED')).to.not.equal(undefined)\n })\n\n it('자산은 씬의 문으로 등록한다 — 보드는 그것을 읽지 않고 씬에 넘긴다', async () => {\n const { fetch } = fetcherOf({ EQ_V3: v3PayloadOf('EQ_V3') })\n\n await createFigureResolver(fetch)(['EQ_V3'])\n\n expect(hasFigureV3('EQ_V3')).to.equal(true)\n /* 도면은 type 하나만 적으면 그려진다. */\n expect(Component.register('EQ_V3')).to.not.equal(undefined)\n })\n\n it('자산이 아닌 것(format 이 v3 가 아닌 답)은 그 type 만 실패로 남는다 — 옛 청사진을 그리지 않는다', async () => {\n const { fetch } = fetcherOf({ EQ_NEW: v3PayloadOf('EQ_NEW'), EQ_OLD: { version: 1, type: 'EQ_OLD', groups: [] } })\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_NEW', 'EQ_OLD'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('not a figure asset: EQ_OLD')\n expect(hasFigureV3('EQ_NEW')).to.equal(true)\n expect(hasFigureV3('EQ_OLD')).to.equal(false)\n })\n\n it('읽을 수 없는 V3 자산은 그 type 만 실패로 남는다', async () => {\n const broken = v3PayloadOf('EQ_V3_BROKEN')\n broken.asset.appearance = []\n const { fetch } = fetcherOf({ EQ_BESIDE_V3: v3PayloadOf('EQ_BESIDE_V3'), EQ_V3_BROKEN: broken })\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_BESIDE_V3', 'EQ_V3_BROKEN'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('EQ_V3_BROKEN')\n expect(hasFigureV3('EQ_BESIDE_V3')).to.equal(true)\n expect(hasFigureV3('EQ_V3_BROKEN')).to.equal(false)\n })\n\n it('발행된 것이 없으면 조용히 자리표시로 남는다 — 거절이 아니다', async () => {\n const { fetch } = fetcherOf({})\n\n let rejected = false\n try {\n await createFigureResolver(fetch)(['EQ_NOT_PUBLISHED'])\n } catch {\n rejected = true\n }\n\n expect(rejected).to.equal(false)\n expect(hasFigureV3('EQ_NOT_PUBLISHED')).to.equal(false)\n })\n\n it('물을 수 없으면 거절한다. 그때도 답을 받은 것은 등록된다', async () => {\n const { fetch } = fetcherOf({ EQ_BESIDE_BROKEN: v3PayloadOf('EQ_BESIDE_BROKEN') }, ['EQ_BROKEN'])\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_BESIDE_BROKEN', 'EQ_BROKEN'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('EQ_BROKEN')\n expect(message).to.not.contain('EQ_BESIDE_BROKEN')\n expect(hasFigureV3('EQ_BESIDE_BROKEN')).to.equal(true)\n })\n\n it('읽을 수 없는 자산은 그 type 만 실패로 남는다 — 다른 type 을 막지 않는다', async () => {\n const { fetch } = fetcherOf({\n EQ_BESIDE_MALFORMED: v3PayloadOf('EQ_BESIDE_MALFORMED'),\n EQ_MALFORMED: { format: 'v3', type: 'EQ_MALFORMED', asset: { version: 'figure-v3-asset-1' } }\n })\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_BESIDE_MALFORMED', 'EQ_MALFORMED'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('EQ_MALFORMED')\n expect(hasFigureV3('EQ_BESIDE_MALFORMED')).to.equal(true)\n expect(hasFigureV3('EQ_MALFORMED')).to.equal(false)\n })\n\n it('씬의 자리에 앉아 동작한다 — 모델의 모르는 type 이 해석 뒤에 남지 않는다', async () => {\n const { fetch } = fetcherOf({ EQ_ON_A_BOARD: v3PayloadOf('EQ_ON_A_BOARD') })\n const takeBack = registerTypeResolver(createFigureResolver(fetch))\n\n try {\n const model = {\n type: 'container',\n components: [\n { type: 'EQ_ON_A_BOARD', left: 0, top: 0, width: 100, height: 100 },\n { type: 'EQ_NEVER_PUBLISHED', left: 0, top: 0, width: 100, height: 100 }\n ]\n }\n\n const resolution = await resolveUnknownTypes(model)\n\n expect(resolution.unresolved).to.deep.equal(['EQ_NEVER_PUBLISHED'])\n expect(resolution.failed).to.deep.equal([])\n expect(hasFigureV3('EQ_ON_A_BOARD')).to.equal(true)\n } finally {\n takeBack()\n }\n })\n})\n"]}
1
+ {"version":3,"file":"figure-provider.test.js","sourceRoot":"","sources":["../../test/figure-provider.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing'\n\nimport { Component, hasFigure, registerTypeResolver, resetFigures, resolveUnknownTypes } from '@hatiolab/things-scene'\n\nimport { createFigureResolver } from '../src/figure-provider.js'\n\n/**\n * The path a published figure takes to a board (ADR-0063 결정 2).\n *\n * things-scene holds the seat and knows nothing about figures; this package fills it. What is\n * checked here is the part that belongs to the board: which names are asked about, what happens to\n * the answer, and how \"nobody published this\" stays apart from \"could not ask\".\n *\n * The payload below is written out rather than built with figure-model: this package does not read it, it passes it\n * to the scene's own registration, and a fixture that drifts from the format should fail loudly here rather than\n * draw nothing at runtime.\n */\n\n/** What the door hands over: a figure asset. One box standing on the floor, its room declared. */\nconst figureAssetOf = (type: string) => ({\n version: 'figure-asset-1',\n name: type,\n document: {\n version: 'figure-prototype-1',\n model: {\n version: 'r3-spatial-1',\n inputs: [],\n constants: [\n { id: 'w', unit: 'mm', value: 100 },\n { id: 'half', unit: 'mm', value: 50 },\n { id: 'minusHalf', unit: 'mm', value: -50 },\n { id: 'zero', unit: 'mm', value: 0 },\n { id: 'a0', unit: 'deg', value: 0 }\n ],\n nodes: [\n { id: 'body.shape', op: 'box-shape@1', args: ['w', 'w', 'w'], outputs: { shape: 'body.s' }, params: { frame: 'body.local' } },\n {\n id: 'body.pose',\n op: 'rigid@1',\n args: ['zero', 'half', 'zero', 'a0', 'a0', 'a0'],\n outputs: { pose: 'body.p' },\n params: { from: 'body.local', to: 'asset' }\n },\n { id: 'body', op: 'place@1', args: ['body.s', 'body.p'], outputs: { placed: 'body.placed' } }\n ]\n },\n capabilities: { version: 'r3-capability-3', assetFrame: 'asset', bindings: [] }\n },\n designInputs: {},\n stateDefaults: {},\n palette: { 'palette.primary': '#477b9e' },\n appearance: [{ target: 'body', material: { token: 'palette.primary' } }],\n occupancy: {\n bounds: { x: { min: 'minusHalf', max: 'half' }, y: { min: 'zero', max: 'w' }, z: { min: 'minusHalf', max: 'half' } },\n placement: 'floor'\n }\n})\n\nconst figurePayloadOf = (type: string) => ({ type, asset: figureAssetOf(type) })\n\n/** Records what was asked for, and answers from a table. */\nfunction fetcherOf(published: Record<string, unknown>, failing: string[] = []) {\n const asked: string[] = []\n\n return {\n asked,\n fetch: async (type: string) => {\n asked.push(type)\n if (failing.includes(type)) {\n throw new Error(`no route to the door (${type})`)\n }\n return (published[type] ?? null) as never\n }\n }\n}\n\ndescribe('figure 공급자 — 보드가 발행된 Figure 를 받는 길', () => {\n afterEach(() => {\n resetFigures()\n })\n\n it('대문자 이름만 서버에 묻는다 — 씬의 기본 type 과 오타는 문을 지나지 않는다', async () => {\n const { asked, fetch } = fetcherOf({ EQ_MIXER: figurePayloadOf('EQ_MIXER') })\n\n await createFigureResolver(fetch)(['EQ_MIXER', 'rect', 'Conveyor', 'text', 'VEH_AGV_01'])\n\n expect(asked).to.deep.equal(['EQ_MIXER', 'VEH_AGV_01'])\n })\n\n it('이미 등록된 type 은 묻지 않는다 — 그리고 있는 컴포넌트를 figure 가 덮지 않는다', async () => {\n const { asked, fetch } = fetcherOf({ EQ_TAKEN: figurePayloadOf('EQ_TAKEN') })\n\n /* Somebody else already draws this name — a plugin, an app's own component. */\n Component.register('EQ_TAKEN', class Taken extends Component {} as never)\n\n await createFigureResolver(fetch)(['EQ_TAKEN'])\n\n expect(asked).to.deep.equal([])\n expect(hasFigure('EQ_TAKEN')).to.equal(false)\n })\n\n it('받은 자산을 등록한다 — 도면은 type 만 적으면 된다', async () => {\n const { fetch } = fetcherOf({ EQ_REGISTERED: figurePayloadOf('EQ_REGISTERED') })\n\n await createFigureResolver(fetch)(['EQ_REGISTERED'])\n\n expect(hasFigure('EQ_REGISTERED')).to.equal(true)\n /* The component type is registered with it — the model writes `type` and nothing else. */\n expect(Component.register('EQ_REGISTERED')).to.not.equal(undefined)\n })\n\n it('자산은 씬의 문으로 등록한다 — 보드는 그것을 읽지 않고 씬에 넘긴다', async () => {\n const { fetch } = fetcherOf({ EQ: figurePayloadOf('EQ') })\n\n await createFigureResolver(fetch)(['EQ'])\n\n expect(hasFigure('EQ')).to.equal(true)\n /* 도면은 type 하나만 적으면 그려진다. */\n expect(Component.register('EQ')).to.not.equal(undefined)\n })\n\n it('자산이 없는 답은 그 type 만 실패로 남는다 — 옛 청사진을 그리지 않는다', async () => {\n const { fetch } = fetcherOf({ EQ_NEW: figurePayloadOf('EQ_NEW'), EQ_OLD: { version: 1, type: 'EQ_OLD', groups: [] } })\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_NEW', 'EQ_OLD'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('not a figure asset: EQ_OLD')\n expect(hasFigure('EQ_NEW')).to.equal(true)\n expect(hasFigure('EQ_OLD')).to.equal(false)\n })\n\n it('읽을 수 없는 자산은 그 type 만 실패로 남는다', async () => {\n const broken = figurePayloadOf('EQ_ASSET_BROKEN')\n broken.asset.appearance = []\n const { fetch } = fetcherOf({ EQ_BESIDE: figurePayloadOf('EQ_BESIDE'), EQ_ASSET_BROKEN: broken })\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_BESIDE', 'EQ_ASSET_BROKEN'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('EQ_ASSET_BROKEN')\n expect(hasFigure('EQ_BESIDE')).to.equal(true)\n expect(hasFigure('EQ_ASSET_BROKEN')).to.equal(false)\n })\n\n it('발행된 것이 없으면 조용히 자리표시로 남는다 — 거절이 아니다', async () => {\n const { fetch } = fetcherOf({})\n\n let rejected = false\n try {\n await createFigureResolver(fetch)(['EQ_NOT_PUBLISHED'])\n } catch {\n rejected = true\n }\n\n expect(rejected).to.equal(false)\n expect(hasFigure('EQ_NOT_PUBLISHED')).to.equal(false)\n })\n\n it('물을 수 없으면 거절한다. 그때도 답을 받은 것은 등록된다', async () => {\n const { fetch } = fetcherOf({ EQ_BESIDE_BROKEN: figurePayloadOf('EQ_BESIDE_BROKEN') }, ['EQ_BROKEN'])\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_BESIDE_BROKEN', 'EQ_BROKEN'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('EQ_BROKEN')\n expect(message).to.not.contain('EQ_BESIDE_BROKEN')\n expect(hasFigure('EQ_BESIDE_BROKEN')).to.equal(true)\n })\n\n it('읽을 수 없는 자산은 그 type 만 실패로 남는다 — 다른 type 을 막지 않는다', async () => {\n const { fetch } = fetcherOf({\n EQ_BESIDE_MALFORMED: figurePayloadOf('EQ_BESIDE_MALFORMED'),\n EQ_MALFORMED: { type: 'EQ_MALFORMED', asset: { version: 'figure-asset-1' } }\n })\n\n let message = ''\n try {\n await createFigureResolver(fetch)(['EQ_BESIDE_MALFORMED', 'EQ_MALFORMED'])\n } catch (error) {\n message = error instanceof Error ? error.message : String(error)\n }\n\n expect(message).to.contain('EQ_MALFORMED')\n expect(hasFigure('EQ_BESIDE_MALFORMED')).to.equal(true)\n expect(hasFigure('EQ_MALFORMED')).to.equal(false)\n })\n\n it('씬의 자리에 앉아 동작한다 — 모델의 모르는 type 이 해석 뒤에 남지 않는다', async () => {\n const { fetch } = fetcherOf({ EQ_ON_A_BOARD: figurePayloadOf('EQ_ON_A_BOARD') })\n const takeBack = registerTypeResolver(createFigureResolver(fetch))\n\n try {\n const model = {\n type: 'container',\n components: [\n { type: 'EQ_ON_A_BOARD', left: 0, top: 0, width: 100, height: 100 },\n { type: 'EQ_NEVER_PUBLISHED', left: 0, top: 0, width: 100, height: 100 }\n ]\n }\n\n const resolution = await resolveUnknownTypes(model)\n\n expect(resolution.unresolved).to.deep.equal(['EQ_NEVER_PUBLISHED'])\n expect(resolution.failed).to.deep.equal([])\n expect(hasFigure('EQ_ON_A_BOARD')).to.equal(true)\n } finally {\n takeBack()\n }\n })\n})\n"]}
@@ -1,6 +1,6 @@
1
1
  import { expect, fixture, html } from '@open-wc/testing';
2
2
  import { executeServerCommand } from '@web/test-runner-commands';
3
- import { registerTypeResolver, resetFiguresV3 } from '@hatiolab/things-scene';
3
+ import { registerTypeResolver, resetFigures } from '@hatiolab/things-scene';
4
4
  import { createResolvedScene } from '../src/resolved-scene.js';
5
5
  import '../src/ox-board-preview.js';
6
6
  /**
@@ -40,7 +40,7 @@ describe('모르는 type 이 없으면 아무에게도 묻지 않는다', () =>
40
40
  });
41
41
  afterEach(() => {
42
42
  takeBack();
43
- resetFiguresV3();
43
+ resetFigures();
44
44
  });
45
45
  it('씬의 기본 type 만 있는 보드는 공급자를 부르지 않는다', async () => {
46
46
  var _a;
@@ -60,7 +60,7 @@ describe('기다리는 동안 화면이 바뀌면 늦게 온 씬은 들어서지
60
60
  let takeBack;
61
61
  afterEach(() => {
62
62
  takeBack === null || takeBack === void 0 ? void 0 : takeBack();
63
- resetFiguresV3();
63
+ resetFigures();
64
64
  });
65
65
  it('앞의 모델을 풀고 돌아왔을 때 미리보기가 다른 모델을 들고 있으면 그 씬은 버린다', async () => {
66
66
  /* The first model's type resolves slowly; the second one has nothing to resolve. */
@@ -1 +1 @@
1
- {"version":3,"file":"resolved-scene.test.js","sourceRoot":"","sources":["../../test/resolved-scene.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, html } from '@open-wc/testing'\nimport type { LitElement } from 'lit'\nimport { executeServerCommand } from '@web/test-runner-commands'\n\nimport { registerTypeResolver, resetFiguresV3 } from '@hatiolab/things-scene'\n\nimport { createResolvedScene } from '../src/resolved-scene.js'\nimport '../src/ox-board-preview.js'\n\n/**\n * The one door a model goes through to become a scene (ADR-0063 결정 2).\n *\n * Three things are counted here, and each of them is something that goes wrong quietly otherwise:\n * a scene built somewhere else never resolves its types, a board of ordinary components pays for a\n * server round trip it does not need, and a scene that was waiting lands on a viewer that has\n * already moved on.\n */\n\nconst KNOWN_MODEL = {\n type: 'container',\n components: [{ type: 'rect', left: 0, top: 0, width: 100, height: 100 }]\n}\n\nconst modelWith = (types: string[]) => ({\n type: 'container',\n components: types.map((type, index) => ({ type, left: index * 10, top: 0, width: 100, height: 100 }))\n})\n\ndescribe('씬을 만드는 문은 하나다', () => {\n it('things-scene 의 create 를 읽는 파일은 resolved-scene.ts 하나뿐이다', async () => {\n /*\n * 세는 범위는 이 꾸러미와 `@operato/process` 다 — 문은 여기 있고 그 꾸러미가 둘째 소비자다.\n * 이 꾸러미만 보던 규칙은 옆에 씬 둘이 서 있는 동안 「문은 하나」라고 답하고 있었다.\n */\n const files = await executeServerCommand<unknown, string[]>('files-importing-scene-create')\n\n expect(files).to.deep.equal(['src/resolved-scene.ts'])\n })\n})\n\ndescribe('모르는 type 이 없으면 아무에게도 묻지 않는다', () => {\n let asked: string[][]\n let takeBack: () => void\n\n beforeEach(() => {\n asked = []\n takeBack = registerTypeResolver(async types => {\n asked.push([...types])\n })\n })\n\n afterEach(() => {\n takeBack()\n resetFiguresV3()\n })\n\n it('씬의 기본 type 만 있는 보드는 공급자를 부르지 않는다', async () => {\n const scene = await createResolvedScene({ model: KNOWN_MODEL })\n\n expect(asked).to.deep.equal([])\n expect(scene).to.not.equal(null)\n\n scene?.release?.()\n })\n\n it('모르는 type 이 있을 때만 부른다', async () => {\n const scene = await createResolvedScene({ model: modelWith(['rect', 'EQ_ASKED_ABOUT']) })\n\n expect(asked).to.deep.equal([['EQ_ASKED_ABOUT']])\n\n scene?.release?.()\n })\n})\n\ndescribe('기다리는 동안 화면이 바뀌면 늦게 온 씬은 들어서지 않는다', () => {\n let takeBack: () => void\n\n afterEach(() => {\n takeBack?.()\n resetFiguresV3()\n })\n\n it('앞의 모델을 풀고 돌아왔을 때 미리보기가 다른 모델을 들고 있으면 그 씬은 버린다', async () => {\n /* The first model's type resolves slowly; the second one has nothing to resolve. */\n let releaseFirst: () => void = () => {}\n const firstResolved = new Promise<void>(resolve => {\n releaseFirst = resolve\n })\n\n takeBack = registerTypeResolver(async types => {\n if (types.includes('EQ_SLOW')) {\n await firstResolved\n }\n })\n\n const element = (await fixture(html`<ox-board-preview></ox-board-preview>`)) as LitElement & {\n boardModel: unknown\n _scene: { root: { components: unknown[] } } | null\n }\n\n element.boardModel = modelWith(['EQ_SLOW'])\n await element.updateComplete\n\n /* The second model arrives while the first one is still waiting on its type. */\n element.boardModel = modelWith(['rect', 'rect'])\n await element.updateComplete\n\n releaseFirst()\n await new Promise(resolve => setTimeout(resolve, 0))\n\n expect(element._scene).to.not.equal(null)\n expect(element._scene!.root.components.length).to.equal(2)\n })\n})\n"]}
1
+ {"version":3,"file":"resolved-scene.test.js","sourceRoot":"","sources":["../../test/resolved-scene.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, html } from '@open-wc/testing'\nimport type { LitElement } from 'lit'\nimport { executeServerCommand } from '@web/test-runner-commands'\n\nimport { registerTypeResolver, resetFigures } from '@hatiolab/things-scene'\n\nimport { createResolvedScene } from '../src/resolved-scene.js'\nimport '../src/ox-board-preview.js'\n\n/**\n * The one door a model goes through to become a scene (ADR-0063 결정 2).\n *\n * Three things are counted here, and each of them is something that goes wrong quietly otherwise:\n * a scene built somewhere else never resolves its types, a board of ordinary components pays for a\n * server round trip it does not need, and a scene that was waiting lands on a viewer that has\n * already moved on.\n */\n\nconst KNOWN_MODEL = {\n type: 'container',\n components: [{ type: 'rect', left: 0, top: 0, width: 100, height: 100 }]\n}\n\nconst modelWith = (types: string[]) => ({\n type: 'container',\n components: types.map((type, index) => ({ type, left: index * 10, top: 0, width: 100, height: 100 }))\n})\n\ndescribe('씬을 만드는 문은 하나다', () => {\n it('things-scene 의 create 를 읽는 파일은 resolved-scene.ts 하나뿐이다', async () => {\n /*\n * 세는 범위는 이 꾸러미와 `@operato/process` 다 — 문은 여기 있고 그 꾸러미가 둘째 소비자다.\n * 이 꾸러미만 보던 규칙은 옆에 씬 둘이 서 있는 동안 「문은 하나」라고 답하고 있었다.\n */\n const files = await executeServerCommand<unknown, string[]>('files-importing-scene-create')\n\n expect(files).to.deep.equal(['src/resolved-scene.ts'])\n })\n})\n\ndescribe('모르는 type 이 없으면 아무에게도 묻지 않는다', () => {\n let asked: string[][]\n let takeBack: () => void\n\n beforeEach(() => {\n asked = []\n takeBack = registerTypeResolver(async types => {\n asked.push([...types])\n })\n })\n\n afterEach(() => {\n takeBack()\n resetFigures()\n })\n\n it('씬의 기본 type 만 있는 보드는 공급자를 부르지 않는다', async () => {\n const scene = await createResolvedScene({ model: KNOWN_MODEL })\n\n expect(asked).to.deep.equal([])\n expect(scene).to.not.equal(null)\n\n scene?.release?.()\n })\n\n it('모르는 type 이 있을 때만 부른다', async () => {\n const scene = await createResolvedScene({ model: modelWith(['rect', 'EQ_ASKED_ABOUT']) })\n\n expect(asked).to.deep.equal([['EQ_ASKED_ABOUT']])\n\n scene?.release?.()\n })\n})\n\ndescribe('기다리는 동안 화면이 바뀌면 늦게 온 씬은 들어서지 않는다', () => {\n let takeBack: () => void\n\n afterEach(() => {\n takeBack?.()\n resetFigures()\n })\n\n it('앞의 모델을 풀고 돌아왔을 때 미리보기가 다른 모델을 들고 있으면 그 씬은 버린다', async () => {\n /* The first model's type resolves slowly; the second one has nothing to resolve. */\n let releaseFirst: () => void = () => {}\n const firstResolved = new Promise<void>(resolve => {\n releaseFirst = resolve\n })\n\n takeBack = registerTypeResolver(async types => {\n if (types.includes('EQ_SLOW')) {\n await firstResolved\n }\n })\n\n const element = (await fixture(html`<ox-board-preview></ox-board-preview>`)) as LitElement & {\n boardModel: unknown\n _scene: { root: { components: unknown[] } } | null\n }\n\n element.boardModel = modelWith(['EQ_SLOW'])\n await element.updateComplete\n\n /* The second model arrives while the first one is still waiting on its type. */\n element.boardModel = modelWith(['rect', 'rect'])\n await element.updateComplete\n\n releaseFirst()\n await new Promise(resolve => setTimeout(resolve, 0))\n\n expect(element._scene).to.not.equal(null)\n expect(element._scene!.root.components.length).to.equal(2)\n })\n})\n"]}