diff --git a/utils/jex/README.md b/utils/jex/README.md index 4dfe07a..adf7ae3 100644 --- a/utils/jex/README.md +++ b/utils/jex/README.md @@ -29,6 +29,7 @@ business context, which is the focus of the Vanillae project. Jex: simple JavaScript packaging system COMMANDS: + man show the manual dwim- init, pull, build dwim+ init, pull, build, mindist, push cfgbarf barf out the jex.eterms file (mostly to make sure it parses correctly) @@ -38,7 +39,7 @@ COMMANDS: echo pkgname name of current package echo pkgdir echo $HOME/.jex/dev/realm-name-X.Y.Z echo deps list dependencies of current package - echo pathof PKG list the path to PKG or + echo pathof PKG list the path to PKG or init mkdir -p $HOME/.jex/dev build tsc && cp -r ./src/jex_include ./dist/ -w, --weak continue building even if tsc fails diff --git a/utils/jex/priv/MANUAL.txt b/utils/jex/priv/MANUAL.txt new file mode 100644 index 0000000..d2eb543 --- /dev/null +++ b/utils/jex/priv/MANUAL.txt @@ -0,0 +1,239 @@ +===================================================================== +tl;dr +===================================================================== + +You can get this by running jex --help + +COMMANDS: + man show the manual + dwim- init, pull, build + dwim+ init, pull, build, mindist, push + cfgbarf barf out the jex.eterms file (mostly to make sure it parses correctly) + echo home echo $HOME + echo jexdir echo $HOME/.jex + echo devdir echo $HOME/.jex/dev + echo pkgname name of current package + echo pkgdir echo $HOME/.jex/dev/realm-name-X.Y.Z + echo deps list dependencies of current package + echo pathof PKG list the path to PKG or + init mkdir -p $HOME/.jex/dev + build tsc && cp -r ./src/jex_include ./dist/ + -w, --weak continue building even if tsc fails + -f, --force use cp -rf instead of cp -r + mindist mkdir jex_mindist && cp -r src jex_mindist && cp -r dist jex_mindist && rm -r jex_mindist/src/jex_include + -f, --force use cp -rf instead of cp -r + push rsync -a jex_mindist/ PKGDIR + ls ls $HOME/.jex/dev + tree tree $HOME/.jex/ + rmpkg PKG rm -r $HOME/.jex/dev/PKG + pull pull each dependency into src/jx_include + + +===================================================================== +JEX MANUAL +===================================================================== + +Jex is a simple packaging/dependency system for TypeScript/JavaScript +projects. + +As of now, Jex is a glorified shell script that automates a lot of +the tedium in building sidekick, JR, etc. Jex is very much a work in +progress, so these instructions are subject to change. + +Jex is currently hyper-specialized to our use cases inside of +Vanillae, and is probably (currently) unsuitable for your use case. +For instance, Jex assumes you are running a UNIX-like system with +standard UNIX programs installed (e.g. tree, rsync, tar, etc). It +also makes very strong assumptions about your project structure and +how you want to distribute your project. + +Our long-term goal is to build Jex out into a proper secure packaging +system, and completely remove any dependency on NPM. NPM comes with +a lot of unfixable security issues that present an unacceptable risk +in a business context. Developing software for the business context +is the focus of the Vanillae project. + +You'll see how it works and what the philosophy is if you keep +reading. + + +===================================================================== +HOW IT WORKS +===================================================================== + +To start off, we run `jex init` + + [~] % jex init + $ mkdir -p /home/pharpend/.jex/dev + +As I said above, jex is currently a glorified shell script. Much like +`make`, jex prints the command it's running with a `$` at the +beginning of the line. + +We can get a sense of what will go in this directory by running `jex +tree` (yours will not look like this): + + [~] % jex tree + $ tree /home/pharpend/.jex + /home/pharpend/.jex + └── dev + ├── local-awcp-0.1.0 + │   ├── dist + │   │   ├── awcp.d.ts + │   │   ├── awcp.js + │   │   ├── awcp.js.map + │   │   └── jex_include + │   └── src + │   └── awcp.ts + ├── local-parasite-0.1.0 + │   ├── dist + │   │   ├── ae_compiler.d.ts + │   │   ├── ae_compiler.js + │   │   ├── ae_compiler.js.map + │   │   ├── ae_node.d.ts + │   │   ├── ae_node.js + │   │   ├── ae_node.js.map + │   │   ├── jex_include + │   │   ├── net.d.ts + │   │   ├── net.js + │   │   └── net.js.map + │   └── src + │   ├── ae_compiler.ts + │   ├── ae_node.ts + │   └── net.ts + └── local-sidekick-0.1.0 + ├── dist + │   ├── jex_include + │   │   └── local-awcp-0.1.0 + │   │   ├── dist + │   │   │   ├── awcp.d.ts + │   │   │   ├── awcp.js + │   │   │   ├── awcp.js.map + │   │   │   └── jex_include + │   │   └── src + │   │   └── awcp.ts + │   ├── sidekick.d.ts + │   ├── sidekick.js + │   └── sidekick.js.map + └── src + └── sidekick.ts + + 17 directories, 24 files + +Currently, Jex is managing 3 packages for me: + +1. awcp +2. parasite +3. sidekick + +In a secure context, we want to avoid opaque rewrites whenever +possible. This rules out bundling or minifying tools such as +browserify. We want the code that is running in the user's browser +to be human-readable and to have a straightforward mapping to +the original source. + +Let's start with the simplest package which is `awcp`. This is the +source directory listing + + [v/libs pharpend/develop] % tree awcp + awcp + ├── dist + │   ├── awcp.d.ts + │   ├── awcp.js + │   ├── awcp.js.map + │   └── jex_include + ├── erl_crash.dump + ├── jex.eterms + ├── jex_mindist + │   ├── dist + │   │   ├── awcp.d.ts + │   │   ├── awcp.js + │   │   ├── awcp.js.map + │   │   └── jex_include + │   └── src + │   └── awcp.ts + ├── LICENSE + ├── Makefile + ├── README.md + ├── src + │   ├── awcp.ts + │   └── jex_include + └── tsconfig.json + + 8 directories, 14 files + +There is only one source file: `/src/awcp.ts`. There is a directory +called `/src/jex_include/` which is empty. If awcp had dependencies, +this is where they would go. + +The file tree that ends up in `~/.jex/dev` is the `jex_mindist` +directory. Let's focus on that + + [v/libs pharpend/develop] % tree awcp/jex_mindist + awcp/jex_mindist + ├── dist + │   ├── awcp.d.ts + │   ├── awcp.js + │   ├── awcp.js.map + │   └── jex_include + └── src + └── awcp.ts + + 3 directories, 4 files + +As you can see, it's the same tree + + [v/libs pharpend/develop] % tree ~/.jex/dev/local-awcp-0.1.0 + /home/pharpend/.jex/dev/local-awcp-0.1.0 + ├── dist + │   ├── awcp.d.ts + │   ├── awcp.js + │   ├── awcp.js.map + │   └── jex_include + └── src + └── awcp.ts + + 3 directories, 4 files + +Briefly, jex is built around the assumptions that you want simplicity, +transparency, and composability, possibly at the expense of some +duplication. + +It's assumed that you are developing JS to execute in the context of +a website, that you are writing only a small amount of JS (i.e. NOT +framework JS or a single-page-application), and that serving a +JavaScript file tree does not present a bandwidth issue. Everything +has a version number, so that you can properly take advantage of +caching. + +The idea is that you want to be able to take that file tree above, +make it into a tarball, drop it on your server, and have it "just +work". Or, you can drop the whole tree into your existing project +and have it "just work". We want the source map to work properly, so +the TypeScript source is included in the bundle. + +Let's switch over to the Sidekick project. Sidekick depends on AWCP. + + [src/v pharpend/develop] % tree sidekick/src + sidekick/src + ├── jex_include + │   └── local-awcp-0.1.0 + │   ├── dist + │   │   ├── awcp.d.ts + │   │   ├── awcp.js + │   │   ├── awcp.js.map + │   │   └── jex_include + │   └── src + │   └── awcp.ts + └── sidekick.ts + + 5 directories, 5 files + +To import AWCP, `sidekick.ts` contains this line + + import * as awcp from './jex_include/local-awcp-0.1.0/dist/awcp.js'; + +Notice that we're importing the JS file, not the TS file. TypeScript +gets its type information from the `dist/awcp.d.ts` file, not from +the `src/awcp.ts` file. The `src/awcp.ts` file is only included so +the source map works properly in the browser's debugger. diff --git a/utils/jex/src/jex.erl b/utils/jex/src/jex.erl index 1536c5e..f03af2b 100644 --- a/utils/jex/src/jex.erl +++ b/utils/jex/src/jex.erl @@ -10,8 +10,8 @@ -module(jex). -vsn("0.1.0"). --license("MIT"). -export([start/1]). +-compile(export_all). -include("$zx_include/zx_logger.hrl"). @@ -22,6 +22,7 @@ start(ArgV) -> ok = log(info, "ArgV: ~tp", [ArgV]), ok = dispatch(ArgV), + %ok. zx:silent_stop(). help() -> @@ -42,6 +43,7 @@ help_screen() -> ["Jex: simple JavaScript packaging system\n" "\n" "COMMANDS:\n" + " man show the manual\n" " dwim- init, pull, build\n" " dwim+ init, pull, build, mindist, push\n" " cfgbarf barf out the jex.eterms file (mostly to make sure it parses correctly)\n" @@ -66,6 +68,7 @@ help_screen() -> ]. +dispatch(["man"]) -> man(); dispatch(["dwim-"]) -> dwim(minus); dispatch(["dwim+"]) -> dwim(plus); dispatch(["cfgbarf"]) -> cfgbarf(); @@ -87,6 +90,17 @@ dispatch(_) -> help(). +%%----------------------------------------------------------------------------- +%% jex man +%%----------------------------------------------------------------------------- + +man() -> + ManFile = filename:join([zx:get_home(), "priv", "MANUAL.txt"]), + {ok, ManBytes} = file:read_file(ManFile), + io:format("~ts~n", [string:chomp(ManBytes)]). + %os:cmd(io_lib:format("less ~ts", [ManFile])), + %ok. + %%----------------------------------------------------------------------------- %% jex dwim