Fork me on GitHub
#nbb
<
2023-05-29
>
Pradeep B10:05:53

Anyone used or tried nbb with a nest.js project? I have tried doing it same way as express.js/cljs integration however didn’t work. Tried following things: • created a simple nest.js service ( nest new project-name ) • ran with npm run start and it worked fine • created hello.cljs file and tried using this in app.service.ts file, it failed to load • tried converting to type: module and ran it failed with another error. Anyone ever tried this combination nest.js + nbb clojure module? Idea to plug some new clojure code into some running nest.js repo/service.

Pradeep B10:05:42

context of generated dist/app.service.js file

borkdude10:05:30

what output did you see?

borkdude10:05:06

"it didn't work" is not very informative without elaborate error output or a repro that I could run locally

borkdude10:05:26

oh I see, the error is on the right, I'm sorry

borkdude10:05:13

yes, nbb is an ES6 project, your project should also be compiled as an ES6 project, but it's compiled as CJS project

Pradeep B10:05:29

right, i am trying to build with “cjs” type for nest.js however no success. will try few more things and add more details.

borkdude10:05:28

you can import nbb with a dynamic import though

borkdude10:05:33

async function loadNbbFile(file) {
  const nbb = await import('nbb');
  await nbb.loadFile(file);
}

(async () => await loadNbbFile('hello.cljs'))();

Pradeep B10:05:01

that will be one way, i am trying now. https://dev.to/wolfejw86/the-commonjs-vs-es-modules-war-is-taxing-for-us-regular-folks-out-here-one-way-to-interop-55e tried this one and for some weird reason getting argument mismatch error even when it correct ( trying this further).

borkdude10:05:07

I don't think the const DynamicImport has any benefits over using dynamic import directly?

borkdude10:05:55

I mean, you can just write:

async myImport(module) {
  return import(module);
}

yes 2
borkdude10:05:12

or even just import which is already a function

👀 2
borkdude10:05:43

(await import('nbb')).default

borkdude10:05:24

(async () => console.log( (await import('nbb')) ))()

Pradeep B10:05:29

yes simple await will work, i was overlooking and missed the change in app.service.ts (that’s where argument count mismatch).

borkdude10:05:44

there is no default export in nbb, you need to use .loadString or whatever directly.

borkdude10:05:02

or just pass the whole nbb itself

borkdude10:05:26

either way, don't do .default , there is none on the nbb module

Pradeep B13:05:18

that also didn’t work... however it moved 1 step ahead and now control reached nestjs framework level and that threw same exception. Will try out few more things, if this works it will be great fun and easy migration to clojure stack :)

borkdude13:05:07

You still have import from 'nbb' on the right, this is causing the error

borkdude13:05:41

the top level import

Pradeep B14:05:35

tried removing it earlier (later only got that to pull the type) - retrying without that fully (it will require some change in app.service.ts constructor (i.e., line number 7)

borkdude14:05:59

loadFile is a function of string -> Promise<Any> if that helps

Pradeep B14:05:00

not sure, trying few combinations. Wouldn’t it be helpful if we add a default export to nbb package it self?

borkdude14:05:34

default exports aren't mandatory and I would say even an anti-pattern. there is no single thing that is "default" about the nbb API

🆗 2
Pradeep B14:05:43

never liked js eco-system (long live Java eco-system) and now this is adding more reasons to it.

borkdude14:05:25

perhaps typescript is trying to be clever and rewrites (await import('nbb').loadFile) to a top level import which then gets compiled as require. To work around this can you write:

async function myLoadFile(file) {
  const nbb = await import('nbb');
  return nbb.loadFile(file);
}
and then pass myLoadFile?

borkdude14:05:43

If that doesn't work, perhaps then I get why they used Function in the earlier example

Pradeep B14:05:42

let me try. and thanks for all the proactive help so far.

👍 2
borkdude14:05:06

The const dynamicImport one I mean, perhaps TS is too clever and tries to optimize it when you don't write it using that

Pradeep B14:05:31

this time server started, one more step forward. however failing to load cljs while accessing the endpoint (locahost:3000).

borkdude14:05:19

ah yes, that's it:

For what it's worth, if we were in regular Javascript land this would work by itself, but wouldn't you know it, TypeScript has it's own problems with this one - it's actually rewriting that dynamic import as a require statement 😢. It's even sadder to realize that there's no way around this without hiding your dynamic import from the TypeScript compiler with a hackier method.

borkdude14:05:09

yes, please use the const dynamicImport you head earlier, TS is rewriting dynamic import

borkdude14:05:27

or just use a freaking .js file - screw ts ;)

2
Pradeep B14:05:21

this is 1 more step forward. now no error in module loading however data from cljs file is not returned in the api response. can’t use .js as want to migrate some existing service with nestjs(typescript) to clj.

borkdude14:05:33

What is in your .cljs file?

Pradeep B14:05:32

(ns hello)

;; variation 1 tried
;; (defn someData []
;;   "Hi, please show up in api response")

;; variation 2 tried
(defn someData []
 {:a "Hi, please show up in api response"})

#js {:someData someData}
got this from the nbb docs.

borkdude14:05:27

> however data from cljs file is not returned in the api response where are you calling the someData function then?

Pradeep B14:05:55

in the app.controller.ts the getHello function is getting called which is injected in the app.service.ts

Pradeep B14:05:23

i guess it might be because of promise type, will try without that.

Pradeep B14:05:58

changing (removed the promise, and made it only string) the return type of the getHello also didn’t help.

borkdude14:05:35

isn't what you're seeing here a JS object being printed?

borkdude14:05:58

you are returning a JS object from the loadFile call (async, so you might want to add an await in there)

borkdude14:05:08

just console.log it and it will hopefully become clear to you

🆗 2
borkdude14:05:49

What I mean is:

getHello(): Promise<string> {
  const loadFileResult = await this.loadFile("...");
  const { someData } = loadFileResult;
  const result = someData();
  console.log(result);
  return result;
}

borkdude14:05:53

The result of someData is not a string, but a CLJS map in your code, but hopefully you get the idea

Pradeep B14:05:18

yes, this piece of code worked for me. Thanks so much, you are awesome @U04V15CAJ gratitude-danke. Just relooking at organising it now for better usage.

borkdude14:05:52

cool :)

🙌 2