create-mendix-widget-gleam 1.0.8 → 1.1.1
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/package.json +1 -1
- package/src/index.mjs +3 -2
- package/template/docs/glendix_guide.md +112 -7
- package/template/gleam.toml +1 -1
- package/template/manifest.toml +0 -11
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ my-widget/
|
|
|
27
27
|
editor_preview.gleam # Studio Pro 디자인 뷰 미리보기
|
|
28
28
|
components/
|
|
29
29
|
hello_world.gleam # Hello World 공유 컴포넌트
|
|
30
|
-
gleam.toml # Gleam 프로젝트 설정 (glendix >= 1.
|
|
30
|
+
gleam.toml # Gleam 프로젝트 설정 (glendix >= 1.2.0 의존성 포함)
|
|
31
31
|
CLAUDE.md # AI 어시스턴트용 프로젝트 컨텍스트
|
|
32
32
|
```
|
|
33
33
|
|
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -176,7 +176,7 @@ Gleam 언어로 Mendix Pluggable Widget을 개발하여 "Hello World"를 화면
|
|
|
176
176
|
- **Gleam** → JavaScript 컴파일 (target: javascript)
|
|
177
177
|
- **[glendix](https://hexdocs.pm/glendix/)** — React + Mendix Pluggable Widget API의 Gleam FFI 바인딩 (Hex 패키지)
|
|
178
178
|
- **Mendix Pluggable Widget** (React 19)
|
|
179
|
-
- **Package Manager**: ${pm} (npm 의존성은 \`gleam run -m glendix/install\`로 설치)
|
|
179
|
+
- **Package Manager**: ${pm} (기본 npm 의존성은 \`gleam run -m glendix/install\`로 설치, \`bindings.json\` 외부 React 패키지는 수동 설치 필요)
|
|
180
180
|
- **Build**: \`@mendix/pluggable-widgets-tools\` (Rollup 기반)
|
|
181
181
|
|
|
182
182
|
## Architecture
|
|
@@ -215,7 +215,7 @@ React/Mendix FFI 바인딩은 이 프로젝트에 포함되지 않으며, [glend
|
|
|
215
215
|
## Commands
|
|
216
216
|
|
|
217
217
|
\`\`\`bash
|
|
218
|
-
gleam run -m glendix/install # 의존성 설치
|
|
218
|
+
gleam run -m glendix/install # 의존성 설치 + 바인딩 코드 생성 (외부 React 패키지는 사전에 수동 설치 필요)
|
|
219
219
|
gleam run -m glendix/build # 위젯 프로덕션 빌드 (.mpk 생성)
|
|
220
220
|
gleam run -m glendix/dev # 개발 서버 (HMR, port 3000)
|
|
221
221
|
gleam run -m glendix/start # Mendix 테스트 프로젝트와 연동 개발
|
|
@@ -245,6 +245,7 @@ React:
|
|
|
245
245
|
- \`glendix/react/hook\` — React Hooks (useState, useEffect 등)
|
|
246
246
|
- \`glendix/react/event\` — 이벤트 타입 + 값 추출
|
|
247
247
|
- \`glendix/react/html\` — HTML 태그 편의 함수
|
|
248
|
+
- \`glendix/binding\` — 외부 React 컴포넌트 바인딩
|
|
248
249
|
|
|
249
250
|
Mendix:
|
|
250
251
|
- \`glendix/mendix\` — \`ValueStatus\`, \`ObjectItem\`, Props 접근자
|
|
@@ -45,9 +45,11 @@ glendix = { path = "../glendix" }
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
|
|
48
|
+
gleam run -m glendix/install
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
> `glendix/install`은 패키지 매니저를 자동 감지하여 의존성을 설치하고, `bindings.json`이 있으면 외부 React 컴포넌트 바인딩도 자동 생성합니다.
|
|
52
|
+
|
|
51
53
|
#### 4) 빌드 확인
|
|
52
54
|
|
|
53
55
|
```bash
|
|
@@ -198,11 +200,87 @@ react.none() // React null 반환
|
|
|
198
200
|
|
|
199
201
|
#### 외부 React 컴포넌트 사용
|
|
200
202
|
|
|
203
|
+
`glendix/binding` 모듈로 외부 React 라이브러리를 **`.mjs` 없이** 사용합니다.
|
|
204
|
+
|
|
205
|
+
**1단계: `bindings.json` 작성** (프로젝트 루트)
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"recharts": {
|
|
210
|
+
"components": ["PieChart", "Pie", "Cell", "LineChart", "Line",
|
|
211
|
+
"XAxis", "YAxis", "CartesianGrid", "Tooltip", "Legend",
|
|
212
|
+
"ResponsiveContainer"]
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**2단계: 패키지 설치** — `bindings.json`에 등록한 패키지는 위젯 프로젝트의 `node_modules`에 설치되어 있어야 합니다. 생성된 `binding_ffi.mjs`가 해당 패키지를 직접 import하므로, Rollup이 번들링할 때 resolve할 수 있어야 합니다.
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# 사용 중인 패키지 매니저에 맞게 설치
|
|
221
|
+
npm install recharts
|
|
222
|
+
# 또는
|
|
223
|
+
pnpm add recharts
|
|
224
|
+
# 또는
|
|
225
|
+
yarn add recharts
|
|
226
|
+
# 또는
|
|
227
|
+
bun add recharts
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**3단계: `gleam run -m glendix/install`** 실행 (바인딩 자동 생성)
|
|
231
|
+
|
|
232
|
+
**4단계: 순수 Gleam 래퍼 모듈 작성** (편의용, 선택사항)
|
|
233
|
+
|
|
201
234
|
```gleam
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
235
|
+
// src/chart/recharts.gleam — 순수 Gleam, FFI 없음!
|
|
236
|
+
import glendix/binding
|
|
237
|
+
import glendix/react.{type Component}
|
|
238
|
+
|
|
239
|
+
fn m() { binding.module("recharts") }
|
|
240
|
+
|
|
241
|
+
pub fn pie_chart() -> Component { binding.resolve(m(), "PieChart") }
|
|
242
|
+
pub fn pie() -> Component { binding.resolve(m(), "Pie") }
|
|
243
|
+
pub fn cell() -> Component { binding.resolve(m(), "Cell") }
|
|
244
|
+
pub fn tooltip() -> Component { binding.resolve(m(), "Tooltip") }
|
|
245
|
+
pub fn legend() -> Component { binding.resolve(m(), "Legend") }
|
|
246
|
+
pub fn responsive_container() -> Component {
|
|
247
|
+
binding.resolve(m(), "ResponsiveContainer")
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**5단계: 위젯에서 사용**
|
|
252
|
+
|
|
253
|
+
```gleam
|
|
254
|
+
import chart/recharts
|
|
255
|
+
import glendix/react
|
|
256
|
+
import glendix/react/prop
|
|
257
|
+
|
|
258
|
+
pub fn my_pie_chart(data) -> react.ReactElement {
|
|
259
|
+
react.component(recharts.responsive_container(),
|
|
260
|
+
prop.new() |> prop.int("width", 400) |> prop.int("height", 300),
|
|
261
|
+
[
|
|
262
|
+
react.component(recharts.pie_chart(), prop.new(), [
|
|
263
|
+
react.component(recharts.pie(),
|
|
264
|
+
prop.new()
|
|
265
|
+
|> prop.any("data", data)
|
|
266
|
+
|> prop.string("dataKey", "value"),
|
|
267
|
+
[],
|
|
268
|
+
),
|
|
269
|
+
react.component(recharts.tooltip(), prop.new(), []),
|
|
270
|
+
react.component(recharts.legend(), prop.new(), []),
|
|
271
|
+
]),
|
|
272
|
+
],
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
래퍼 모듈 없이 직접 사용하는 것도 가능합니다:
|
|
278
|
+
|
|
279
|
+
```gleam
|
|
280
|
+
import glendix/binding
|
|
281
|
+
|
|
282
|
+
let rc = binding.module("recharts")
|
|
283
|
+
react.component(binding.resolve(rc, "PieChart"), props, children)
|
|
206
284
|
```
|
|
207
285
|
|
|
208
286
|
### 3.2 Props 빌더
|
|
@@ -1305,8 +1383,8 @@ pub fn dashboard(props) -> ReactElement {
|
|
|
1305
1383
|
| 문제 | 원인 | 해결 |
|
|
1306
1384
|
|---|---|---|
|
|
1307
1385
|
| `gleam build` 실패: glendix를 찾을 수 없음 | `gleam.toml`의 경로가 잘못됨 | `path = "../glendix"` 경로 확인 |
|
|
1308
|
-
| `react is not defined` | peer dependency 미설치 | `
|
|
1309
|
-
| `Big is not a constructor` | big.js 미설치 | `
|
|
1386
|
+
| `react is not defined` | peer dependency 미설치 | `gleam run -m glendix/install` |
|
|
1387
|
+
| `Big is not a constructor` | big.js 미설치 | `gleam run -m glendix/install` |
|
|
1310
1388
|
|
|
1311
1389
|
### 런타임 에러
|
|
1312
1390
|
|
|
@@ -1315,6 +1393,10 @@ pub fn dashboard(props) -> ReactElement {
|
|
|
1315
1393
|
| `Cannot read property of undefined` | 존재하지 않는 prop 접근 | `get_prop` (Option) 대신 `get_prop_required` 사용 시 prop 이름 확인 |
|
|
1316
1394
|
| `set_value` 호출 시 에러 | read_only 상태에서 값 설정 | `ev.is_editable(attr)` 확인 후 설정 |
|
|
1317
1395
|
| Hook 순서 에러 | 조건부로 Hook 호출 | Hook은 항상 동일한 순서로 호출해야 함 (React Rules of Hooks) |
|
|
1396
|
+
| `바인딩이 생성되지 않았습니다` | `binding_ffi.mjs`가 스텁 상태 | `gleam run -m glendix/install` 실행 |
|
|
1397
|
+
| `could not be resolved – treating it as an external dependency` | `bindings.json`에 등록한 패키지가 `node_modules`에 없음 | `npm install <패키지명>` 등으로 설치 후 재빌드 |
|
|
1398
|
+
| `바인딩에 등록되지 않은 모듈` | `bindings.json`에 해당 패키지 미등록 | `bindings.json`에 패키지와 컴포넌트 추가 후 재설치 |
|
|
1399
|
+
| `모듈에 없는 컴포넌트` | `bindings.json`의 `components`에 해당 컴포넌트 미등록 | `components` 배열에 추가 후 재설치 |
|
|
1318
1400
|
|
|
1319
1401
|
### 일반적인 실수
|
|
1320
1402
|
|
|
@@ -1361,5 +1443,28 @@ list.map(items, fn(item) {
|
|
|
1361
1443
|
let month = date.month(my_date) // 1~12 (Gleam 기준, 변환 불필요)
|
|
1362
1444
|
```
|
|
1363
1445
|
|
|
1446
|
+
**4. 외부 React 컴포넌트용 `.mjs` 파일을 직접 작성하지 마세요:**
|
|
1447
|
+
|
|
1448
|
+
```gleam
|
|
1449
|
+
// 잘못된 방법 — 수동 FFI 작성
|
|
1450
|
+
// recharts_ffi.mjs를 만들고 @external로 연결하는 것
|
|
1451
|
+
|
|
1452
|
+
// 올바른 방법 — bindings.json + glendix/binding 사용
|
|
1453
|
+
import glendix/binding
|
|
1454
|
+
let rc = binding.module("recharts")
|
|
1455
|
+
let pie = binding.resolve(rc, "PieChart")
|
|
1456
|
+
react.component(pie, props, children)
|
|
1457
|
+
```
|
|
1458
|
+
|
|
1459
|
+
**5. `binding.resolve()`에서 컴포넌트 이름을 snake_case로 바꾸지 마세요:**
|
|
1460
|
+
|
|
1461
|
+
```gleam
|
|
1462
|
+
// 잘못된 예
|
|
1463
|
+
binding.resolve(m(), "pie_chart")
|
|
1464
|
+
|
|
1465
|
+
// 올바른 예 — JavaScript 원본 이름(PascalCase) 그대로 사용
|
|
1466
|
+
binding.resolve(m(), "PieChart")
|
|
1467
|
+
```
|
|
1468
|
+
|
|
1364
1469
|
---
|
|
1365
1470
|
|
package/template/gleam.toml
CHANGED
package/template/manifest.toml
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# This file was generated by Gleam
|
|
2
|
-
# You typically do not need to edit this file
|
|
3
|
-
|
|
4
|
-
packages = [
|
|
5
|
-
{ name = "gleam_stdlib", version = "0.70.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86949BF5D1F0E4AC0AB5B06F235D8A5CC11A2DFC33BF22F752156ED61CA7D0FF" },
|
|
6
|
-
{ name = "glendix", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glendix", source = "hex", outer_checksum = "9E1B78EEABCC0193F028BB271C3E60565C587E5E901FE553509ECF38D981B58A" },
|
|
7
|
-
]
|
|
8
|
-
|
|
9
|
-
[requirements]
|
|
10
|
-
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
|
|
11
|
-
glendix = { version = ">= 1.0.0 and < 2.0.0" }
|