create-mendix-widget-gleam 2.0.6 → 2.0.8
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/package.json +1 -1
- package/src/index.mjs +123 -49
- package/template/_gitignore +7 -0
- package/template/docs/glendix_guide.md +2295 -2215
- package/template/gleam.toml +1 -1
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -197,19 +197,20 @@ async function generateClaudeMd(targetDir, names, pm, pmConfig) {
|
|
|
197
197
|
|
|
198
198
|
const content = `# ${names.pascalCase}
|
|
199
199
|
|
|
200
|
-
Gleam 언어로 Mendix Pluggable Widget을
|
|
200
|
+
Gleam 언어로 Mendix Pluggable Widget을 개발하는 프로젝트.
|
|
201
201
|
|
|
202
202
|
## Goal
|
|
203
203
|
|
|
204
|
-
**JSX를 사용하지 않고, 오직 Gleam으로만** 위젯을 작성한다. Gleam 코드를 JavaScript로 컴파일하고, 컴파일된 JS가 곧 Mendix Pluggable Widget의 진입점이 된다.
|
|
204
|
+
**JSX를 사용하지 않고, 오직 Gleam으로만** 위젯을 작성한다. Gleam 코드를 JavaScript로 컴파일하고, 컴파일된 JS가 곧 Mendix Pluggable Widget의 진입점이 된다.
|
|
205
205
|
|
|
206
206
|
## Tech Stack
|
|
207
207
|
|
|
208
208
|
- **Gleam** → JavaScript 컴파일 (target: javascript)
|
|
209
|
-
- **[glendix](https://hexdocs.pm/glendix/)** — React + Mendix Pluggable Widget API의 Gleam FFI 바인딩 (Hex 패키지)
|
|
209
|
+
- **[glendix](https://hexdocs.pm/glendix/)** — React + Mendix Pluggable Widget API의 Gleam FFI 바인딩 (Hex 패키지). React 원시 함수와 Mendix 런타임 타입 접근자를 타입 안전하게 제공
|
|
210
210
|
- **Mendix Pluggable Widget** (React 19)
|
|
211
211
|
- **Package Manager**: ${pm} (기본 npm 의존성은 \`gleam run -m glendix/install\`로 설치, \`bindings.json\` 외부 React 패키지는 수동 설치 필요)
|
|
212
212
|
- **Build**: \`@mendix/pluggable-widgets-tools\` (Rollup 기반)
|
|
213
|
+
- **Package**: \`.mpk\` (ZIP 아카이브) → Mendix Studio Pro에 배포
|
|
213
214
|
|
|
214
215
|
## Architecture
|
|
215
216
|
|
|
@@ -220,28 +221,94 @@ src/
|
|
|
220
221
|
editor_preview.gleam # Studio Pro 디자인 뷰 미리보기
|
|
221
222
|
components/
|
|
222
223
|
hello_world.gleam # Hello World 공유 컴포넌트
|
|
223
|
-
${names.pascalCase}.xml # 위젯 속성 정의
|
|
224
|
+
${names.pascalCase}.xml # 위젯 속성 정의 (Mendix Studio Pro용)
|
|
224
225
|
package.xml # Mendix 패키지 매니페스트
|
|
225
226
|
ui/
|
|
226
227
|
${names.pascalCase}.css # 위젯 스타일시트
|
|
227
228
|
widgets/ # .mpk 위젯 파일 (glendix/widget로 바인딩)
|
|
228
229
|
bindings.json # 외부 React 컴포넌트 바인딩 설정
|
|
229
|
-
package.json # npm 의존성 (React,
|
|
230
|
-
gleam.toml # Gleam 프로젝트 설정
|
|
230
|
+
package.json # npm 의존성 (React, 빌드 도구 등)
|
|
231
|
+
gleam.toml # Gleam 프로젝트 설정
|
|
231
232
|
docs/
|
|
232
|
-
gleam_language_tour.md # Gleam 언어 레퍼런스
|
|
233
|
-
glendix_guide.md # glendix 사용 가이드
|
|
233
|
+
gleam_language_tour.md # Gleam 언어 레퍼런스 (문법 전체)
|
|
234
|
+
glendix_guide.md # glendix 사용 가이드 (React/Mendix 바인딩 전체)
|
|
234
235
|
\`\`\`
|
|
235
236
|
|
|
236
|
-
|
|
237
|
+
## glendix — React + Mendix 바인딩 패키지
|
|
238
|
+
|
|
239
|
+
React FFI와 Mendix API 바인딩은 별도 Hex 패키지 [glendix](https://hexdocs.pm/glendix/)로 분리되어 있다. 이 프로젝트는 glendix를 의존성으로 사용한다.
|
|
240
|
+
|
|
241
|
+
glendix가 제공하는 모듈:
|
|
242
|
+
|
|
243
|
+
React:
|
|
244
|
+
- \`glendix/react\` — 핵심 타입(\`ReactElement\`, \`JsProps\`, \`Component\`, \`Context\`, \`Ref\`) + \`element\`/\`element_\`/\`void_element\`/\`component_el\`/\`component_el_\`/\`void_component_el\`/\`fragment\`/\`text\`/\`none\` + 조건부 렌더링(\`when\`, \`when_some\`) + \`define_component\`/\`memo\`/\`StrictMode\`/\`Suspense\`/\`Profiler\`/\`portal\`/\`forwardRef\`
|
|
245
|
+
- \`glendix/react/attribute\` — Attribute 리스트 API (\`[attribute.class("x"), event.on_click(handler)]\`) + 90+ HTML 속성 함수 + \`attribute.none()\` 조건부 속성
|
|
246
|
+
- \`glendix/react/hook\` — React Hooks (\`useState\`, \`useEffect\`, \`useLayoutEffect\`, \`useInsertionEffect\`, \`useMemo\`, \`useCallback\`, \`useRef\`, \`useReducer\`, \`useContext\`, \`useId\`, \`useTransition\`, \`useDeferredValue\`, \`useOptimistic\`, \`useImperativeHandle\`, \`useLazyState\`, \`useSyncExternalStore\`, \`useDebugValue\`)
|
|
247
|
+
- \`glendix/react/event\` — 15개 이벤트 타입 + 148+ 핸들러 Attribute (캡처 단계 포함) + 67+ 접근자
|
|
248
|
+
- \`glendix/react/html\` — 75+ HTML 태그 편의 함수 (순수 Gleam, FFI 없음)
|
|
249
|
+
- \`glendix/react/svg\` — 57 SVG 요소 편의 함수 (순수 Gleam, FFI 없음)
|
|
250
|
+
- \`glendix/react/svg_attribute\` — 97+ SVG 전용 속성 함수 (순수 Gleam, FFI 없음)
|
|
251
|
+
- \`glendix/binding\` — 외부 React 컴포넌트 바인딩 (\`bindings.json\` + \`binding.module\`/\`binding.resolve\`)
|
|
252
|
+
- \`glendix/widget\` — .mpk 위젯 컴포넌트 바인딩 (\`widget.component\`)
|
|
253
|
+
|
|
254
|
+
Mendix:
|
|
255
|
+
- \`glendix/mendix\` — \`ValueStatus\`, \`ObjectItem\`, JsProps 접근자
|
|
256
|
+
- \`glendix/mendix/editable_value\` — 편집 가능한 값
|
|
257
|
+
- \`glendix/mendix/action\` — 액션 실행
|
|
258
|
+
- \`glendix/mendix/dynamic_value\` — 동적 읽기 전용 값
|
|
259
|
+
- \`glendix/mendix/list_value\` — 리스트 데이터 + 정렬/필터
|
|
260
|
+
- \`glendix/mendix/list_attribute\` — 리스트 아이템별 접근
|
|
261
|
+
- \`glendix/mendix/selection\` — 단일/다중 선택
|
|
262
|
+
- \`glendix/mendix/reference\` — 단일 연관 참조 (ReferenceValue)
|
|
263
|
+
- \`glendix/mendix/reference_set\` — 다중 연관 참조 (ReferenceSetValue)
|
|
264
|
+
- \`glendix/mendix/date\` — JS Date 래퍼 (월 1-based)
|
|
265
|
+
- \`glendix/mendix/big\` — Big.js 고정밀 십진수 래퍼
|
|
266
|
+
- \`glendix/mendix/file\` — 파일/이미지
|
|
267
|
+
- \`glendix/mendix/icon\` — 아이콘
|
|
268
|
+
- \`glendix/mendix/formatter\` — 값 포맷팅/파싱
|
|
269
|
+
- \`glendix/mendix/filter\` — 필터 조건 빌더
|
|
270
|
+
|
|
271
|
+
빌드 스크립트:
|
|
272
|
+
- \`glendix/cmd\` — 셸 명령어 실행 + 패키지 매니저 자동 감지 (\`exec\`, \`detect_runner\`, \`run_tool\`)
|
|
273
|
+
- \`glendix/build\` — 프로덕션 빌드 (\`gleam run -m glendix/build\`)
|
|
274
|
+
- \`glendix/dev\` — 개발 서버 (\`gleam run -m glendix/dev\`)
|
|
275
|
+
- \`glendix/start\` — Mendix 연동 (\`gleam run -m glendix/start\`)
|
|
276
|
+
- \`glendix/install\` — 의존성 설치 (\`gleam run -m glendix/install\`)
|
|
277
|
+
- \`glendix/release\` — 릴리즈 빌드 (\`gleam run -m glendix/release\`)
|
|
278
|
+
- \`glendix/lint\` — ESLint 실행 (\`gleam run -m glendix/lint\`)
|
|
279
|
+
- \`glendix/lint_fix\` — ESLint 자동 수정 (\`gleam run -m glendix/lint_fix\`)
|
|
280
|
+
- \`glendix/marketplace\` — Mendix Marketplace 위젯 검색/다운로드 (\`gleam run -m glendix/marketplace\`)
|
|
281
|
+
|
|
282
|
+
## Integration Strategy: Gleam + glendix → Mendix Widget
|
|
283
|
+
|
|
284
|
+
JSX 파일 없이 Gleam + glendix로 위젯을 구현한다. glendix가 React 원시 함수와 Mendix 런타임 타입 접근을 타입 안전하게 제공하므로, 위젯 프로젝트에서는 비즈니스 로직에만 집중한다.
|
|
285
|
+
|
|
286
|
+
핵심 원리:
|
|
287
|
+
- Gleam 함수 \`fn(JsProps) -> ReactElement\`는 React 함수형 컴포넌트와 동일한 시그니처
|
|
288
|
+
- glendix의 FFI 레이어(\`react_ffi.mjs\`, \`mendix_ffi.mjs\`)는 얇은 어댑터일 뿐, 위젯 로직과 UI 구조는 전부 Gleam 코드
|
|
289
|
+
- Mendix가 전달하는 props(순수 JS 객체)를 \`mendix.get_prop\`/\`mendix.get_string_prop\` 등으로 접근
|
|
290
|
+
- Mendix 복합 타입(\`EditableValue\`, \`ActionValue\`, \`ListValue\` 등)은 opaque type + FFI 접근자로 타입 안전하게 다룸
|
|
291
|
+
- JS \`undefined\` ↔ Gleam \`Option\` 변환은 FFI 경계에서 자동 처리
|
|
292
|
+
- HTML 속성은 Attribute 리스트 기반 선언적 API로 구성 (\`[attribute.class("x"), event.on_click(handler)]\`)
|
|
293
|
+
- Gleam List는 linked list이므로 FFI에서 \`.toArray()\` 호출 후 React.createElement에 spread
|
|
294
|
+
- Gleam 튜플 \`#(a, b)\` = JS \`[a, b]\` — useState 반환값과 직접 호환
|
|
295
|
+
|
|
296
|
+
핵심 제약사항:
|
|
297
|
+
- Mendix 위젯의 진입점은 MUST React 컴포넌트여야 한다 (\`pluginWidget="true"\`)
|
|
298
|
+
- Gleam 컴파일 출력은 ES 모듈 형식이므로 Rollup 번들링과 호환된다
|
|
299
|
+
- 위젯 ID 형식: \`mendix.${names.lowerCase}.${names.pascalCase}\`
|
|
300
|
+
- JSX 파일을 작성하지 않는다. 모든 React 로직은 Gleam + glendix로 구현한다
|
|
301
|
+
- Gleam 컴파일 출력이 Mendix 빌드 도구의 진입점으로 연결되도록 빌드 설정 커스터마이징이 필요하다
|
|
237
302
|
|
|
238
303
|
## Build Pipeline
|
|
239
304
|
|
|
240
305
|
\`\`\`
|
|
241
306
|
[src/*.gleam] + [glendix 패키지 (Hex)]
|
|
242
|
-
↓ gleam run -m glendix/build
|
|
243
|
-
[build/dev/javascript/${names.snakeCase}/*.mjs]
|
|
244
|
-
[build/dev/javascript/glendix/glendix/*.mjs]
|
|
307
|
+
↓ gleam run -m glendix/build (내부적으로 gleam build 자동 수행)
|
|
308
|
+
[build/dev/javascript/${names.snakeCase}/*.mjs] (gleam.toml name 기준)
|
|
309
|
+
[build/dev/javascript/glendix/glendix/*.mjs] (glendix 컴파일 출력)
|
|
310
|
+
[build/dev/javascript/glendix/glendix/react_ffi.mjs]
|
|
311
|
+
[build/dev/javascript/glendix/glendix/mendix_ffi.mjs]
|
|
245
312
|
↓ 브릿지 JS (자동 생성)가 import
|
|
246
313
|
↓ Rollup (pluggable-widgets-tools build:web)
|
|
247
314
|
[dist/1.0.0/mendix.${names.lowerCase}.${names.pascalCase}.mpk]
|
|
@@ -249,8 +316,10 @@ React/Mendix FFI 바인딩은 이 프로젝트에 포함되지 않으며, [glend
|
|
|
249
316
|
|
|
250
317
|
## Commands
|
|
251
318
|
|
|
319
|
+
모든 명령어는 \`gleam\`으로 통일. \`gleam run -m\`은 Gleam 컴파일을 자동 수행한 뒤 스크립트를 실행한다.
|
|
320
|
+
|
|
252
321
|
\`\`\`bash
|
|
253
|
-
gleam run -m glendix/install # 의존성 설치 + 바인딩 코드
|
|
322
|
+
gleam run -m glendix/install # 의존성 설치 (Gleam deps 자동 + PM 자동 감지, bindings.json 바인딩 코드 생성. 단, 외부 React 패키지는 사전에 수동 설치 필요)
|
|
254
323
|
gleam run -m glendix/build # 위젯 프로덕션 빌드 (.mpk 생성)
|
|
255
324
|
gleam run -m glendix/dev # 개발 서버 (HMR, port 3000)
|
|
256
325
|
gleam run -m glendix/start # Mendix 테스트 프로젝트와 연동 개발
|
|
@@ -258,7 +327,7 @@ gleam run -m glendix/lint # ESLint 실행
|
|
|
258
327
|
gleam run -m glendix/lint_fix # ESLint 자동 수정
|
|
259
328
|
gleam run -m glendix/release # 릴리즈 빌드
|
|
260
329
|
gleam run -m glendix/marketplace # Mendix Marketplace 위젯 검색/다운로드
|
|
261
|
-
gleam build --target javascript # Gleam → JS 컴파일만
|
|
330
|
+
gleam build --target javascript # Gleam → JS 컴파일만 (스크립트 없이)
|
|
262
331
|
gleam test # Gleam 테스트 실행
|
|
263
332
|
gleam format # Gleam 코드 포맷팅
|
|
264
333
|
\`\`\`
|
|
@@ -268,52 +337,57 @@ gleam format # Gleam 코드 포맷팅
|
|
|
268
337
|
\`docs/glendix_guide.md\` 파일에 glendix 패키지의 사용법이 수록되어 있다. 주요 내용:
|
|
269
338
|
- 프로젝트 설정 및 첫 번째 위젯 만들기
|
|
270
339
|
- 핵심 개념: opaque 타입, undefined ↔ Option 변환, Attribute 리스트 API
|
|
271
|
-
- React 바인딩: 엘리먼트
|
|
272
|
-
- Mendix 바인딩: Props 접근, ValueStatus, EditableValue, ActionValue, DynamicValue, ListValue, ListAttribute, Selection, Reference, Filter
|
|
340
|
+
- React 바인딩: 엘리먼트 생성(\`element\`/\`element_\`/\`void_element\`/\`component_el\`), Attribute 리스트, HTML 태그 함수, Hooks(\`useState\`/\`useEffect\`/\`useMemo\`/\`useCallback\`/\`useRef\` 등), 이벤트 처리, 조건부/리스트 렌더링, 스타일, 외부 React 컴포넌트 바인딩(\`bindings.json\`), .mpk 위젯 바인딩(\`widgets/\`)
|
|
341
|
+
- Mendix 바인딩: Props 접근, ValueStatus, EditableValue, ActionValue, DynamicValue, ListValue(페이지네이션/정렬), ListAttribute, Selection, Reference, Filter 빌더, JsDate, Big, FileValue/WebIcon/ValueFormatter
|
|
273
342
|
- Marketplace 연동: Mendix Marketplace에서 위젯 검색/다운로드 (\`glendix/marketplace\`)
|
|
274
343
|
- 실전 패턴: 폼 입력 위젯, 데이터 테이블, 검색 가능 리스트, 컴포넌트 합성
|
|
275
|
-
-
|
|
344
|
+
- 트러블슈팅: 빌드/런타임 에러, Hook 규칙
|
|
276
345
|
|
|
277
|
-
##
|
|
278
|
-
|
|
279
|
-
React:
|
|
280
|
-
- \`glendix/react\` — 핵심 타입 + element/element_/void_element/component_el + fragment/text/none + 조건부 렌더링 + define_component/memo/Context
|
|
281
|
-
- \`glendix/react/attribute\` — Attribute 리스트 API (90+ HTML 속성 함수)
|
|
282
|
-
- \`glendix/react/hook\` — React Hooks (useState, useEffect, useMemo, useCallback, useRef 등)
|
|
283
|
-
- \`glendix/react/event\` — 15개 이벤트 타입 + 148+ 핸들러 Attribute + 67+ 접근자
|
|
284
|
-
- \`glendix/react/html\` — 75+ HTML 태그 편의 함수
|
|
285
|
-
- \`glendix/react/svg\` — 57 SVG 요소 편의 함수
|
|
286
|
-
- \`glendix/react/svg_attribute\` — 97+ SVG 전용 속성 함수
|
|
287
|
-
- \`glendix/binding\` — 외부 React 컴포넌트 바인딩
|
|
288
|
-
- \`glendix/widget\` — .mpk 위젯 컴포넌트 바인딩
|
|
289
|
-
- \`glendix/marketplace\` — Mendix Marketplace 위젯 검색/다운로드
|
|
346
|
+
## Gleam Language Reference
|
|
290
347
|
|
|
291
|
-
|
|
292
|
-
-
|
|
293
|
-
- \`
|
|
294
|
-
- \`
|
|
295
|
-
- \`
|
|
296
|
-
- \`
|
|
297
|
-
- \`
|
|
298
|
-
- \`glendix/mendix/selection\` — 단일/다중 선택
|
|
299
|
-
- \`glendix/mendix/reference\` — 단일 연관 참조
|
|
300
|
-
- \`glendix/mendix/reference_set\` — 다중 연관 참조
|
|
301
|
-
- \`glendix/mendix/date\` — JS Date 래퍼
|
|
302
|
-
- \`glendix/mendix/big\` — Big.js 고정밀 십진수 래퍼
|
|
303
|
-
- \`glendix/mendix/file\` — 파일/이미지
|
|
304
|
-
- \`glendix/mendix/icon\` — 아이콘
|
|
305
|
-
- \`glendix/mendix/formatter\` — 값 포맷팅/파싱
|
|
306
|
-
- \`glendix/mendix/filter\` — 필터 조건 빌더
|
|
348
|
+
\`docs/gleam_language_tour.md\` 파일에 Gleam 문법 전체가 수록되어 있다. 주요 특징:
|
|
349
|
+
- 정적 타입, 불변 데이터, 패턴 매칭
|
|
350
|
+
- \`pub fn\` 으로 외부 공개 함수 선언
|
|
351
|
+
- \`import gleam/모듈\` 로 표준 라이브러리 사용
|
|
352
|
+
- JavaScript 타겟 시 \`@external(javascript, "모듈", "함수")\` 로 JS 함수 호출 가능
|
|
353
|
+
- Result 타입(\`Ok\`, \`Error\`)으로 에러 처리
|
|
354
|
+
- \`use\` 키워드로 콜백 체이닝 간소화
|
|
307
355
|
|
|
308
356
|
## Mendix Widget Conventions
|
|
309
357
|
|
|
310
|
-
-
|
|
311
|
-
-
|
|
312
|
-
- 위젯
|
|
358
|
+
- \`src/${names.pascalCase}.xml\`: 위젯 속성 정의. \`<property>\` 추가 시 빌드 도구가 자동으로 타입 생성
|
|
359
|
+
- \`src/package.xml\`: 패키지 매니페스트. \`widgetFile\` 경로와 컴파일 출력 경로 지정
|
|
360
|
+
- 위젯 컴포넌트는 \`default export\` 또는 \`named export\` 함수형 React 컴포넌트
|
|
361
|
+
- \`needsEntityContext="true"\` → 위젯이 Mendix 데이터 컨텍스트 필요
|
|
362
|
+
- \`offlineCapable="true"\` → 오프라인 지원
|
|
363
|
+
- editorConfig도 Gleam으로 작성. 브릿지 JS는 glendix가 빌드 시 자동 생성/삭제한다
|
|
364
|
+
|
|
365
|
+
## Mendix Documentation
|
|
366
|
+
|
|
367
|
+
Mendix 공식 문서 사이트(docs.mendix.com)는 접근 불가. 대신 GitHub raw 소스를 사용:
|
|
368
|
+
- Base: \`https://github.com/mendix/docs/blob/development/content/en/docs\`
|
|
369
|
+
- Pluggable Widgets API: \`apidocs-mxsdk/apidocs/pluggable-widgets/\`
|
|
370
|
+
- How-to: \`howto/extensibility/\`
|
|
371
|
+
- Widget 빌드 도구 소스: \`https://github.com/mendix/widgets-tools\`
|
|
372
|
+
- 공식 위젯 예제: \`https://github.com/mendix/web-widgets\`
|
|
373
|
+
|
|
374
|
+
## Important Notes
|
|
375
|
+
|
|
376
|
+
- Gleam 컴파일 출력 경로와 Rollup 번들링 입력 경로가 MUST 일치해야 한다
|
|
377
|
+
- \`package.json\`의 \`packagePath: "mendix"\`가 위젯 배포 경로를 결정한다
|
|
378
|
+
- Mendix 위젯 이름은 영문자(a-zA-Z)만 허용된다
|
|
379
|
+
- \`.mpk\` 파일은 \`dist/\` 디렉토리에 생성된다
|
|
380
|
+
- 테스트 프로젝트 경로: \`./tests/testProject\`
|
|
381
|
+
- Gleam→JS→Mendix Widget 파이프라인은 공식 지원되지 않는 조합이므로, 빌드 설정 커스터마이징이 필요할 수 있다
|
|
382
|
+
- **JSX/JS 파일을 직접 작성하지 않는다.** 모든 위젯 로직과 UI는 Gleam으로 작성하고 JS로 컴파일한다
|
|
383
|
+
- Mendix 빌드 도구가 요구하는 브릿지 JS 파일(진입점, editorConfig, editorPreview)은 glendix가 빌드 시 자동 생성/삭제한다. 수동 관리 불필요
|
|
384
|
+
- Redraw 등 외부 Gleam React 라이브러리는 사용하지 않는다. glendix가 Gleam FFI로 React API를 직접 바인딩한다
|
|
385
|
+
- React/Mendix FFI 바인딩은 glendix 패키지에서 제공한다. 위젯 프로젝트에 FFI 파일을 직접 작성하지 않는다
|
|
313
386
|
|
|
314
387
|
## Code Style
|
|
315
388
|
|
|
316
389
|
- Gleam 파일: \`gleam format\` 사용
|
|
390
|
+
- Gleam 컴파일 출력 JS: 수동 편집하지 않는다
|
|
317
391
|
- 한국어 주석 사용
|
|
318
392
|
`;
|
|
319
393
|
|