Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .github/deno-to-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ dependencies:
npmjs.com: '*'
---*/

import { build, emptyDir } from "https://deno.land/x/dnt@0.38.0/mod.ts";
import SemVer from "../src/utils/semver.ts";
import { build, emptyDir } from "https://deno.land/x/dnt@0.38.0/mod.ts"
import SemVer from "../src/utils/semver.ts"

await emptyDir("./dist");
await emptyDir("./dist")

const version = (() => {
try {
return new SemVer(Deno.args[0]).toString();
return new SemVer(Deno.args[0]).toString()
} catch {
console.warn("no version specified, do not release this!")
return '0.0.0'
return "0.0.0"
}
})()

Expand All @@ -43,7 +43,7 @@ await build({
mappings: {
"https://deno.land/x/is_what@v4.1.15/src/index.ts": "is-what",
"https://deno.land/x/outdent@v0.8.0/mod.ts": "outdent",
"./src/utils/flock.deno.ts": "./src/utils/flock.node.ts"
"./src/utils/flock.deno.ts": "./src/utils/flock.node.ts",
},
package: {
name: "@teaxyz/lib",
Expand All @@ -64,24 +64,24 @@ await build({
exports: {
"./src/src/utils/semver": {
//TODO remove when gui is updated to use `@teaxyz/lib/semver`
import: "./src/src/utils/semver.ts"
import: "./src/src/utils/semver.ts",
},
"./semver": {
import: "./esm/src/utils/semver.js",
require: "./script/src/utils/semver.js"
require: "./script/src/utils/semver.js",
},
"./plumbing/*": {
"import": "./esm/src/plumbing/*.js",
"require": "./script/src/plumbing/*.js"
"require": "./script/src/plumbing/*.js",
},
"./hooks/*": {
"import": "./esm/src/hooks/*.js",
"require": "./script/src/hooks/*.js"
}
}
"require": "./script/src/hooks/*.js",
},
},
},
postBuild() {
Deno.copyFileSync("LICENSE.txt", "dist/LICENSE.txt");
Deno.copyFileSync("README.md", "dist/README.md");
Deno.copyFileSync("LICENSE.txt", "dist/LICENSE.txt")
Deno.copyFileSync("README.md", "dist/README.md")
},
});
})
36 changes: 18 additions & 18 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"request": "launch",
"name": "Debug Test",
"type": "node",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "deno",
"runtimeArgs": [
"test",
"--unstable",
"--inspect-brk",
"--allow-all",
"${file}",
],
"attachSimplePort": 9229
}
]
"version": "0.2.0",
"configurations": [
{
"request": "launch",
"name": "Debug Test",
"type": "node",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "deno",
"runtimeArgs": [
"test",
"--unstable",
"--inspect-brk",
"--allow-all",
"${file}"
],
"attachSimplePort": 9229
}
]
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"deno.enable": true,
"deno.lint": true,
"deno.unstable": true,
"deno.config": "deno.json"
"deno.config": "deno.jsonc"
}
155 changes: 69 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
</a>
</p>


# libtea

tea aims to provide packaging primitives. This library is a route to that
goal. libtea can install and provide sandboxed environments for packages that
have no effect on the wider system without you or your user needing to install
[tea/cli].
tea aims to provide packaging primitives. This library is a route to that goal. libtea can install
and provide sandboxed environments for packages that have no effect on the wider system without you
or your user needing to install [tea/cli].

## Getting Started

Expand All @@ -39,10 +37,10 @@ import * as tea from "https://deno.land/x/libtea/mod.ts"
## Usage

