Fork me on GitHub
#beginners
<
2021-09-22
>
John Bradens03:09:52

I'm trying to deploy my app to heroku and I keep getting this error: The required namespace "react" is not available, it was required by "reagent/core.cljs".

John Bradens03:09:02

But I have "react": "17.0.2-0", "react-dom": "17.0.2-0", "react-highlight.js": "1.0.7", all in my package.json and I also put [cljsjs/react "17.0.2-0"] [cljsjs/react-dom "17.0.2-0"] in my project.clj. I also did npm install react. I'm not sure what I'm doing wrong?

Chase12:09:13

Are you using a bin/build file to add extra instructions? Mine looks like this:

#!/usr/bin/env bash                                                                                                 
npm install                                                                                                         
npx shadow-cljs release app                                                                                         
clojure -X:uberjar :jar ai.jar 
as I have a clojure backend too. Do you have both the clojure and node buildpacks installed?

Chase12:09:12

I'm also using deps.edn instead of lein so that clojure command would be different.

Chase12:09:37

I used some of the advice from here: https://folcon.github.io/post/2020-04-12-Fulcro-on-Heroku/ even though I'm not using fulcro and also got some help here on slack.

John Bradens15:09:24

Thanks @U9J50BY4C . Is a bin/build file, just a file with that name and no extension?

John Bradens15:09:42

I'm a total newbie and trying to google "bin/build" file but not getting much results about it 😕 Or is it a file called build in the bin folder?

John Bradens15:09:30

I'm also not sure if I have all the buildpacks installed. How do I check for that? Thanks again for the help @U9J50BY4C

Chase16:09:13

Yeah the file itself is just called build and you put it in a bin folder. Check out that link I gave you above for an example and it also explains how to add multiple buildpacks

Chase16:09:42

Here is my repo to see a little bit what is going on.

Chase16:09:00

I was new to all this about 2 weeks ago myself. Haha

John Bradens18:09:32

Thanks again. For some reason I'm getting the same error The required namespace "react" is not available, it was required by "reagent/core.cljs" after making adding the build file. I'll keep looking through the links and see what happened. I am using lein

John Bradens18:09:46

I don't think I'm using nodejs. Or because I'm using Reagent and react does that mean I am using nodejs? I get errors when I use that buildpack

Chase18:09:01

Do you want to share your repo? I think you will need node. Make sure you have the node buildpack first, then the clojure one.

Chase18:09:01

λ ~/projects/clojure/ai : heroku buildpacks
=== ai-marketing-copy Buildpack URLs
1. heroku/nodejs
2. heroku/clojure

Chase18:09:22

Did you also run chmod on that build file like that website I sent you suggested?

John Bradens18:09:42

I did run chmod u+x bin/build, and the buildpack commands that are in the blog post you sent from Alien Brain

John Bradens18:09:46

I copied the bin/build file exactly as in the blog post, but I'm not sure if I should have changed it at all for my own project... I also added the line to shadow-cljs.edn that it said. But, I don't have a deps.edn so I didn't make that change that was in the blog.

John Bradens18:09:15

Thanks again for helping, I really appreciate it @U9J50BY4C !

Chase20:09:00

Are you able to run shadow-cljs release app successfully on your own computer?

Chase20:09:40

And yeah since you are using lein, that bin/build file (which I did not see in your repo) should have something like lein uberjar instead of clojure -X:uberjar :jar ... like I have in mine.

Chase20:09:56

I too started with the big ole luminus framework and just couldn't wrap my head around it, including getting it deployed. Unfortunately the long conversations I had with others have already been archived and it's a struggle finding such things in the slack archive.

John Bradens20:09:41

Thanks @U9J50BY4C I get some warnings but the build does complete successfully. I think you're right about the lein uberjar. I replaced the other line with lein uberjar but it's still not working. 😕

John Bradens20:09:58

I also wish it was easier to find archived messages on here

John Bradens20:09:48

I might ask again in some of the other channels and crowdsource some more ideas

Chase22:09:57

Definitely. I know it's frustrating. I can't remember if I eventually got it working with leiningen/luminus before deciding to start from scratch and learn without a template.

Chase22:09:03

Is the nodejs buildpack listed first? I feel like it is calling your clojure code before compiling the clojurescript code so the cljs hasn't been compiled down to js yet and thus not finding react. These are just wild guesses from my part though, I'm pretty newbish myself.

Chase22:09:29

