{"id":17117522,"url":"https://github.com/holyjak/fulcro-troubleshooting","last_synced_at":"2025-04-13T04:35:09.052Z","repository":{"id":53780416,"uuid":"341284221","full_name":"holyjak/fulcro-troubleshooting","owner":"holyjak","description":"A development-time library for Fulcro that helps to detect problems earlier and find and fix their root cause faster","archived":false,"fork":false,"pushed_at":"2024-01-26T12:24:05.000Z","size":215,"stargazers_count":16,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T21:22:57.207Z","etag":null,"topics":["clojure","fulcro","troubleshooting","webdev"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/holyjak.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-02-22T17:39:54.000Z","updated_at":"2024-12-05T14:48:15.000Z","dependencies_parsed_at":"2022-09-11T21:30:27.169Z","dependency_job_id":"95259231-5512-493a-9fc8-928a009c291c","html_url":"https://github.com/holyjak/fulcro-troubleshooting","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holyjak%2Ffulcro-troubleshooting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holyjak%2Ffulcro-troubleshooting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holyjak%2Ffulcro-troubleshooting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holyjak%2Ffulcro-troubleshooting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/holyjak","download_url":"https://codeload.github.com/holyjak/fulcro-troubleshooting/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248664125,"owners_count":21141902,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","fulcro","troubleshooting","webdev"],"created_at":"2024-10-14T17:51:57.391Z","updated_at":"2025-04-13T04:35:09.030Z","avatar_url":"https://github.com/holyjak.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fulcro-troubleshooting\n\nA development-time library for [Fulcro](https://fulcro.fulcrologic.com/) that helps to detect problems earlier and find and fix their root cause faster.\n\nFor additional help, see the [Fulcro Troubleshooting Decision Tree](https://blog.jakubholy.net/2020/troubleshooting-fulcro/).\n\nTable of content:\n\n* [Rationale](#rationale)\n* [What can it do?](#what-can-it-do)\n* [Status](#status)\n* [Usage](#usage)\n* ...\n\n## Rationale\n\nFulcro does an awesome job of checking your code and providing helpful messages but it is inherently limited by the fact that most of its checks are compile-time. `fulcro-troubleshooting` checks your application at run time and thus has much more insight into what is really going on. It also integrates with the UI so that you see the errors and warnings right in the UI, next to the place where you observe the problem.\n\n## What can it do?\n\n### Check: Proper query inclusion\n\nWarn you when a component's query is not included in its parent's:\n\n![demo missing join](doc/demo-missing-join.png)\n\nExperimental configuration (subject to change):\n\n```clojure\n(set! holyjak.fulcro-troubleshooting/*config*\n      ;; return truthy to check the inclusion of the component's query in an ancestor\n      {:query-inclusion-filter (fn [component-instance comp-class] \n                                 (not= comp-class :com.example.ui/MyComponent))})\n;; OR: (when goog.DEBUG (set! js/holyjak.fulcro_troubleshooting._STAR_config_STAR_ {..}))\n```\n### Check: Valid idents\n\nWarn when there is something fishy about the component's ident:\n\n![demo bad ident - map](doc/demo-bad-ident-map.jpg)\n![demo bad ident - nil](doc/demo-bad-ident-nil.jpg)\n\n### Check: Presence of child data\n\nWarn when there is no data for a child, perhaps because the data has failed to load, or is at the wrong place of the DB, or because you have not provided `:initial-state` for the component (which is optional but crucial e.g. for Link Query - only components):\n\n![demo missing join data](doc/demo-missing-join-data.jpg)\n\nExperimental configuration (subject to change):\n\n```clojure\n(set! holyjak.fulcro-troubleshooting/*config*\n      ;; return truthy for any join prop that should be checked for having non-nil data in the props:\n      {:join-prop-filter (fn [component-instance prop] (not= prop :jh/address))})\n;; OR: (when goog.DEBUG (set! js/holyjak.fulcro_troubleshooting._STAR_config_STAR_ {..}))\n```\n\nYou can also get rid of this warning by using `:initial-state` and setting it to something non-nil such as `[]` for a list or `{}` for a map. (Though remember that in the Template Form `{}` means \"include initial state from the child\" so, if there is a child element for that prop, set also its initial state. And remember to propagate the initial state up all the way to the root component.)\n\n### Check: Valid :initial-state\n\nIdeally, you would use the [template form](https://book.fulcrologic.com/#_template_mode) of `:initial-state` as it checks that you only include props that you query for.\n\nThis check controls that (a) you actually return either nil or a map and (b) that the map has no key\nyou do not query for (contrary to the template form check, this works also for the lambda form,\nthough it is less powerful).\n\nFor example, given the following component:\n\n```clojure\n(defsc Character [_ _]\n  {:query [:character/fname :character/surname :character/age]\n   :ident :character/id\n   :initial-state (fn [p] {:character/id (:id p)\n                           :character/fname \"Jon\"\n                           :ui/alive? true\n                           :character/surname \"Snow\"\n                           :character/sex :m\n                           :character/age 18})}\n  ...))\n```\n\nwe'd get a warning like this one:\n\n![demo lambda initial state extras](doc/demo-init-state-extras.png)\n\nExperimental configuration (subject to change):\n\n```clojure\n(set! holyjak.fulcro-troubleshooting/*config*\n      ;; return truthy for any initial state key that should be checked for having being in the query:\n      {:initial-state-filter (fn [component-instance prop] (not= prop :jh/address))})\n;; OR: (when goog.DEBUG (set! js/holyjak.fulcro_troubleshooting._STAR_config_STAR_ {..}))\n```\n\n### Check: No duplicates in a query\n\nWarn when the same property is used repeatedly in a query (ignoring the content of sub-queries). \nDuplicates don't make sense, since a property can only be included once in the props map anyway.\nIt can cause unexpected behavior, in the least all but one of the occurrences being ignored.\n\nExample:\n\n```clojure\n(defsc User [_ props]\n  {:query [{:user/location (comp/get-query Location)} :user/name #_... :user/location]\n   :ident (fn [] [:component/id :User])}\n   ...)\n```\n\n![demo duplicates in a query](doc/demo-duplicate-query-props.png)\n\n### User components get wrapped with [React Error Boundary](https://book.fulcrologic.com/#_react_errors)\n\nNon-Fulcro components are wrapped with an Error Boundary so that if their render throws an exception, it is caught and displayed in the UI, instead of taking the whole page down.\n\n## Status\n\nMature. Bugs are fixed, pull requests reviewed, and feature requests considered.\n\nGet in touch with `@holyjak` in the `#fulcro` channel of the Clojurians Slack if you have any questions, problems, ideas, or comments.\n\n## Usage\n\nYou need to do three things:\n\n(1) Add the library to your project:\n\n```clojure\n;; deps.edn\n:aliases\n{:dev {:extra-deps {holyjak/fulcro-troubleshooting\n                    {:git/url \"https://github.com/holyjak/fulcro-troubleshooting\"\n                     ;; BEWARE: run `clojure -X:deps git-resolve-tags` to insert \n                     ;; the correct :sha (warning: it will reformat the file :'( )\n                     :sha \"b3648778862b5f0cb792134f459092e59ec2d663\" :tag \"latest\"\n                     }}}\n```\n\nTIP: Use **Fulcro ≧ 3.7.1** (3.7.1 prevents some false positives).\n\n(2) Make sure that the `:dev` alias is activated and the library's namespace is automatically required:\n\n```clojure\n;; shadow-cljs.edn\n{:deps {:aliases [:dev]} ; \u003c-- this\n :builds {:main {:devtools {:preloads [holyjak.fulcro-troubleshooting ...] ...} ; \u003c-- and this\n                 ...}}}\n```\n\n\n(3) When you create your Fulcro/RAD app, add the middleware provided by the library:\n\n```clojure\n(ns my.app\n  (:require\n    ;; [holyjak.fulcro-troubleshooting] ; add if you haven't added it as :preload\n    [com.fulcrologic.fulcro.application :as app]))\n\n(defonce app (app/fulcro-app {:render-middleware \n                              (when goog.DEBUG js/holyjak.fulcro_troubleshooting.troubleshooting_render_middleware)}))\n;; we use js/.. instead of holyjak.fulcro-troubleshooting/troubleshooting-render-middleware so that\n;; the code will still compile for prod release, when the lib is not included\n```\n\n## Limitations\n\n### fulcro-rad-demo\n\nWe have some false-positives when applied to [fulcro-rad-demo](https://github.com/fulcrologic/fulcro-rad-demo/), as of 2024-01:\n\n* `/account-master-detail` - warns about nil join prop :ui/account until an account is selected from the list. (Not sure I can do anything about it, perhaps other than not checking :ui props?)\n \n## Feature ideas\n\n- check initial state (if present) to be a map with keys \u003c= query keys\n\n## License\n\nCopyleft 2021 Jakub Holý\n\nDistributed under the Unlicense, see http://unlicense.org/.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholyjak%2Ffulcro-troubleshooting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fholyjak%2Ffulcro-troubleshooting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholyjak%2Ffulcro-troubleshooting/lists"}