```ts
import { porcelain } from "@teaxyz/lib";
const { run } = porcelain;
import { porcelain } from "@teaxyz/lib"
const { run } = porcelain

await run(`python -c 'print("Hello, World!")'`);
await run(`python -c 'print("Hello, World!")'`)
// ^^ installs python and its deps (into ~/.tea/python.org/v3.x.y)
// ^^ runs the command
// ^^ output goes to the terminal
Expand All @@ -53,73 +51,68 @@ await run(`python -c 'print("Hello, World!")'`);
Capture stdout easily:

```ts
const { stdout } = await run(`ruby -e 'puts ", World!"'`, { stdout: true });
console.log("Hello,", stdout);
const { stdout } = await run(`ruby -e 'puts ", World!"'`, { stdout: true })
console.log("Hello,", stdout)
```

> `{ stderr: true }` also works.

If there’s a non-zero exit code, we `throw`. However, when you need to,
you can capture it instead:
If there’s a non-zero exit code, we `throw`. However, when you need to, you can capture it instead:

```ts
const { status } = await run(`perl -e 'exit(7)'`, { status: true });
assert(status == 7); // ^^ didn’t throw!
const { status } = await run(`perl -e 'exit(7)'`, { status: true })
assert(status == 7) // ^^ didn’t throw!
```

> The run function’s options also takes `env` if you need to supplement or
> replace the inherited environment (which is passed by default).
> The run function’s options also takes `env` if you need to supplement or replace the inherited
> environment (which is passed by default).

Need a specific version of something? [tea][tea/cli] can install any version
of any package:
Need a specific version of something? [tea][tea/cli] can install any version of any package:

```ts
await run(["node^16", "-e", "console.log(process.version)"]);
await run(["node^16", "-e", "console.log(process.version)"])
// => v16.18.1
```

> Notice we passed args as `string[]`. This is also supported and is often
> preferable since shell quoting rules can be tricky. If you pass `string[]`
> we execute the command directly rather than via `/bin/sh`.
> Notice we passed args as `string[]`. This is also supported and is often preferable since shell
> quoting rules can be tricky. If you pass `string[]` we execute the command directly rather than
> via `/bin/sh`.

All of tea’s packages are relocatable so you can configure libtea to install
wherever you want:
All of tea’s packages are relocatable so you can configure libtea to install wherever you want:

```ts
import { hooks, Path, porcelain } from "tea";
const { install } = porcelain;
const { useConfig } = hooks;
import { hooks, Path, porcelain } from "tea"
const { install } = porcelain
const { useConfig } = hooks

useConfig({ prefix: Path.home().join(".local/share/my-app") });
useConfig({ prefix: Path.home().join(".local/share/my-app") })
// ^^ must be done **before** any other libtea calls

const go = await install("go.dev");
const go = await install("go.dev")
// ^^ go.path = /home/you/.local/share/my-app/go.dev/v1.20.4
```

### Designed for Composibility

The library is split into [plumbing](src/plumbing) and [porcelain](src/porcelain) (copying git’s lead).
The porcelain is what most people need, but if you need more control, dive
into the porcelain sources to see how to use the plumbing primitives to get
precisely what you need.
The library is split into [plumbing](src/plumbing) and [porcelain](src/porcelain) (copying git’s
lead). The porcelain is what most people need, but if you need more control, dive into the porcelain
sources to see how to use the plumbing primitives to get precisely what you need.

For example if you want to run a command with node’s `spawn` instead it is
simple enough to first use our porcelain `install` function then grab the
`env` you’ll need to pass to `spawn` using our `useShellEnv` hook.
For example if you want to run a command with node’s `spawn` instead it is simple enough to first
use our porcelain `install` function then grab the `env` you’ll need to pass to `spawn` using our
`useShellEnv` hook.

Perhaps what you create should go into the porcelain? If so, please open a PR.

### Logging

Most functions take an optional `logger` parameter so you can output logging
information if you so choose. `tea/cli` has a fairly sophisticated logger, so
go check that out if you want. For our porcelain functions we provide a simple
debug-friendly logger (`ConsoleLogger`) that will output everything via
`console.error`:
Most functions take an optional `logger` parameter so you can output logging information if you so
choose. `tea/cli` has a fairly sophisticated logger, so go check that out if you want. For our
porcelain functions we provide a simple debug-friendly logger (`ConsoleLogger`) that will output
everything via `console.error`:

```ts
import { porcelain, plumbing, utils } from "tea"
import { plumbing, porcelain, utils } from "tea"
const { ConsoleLogger } = utils
const { run } = porcelain

Expand All @@ -129,52 +122,45 @@ await run("youtube-dl youtu.be/xiq5euezOEQ", { logger }).exec()

### Caveats

We have our own implementation of semver because open source has existed for
decades and Semantic Versioning is much newer than that. Our implementation is
quite compatible but not completely so. Use our semver with libtea.
Our implementation is 100% compatible with strings output from node’s own
semver.
We have our own implementation of semver because open source has existed for decades and Semantic
Versioning is much newer than that. Our implementation is quite compatible but not completely so.
Use our semver with libtea. Our implementation is 100% compatible with strings output from node’s
own semver.