Another wild guess from me is maybe take out that :prep-task command in your :uberjar alias of your project.clj config. That bin/build file is doing the npm install and shadow-cljs release app so maybe trying to call it again when compiling your clojure into an uberjar is messing things up.

Chase22:09:23

The other option here if you can't get this working is building this all in a docker file and just uploading that docker build to heroku. That is what a couple others ended up doing when I was asking them. I don't know docker though so I found my way and ran with that.

John Bradens22:09:52

Turns out I had the clojure buildpack listed first. Now I just changed it to be nodejs listed first, and I get an error that I need to do npm install before continuing because the package.json and package-lock.json are not in sync. It says " npm ERR! Missing: [email protected] remote:    npm ERR! Missing: [email protected] " but I can see them in both files :thinking_face: Is it correct to have nodejs first, or clojure first? I seem to get different errors depending on which one I do.

John Bradens22:09:12

I'll look into Docker too. And I'll take out the :prep-task command right now and see if that helps.

Chase22:09:51

what is in your bin/build file?

John Bradens22:09:08

#!/usr/bin/env bash
npm install
npx shadow-cljs release main
lein uberjar

Chase22:09:37

looks right to me. Nodejs buildpack should be first. When you push to heroku does it say something like "detected bin/build file so using those instructions" or whatever?

John Bradens23:09:27

No it doesn't actually...

John Bradens23:09:43

I do

git push heroku main

Chase23:09:06

where do you have that file?

John Bradens23:09:11

And then I get

Enumerating objects: 173, done.
Counting objects: 100% (173/173), done.
Delta compression using up to 4 threads
Compressing objects: 100% (150/150), done.
Writing objects: 100% (173/173), 510.65 KiB | 7.40 MiB/s, done.
Total 173 (delta 17), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpacks:
remote:        1. heroku/nodejs
remote:        2. heroku/clojure
remote: -----> Node.js app detected
remote:        
remote: -----> Creating runtime environment
remote:        
remote:        NPM_CONFIG_LOGLEVEL=error
remote:        NODE_VERBOSE=false
remote:        NODE_ENV=production
remote:        NODE_MODULES_CACHE=true
remote:        
remote: -----> Installing binaries
remote:        engines.node (package.json):  unspecified
remote:        engines.npm (package.json):   unspecified (use default)
remote:        
remote:        Resolving node version 14.x...
remote:        Downloading and installing node 14.17.6...
remote:        Using default npm version: 6.14.15
remote:        
remote: -----> Installing dependencies
remote:        Installing node modules
remote:        npm ERR! cipm can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.
remote:        npm ERR! 
remote:        npm ERR! 
remote:        npm ERR! Missing: [email protected]
remote:        npm ERR! Missing: [email protected]
remote:        npm ERR! 
remote:        
remote:        npm ERR! A complete log of this run can be found in:
remote:        npm ERR!     /tmp/npmcache.CuKJM/_logs/2021-09-22T22_59_41_912Z-debug.log
remote: 
remote: -----> Build failed
remote:        
remote:        We're sorry this build is failing! You can troubleshoot common issues here
remote:        
remote:        
remote:        Some possible problems:
remote:        
remote:        - Node version not specified in package.json
remote:          
remote:        
remote:        Love,
remote:        Heroku

John Bradens23:09:57

In the root directory, I have a bin folder and then the build. I just realized, I might want it somewhere else right?

Chase23:09:49

No, that's where I have it. Try running chmod u+x bin/build again.

Chase23:09:11

Do you see a little asterisk or something after running that command?

John Bradens23:09:27

When I run that command, nothing happens

John Bradens23:09:38

Where would I see the asterisk?

Chase23:09:32

I see it like that in my text editor (nvim)

John Bradens23:09:20

Oh I see. I am just using my terminal window on a mac. I use Emacs but haven't figured out how to run terminal commands from there yet or set up the nice file trees...

Chase23:09:44

terminal window on mac should be fine to run that command.

Chase23:09:08

you might need sudo before that command but I'm reaching there

John Bradens23:09:37

Do you think I should be getting something instead of no output?

Chase23:09:03

no, I don't think you see anything

John Bradens23:09:23

Ok great. I did sudo too, and it asked for my password, but same effect. Thanks again.

Chase23:09:27

And just to confirm, you have done something like git add . and git commit -m "added bin/build file" before doing this push right?

John Bradens23:09:48

I don't think I did the "added bin/build file"

John Bradens23:09:06

Thanks for checking. Do I have to re-do git add now? I did the git add and git commit before adding the bin/build file

Chase23:09:14

oh yeah, definitely

John Bradens23:09:17

