-
-
Notifications
You must be signed in to change notification settings - Fork 210
/
system.clj
760 lines (658 loc) · 27.2 KB
/
system.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
(ns figwheel-sidecar.system
(:require
[figwheel-sidecar.utils :as utils]
[figwheel-sidecar.build-utils :as butils]
[figwheel-sidecar.config :as config]
[figwheel-sidecar.repl :as frepl]
[figwheel-sidecar.components.css-watcher :as css-watch]
[figwheel-sidecar.components.cljs-autobuild :as autobuild]
[figwheel-sidecar.components.figwheel-server :as server]
[strictly-specking-standalone.ansi-util :refer [with-color-when color-text]]
[com.stuartsierra.component :as component]
[suspendable.core :refer [Suspendable]]
[clojure.pprint :as p]
[clojure.java.io :as io]
[clojure.set :refer [difference union intersection]]
[clojure.string :as string]))
;; exporting functionality inorder to make figwheel-sidecar.system
;; the main require for scripting figwheel
(def fetch-config config/fetch-config)
(defn css-watcher [opts]
(component/using
(css-watch/css-watcher opts)
{:figwheel-server :figwheel-system}))
(declare build-config->key)
(defn add-builds [system build-configs]
(reduce
(fn [sys build-config]
(assoc sys
(build-config->key build-config)
(component/using
(autobuild/cljs-autobuild {:build-config build-config})
[:figwheel-server])))
system
build-configs))
(defn get-builds-to-start [figwheel-server build-ids]
(config/narrow-builds* (:builds figwheel-server) build-ids))
(defn add-initial-builds [{:keys [figwheel-server] :as system} build-ids]
(let [builds-to-start (get-builds-to-start figwheel-server build-ids)]
(add-builds system builds-to-start)))
(defn add-css-watcher [system css-dirs]
(if (not-empty css-dirs)
(assoc system :css-watcher (css-watcher {:watch-paths css-dirs}))
system))
(defn add-nrepl-server [system {:keys [nrepl-port] :as options}]
(when nrepl-port
(try
(require 'figwheel-sidecar.components.nrepl-server)
(catch Throwable e
(throw
(ex-info
"You must supply an nREPL dependency in order to start an nREPL server" {})))))
(if nrepl-port
(if-let [comp
(resolve 'figwheel-sidecar.components.nrepl-server/nrepl-server-component)]
(assoc system :nrepl-server (comp options))
system)
system))
;; Initially I really wanted a bunch of top level components that
;; relied on a figwheel server. I wanted this to be simple and
;; intuitive. Like so
(comment
;; Example: THIS DOES NOT WORK!!!
(component/system-map
:figwheel-server (figwheel-server (config/fetch-config))
:example-autobuild (component/using
(cljs-autobuild {:build-id "example" })
[:figwheel-server])
:css-watcher (component/using
(css-watcher {:watch-paths ["resources/public/css"]})
[:figwheel-server])))
;; Unfortunately the requirement that the overal system be controlled
;; from the CLJS repl make this difficult and forced invasive
;; requirements on the overall system. For this reason I have introduced and
;; overall component called FigwheelSystem that is a containing
;; component for a system that contains a figwheel-server and an ever
;; changing set of autobuilds that can be controlled from the repl.
;;
;; The FigwheelSystem will start autobuilding the builds according to
;; the supplied :build-ids, just as figwheel does now.
;;
;; This sets us up for a future that looks like this:
(comment
(component/system-map
:figwheel-system (figwheel-system (config/fetch-config))
:css-watcher (component/using
(css-watcher {:build-id "example" })
{:figwheel-server :figwheel-system})
:cljs-socket-repl (component/using
(cljs-socket-repl {:build-id "example"})
[:figwheel-system])))
;; Being able to supply a mutable figwheel system that can be
;; controlled by a CLJS socket repl is very desirable.
;;
;; That being said if one doesn't want the CLJS repl to be able to
;; control which builds are running etc then one can revert the method
;; described first.
;;
;; Here is our FigwheelSystem it's just a wrapper component that
;; provides the same behavior/protocol as the
;; contained :figwheel-server
;;
;; This allows components in the greater system to send messages to
;; the connected clients.
(defrecord FigwheelSystem [system]
component/Lifecycle
(start [this]
(if-not (:system-running this)
(do
(swap! system component/start)
(assoc this :system-running true))
this))
(stop [this]
(if (:system-running this)
(do
(swap! system component/stop)
(assoc this :system-running false))
this))
server/ChannelServer
(-send-message [this channel-id msg-data callback]
(server/-send-message (:figwheel-server @system)
channel-id msg-data callback))
(-connection-data [this]
(server/-connection-data (:figwheel-server @system)))
(-actual [this] (:figwheel-server @system))
Suspendable
(suspend [this] (assoc this :suspended? true))
(resume [this old-this]
(if (:suspended? old-this)
(-> this
(assoc :system-running (:system-running old-this))
(assoc :system (:system old-this)))
(do (when old-this (component/stop old-this))
(component/start this)))))
(defn figwheel-system [config-data]
(let [{:keys [build-ids] :as options}
(if (config/figwheel-internal-config-data? config-data)
(:data config-data)
config-data)
system
(atom
(-> (component/system-map
:figwheel-server (server/figwheel-server options))
(add-initial-builds (map name build-ids))))]
(map->FigwheelSystem {:system system})))
(defn create-figwheel-system
"This creates a complete Figwheel only system. It conditionally adds
a CSS watcher if the configuration contains :css-dirs and
conditionally adds an nREPL server component if the Figwheel
configuration contains an :nrepl-port key.
This takes a figwheel configuration consisting
of :figwheel-options, :all-builds, and :build-ids.
If you only have a few components to add to this system then you can
assoc them onto the created system before you start like so.
(def my-system
(assoc (create-figwheel-system (config/fetch-config))
:html-reload
(component/using
(html-reloader {:watch-paths [\"resources/public\"]})
[:figwheel-system])
:web-server (my-webserver-component)))"
[config-data]
(let [{:keys [figwheel-options all-builds build-ids] :as options}
(if (config/figwheel-internal-config-data? config-data)
(:data config-data)
config-data)]
(-> (component/system-map
:figwheel-system (figwheel-system options))
(add-css-watcher (:css-dirs figwheel-options))
(add-nrepl-server (select-keys figwheel-options [:nrepl-port
:nrepl-host
:nrepl-middleware])))))
;; figwheel system
(def id->key #(str "autobuild-" (name %)))
(defn key->id [build-key]
(->> (string/split build-key #"-")
rest
(string/join "-")))
(def build-config->key (comp id->key :id))
(defn id->build-config [system id]
(get-in system [:figwheel-server :builds (name id)]))
(defn build-key? [k]
(.startsWith (name k) "autobuild-"))
(defn valid-key? [system key]
(if-let [key (get system (name key))]
true
(do
(println "Figwheel: invalid build id -" (key->id key))
false)))
(defn all-build-keys [system]
(set
(doall
(filter build-key? (keys system)))))
(defn ids-or-all-build-keys* [system ids]
(set
(doall
(if (not-empty ids)
(map id->key ids)
(all-build-keys system)))))
(defn ids-or-all-build-keys [system ids]
(set
(doall
(filter (partial valid-key? system)
(ids-or-all-build-keys* system ids)))))
(defn watchers-running [system]
(doall
(filter (fn [key] (get-in system [key :file-watcher]))
(all-build-keys system))))
;; figwheel system control function helpers
(defn build-diff
"Makes sure that the autobuilds in the system match the build-ids provided"
[system ids]
(let [ids (set (map id->key ids))
build-keys (all-build-keys system)]
{:builds-to-add (map key->id (difference ids build-keys))
:builds-to-remove (map key->id (difference build-keys ids))}))
(defn system-remove
"Remove the ids from the system"
[system ids]
(let [build-keys (map id->key ids)
system (component/stop-system system build-keys)]
(reduce dissoc system build-keys)))
(defn add-autobuilder [system build-id]
(if-let [build-config (id->build-config system build-id)]
(assoc system
(id->key build-id)
(component/using
(autobuild/cljs-autobuild {:build-config build-config})
[:figwheel-server]))
system))
(defn patch-system-builds [system ids]
(let [{:keys [builds-to-remove builds-to-add]} (build-diff system ids)
system (system-remove system builds-to-remove)]
(reduce add-autobuilder system builds-to-add)))
(defn stop-and-start-watchers [system build-ids thunk]
(let [build-keys (ids-or-all-build-keys system build-ids)
all-present-build-keys (all-build-keys system)
build-keys-keep (difference all-present-build-keys build-keys)
running-build-keys (watchers-running system)]
(-> system
(patch-system-builds (mapv key->id build-keys-keep))
thunk
(patch-system-builds (mapv key->id build-keys))
(component/start-system running-build-keys))))
(defn use-color? [system]
(config/use-color? (:figwheel-server system)))
;; start System Control Functions
;; These commands are intended to be run from a Clojure REPL or to be
;; integrated as special functions in the CLJS REPL
;; These commands alter the figwheel system and manage the running autobuilds
(defn stop-autobuild
"Stops autobuilding the specific ids or all currently running autobuilds"
[system ids]
(println "Figwheel: Stoping autobuild")
(component/stop-system system (ids-or-all-build-keys system ids)))
(defn switch-to-build
"Switches autobuilding from the current autobuilds to the given build ids"
[system ids]
(let [system (if (not-empty ids)
(patch-system-builds system ids)
system)]
(component/start-system system (ids-or-all-build-keys system ids))))
(defn start-autobuild
"Either starts all the current autobuilds or adds the supplied build
and starts autobuilding it."
[system ids]
(println "Figwheel: Starting autobuild")
(let [current-ids (set (mapv key->id (all-build-keys system)))
total-ids (union current-ids (set ids))]
(switch-to-build system total-ids)))
(defn clear-compiler-env-for-build-id [system build-id]
(update-in system [:figwheel-server :builds build-id] butils/add-compiler-env))
(defn- clean-build
"Deletes compiled assets for given id."
[system id]
(if-let [build-options
(get-in system [:figwheel-server :builds (name id) :build-options])]
(do
(println "Figwheel: Cleaning build -" id)
(utils/clean-cljs-build* build-options)
(clear-compiler-env-for-build-id system id))
system))
;; this is going to require a stop and start of the ids
;; and clearing the compiler-env for these builds
(defn running-versus-not-running [system ids]
(let [running-set (set (map key->id (watchers-running system)))
id-set (set (map name ids))]
{:not-running-ids (difference id-set running-set)
:running-ids (intersection id-set running-set)}))
;; this is actually really complicated based on what is running etc.
(defn clean-builds
"Deletes the compiled assets for the given ids or cleans all the
current autobuilds. This command stops and starts the autobuilds."
[system ids]
(let [{:keys [not-running-ids running-ids]}
(running-versus-not-running system ids)
system (reduce clean-build system not-running-ids)
process-ids (if (empty? ids)
(map key->id
(ids-or-all-build-keys system running-ids))
running-ids)]
(if-let [ids (not-empty process-ids)]
(stop-and-start-watchers
system ids
#(reduce clean-build % ids))
system)))
;; doesn't change the system
(defn- build-once* [system id]
(if-let [build-config
(id->build-config system (name id))]
(do
(println "Figwheel: Building once -" (name id))
;; we are allwing build to be overridden at the system level
((or
(:cljs-build-fn system)
(get-in system [:figwheel-server :cljs-build-fn])
autobuild/figwheel-build)
(assoc system :build-config build-config))
system)
(do
(println (str "Build config for " id " not found.")))))
;; doesn't alter the system
(defn build-once
"Builds the given ids or the current builds once"
[system ids]
(doseq [build-ids (mapv key->id
(ids-or-all-build-keys* system ids))]
(build-once* system build-ids))
system)
(defn reset-autobuild
"Alias for clean-builds"
[system]
(clean-builds system nil))
(defn fetch-config-print-errors []
(try
(fetch-config)
(catch Throwable e
(if (-> e ex-data :reason (= :figwheel-configuration-validation-error))
(do
(println (.getMessage e))
{})
(throw e)))))
(defn get-project-builds []
(into (array-map)
(map
(fn [x]
[(:id x)
(butils/add-compiler-env x)])
(-> (fetch-config-print-errors) :data :all-builds))))
(defn reload-config
"Resets the system and reloads the the confgiguration as best it can."
[system]
(with-color-when (use-color? system)
(let [ids (mapv key->id (all-build-keys system))]
(stop-and-start-watchers
system ids
(fn [system]
(println "Figwheel: Reloading build config information")
(if-let [new-builds (not-empty (get-project-builds))]
(assoc-in (doall (reduce clean-build system ids))
[:figwheel-server :builds]
new-builds)
(do
(println "No reload config found in project.clj")
system)))))))
(defn print-config
"Prints out the build config for the given ids or all the build configs"
[system ids]
(let [ids (or (not-empty ids)
(keys (get-in system [:figwheel-server :builds])))]
(doseq [build-confg (map (partial id->build-config system) ids)]
(p/pprint (dissoc build-confg :compiler-env))))
system)
;; doesn't alter the system
(defn fig-status
"Prints out the status of the running figwheel system"
[system]
(let [connection-count (server/connection-data (:figwheel-server system))
watched-builds (mapv key->id (watchers-running system))]
(println "Figwheel System Status")
(println "----------------------------------------------------")
(when (not-empty watched-builds)
(println "Watching builds:" watched-builds))
(println "Client Connections")
(when connection-count
(doseq [[id v] connection-count]
(println "\t" (str (if (nil? id) "any-build" id) ":")
v (str "connection" (if (= 1 v) "" "s")))))
(println "----------------------------------------------------"))
system)
;; end System Control Functions
;; repl interaction
(defn namify [arg]
(if (seq? arg)
(when (= 'quote (first arg))
(str (second arg)))
(name arg)))
(defn make-special-fn [f]
(fn self
([a b c] (self a b c nil))
([_ _ [_ & args] _]
;; are we only accepting string ids?
(f (keep namify args)))))
;; going to work with an atom and swap!
;; The commands are side effecting but they are also idempotent
;; the mode of working is going to be one command after another in
;; an interactive repl
(defn system-setter [func system-atom]
(fn [& args]
(reset! system-atom (apply func @system-atom args))))
(defn build-figwheel-special-fns [system]
{'start-autobuild (make-special-fn (system-setter start-autobuild system))
'stop-autobuild (make-special-fn (system-setter stop-autobuild system))
'switch-to-build (make-special-fn (system-setter switch-to-build system))
'clean-builds (make-special-fn (system-setter clean-builds system))
'build-once (make-special-fn (system-setter build-once system))
'reset-autobuild (make-special-fn (system-setter
(fn [sys _] (reset-autobuild sys))
system))
'reload-config (make-special-fn (system-setter
(fn [sys _] (reload-config sys))
system))
'print-config (make-special-fn (system-setter print-config system))
'fig-status (make-special-fn (system-setter
(fn [sys _] (fig-status sys))
system))})
(def repl-function-docs
"Figwheel Controls:
(stop-autobuild) ;; stops Figwheel autobuilder
(start-autobuild id ...) ;; starts autobuilder focused on optional ids
(switch-to-build id ...) ;; switches autobuilder to different build
(reset-autobuild) ;; stops, cleans, and starts autobuilder
(reload-config) ;; reloads build config and resets autobuild
(build-once id ...) ;; builds source one time
(clean-builds id ..) ;; deletes compiled cljs target files
(print-config id ...) ;; prints out build configurations
(fig-status) ;; displays current state of system
(figwheel.client/set-autoload false) ;; will turn autoloading off
(figwheel.client/set-repl-pprint false) ;; will turn pretty printing off
Switch REPL build focus:
:cljs/quit ;; allows you to switch REPL to another build
Docs: (doc function-name-here)
Exit: :cljs/quit
Results: Stored in vars *1, *2, *3, *e holds last exception object")
(defn figwheel-repl-options
[repl-options system]
(update-in repl-options [:special-fns]
merge
(build-figwheel-special-fns system)))
(defn start-figwheel-repl [system build repl-options]
(let [{:keys [figwheel-server build-ids]} @system]
;; TODO should I add this this be conditional on not running?
;; (start-autobuild system build-ids)
;; (newline)
(print "Launching ClojureScript REPL")
(when-let [id (:id build)] (println " for build:" id))
(println repl-function-docs)
(println "Prompt will show when Figwheel connects to your application")
(frepl/repl
build
figwheel-server
(figwheel-repl-options repl-options system))))
;; choosing which build for the repl to focus on is a bit tricky
;; and we are not considering which builds are connected
;; I think that would just add confusion
(defn choose-repl-build-id [system]
(let [focused-build-ids (map key->id (all-build-keys system))]
(if (not-empty focused-build-ids)
(first focused-build-ids)
(let [{:keys [build-ids all-builds]} system]
(:id (first (config/narrow-builds* all-builds build-ids)))))))
(defn get-build-choice [choices]
(let [choices (set (map name choices))]
(when (> (count choices) 1)
(loop []
(print (str "Choose focus build for CLJS REPL (" (clojure.string/join ", " choices) ") or quit > "))
(flush)
(let [res (read-line)]
(cond
(nil? res) false
(choices res) res
(= res "quit") false
(= res "exit") false
:else
(do
(println (str "Error: " res " is not a valid choice"))
(recur))))))))
(defn choose-repl-build [system build-id]
(let [builds (get-in system [:figwheel-server :builds])]
(or (and build-id
(when-let [build (get builds build-id)]
(and (config/optimizations-none? build)
build)))
(get builds (choose-repl-build-id system)))))
(defn initial-repl-focus-build-id [system]
(when-let [build-key (first (all-build-keys system))]
(key->id build-key)))
(defn repl-env*
([system] (repl-env* system nil))
([system start-build-id] (repl-env* system nil {}))
([system start-build-id repl-options]
(let [build-id (or
start-build-id
(initial-repl-focus-build-id @system))
{:keys [figwheel-server]} @system]
;; from figwheel-cljs-repl*
(when-let [build (choose-repl-build @system build-id)]
;; always used in nrepl
;; from start-figwheel-repl
(frepl/cljs-repl-env
build
figwheel-server
(figwheel-repl-options repl-options system))))))
(defn figwheel-cljs-repl* [system build-id repl-options]
(when-let [build (choose-repl-build @system build-id)]
(start-figwheel-repl system build repl-options)))
(defn build-switching-cljs-repl* [system start-build-id repl-options]
(if (frepl/in-nrepl-env?)
(figwheel-cljs-repl* system start-build-id repl-options) ;; no build switching
(loop [build-id start-build-id]
(figwheel-cljs-repl* system build-id repl-options)
(let [builds (get-in @system [:figwheel-server :builds])]
(when-let [chosen-build-id
(get-build-choice
(keep :id (filter config/optimizations-none? (vals builds))))]
(recur chosen-build-id))))))
(defn cljs-repl*
([system] (cljs-repl* system nil))
([system start-build-id] (cljs-repl* system nil {}))
([system start-build-id repl-options]
(let [build-id (or
start-build-id
(initial-repl-focus-build-id @system))]
(if (frepl/in-nrepl-env?)
(figwheel-cljs-repl* system build-id repl-options)
(build-switching-cljs-repl* system build-id repl-options)))))
;; takes a FigwheelSystem
(defn figwheel-cljs-repl
([figwheel-system]
(figwheel-cljs-repl figwheel-system nil))
([figwheel-system build-id]
(figwheel-cljs-repl figwheel-system build-id {}))
([{:keys [system]} build-id repl-options]
(figwheel-cljs-repl* system build-id repl-options)))
;; takes a FigwheelSystem this will not work for nrepl
(defn build-switching-cljs-repl
([figwheel-system] (build-switching-cljs-repl figwheel-system nil))
([figwheel-system start-build-id]
(build-switching-cljs-repl figwheel-system start-build-id {}))
([{:keys [system]} start-build-id repl-options]
(build-switching-cljs-repl* system start-build-id repl-options)))
(defn start-repl
([start-fn figwheel-system]
(start-repl start-fn figwheel-system nil {}))
([start-fn figwheel-system start-build-id]
(start-repl start-fn figwheel-system start-build-id {}))
([start-fn {:keys [system]} start-build-id repl-options]
(start-fn system
(or
start-build-id
(initial-repl-focus-build-id @system))
repl-options)))
(defn cljs-repl
[& args]
(apply start-repl cljs-repl* args))
(defn repl-env
[& args]
(apply start-repl repl-env* args))
;; figwheel starting and stopping helpers
(defn unwrap-component-exception [e]
(if (-> e ex-data :reason (= :com.stuartsierra.component/component-function-threw-exception))
(unwrap-component-exception (.getCause e))
e))
(defn dispatch-system-component-errors [component-control-fn]
(try
(component-control-fn)
(catch Throwable e
(let [orig-exception (unwrap-component-exception e)
[escape reason] ((juxt :escape-system-exceptions :reason)
(ex-data orig-exception))]
(if escape
(do (println (.getMessage orig-exception))
(when-not (#{:initial-cljs-build-exception :unable-to-bind-port} reason)
(throw (.getCause orig-exception))))
(throw e))))))
;; This should eventually take a figwheel config data
(defn start-figwheel-system [{:keys [figwheel-options all-builds build-ids] :as options}]
(let [system (create-figwheel-system options)]
(dispatch-system-component-errors #(component/start system))))
(defn parse-start-figwheel-args [args]
(cond (empty? args)
[(config/fetch-config) nil]
(map? (first args))
[(first args) (not-empty (rest args))]
((some-fn string? symbol? keyword?) (first args))
[(config/fetch-config) args]
:else
(throw
(ex-info (str "Bad arguments passed to start-figwheel!\n"
" First argument should be a map? or named?\n"
" start-figwheel! is normally called with a configuration\n"
" plus a the build-ids to start."
" Or optionally just the build ids to start." )
{:reason :bad-arguments-passed-to-start-figwheel
:args args}))))
(defn start-figwheel!* [config-options build-ids]
(let [internal-config-data
(-> config-options
config/->config-source
config/config-source->prepped-figwheel-internal
config/adjust-to-internal-configuration-representation
:data)
internal-config-data (if (not-empty build-ids)
(do
(config/report-if-bad-build-ids
(map :id (:all-builds internal-config-data))
build-ids)
(assoc internal-config-data :build-ids build-ids))
internal-config-data)]
(start-figwheel-system internal-config-data)))
(defn start-figwheel!
"This function will start the figwheel system.
(start-figwheel!)
If called with no arguments it will load and validate the
configuration found in your project.clj or a figwheel.edn file in
the root of your project. If there is a figwheel.edn file any
configuration information found in the project.clj will be ignored.
(start-figwheel! \"example\" \"example-admin\" ...)
You can also supply the build ids that you want figwheel to start
autobuilding. If these ids aren't available in the builds specified
in the found configuration this function will throw an error.
(start-figwheel!
;; using the configuration shape of figwheel.edn
{:server-port 5000
:builds [{:id ...}]}
(start-figwheel!
;; using the configuration shape of figwheel.edn
{:server-port 5000
:builds (figwheel-sidecar.config/get-project-builds)
:builds-to-start [\"example\"]})
(start-figwheel!
;; using the soon to be deprecated legacy configuration shape
{:figwheel-options { :server-port 4000 }
:all-builds [{:id ...}]
:build-ids [\"example\"]})
As seen above you can also directly supply a configuration Map that
has the shape of a figwheel.edn file or the legacy format which will
be deprecated in the near future.
(start-figwheel! (figwheel-sidecar.config/fetch-config) \"example\" \"example-admin\")
After supplying a configuration, you can also list the build-ids that
you would like to start."
[& args]
(apply start-figwheel!* (parse-start-figwheel-args args)))
(defn stop-figwheel! [system]
(component/stop system))
;; this is a blocking call
(defn start-figwheel-and-cljs-repl! [autobuild-options]
(when-let [system (start-figwheel! autobuild-options)]
(cljs-repl (:figwheel-system system))))