Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,38 @@ pub fn pie_chart(

npm バインディングは Glendix 単体で動作します。

非同期の準備が必要な module は拡張 table 形式で設定します。

```toml
[tools.glendix.bindings."@ironcalc/workbook"]
exports = ["Workbook"]
initializer = "init"
retry = "on-failure"
```

`initializer` は引数なしで呼び出され、Promise を返す export 名です。`retry` は
既定値の `"never"`(明示的に reset するまで失敗を cache)または
`"on-failure"`(失敗結果を state に記録した後、次の呼び出しで再試行)です。
非 React API だけを使う module は `exports` を省略できます。従来の文字列・配列
形式は初期化不要の module としてそのまま動作します。

`binding.initialization` で caller-owned state を作り、`binding.initialize` が返す
`ModuleInitialization` を application model に保存します。`Initializing` 中の
同時呼び出しは同じ Promise を共有します。完了結果を
`binding.settle_initialization` に渡した後、`binding.initialized_module` から同じ
ready module を rendering と非 React API の両方で利用できます。Lustre は
`binding.initialization_effect`、React Suspense は同じ Promise に
`binding.use_initialization` を利用できます。`binding.reset_initialization` は
失敗済みまたは ready の状態を明示的に reset します。

TOML の package/export 名は Glendix 自体の compile 後に読み込まれるため、installer
は生成 FFI 境界を 1 つ保持します。この境界は決定的な static named import、metadata
参照、initializer の直接呼び出しだけを行います。Promise の生成、one-flight 共有、
結果変換、retry state、完了 dispatch は `gleam/javascript/promise` を使う Gleam
コードが担当します。dynamic `import()` や生成 Promise cache は使わないため、
Rollup と WebAssembly asset 検出の決定性も維持されます。


## ブラウザ環境とオブジェクト prop

`glendix/js/environment` は `window.matchMedia` を型付き境界の内側に隠し、ウィ
Expand Down
32 changes: 32 additions & 0 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,38 @@ pub fn pie_chart(
npm 바인딩은 Glendix만으로 동작한다. `binding.element_`와
`binding.void_element`도 제공한다.

비동기 준비가 필요한 모듈은 확장 테이블 형식으로 설정한다.

```toml
[tools.glendix.bindings."@ironcalc/workbook"]
exports = ["Workbook"]
initializer = "init"
retry = "on-failure"
```

`initializer`는 인자 없이 호출하며 Promise를 반환하는 export 이름이다. `retry`는
기본값인 `"never"`(명시적으로 reset할 때까지 실패를 캐시) 또는
`"on-failure"`(실패 결과를 state에 반영한 뒤 다음 호출에서 재시도)다. React
컴포넌트가 아닌 API만 쓰는 모듈은 `exports`를 생략할 수 있다. 기존 문자열과
문자열 배열 형식은 초기화가 필요 없는 모듈로 그대로 동작한다.

`binding.initialization`으로 caller-owned state를 만들고 `binding.initialize`가
반환한 `ModuleInitialization`을 애플리케이션 model에 저장한다. `Initializing`
상태의 동시 호출은 같은 Promise를 공유한다. 완료 결과를
`binding.settle_initialization`에 전달한 뒤 `binding.initialized_module`로 같은
준비 완료 모듈을 렌더링과 non-React API에서 함께 사용한다. Lustre는
`binding.initialization_effect`, React Suspense는 같은 Promise에
`binding.use_initialization`을 사용할 수 있다. `binding.reset_initialization`은
실패 또는 준비 완료 상태를 명시적으로 초기화한다.

TOML의 package/export 이름은 Glendix가 이미 compile된 뒤 읽히므로 installer는
생성된 FFI 경계를 하나 유지한다. 이 경계는 결정적인 정적 named import, metadata
조회, initializer 직접 호출만 수행한다. Promise 생성·one-flight 공유·결과 변환·retry
state·완료 dispatch는 `gleam/javascript/promise`를 사용하는 Gleam 코드가 담당한다.
동적 `import()`나 생성된 Promise cache가 없으므로 Rollup과 WebAssembly asset 탐색도
결정적으로 유지된다.


## 브라우저 환경과 객체 prop

`glendix/js/environment`는 `window.matchMedia`를 타입 경계 뒤에 숨겨, 위젯이
Expand Down
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,57 @@ pub fn pie_chart(
`binding.element_` creates an element with children only, and
`binding.void_element` creates one without children.

Modules that require asynchronous setup use the extended table form:

```toml
[tools.glendix.bindings."@ironcalc/workbook"]
exports = ["Workbook"]
initializer = "init"
retry = "on-failure"
```

`initializer` names a zero-argument export that must return a Promise. `retry`
is either `"never"` (the default, which caches a failure until explicit reset)
or `"on-failure"` (the next initialization call may start a new attempt after
the failed result has been recorded). `exports` may be omitted for modules used
only through non-React APIs. Legacy string and array values require no
initialization and remain ready immediately.

```gleam
import gleam/javascript/promise
import glendix/binding

pub fn load(
module module: binding.JsModule,
) -> #(
binding.ModuleInitialization,
promise.Promise(Result(Nil, binding.InitializationError)),
) {
module
|> binding.initialization
|> binding.initialize
}
```

Store the returned `ModuleInitialization` in the application model. Concurrent
calls made with its `Initializing` value return the same Promise. When that
Promise completes, pass its result to `binding.settle_initialization`; then
`binding.initialized_module` makes the same ready module available to rendering
and non-React consumers. `binding.initialization_effect` dispatches the result
through Lustre, while `binding.use_initialization` consumes the same attempt in
a React Suspense boundary. `binding.reset_initialization` explicitly clears a
settled failure (or reinitializes a ready configured module).

The installer retains one generated FFI boundary because the package and export
names are read from `gleam.toml` after Glendix itself has compiled; Gleam
`@external` package/export literals must exist before compilation. That boundary
contains deterministic static named imports, metadata lookup, and the direct
initializer call only. Promise creation, one-flight sharing, result mapping,
retry state, and completion dispatch are implemented in Gleam with
`gleam/javascript/promise`. No dynamic `import()` or generated Promise cache is
used, so Rollup can still discover module WebAssembly assets.


## Browser environment and object props

`glendix/js/environment` reads the browser color-scheme preference behind a
Expand Down
23 changes: 23 additions & 0 deletions glendix_guide.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,29 @@ pub fn pie_chart(

npm バインディングは Glendix 単体で動作します。

非同期準備が必要な module は拡張形式で設定します。

```toml
[tools.glendix.bindings."@ironcalc/workbook"]
exports = ["Workbook"]
initializer = "init"
retry = "on-failure"
```

initializer は引数なしで呼び出され、Promise を返す必要があります。`retry` の既定値
`"never"` は reset まで失敗を cache し、`"on-failure"` は失敗結果の記録後に次の
試行を許可します。`binding.initialization` と `binding.initialize` が返す
`ModuleInitialization` を model に保存すると、同時呼び出しは同じ Promise を共有
します。完了は `binding.settle_initialization` で記録し、
`binding.initialized_module` を rendering と非 React API で共有します。Lustre は
`binding.initialization_effect`、React Suspense は `binding.use_initialization` を
利用できます。

生成コードは TOML で選択した export の static import と直接呼び出しだけを担当し、
Promise と retry の orchestration は `gleam/javascript/promise` ベースの Gleam
コードにあります。dynamic `import()` や生成 Promise cache は使いません。


## ブラウザ環境とオブジェクト prop

`glendix/js/environment` を使うと、`window.matchMedia` を公開せずに
Expand Down
23 changes: 23 additions & 0 deletions glendix_guide.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,29 @@ pub fn pie_chart(
npm 바인딩은 Glendix만으로 동작한다. `binding.element_`와
`binding.void_element`도 제공한다.

비동기 준비가 필요한 모듈은 확장 형식으로 설정한다.

```toml
[tools.glendix.bindings."@ironcalc/workbook"]
exports = ["Workbook"]
initializer = "init"
retry = "on-failure"
```

initializer는 인자 없이 호출하며 Promise를 반환해야 한다. `retry` 기본값
`"never"`는 reset 전까지 실패를 캐시하고, `"on-failure"`는 실패 결과를 반영한 뒤
다음 시도를 허용한다. `binding.initialization`과 `binding.initialize`로 만든
`ModuleInitialization`을 model에 저장하면 동시 호출이 같은 Promise를 공유한다.
완료 결과는 `binding.settle_initialization`으로 반영하고,
`binding.initialized_module`을 렌더링과 non-React API가 함께 사용한다. Lustre는
`binding.initialization_effect`, React Suspense는 `binding.use_initialization`을
사용한다.

생성 코드는 TOML로 선택한 export의 정적 import와 직접 호출만 담당한다. Promise와
retry orchestration은 `gleam/javascript/promise` 기반 Gleam 코드에 있으며 동적
`import()`나 생성된 Promise cache를 사용하지 않는다.


## 브라우저 환경과 객체 prop

`glendix/js/environment`를 사용하면 `window.matchMedia`를 노출하지 않고
Expand Down
26 changes: 26 additions & 0 deletions glendix_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,32 @@ pub fn pie_chart(
`binding.element_` creates an element with children only, and
`binding.void_element` creates one without children.

For a module that must finish asynchronous setup before use, configure an
extended binding:

```toml
[tools.glendix.bindings."@ironcalc/workbook"]
exports = ["Workbook"]
initializer = "init"
retry = "on-failure"
```

The initializer must be a zero-argument Promise-returning export. `retry` is
`"never"` by default (cache failure until `binding.reset_initialization`) or
`"on-failure"` (allow a later attempt after settlement). Create state with
`binding.initialization`, call `binding.initialize`, and store the returned
`ModuleInitialization`. Concurrent calls share its Promise. Record completion
with `binding.settle_initialization`, then use `binding.initialized_module` for
both rendering and non-React consumers. Lustre can use
`binding.initialization_effect`; React Suspense can use
`binding.use_initialization` with that same Promise.

Glendix keeps only a generated static-import/direct-call FFI for names selected
from TOML after package compilation. All Promise and retry orchestration uses
`gleam/javascript/promise`; the generated code has no dynamic import or Promise
cache, preserving deterministic Rollup and WebAssembly asset discovery.


## Browser environment and object props

Use `glendix/js/environment` to read `prefers-color-scheme` without exposing
Expand Down
Loading
Loading