Setting `useConfig()` is not thread safe. Thus if you are using web workers
you must ensure the initial call to `useConfig()` is called on the main thread
before any other calls might happen. We call it explicitly in our code so you
will need to call it yourself in such a case. This is not ideal and we’d
appreciate your help in fixing it.
Setting `useConfig()` is not thread safe. Thus if you are using web workers you must ensure the
initial call to `useConfig()` is called on the main thread before any other calls might happen. We
call it explicitly in our code so you will need to call it yourself in such a case. This is not
ideal and we’d appreciate your help in fixing it.

The plumbing has no magic. Libraries need well defined behavior.
You’ll need to read the docs to use them effectively.
The plumbing has no magic. Libraries need well defined behavior. You’ll need to read the docs to use
them effectively.

libtea almost certainly will not work in a browser. Potentially it's possible.
The first step would be compiling our bottles to WASM. We could use your help
with that…
libtea almost certainly will not work in a browser. Potentially it's possible. The first step would
be compiling our bottles to WASM. We could use your help with that…

We use a hook-like pattern because it is great. This library is not itself
designed for React.
We use a hook-like pattern because it is great. This library is not itself designed for React.

We support the same platforms as [tea/cli].

## What Packages are Available?

We can install anything in the [pantry].

If something you need is not there, adding to the pantry has been designed to
be an easy and enjoyable process. Your contribution is both welcome and
desired!
If something you need is not there, adding to the pantry has been designed to be an easy and
enjoyable process. Your contribution is both welcome and desired!

To see what is available refer to the [pantry] docs or you can run:
`tea pkg search foo`.
To see what is available refer to the [pantry] docs or you can run: `tea pkg search foo`.

&nbsp;

# Interesting Uses

* You can grab cURL’s CA certificates which we pkg and keep up to date
(`curl.se/ca-certs`). These are commonly needed across ecosystems but not
always easily accessible.
* grab libraries that wrappers need like openssl or sqlite
* run a real database (like postgres) easily
* load local AI models and their engines
* load libraries and then use ffi to load symbols
- You can grab cURL’s CA certificates which we pkg and keep up to date (`curl.se/ca-certs`). These
are commonly needed across ecosystems but not always easily accessible.
- grab libraries that wrappers need like openssl or sqlite
- run a real database (like postgres) easily
- load local AI models and their engines
- load libraries and then use ffi to load symbols

&nbsp;

Expand All @@ -186,24 +172,23 @@ We would be thrilled to hear your ideas† or receive your pull requests.

## Anatomy

The code is written with Deno (just like [tea/cli]) but is compiled to a
node package for wider accessibility (and ∵ [tea/gui] is node/electron).
The code is written with Deno (just like [tea/cli]) but is compiled to a node package for wider
accessibility (and ∵ [tea/gui] is node/electron).

The library is architected into hooks, plumbing and porcelain. Where the hooks
represent the low level primitives of pkging, the plumbing glues those
primitives together into useful components and the porcelain is a user
friendly *façade* pattern for the plumbing.
The library is architected into hooks, plumbing and porcelain. Where the hooks represent the low
level primitives of pkging, the plumbing glues those primitives together into useful components and
the porcelain is a user friendly _façade_ pattern for the plumbing.

## Supporting Other Languages

We would love to port this code to every language. We are deliberately keeping
the scope *tight*. Probably we would prefer to have one repo per language.
We would love to port this code to every language. We are deliberately keeping the scope _tight_.
Probably we would prefer to have one repo per language.

tea has sensible rules for how packages are defined and installed so writing
a port should be simple.
tea has sensible rules for how packages are defined and installed so writing a port should be
simple.

We would love to explore how possible writing this in rust and then compiling
to WASM for all other languages would be. Can you help?
We would love to explore how possible writing this in rust and then compiling to WASM for all other
languages would be. Can you help?

Open a [discussion] to start.

Expand All @@ -217,7 +202,6 @@ Open a [discussion] to start.

&nbsp;


# Tasks

Run eg. `xc coverage` or `xc bump patch`.
Expand All @@ -233,8 +217,7 @@ open cov_profile/html/index.html

## Bump

Bumps version by creating a pre-release which then engages the deployment
infra in GitHub Actions.
Bumps version by creating a pre-release which then engages the deployment infra in GitHub Actions.

Inputs: LEVEL

Expand Down
7 changes: 2 additions & 5 deletions deno.json → deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
"strict": true
},
"fmt": {
"files": {
"exclude": [
"./"
]
}
"semiColons": false,
"lineWidth": 100
},
"tea": {
"dependencies": {
Expand Down
Loading