Sorry if this is too many basic questions

John Bradens23:09:23

Thanks so much. I'll try that right now.

Chase23:09:28

heroku is using the git file for all of this

Chase23:09:42

hence the git push heroku main

John Bradens23:09:26

Wow so the whole time I was making changes, heroku had no idea 😅

John Bradens23:09:51

It is running now. I saw it says running bin/build. Yay!

Chase23:09:07

Just to prepare you, even if this compiles correctly there is a chance you don't see anything show up on your deployed site. That is because Heroku also requires you to pull in their own port while you might have just hard set one in your code.

Chase23:09:24

I gotta step away for a bit though. gl

John Bradens23:09:36

Ok thank you!!!

Chase16:09:46

Did ya get it working @U02387J8EKG?

John Bradens17:09:45

Thanks for checking in @U9J50BY4C. I'm getting the error Error: Could not find or load main class"

John Bradens17:09:18

Do you know what main it is referring to? I have main in my project.clj file, and in my build it said "shadow-cljs release main". I tried changing it to release app, because in my build map in shadow-cljs.edn it says app instead of main, but I still get the same error.

John Bradens17:09:14

I'm going to try changing the shadow-cljs.edn file to say main instead of app

Chase18:09:43

That should actually be from the java side of things I think if it is talking about a class

John Bradens03:09:44

It compiles fine using shadow-cljs to my localhost, but it won't compile when I try to push to heroku. Any idea what I'm missing?

Clojure Newbie12:09:20

