Fork me on GitHub
#shadow-cljs
<
2022-05-15
>
thheller06:05:06

@kovas.palunas I don't expect a development build to work. as I said it expects not and as such uses node features. shadow-cljs release app might.

thheller06:05:04

instead of resolve use exists? js/SpreadsheetApp

thheller06:05:31

can you point me to some documentation about apps scripts? do they support ES modules? ie. import/export?

thheller06:05:40

the whole point of the shadow-cljs :target abstraction is to make target specific builds. there could absolutely be a :target :google-apps-script. I just have never used that so I don't know how it needs to be bundled

Kovas Palunas17:05:50

thanks for the gist link! i ended up solving that problem with a simple defn that takes in anonymous functions to execute: https://github.com/kovasap/autojournal-on-gas/blob/fe8e80c358f0dce2e9852f8d2f6f7813b23008be/src/autojournal/env_switching.cljs#L3. the resolve call i'm using now works well - is exists? just a better name for the same functionality?

Kovas Palunas17:05:41

apps script is interesting in that it's a (AFAIK) totally self contained development environment: https://developers.google.com/apps-script/overview?hl=en

Kovas Palunas17:05:23

usually you would write code in their browser editor and run it. it interacts with various google products via its own special API

Kovas Palunas17:05:14

it has a CLI utility for local development (not in their browser editor) https://github.com/google/clasp

Kovas Palunas17:05:40

my understanding is that apps script code should be bundled as just one big flat js file with everything in it

Kovas Palunas17:05:06

and no undefined names (that would otherwise be defined in other places)

Kovas Palunas17:05:47

AFAIK apps script does not support js dependencies of any kind (although if they were inlined in the bit flat file that would work)

Kovas Palunas17:05:27

one interesting quirk of apps script also is that it doesn't like namespaced names. https://lambdaisland.com/blog/2016-10-01-clojurescript-and-google-apps-script describes a workaround. i'm currently just appending some non-namespaced functions that call my core functionality to my big js file in a bash script

Kovas Palunas19:05:35

btw it looks like shadow-cljs release app does not work due to google apps script seeing a syntax error in the generated js file. perhaps this is because of subtle differences between javascript and google apps script

Kovas Palunas19:05:24

strangely, the lein cljsbuild once command's output is interpreted just fine. i think this has to do with the clojurescript version. I'm using "1.10.439" in my project.clj and saw that using "1.10.773" led to this syntax error

thheller19:05:40

define syntax error

Kovas Palunas19:05:43

i should probably try using this older version in my shadow-cljs

thheller19:05:54

it really is much easier to answer question if you provide the actual errors

thheller19:05:59

no just say that there is an error 😛

Kovas Palunas19:05:05

yeah i know, one sec

Kovas Palunas19:05:28

the message is 'Syntax error: Missing ; before statement. line: 24 file: Code',, let me get a link to the file

thheller19:05:16

try with shadow-cljs release app --pseudo-names or --debug

thheller19:05:33

also whats in line 24?

Kovas Palunas19:05:14

getting it, one sec

thheller19:05:27

also try :compiler-options {:output-feature-set :es5} in your build config. maybe it doesn't like newer syntax

thheller19:05:28

this also only applies to dev builds. release will be a single file

👍 1
Kovas Palunas19:05:36

i just tried a release build here, but got the same syntax errors

Kovas Palunas19:05:58

errors: [
    {
      message: 'Syntax error: Missing ) after formal parameters. line: 1420 file: Code',
      domain: 'global',
      reason: 'badRequest'
    }
  ]

Kovas Palunas19:05:04

