diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml index 1fddea9..fa243be 100644 --- a/.github/workflows/upload.yaml +++ b/.github/workflows/upload.yaml @@ -11,21 +11,31 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 + timeout-minutes: 20 steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@v7.0.1 + with: + persist-credentials: false - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.1.0 + - uses: actions/setup-node@v6.5.0 with: node-version: 24 + package-manager-cache: false - name: Enable Corepack run: corepack enable && corepack prepare yarn@4.18.0 --activate - - uses: calcit-lang/setup-calcit@704b3f5cd6f9ce3bd1e0c926dbdd1d181adb8180 # v1 + - uses: calcit-lang/setup-calcit@v1.5.0 + with: + tools: calcit,caps + caps-version: '0.1.1' + deps-file: deps.cirru - name: Install dependencies run: | + test ! -e compact.cirru + test ! -e package.cirru caps --strict --ci yarn install --immutable @@ -36,13 +46,29 @@ jobs: run: | calcit calcit.cirru edit format git diff --exit-code -- calcit.cirru - calcit calcit.cirru --check-only - calcit calcit.cirru analyze dynamic-methods --summary-only --format json | jq -e '.data.summary.findings == 0' + calcit --check-only --all-defs --format json + calcit --check-only --ns app.main --ns app.config --ns app.schema --ns app.updater --format json + calcit fix --workflow strict --verify --format json | jq -e '.data.workflow.status == "passed" and .diagnostics == []' + calcit analyze weak-types --only dynamic-method --summary-only --format json | jq -e '.data.summary.findings == 0' + calcit analyze weak-types --only deprecated-call --summary-only --format json | jq -e '.data.summary.calls == 0' - name: Compile and build web app + env: + VITE_BASE_URL: ${{ github.event_name == 'pull_request' && './' || format('https://cos-sh.tiye.me/{0}/', github.repository) }} run: | - calcit calcit.cirru js - yarn vite build --base=./ + yarn build + + - name: Upload and verify frontend resources on COS + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: worktools/cos-upload-action@v1.2.0 + with: + source-dir: dist/assets + bucket: ${{ secrets.COS_BUCKET }} + region: ap-shanghai + prefix: ${{ github.repository }}/assets/ + public-base-url: https://cos-sh.tiye.me/${{ github.repository }}/assets/ + secret-id: ${{ secrets.COS_SECRET_ID }} + secret-key: ${{ secrets.COS_SECRET_KEY }} - name: Install verified rsync run: | @@ -104,6 +130,17 @@ jobs: - name: mdbook build run: mdbook build && mv -v book/html/index.html book/html/mdbook.html + - name: Preserve PR preview for browser acceptance + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v7.0.2 + with: + name: respo-guidebook-preview + path: | + dist + book/html + if-no-files-found: error + retention-days: 7 + - name: Deploy mdBook if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: | diff --git a/.gitignore b/.gitignore index 1e66559..f462c43 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ book/ .DS_Store .yarn/install-state.gz +.calcit/ diff --git a/.yarnrc.yml b/.yarnrc.yml index c6e0f6b..3186f3f 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1,3 +1 @@ nodeLinker: node-modules -npmPreapprovedPackages: - - "@calcit/procs@0.20.0" diff --git a/README.md b/README.md index 5bd10ce..e459de9 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,48 @@ -## Calcit Guide Book +# Respo Guidebook + +配对正式 Calcit CLI / `@calcit/procs` 0.30.1,以及已发布的 Docs Workflow 0.0.37、 +Respo 0.16.124、Reel 0.6.41、UI 0.8.0 和 JS-FFI 0.2.5。升级后重新安装依赖并完整 +刷新页面,不混用旧 CLI/alpha runtime。UI 0.8 基础样式可能影响外观。源码仅使用 +`calcit.cirru` 与 `deps.cirru`,不生成 compact/package.cirru。 + +Guide 说明当前 Ref/watch、Option、widget/app dispatch、名义 Store 和宿主边界。 +旧 Beginner Guide/API 仍有历史片段,尚未全部迁移或独立执行;站点构建通过不代表 +所有旧示例都可用于当前版本。新应用以维护中的模板和已发布接口为准。 + +## 开发与验收 + +Node 24、Yarn 4.18.0、正式 0.30.1 CLI: + +```bash +corepack enable +caps --strict --ci +yarn install --immutable +caps verify --toolchain +calcit --check-only --all-defs +calcit fix --workflow strict --verify +yarn dev +``` + +`yarn build` 默认使用相对资源路径,`VITE_BASE_URL` 可指定前端 CDN 根路径。CI +检查所有定义、公开 namespace、完整 strict、旧调用与动态方法,构建 SPA/mdBook +并保存 PR 预览。原项目没有定义附带测试,零个测试不等于业务覆盖;浏览器导航、 +搜索与刷新需另行验收。页面 `hud!` 错误展示保留。 + +## 部署边界 + +生产 SPA 引用 `https://cos-sh.tiye.me/Respo/guidebook/` 下的静态 assets,COS 只用 +action 内置校验,不新增脚本。原 SPA/mdBook 的 rsync 目录均保持 +`/web-assets/repo/Respo/guidebook`,无服务端部署。本 PR 不自动合并或发版。 +组织级 COS secrets 需要授权本仓库;PR 不读取部署凭据、不运行 COS 或 rsync。 +原 SHA256 校验的 rsync/mdBook 安装、SSH 主机校验和 main 部署条件保留。 ```bash cargo install mdbook cargo install mdbook-linkcheck - -mdbook serve +mdbook build ``` -### License +## License MIT diff --git a/assets/main.css b/assets/main.css index b15bb9b..ec35cab 100644 --- a/assets/main.css +++ b/assets/main.css @@ -1,5 +1,5 @@ -@import url("@calcit/docs-workflow/assets/main.css"); +@import url("../.calcit/modules/docs-workflow/assets/main.css"); p img { max-width: 100%; diff --git a/calcit.cirru b/calcit.cirru index ebef5e6..99b3552 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -3,7 +3,7 @@ :about "|Machine-generated snapshot. Do not edit directly — changes will be overwritten. Use `calcit query` to inspect and `calcit edit`/`calcit tree` to modify. Run `calcit docs agents --contract` before mutations; use `--full` for first orientation or changed contract digest. Manual edits must follow format and schema conventions, then run `calcit edit format`." :package |app :entries $ {} $ :default - {} (:description |) (:init-fn 'app.main/main!) (:mode :js) (:reload-fn 'app.main/reload!) + {} (:description |) (:init-fn 'app.main/main!) (:mode :js) (:reload-fn 'app.main/reload!) (:target :browser) :feature-policy $ {} :modules $ [] |respo.calcit/ |respo-ui.calcit/ |respo-markdown.calcit/ |reel.calcit/ |respo-router.calcit/ |docs-workflow/ |js-ffi/ :type-slots $ {} @@ -16,7 +16,7 @@ :schema $ :: 'StructDef 'dev? $ %{} 'CodeEntry (:doc |) :code $ quote $ def dev? - = |dev $ option:unwrap-or (get-env |mode) |release + = |dev $ .unwrap-or (get-env |mode) |release :examples $ [] :schema $ :: 'Bool 'site $ %{} 'CodeEntry (:doc |) @@ -28,50 +28,61 @@ 'app.main $ %{} 'FileEntry :defs $ {} '*reel $ %{} 'CodeEntry (:doc |) - :code $ quote $ defatom *reel (typed/new-reel schema/store) + :code $ quote $ defref *reel (typed/new-reel schema/store) :examples $ [] - :schema $ :: 'Ref $ :: 'reel.typed/State 'app.schema/Op 'app.schema/Store + :schema $ :: 'Ref $ :: 'reel.typed/State 'docs-workflow.schema/Op 'docs-workflow.schema/Store 'dispatch! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn dispatch! (op) - when config/dev? $ match op - (:states _ _) &unit - _ $ js/console.log |Dispatch: op - let - typed-op $ assert-type op 'Enum - control $ typed/decode-control typed-op - reset! *reel $ assert-type - match control - (:some action) (typed/apply-control updater @*reel action) - (:none) - typed/record-op updater @*reel (assert-type typed-op 'app.schema/Op) (generate-id!) (unsafe-coerce js/Date.now 'Number) - :: 'reel.typed/State 'app.schema/Op 'app.schema/Store - , &unit + when config/dev? $ println |Dispatch: op + match (typed/decode-control op) + (:some control) + reset! *reel $ typed/apply-control updater @*reel control + (:none) + match op + (:states cursor data) + match + try-decode-map-as cursor $ :: 'List 'Tag + (:ok typed-cursor) + reset! *reel $ typed/record-op updater @*reel (docs-schema/Op :states typed-cursor data) (generate-id!) + :timestamp $ shared/date-now-snapshot + (:err message) (eprintln message) + (:hydrate-storage data) + match (try-decode-map-as data 'docs-workflow.schema/Store) + (:ok store) + reset! *reel $ typed/record-op updater @*reel (docs-schema/Op :hydrate-storage store) (generate-id!) + :timestamp $ shared/date-now-snapshot + (:err message) (eprintln message) + _ $ eprintln |Unknown-operation: op + , &unit :examples $ [] :schema $ :: 'Fn $ {} (:return 'Unit) - :args $ [] 'Dynamic + :args $ [] 'Enum :features $ #{} :js-ffi 'main! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn main! () (register-languages!) println "|Running mode:" $ if config/dev? |dev |release if config/dev? $ load-console-formatter! render-app! - add-watch *reel :changes $ fn (reel prev) (render-app!) + add-watch! *reel :changes $ fn (reel prev) (render-app!) listen-devtools! |k dispatch! - set-before-unload! $ fn (event) (persist-storage!) - set-interval! persist-storage! 60000 + browser/set-before-unload! $ fn (event) (persist-storage!) + browser/set-interval! persist-storage! 60000 println "|App started." :examples $ [] :schema $ :: 'Fn $ {} (:return 'Unit) :args $ [] :features $ #{} :js-ffi 'mount-target $ %{} 'CodeEntry (:doc |) - :code $ quote $ def mount-target - option:unwrap $ query-selector |.app + :code $ quote $ defn mount-target () + .query-selector (js-cast js/document dom/DomDocument) |.app :examples $ [] - :schema $ :: 'js-ffi.browser/DomElementHost + :schema $ :: 'Fn $ {} + :args $ [] + :features $ #{} :js-ffi + :return $ :: 'JsNullish 'respo.dom/DomElement 'persist-storage! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn persist-storage! () (js/console.log |persist) - storage-set! (:storage-key config/site) + browser/storage-set! (:storage-key config/site) format-cirru-edn $ :store @*reel :examples $ [] :schema $ :: 'Fn $ {} (:return 'Unit) @@ -80,21 +91,26 @@ 'reload! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn reload! () if (nil? build-errors) - do (remove-watch *reel :changes) (clear-cache!) - add-watch *reel :changes $ fn (reel prev) (render-app!) + do (remove-watch! *reel :changes) (clear-cache!) + add-watch! *reel :changes $ fn (reel prev) (render-app!) reset! *reel $ typed/refresh updater @*reel schema/store hud! |ok~ |Ok hud! |error build-errors + , &unit :examples $ [] :schema $ :: 'Fn $ {} (:return 'Unit) :args $ [] :features $ #{} :js-ffi 'render-app! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn render-app! () - match (query-selector |.app) - (:some target) - render! target (comp-container @*reel schema/docs) dispatch! - (:none) &unit + render! (mount-target) (comp-container @*reel schema/docs) + fn (op) + hint-fn $ {} + :args $ [] 'Dynamic + :return 'Unit + :features $ #{} :js-ffi + if (enum? op) (dispatch! op) (raise "|Expected an Enum render action") + , &unit :examples $ [] :schema $ :: 'Fn $ {} (:return 'Unit) :args $ [] @@ -107,108 +123,59 @@ app.updater :refer $ updater app.schema :as schema reel.util :refer $ listen-devtools! - reel.schema :as reel-schema app.config :as config |./calcit.build-errors :default build-errors |bottom-tip :default hud! docs-workflow.config :refer $ register-languages! reel.typed :as typed - js-ffi.browser :refer $ [] DomElementHost query-selector set-before-unload! set-interval! storage-set! + js-ffi.browser :as browser + js-ffi.shared :as shared + respo.dom :as dom + docs-workflow.schema :as docs-schema 'app.schema $ %{} 'FileEntry :defs $ {} - 'Op $ %{} 'CodeEntry (:doc |) - :code $ quote $ defenum Op (:states 'List 'Dynamic) (:hydrate-storage 'app.schema/Store) - :examples $ [] - :schema $ :: 'EnumDef - 'Store $ %{} 'CodeEntry (:doc |) - :code $ quote $ defstruct Store (:states 'Map) - :examples $ [] - :schema $ :: 'StructDef 'docs $ %{} 'CodeEntry (:doc |) :code $ quote $ def docs [] - {} (:title |Home) (:key :home) - :content $ load-doc |home.md - :children $ [] - {} (:title "|Beginner Guide") (:key :beginner-guide) - :content $ load-doc |beginner-guide.md - :children $ [] - {} (:title |Guide) (:key :guide) - :content $ load-doc |guide.md - :children $ [] - {} (:title "|Why Respo") (:key :why-respo) - :content $ load-doc |guide/why-respo.md - {} (:title "|Pros and Cons") (:key :pros-and-cons) - :content $ load-doc |guide/pros-and-cons.md - {} (:title "|DOM Elements") (:key :dom-elements) - :content $ load-doc |guide/dom-elements.md - {} (:title "|DOM Properties") (:key :dom-properties) - :content $ load-doc |guide/dom-properties.md - {} (:title "|DOM Events") (:key :dom-events) - :content $ load-doc |guide/dom-events.md - {} (:title |Styles) (:key :styles) - :content $ load-doc |guide/styles.md - {} (:title "|Virtual DOM") (:key :virtual-dom) - :content $ load-doc |guide/virtual-dom.md - {} (:title "|Define Effect") (:key :defeffect) - :content $ load-doc |apis/defeffect.md - {} (:title "|List Rendering") (:key :render-list) - :content $ load-doc |guide/render-list.md - {} (:title "|Component States") (:key :component-states) - :content $ load-doc |guide/component-states.md - {} (:title "|Hot Swapping") (:key :hot-swapping) - :content $ load-doc |guide/hot-swapping.md - {} (:title "|Base Components") (:key :base-components) - :content $ load-doc |guide/base-components.md - {} (:title "|Server Rendering") (:key :server-rendering) - :content $ load-doc |guide/server-rendering.md - {} (:title "|Trouble Shooting") (:key :trouble-shooting) - :content $ load-doc |guide/trouble-shooting.md - {} (:title |API) (:key :api) - :content $ load-doc |api.md - :children $ [] - {} (:title |defcomp) (:key :defcomp) - :content $ load-doc |apis/defcomp.md - {} (:title |div) (:key :div) - :content $ load-doc |apis/div.md - {} (:title |<>) (:key :expand-tag) - :content $ load-doc |apis/expand-tag.md - {} (:title |defeffect) (:key :defeffect) - :content $ load-doc |apis/defeffect.md - {} (:title |create-element) (:key :create-element) - :content $ load-doc |apis/create-element.md - {} (:title |render!) (:key :render!) - :content $ load-doc |apis/render_.md - {} (:title |clear-cache!) (:key :clear-cache!) - :content $ load-doc |apis/clear-cache_.md - {} (:title |realize-ssr!) (:key :realize-ssr!) - :content $ load-doc |apis/realize-ssr_.md - {} (:title |list->) (:key :list->) - :content $ load-doc |apis/list-_.md - {} (:title |>>) (:key :pick-states) - :content $ load-doc |apis/pick-states.md - {} (:title |comp-space) (:key :comp-space) - :content $ load-doc |apis/comp-space.md - {} (:title |comp-inspect) (:key :comp-inspect) - :content $ load-doc |apis/comp-inspect.md - {} (:title |make-string) (:key :make-string) - :content $ load-doc |apis/make-string.md - {} (:title |render-app) (:key :render-app) - :content $ load-doc |apis/render-app.md - {} (:title |purify-element) (:key :purify-element) - :content $ load-doc |apis/purify-element.md - {} (:title |mute-element) (:key :mute-element) - :content $ load-doc |apis/mute-element.md - {} (:title |find-element-diffs) (:key :find-element-diffs) - :content $ load-doc |apis/find-element-diffs.md - {} (:title |apply-dom-changes) (:key :apply-dom-changes) - :content $ load-doc |apis/apply-dom-changes.md - {} (:title |activate-instance!) (:key :activate-instance) - :content $ load-doc |apis/activate-instance.md - {} (:title |patch-instance!) (:key :patch-instance) - :content $ load-doc |apis/patch-instance.md - {} (:title |Community) (:key :community) - :content $ load-doc |community.md + DocNode :title |Home :key :home :content (load-doc |home.md) :children $ [] + DocNode :title "|Beginner Guide" :key :beginner-guide :content (load-doc |beginner-guide.md) :children $ [] + DocNode :title |Guide :key :guide :content (load-doc |guide.md) :children $ [] + DocNode :title "|Why Respo" :key :why-respo :content (load-doc |guide/why-respo.md) :children $ [] + DocNode :title "|Pros and Cons" :key :pros-and-cons :content (load-doc |guide/pros-and-cons.md) :children $ [] + DocNode :title "|DOM Elements" :key :dom-elements :content (load-doc |guide/dom-elements.md) :children $ [] + DocNode :title "|DOM Properties" :key :dom-properties :content (load-doc |guide/dom-properties.md) :children $ [] + DocNode :title "|DOM Events" :key :dom-events :content (load-doc |guide/dom-events.md) :children $ [] + DocNode :title |Styles :key :styles :content (load-doc |guide/styles.md) :children $ [] + DocNode :title "|Virtual DOM" :key :virtual-dom :content (load-doc |guide/virtual-dom.md) :children $ [] + DocNode :title "|Define Effect" :key :defeffect :content (load-doc |apis/defeffect.md) :children $ [] + DocNode :title "|List Rendering" :key :render-list :content (load-doc |guide/render-list.md) :children $ [] + DocNode :title "|Component States" :key :component-states :content (load-doc |guide/component-states.md) :children $ [] + DocNode :title "|Hot Swapping" :key :hot-swapping :content (load-doc |guide/hot-swapping.md) :children $ [] + DocNode :title "|Base Components" :key :base-components :content (load-doc |guide/base-components.md) :children $ [] + DocNode :title "|Server Rendering" :key :server-rendering :content (load-doc |guide/server-rendering.md) :children $ [] + DocNode :title "|Trouble Shooting" :key :trouble-shooting :content (load-doc |guide/trouble-shooting.md) :children $ [] + DocNode :title |API :key :api :content (load-doc |api.md) :children $ [] + DocNode :title |defcomp :key :defcomp :content (load-doc |apis/defcomp.md) :children $ [] + DocNode :title |div :key :div :content (load-doc |apis/div.md) :children $ [] + DocNode :title |<> :key :expand-tag :content (load-doc |apis/expand-tag.md) :children $ [] + DocNode :title |defeffect :key :defeffect :content (load-doc |apis/defeffect.md) :children $ [] + DocNode :title |create-element :key :create-element :content (load-doc |apis/create-element.md) :children $ [] + DocNode :title |render! :key :render! :content (load-doc |apis/render_.md) :children $ [] + DocNode :title |clear-cache! :key :clear-cache! :content (load-doc |apis/clear-cache_.md) :children $ [] + DocNode :title |realize-ssr! :key :realize-ssr! :content (load-doc |apis/realize-ssr_.md) :children $ [] + DocNode :title |list-> :key :list-> :content (load-doc |apis/list-_.md) :children $ [] + DocNode :title |>> :key :pick-states :content (load-doc |apis/pick-states.md) :children $ [] + DocNode :title |comp-space :key :comp-space :content (load-doc |apis/comp-space.md) :children $ [] + DocNode :title |comp-inspect :key :comp-inspect :content (load-doc |apis/comp-inspect.md) :children $ [] + DocNode :title |make-string :key :make-string :content (load-doc |apis/make-string.md) :children $ [] + DocNode :title |render-app :key :render-app :content (load-doc |apis/render-app.md) :children $ [] + DocNode :title |purify-element :key :purify-element :content (load-doc |apis/purify-element.md) :children $ [] + DocNode :title |mute-element :key :mute-element :content (load-doc |apis/mute-element.md) :children $ [] + DocNode :title |find-element-diffs :key :find-element-diffs :content (load-doc |apis/find-element-diffs.md) :children $ [] + DocNode :title |apply-dom-changes :key :apply-dom-changes :content (load-doc |apis/apply-dom-changes.md) :children $ [] + DocNode :title |activate-instance! :key :activate-instance :content (load-doc |apis/activate-instance.md) :children $ [] + DocNode :title |patch-instance! :key :patch-instance :content (load-doc |apis/patch-instance.md) :children $ [] + DocNode :title |Community :key :community :content (load-doc |community.md) :children $ [] :examples $ [] :schema $ :: 'List 'docs-workflow.schema/DocNode 'load-doc $ %{} 'CodeEntry (:doc |) @@ -223,23 +190,17 @@ :code $ quote $ def store Store :states $ {} $ :cursor ([]) :examples $ [] - :schema $ :: 'app.schema/Store + :schema $ :: 'docs-workflow.schema/Store :ns $ %{} 'NsEntry (:doc |) :code $ quote $ ns app.schema + :require $ docs-workflow.schema :refer $ DocNode Store 'app.updater $ %{} 'FileEntry :defs $ {} $ 'updater %{} 'CodeEntry (:doc |) - :code $ quote $ defn updater (store op op-id op-time) - match op - (:states cursor s) - assoc store :states $ assert-type - update-state-tree (:states store) cursor s - , 'Map - (:hydrate-storage data) data - _ $ do (eprintln "|unknown op:" op) store + :code $ quote $ defn updater (store op op-id op-time) (docs-updater/updater store op op-id op-time) :examples $ [] - :schema $ :: 'Fn $ {} (:return 'app.schema/Store) - :args $ [] 'app.schema/Store 'app.schema/Op 'String 'Number + :schema $ :: 'Fn $ {} (:return 'docs-workflow.schema/Store) + :args $ [] 'docs-workflow.schema/Store 'docs-workflow.schema/Op 'String 'Number :ns $ %{} 'NsEntry (:doc |) :code $ quote $ ns app.updater - :require $ respo.cursor :refer $ [] update-state-tree + :require $ docs-workflow.updater :as docs-updater diff --git a/deps.cirru b/deps.cirru index 24327bc..badd552 100644 --- a/deps.cirru +++ b/deps.cirru @@ -1,10 +1,10 @@ -{} (:calcit-version |0.20.0) +{} (:calcit-version |0.30.1) :version |0.0.4 - :dependencies $ {} (|Respo/reel.calcit |0.6.32) - |Respo/respo-markdown.calcit |0.4.44 - |Respo/respo-router.calcit |0.8.27 - |Respo/respo-ui.calcit |0.7.31 - |Respo/respo.calcit |0.16.113 - |calcit-lang/docs-workflow |0.0.32 - |calcit-lang/js-ffi |0.1.36 + :dependencies $ {} (|Respo/reel.calcit |0.6.41) + |Respo/respo-markdown.calcit |0.4.59 + |Respo/respo-router.calcit |0.8.37 + |Respo/respo-ui.calcit |0.8.0 + |Respo/respo.calcit |0.16.124 + |calcit-lang/docs-workflow |0.0.37 + |calcit-lang/js-ffi |0.2.5 diff --git a/docs/beginner-guide.md b/docs/beginner-guide.md index cc83d52..333b0a8 100644 --- a/docs/beginner-guide.md +++ b/docs/beginner-guide.md @@ -1,3 +1,7 @@ +> Historical tutorial: the old macro expansions, JavaScript access and dispatch +> examples below predate current typed APIs. Start with **Guide** in the sidebar +> for formal 0.30.1 contracts. This is not a standalone checked current app. + Want to explore by yourself? - Minimal App diff --git a/docs/guide.md b/docs/guide.md index 7084a9c..c5703a9 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -1,3 +1,75 @@ -# Guide +# Guide: Calcit 0.30.1 -See posts. +This site pairs formal Calcit CLI / `@calcit/procs` **0.30.1**, Respo +**0.16.124**, Reel **0.6.41** and Docs Workflow **0.0.37**. Use `calcit.cirru` +for source and `deps.cirru` for published module versions; do not restore +`compact.cirru` or `package.cirru`, or mix this runtime with an alpha CLI. + +For a new application, start with the maintained +[Respo template](https://github.com/Respo/respo-calcit-workflow). Check its own +versions before copying code: upgrading this site does not upgrade other apps. + +## State and effects + +Use `defref` / `ref` for retained mutable references, and `add-watch!` / +`remove-watch!` for effectful subscriptions. The historical `defatom`, `atom` and +unmarked watch names are not recommended spellings. Do not hide a missing type +relationship with `unsafe-coerce` merely to pass a check. + +A native counter illustrates an explicit effectful function contract: + +```cirru +ns example.counter + +defref *count 0 + +defn increment! () + hint-fn $ {} + :args $ [] + :return 'Unit + reset! *count $ inc @*count + , &unit +``` + +For browsers, keep DOM ownership in Respo's `respo.dom` contracts. Read host +strings and numbers through published JS-FFI adapters; an unchecked cast does +not prove a JavaScript value has a Calcit schema. Keep JavaScript `bottom-tip` +`hud!` calls in development reload handlers so errors remain visible on-page. + +## Component operations are not application operations + +`respo.core/>>` selects a state branch and carries its cursor. Widget handlers +receive Respo's widget dispatcher; an application `render!` dispatcher receives +one operation. Do not copy the two-argument widget dispatcher's type into the +application entry point. + +Define an application Op enum and validate incoming state cursors/payloads +before constructing it. With typed Reel, retain `State` in a Ref, +handle `typed/decode-control` separately, and use `typed/record-op` for domain +operations. `Date.now` is a host call, not a numeric constant; JS-FFI's +`date-now-snapshot` exposes a checked `:timestamp` value. + +This app uses Docs Workflow's published **DocNode, Store and Op**, plus its +updater. A second nominally distinct Store with identical fields is not +interchangeable with that module's Store. + +## Absence and genuine boundaries + +Calcit's `get` returns an Option. Match `:some` / `:none`, or use `.unwrap-or` +with a meaningful default; use `.unwrap` only for a real presence invariant. +Do not insert arbitrary empty collections merely to silence checks. State +trees and browser event Maps remain heterogeneous boundaries: validate the +fields consumed rather than asserting every event is an unrelated Struct. + +## Verification and older chapters + +Application source is checked with all-definitions analysis, public namespace +checks, full strict diagnostics, and zero deprecated/dynamic-method findings in +CI. Both SPA and mdBook are built. These checks do **not** execute every Markdown +fragment or certify browser/WebSocket application behavior. + +The Beginner Guide and several API chapters are historical design notes. Their +old macro expansions, direct JavaScript access and operation syntax are not +copy-ready 0.30.1 code. Consult the paired published module's `calcit query def` +and `query schema` views and the maintained template. Historical examples need +section-by-section migration, not mechanical renaming without contract checks. diff --git a/docs/home.md b/docs/home.md index f77148e..84dbdc0 100644 --- a/docs/home.md +++ b/docs/home.md @@ -4,12 +4,16 @@ Inspired by React and Reagent. +This site targets formal Calcit/procs **0.30.1**. Choose **Guide** in the sidebar +for current migration notes. Beginner Guide and older API chapters retain +historical material; not every snippet is ported or independently type-checked. + - [Home](http://respo-mvc.org) - [Minimal App](https://github.com/Respo/minimal-respo) - [Demo](http://repo.respo-mvc.org/respo.calcit/) -- [API](./api.md) - [Old Examples](https://github.com/Respo/respo-examples) -Talk to [community](community.md). +Choose API or Community in the sidebar. Relative `.md` links are not SPA +navigation in current Docs Workflow; the separate mdBook is at `mdbook.html`. ![](https://cos-sh.tiye.me/cos-up/bb4c2755050318e864b56f59145d726e-SubstractRespo.png) diff --git a/package.json b/package.json index 37bb417..9aaee65 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,7 @@ { "packageManager": "yarn@4.18.0", "dependencies": { - "@calcit/docs-workflow": "^0.0.7", - "@calcit/procs": "0.20.0" - }, - "resolutions": { - "@cirru/parser.ts": "0.0.9" + "@calcit/procs": "0.30.1" }, "devDependencies": { "bottom-tip": "^0.1.5", @@ -15,5 +11,13 @@ "remarkable": "^2.0.1", "vite": "^8.2.2" }, - "version": "0.0.4" + "version": "0.0.4", + "engines": { + "node": ">=24" + }, + "scripts": { + "compile": "calcit calcit.cirru js", + "build": "yarn compile && vite build --base=${VITE_BASE_URL:-./}", + "dev": "yarn compile && vite" + } } diff --git a/vite.config.mjs b/vite.config.mjs new file mode 100644 index 0000000..b49e9e9 --- /dev/null +++ b/vite.config.mjs @@ -0,0 +1,5 @@ +import {defineConfig} from 'vite'; + +// Caps links exact published sources outside the app; resolve their CSS npm +// imports through this consumer, without modifying the shared module cache. +export default defineConfig({resolve: {preserveSymlinks: true}}); diff --git a/yarn.lock b/yarn.lock index 4bfae0b..020f392 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,41 +5,22 @@ __metadata: version: 10 cacheKey: 10c0 -"@calcit/docs-workflow@npm:^0.0.7": - version: 0.0.7 - resolution: "@calcit/docs-workflow@npm:0.0.7" - dependencies: - "@calcit/procs": "npm:^0.5.41" - checksum: 10c0/28cc4420c4abd6e0d2486fbd5e36bb5adc655d475a807635c573c70a321227d89d41d0f53b5fa23226ca5c5e90bea2fde5808d8ed29f210b6ff3ec0ad229616c +"@calcit/finger-vec@npm:0.1.1": + version: 0.1.1 + resolution: "@calcit/finger-vec@npm:0.1.1" + checksum: 10c0/c75e7f58924a7bb226ca4a47f6b0702021796b096c04d7fb7e9a92cb49b11ca64d654ea10d78bde29a8ac2d2d05ef9e7865efd2b358af2ca989d950b04d529a8 languageName: node linkType: hard -"@calcit/procs@npm:0.20.0": - version: 0.20.0 - resolution: "@calcit/procs@npm:0.20.0" +"@calcit/procs@npm:0.30.1": + version: 0.30.1 + resolution: "@calcit/procs@npm:0.30.1" dependencies: + "@calcit/finger-vec": "npm:0.1.1" "@calcit/ternary-tree": "npm:0.0.26" - "@cirru/parser.ts": "npm:^0.0.9" + "@cirru/parser.ts": "npm:0.0.10" "@cirru/writer.ts": "npm:^0.1.9" - checksum: 10c0/468d59cf4f0468e982b78dded471b93b46d29b05ead23bb4f7fbb560acacc15ce8e3e4e20abb91ebf533cbe90d07c18b2d725b2904bf6c9b9e99a1c81df97723 - languageName: node - linkType: hard - -"@calcit/procs@npm:^0.5.41": - version: 0.5.48 - resolution: "@calcit/procs@npm:0.5.48" - dependencies: - "@calcit/ternary-tree": "npm:0.0.19" - "@cirru/parser.ts": "npm:^0.0.5" - "@cirru/writer.ts": "npm:^0.1.3" - checksum: 10c0/3ded1c2253cc169d69bc85323db17080e129d666c782fb5f16d9af40ee04a09f5f20b7e916c24d19b71f9c13c92d521b008671d412c686afb4542f227a841ee2 - languageName: node - linkType: hard - -"@calcit/ternary-tree@npm:0.0.19": - version: 0.0.19 - resolution: "@calcit/ternary-tree@npm:0.0.19" - checksum: 10c0/32ed0f649e9038e0a0c0725e7e208112d057f460803369001c0f9ecb9807223c97de5cf2252c18b5664c1bffd11f791e1ef3b9547135ac0eae4153eb620c293a + checksum: 10c0/a0f00e3c0c9b3a5a2aea8b97e09f2692aa25039a48a2f7ccb345801fdbc546cbf3bb34ee268a58526baba9fb697781bb7929a5d1f6622816c9422c6c3ba8537b languageName: node linkType: hard @@ -50,17 +31,10 @@ __metadata: languageName: node linkType: hard -"@cirru/parser.ts@npm:0.0.9": - version: 0.0.9 - resolution: "@cirru/parser.ts@npm:0.0.9" - checksum: 10c0/3b13623b8f627ac81adae0cb6a4e3664f0da09115a997ca9b78b8d5d0b0f9b9b18c1ad847e068831cb1052c7da2a00329d2af04421b1024a004eef0ddca5fd7a - languageName: node - linkType: hard - -"@cirru/writer.ts@npm:^0.1.3": - version: 0.1.4 - resolution: "@cirru/writer.ts@npm:0.1.4" - checksum: 10c0/8a4c0a593ddc8eda10030cacba673447c9273008df3376fca1b588b858d4cc6916920404895adb9c5e3e11528fc2b6667bdf6dbb3380aca35b500231c4e47edb +"@cirru/parser.ts@npm:0.0.10": + version: 0.0.10 + resolution: "@cirru/parser.ts@npm:0.0.10" + checksum: 10c0/d66a16bcf49c60865fb8e733a5c219289a7c755c6400dea7e7a8d3166ee7841a623030f35f8ee96e232bc40f974f1b79a0ccdf089947fc5779699485102b5995 languageName: node linkType: hard @@ -714,8 +688,7 @@ __metadata: version: 0.0.0-use.local resolution: "root-workspace-0b6124@workspace:." dependencies: - "@calcit/docs-workflow": "npm:^0.0.7" - "@calcit/procs": "npm:0.20.0" + "@calcit/procs": "npm:0.30.1" bottom-tip: "npm:^0.1.5" cirru-color: "npm:^0.2.3" github-markdown-css: "npm:^5.3.0"