Hi, I am using luminous and trying to use honeysql. I have a queries namespace in which I require db using (:require [shopmap-server.db.core :refer [db]). I also have a line of code that is supposed to pring db, but it prints "object dereferable state..." whereas in the repl it prints what I need which is the object containing a hikari datasource. Could someone please help me out? Thanks!

Apple12:09:23

'dereferable' try (print @db)

Clojure Newbie12:09:42

@zengxh I tried, and it errors since the status is pending and the value is nil

Clojure Newbie12:09:01

It seems to me like the database connection is not actually being loaded or something, but I do not know enough about how clojure works in that sense

Clojure Newbie12:09:12

Sorry I hsould have mentioned that I have tried to deref the variable

Apple12:09:02

in your shopmap-server.db.core namespace there's (defstate ^:dynamic *db* ... )

Apple12:09:38

the next line :start (conman/connect! {:jdbc-url (env :database-url)}) starts the jdbc

Apple12:09:58

and the return value is saved in *db*

Apple12:09:36

(:require [shopmap-server.db.core :refer [*db*]) is it really :refer in there not as?

Clojure Newbie12:09:18

yes it is. should it be as?

Clojure Newbie12:09:57

if so, I will google why

Apple12:09:05

do you see db/xyz in the same .clj file where you use (:require [shopmap-server.db.core :refer [*db*])?

Clojure Newbie12:09:58

this is something I am adding in since luminous uses hugsql and binds a file, not honey. My idea was that I can have a queries file with my honeysql queries and use the db object that is returned from the state

Clojure Newbie12:09:58

creating functions that execute the queries on a connection I get using (.getConnection db ). Before that, I had connected using jdbc/get-datasource with a config defined in the same file, but I am trying to remove the config from the code

Clojure Newbie12:09:49

currently the code looks like(with sensitive info removed): (ns shopmap-server.routes.queries.user (:require [honeysql.core :as sql] [shopmap-server.db.core :refer [*db*]])) (println *db*)

Clojure Newbie12:09:49

When printed in the terminal from lein test-refresh, I get "#object[mount.core.DerefableState addr {:status :pending, :val nil}] whereas when I print it from the nrepl, I get the actual object

Apple12:09:19

oh i get it. it's the db part changed to bold by the editor. then you refering *db* is alright.

Apple12:09:03

my *db* evals to #object[com.zaxxer.hikari.HikariDataSource 0x5415ef3e "HikariDataSource (HikariPool-1)"]

Clojure Newbie12:09:14

yeah that's what mine evals to in the repl

Clojure Newbie12:09:35

so I think I'm doing that part right, which is why I'm a bit confused why it doesn't eval to that in lein test-refresh...

Apple12:09:36

oh lein test

Clojure Newbie12:09:51

it's causing all of my queries to fail basically because the thing is nil

Apple12:09:34

is your file located at test/clj/<proj>/db/core_test.clj

Clojure Newbie12:09:54

which file? the test file?

Clojure Newbie12:09:24

my test file is at /test/clj/shopmap_server/handler_test.clj

Apple12:09:26

you mention 'lein test-refresh'

Apple12:09:26

if your test involves db then take a look at /test/clj/shopmap_server/db/core_test.clj

Apple12:09:46

you'll see in there the db is started for the test while in handler the db is not started

Clojure Newbie12:09:56

there is no file in the db

Clojure Newbie12:09:07

I should be able to see one in a luminous example online though right?

Clojure Newbie12:09:16

I'm sure I"ll find it. Thank you!

Apple12:09:20

(ns guestbook.db.core-test
  (:require
   [guestbook.db.core :refer [*db*] :as db]
   [java-time.pre-java8]
   [luminus-migrations.core :as migrations]
   [clojure.test :refer :all]
   [next.jdbc :as jdbc]
   [guestbook.config :refer [env]]
   [mount.core :as mount]))

(use-fixtures
  :once
  (fn [f]
    (mount/start
     #'guestbook.config/env
     #'guestbook.db.core/*db*)
    (migrations/migrate ["migrate"] (select-keys env [:database-url]))
    (f)))

(deftest test-messages
  (jdbc/with-transaction [t-conn *db* {:rollback-only true}]
    (is (= 1 (db/save-message!
              t-conn
              {:name "Bob"
               :message "Hello, World"}
              {:connection t-conn})))
    (is (= {:name "Bob"
            :message "Hello, World"}
           (-> (db/get-messages t-conn {})
               (first)
               (select-keys [:name :message]))))))

Apple12:09:55

db related test needs to have the db started, in the mount

Apple12:09:36

in luminus framework there're at least the env, db, http-server components started by mount

Apple12:09:19

your handler test involves db and db is not started. i think this may be the problem.

Apple12:09:58

in your /test/clj/shopmap_server/handler_test.clj probably just add db to the use-fixtures

Clojure Newbie12:09:15

I bet that's the problem. I am adding it now, will update in a second

Clojure Newbie12:09:25

that would make complete sense though

Clojure Newbie12:09:09

it works! thank you so much

Clojure Newbie12:09:12

It was a bit confusing to me that they have multiple test files, one in db and one in handler. I should have looked through the test file and seen that the database state was not being loaded. I knew that it wasn't being loaded, but didn't realize it was such a simple thing for me to miss. Thank you so much again, saved me a ton of time, I'll read through more carefully next time haha

Clojure Newbie12:09:45

Saved me a ton of time

sheluchin14:09:17

Is there a shorter way to do this?

(let [foo (fn [x y z]
            {:x x :y y :z z})]
  (map (fn [coll] (apply foo coll)) [[1 2 3]
                                     [4 5 6]]))

delaguardo14:09:20

(letfn [(foo [[x y z]]
          {:x x :y y :z z})]
  (map foo [[1 2 3]
            [4 5 6]]))

sheluchin14:09:31

Great, thanks. I forget about letfn.

R.A. Porter14:09:26

Also

(map #(zipmap [:x :y :z] %) [[1 2 3]
                             [4 5 6]])

sheluchin14:09:26

I suppose that does simplify it a bit more as well. Thanks!

Joel15:09:02

I'm using the replace function, but I actually want values to be replaced with nil if they aren't in the map (instead of identity). I figure there's a simple way/different function that will do that?

dpsutton15:09:37

you want this behavior? (f {:a :A :b :B} [:a :b :c :d]) => [:A :B nil nil]

👍 2
Apple15:09:10

(map #(smap % nil) coll)

noisesmith17:09:29

the nil here is redundant

Apple17:09:46

as dpsutton points out just (map smap coll) will do

noisesmith17:09:20

yes, that too

dpsutton15:09:03

just (map {:a :A :b :B} [:a :b :c :d]) maps are functions so you can just map the map 🙂

🙌 4
🙂 2
pithyless16:09:40

@UH13Y2FSA in case you're not aware, sometimes the juxt function is useful for this:

user=> ((juxt :a :b :c :d) {:a :A :b :B})
[:A :B nil nil]

noisesmith17:09:13

there's also replace if you want the original value if it wasn't in the map

dpsutton17:09:14

replace is where this discussion started and they wanted the nils

👍 2
dpsutton17:09:58

the juxt version above requires that the items in the original collection are invocable which isn't true for collections in general

👍 2
mortemeur17:09:47

can someone point me at a good project that has separate clj/cljs/cljc files and uses reagent? I want to start with a template like that.

mortemeur17:09:01

well, it looks like the default reagent template suits my needs... sorry about that.