goog.loadModule(function(exports) {
  "use strict";
  goog.module("goog.debug.Error");
  goog.module.declareLegacyNamespace();
  function DebugError(msg = undefined, cause = undefined) {  // <- 1420
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, DebugError);
    } else {
      const stack = (new Error()).stack;
      if (stack) {
        this.stack = stack;
      }
    }
 

Kovas Palunas19:05:35

the :es5 option didn't work

Kovas Palunas19:05:45

but i feel like that might be the right idea

Kovas Palunas19:05:18

it would make sense that apps script is equivalent to a certain version of javascript that is not the latest one

Kovas Palunas19:05:40

--pseudo-names didn't work either

Kovas Palunas19:05:53

i figured out that I can set the javascript version used by apps script to use Chrome V8 instead of rhino, which makes the syntax errors go away!

Kovas Palunas19:05:47

now i'm simply getting ErrorReferenceError: global is not defined when i try to run my code

Kovas Palunas19:05:31

using :target :browser gives

12:35:01 PM	Error	Cannot use default debug loader outside of HTML documents.
12:35:01 PM	Error	Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, or setting CLOSURE_NO_DEPS to true.
12:35:01 PM	Error	
TypeError: Cannot set property 'NodeType' of undefined

Kovas Palunas19:05:31

so yeah i think the syntax error problem is solved, but there is still an issue with shadow-cljs output expecting names that are not provided by the apps script environment (the global name at least)

thheller19:05:43

this is with a release build?

thheller19:05:59

watch/compile assumes browser environment. so not expected to work.

thheller19:05:22

global comes from the assumption of running in node

Kovas Palunas19:05:20

yes this is a release build

Kovas Palunas19:05:24

that makes sense

Kovas Palunas19:05:49

if i add var global = {}; to the top i get another error:

goog.dom.NodeType = {ELEMENT:1, ATTRIBUTE:2, TEXT:3, CDATA_SECTION:4, ENTITY_REFERENCE:5, ENTITY:6, PROCESSING_INSTRUCTION:7, COMMENT:8, DOCUMENT:9, DOCUMENT_TYPE:10, DOCUMENT_FRAGMENT:11, NOTATION:12};

Kovas Palunas19:05:57

TypeError: Cannot set property 'NodeType' of undefined

Kovas Palunas19:05:23

because i think

var goog = goog || {};
goog.global = global;

thheller19:05:23

there is no more goog.module or goog.provide in the file right?

thheller19:05:09

> the javascript version used by apps script to use Chrome V8

Kovas Palunas19:05:15

goog.module.get = function(name) {
  return goog.module.getInternal_(name);
};

thheller19:05:22

are there docs on this? I mean what the runtime is capable of?

thheller19:05:31

I mean goog.module(...) calls

Kovas Palunas19:05:53

yes those lines exist goog.module("goog.debug.Error");

Kovas Palunas19:05:00

should they not exist in a release build?

thheller19:05:08

this is not a release build no?

Kovas Palunas19:05:24

i'm calling (run "npx" "shadow-cljs" "release" "autojournal")

thheller19:05:28

welll :optimizations :whitespace

thheller19:05:31

don't do that

thheller19:05:34

at least :simple

Kovas Palunas19:05:16

i still have the missing global problem without :optimizations :whitespace

thheller19:05:59

just add the var global = {} again?

Kovas Palunas19:05:24

i get ErrorReferenceError: process is not defined

Kovas Palunas19:05:41

here

;af(function() {
  return dt();
}, process.argv.slice(2));

Kovas Palunas19:05:08

this is the very last bit of code in the file!

thheller19:05:38

again. :node-script assumes node. try :browser

thheller19:05:21

I'm not asking about v8 in general. I need to know in the context of google apps script what features it supports

thheller19:05:33

node is also v8 and that has global and process just fine

thheller19:05:56

so, are there any docs specifically about what the google apps script runtime is capable of?

Kovas Palunas19:05:52

i haven't found them yet

thheller19:05:25

I would write a custom :target for this that handles all the appscript specific stuff. I just don't have time to look into that currently

thheller20:05:06

maybe the v8 supports import, then dev builds might work. otherwise release only again

thheller20:05:27

but that should not have any process or global references

thheller20:05:47

although it may have globalThis. which may or may not be present in that v8 variant

Kovas Palunas20:05:17

no dice on the :esm yet: message: "Syntax error: SyntaxError: Unexpected token 'export' line: 14202 file: ",

Kovas Palunas20:05:35

no worries!! I'm super grateful for all the tips so far!

thheller20:05:32

if you remove that export line? should be like the last one

thheller20:05:52

I believe you can also just leave out exports in the build config and just use :entries [your.ns]

Kovas Palunas20:05:31

ok i got something working

Kovas Palunas20:05:01

i needed to add "var global = {}; var process = {\"argv\": [\"one\", \"two\"]};" to the top of my file

Kovas Palunas20:05:01

and i needed to remove the (function(){ ... })();

Kovas Palunas20:05:07

wrapping the entire file

Kovas Palunas20:05:21

hacky but it seems to work

Kovas Palunas20:05:41

haha this is kinda silly but i'm glad the problem is solved. i'll make a note to myself to write this up somewhere. or would you take this hack as a contribution for :target :apps-script

thheller20:05:15

well with a custom target it would be less hacky

thheller20:05:24

because the process thing is added by :node-script

thheller20:05:39

as well as all the other stuff pretty much

Kovas Palunas20:05:58

ok that makes sense

thheller20:05:36

you can try to create your own impl. can be in your repo. doesn't need to be part of shadow-cljs itself. no fork or so needed

Kovas Palunas20:05:24

how can i reference my own impl from my shadow-cljs.edn?

thheller20:05:37

if you create a shadow.build.targets.google-apps-script ns or so

thheller20:05:42

just :target :google-apps-script

thheller20:05:04

or :target your.ns with (ns your.ns)

thheller20:05:15

it looks for a process fn just like in the :node-script impl

Kovas Palunas20:05:43

this namespace is in a clj file that I reference with shadow-cljs?

Kovas Palunas20:05:05

or in a fork of shadow-cljs i make?

thheller20:05:17

it is just a clj file in your repo

thheller20:05:22

as I said no fork or anything

thheller20:05:34

just copy the node-script file from above and rename it

thheller20:05:38

then start hacking 😉

thheller20:05:57

run a shadow-cljs clj-repl or work on it from your editor

Kovas Palunas20:05:03

right i guess when you say "your repo" do you mean my own copy of the shadow-cljs repo, or my project repo?

thheller20:05:09

project repo

thheller20:05:32

just needs to be on the classpath. no modification in shadow-cljs required whatsoever

Kovas Palunas20:05:52

can i specify the classpath in shadow-cljs.edn?

Kovas Palunas20:05:08

(i've not worked with clj much, only cljs)

thheller20:05:47

you already do. :source-paths ["src"] so just src/shadow/build/targets/google_apps_script.clj or whatever name you want

thheller20:05:49

sorry way too late to walk you through this. that part happens in the flush call, so the node/flush-optimized