@unconfirmed/sui-effect 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +209 -0
- package/LICENSE +21 -0
- package/LLMS.md +6707 -0
- package/README.md +300 -0
- package/dist/domain/bcs.d.ts +101 -0
- package/dist/domain/bcs.d.ts.map +1 -0
- package/dist/domain/bcs.js +183 -0
- package/dist/domain/bcs.js.map +1 -0
- package/dist/domain/errors.d.ts +595 -0
- package/dist/domain/errors.d.ts.map +1 -0
- package/dist/domain/errors.js +476 -0
- package/dist/domain/errors.js.map +1 -0
- package/dist/domain/executed.d.ts +325 -0
- package/dist/domain/executed.d.ts.map +1 -0
- package/dist/domain/executed.js +253 -0
- package/dist/domain/executed.js.map +1 -0
- package/dist/domain/journal-entry.d.ts +468 -0
- package/dist/domain/journal-entry.d.ts.map +1 -0
- package/dist/domain/journal-entry.js +63 -0
- package/dist/domain/journal-entry.js.map +1 -0
- package/dist/domain/schemas.d.ts +950 -0
- package/dist/domain/schemas.d.ts.map +1 -0
- package/dist/domain/schemas.js +571 -0
- package/dist/domain/schemas.js.map +1 -0
- package/dist/domain/sui-schema.d.ts +12 -0
- package/dist/domain/sui-schema.d.ts.map +1 -0
- package/dist/domain/sui-schema.js +12 -0
- package/dist/domain/sui-schema.js.map +1 -0
- package/dist/extension.d.ts +7 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +7 -0
- package/dist/extension.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +18 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +18 -0
- package/dist/internal.js.map +1 -0
- package/dist/journal.d.ts +51 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +18 -0
- package/dist/journal.js.map +1 -0
- package/dist/script.d.ts +7 -0
- package/dist/script.d.ts.map +1 -0
- package/dist/script.js +7 -0
- package/dist/script.js.map +1 -0
- package/dist/services/Journal.d.ts +76 -0
- package/dist/services/Journal.d.ts.map +1 -0
- package/dist/services/Journal.js +70 -0
- package/dist/services/Journal.js.map +1 -0
- package/dist/services/JournalKeyValueStore.d.ts +73 -0
- package/dist/services/JournalKeyValueStore.d.ts.map +1 -0
- package/dist/services/JournalKeyValueStore.js +155 -0
- package/dist/services/JournalKeyValueStore.js.map +1 -0
- package/dist/services/Script.d.ts +210 -0
- package/dist/services/Script.d.ts.map +1 -0
- package/dist/services/Script.js +441 -0
- package/dist/services/Script.js.map +1 -0
- package/dist/services/Signer.d.ts +132 -0
- package/dist/services/Signer.d.ts.map +1 -0
- package/dist/services/Signer.js +158 -0
- package/dist/services/Signer.js.map +1 -0
- package/dist/services/SubmitConfig.d.ts +175 -0
- package/dist/services/SubmitConfig.d.ts.map +1 -0
- package/dist/services/SubmitConfig.js +52 -0
- package/dist/services/SubmitConfig.js.map +1 -0
- package/dist/services/Sui.d.ts +295 -0
- package/dist/services/Sui.d.ts.map +1 -0
- package/dist/services/Sui.js +414 -0
- package/dist/services/Sui.js.map +1 -0
- package/dist/services/SuiCore.d.ts +227 -0
- package/dist/services/SuiCore.d.ts.map +1 -0
- package/dist/services/SuiCore.js +400 -0
- package/dist/services/SuiCore.js.map +1 -0
- package/dist/services/SuiCoreFake.d.ts +278 -0
- package/dist/services/SuiCoreFake.d.ts.map +1 -0
- package/dist/services/SuiCoreFake.js +1003 -0
- package/dist/services/SuiCoreFake.js.map +1 -0
- package/dist/services/SuiExtension.d.ts +208 -0
- package/dist/services/SuiExtension.d.ts.map +1 -0
- package/dist/services/SuiExtension.js +355 -0
- package/dist/services/SuiExtension.js.map +1 -0
- package/dist/services/SuiGraphQL.d.ts +98 -0
- package/dist/services/SuiGraphQL.d.ts.map +1 -0
- package/dist/services/SuiGraphQL.js +118 -0
- package/dist/services/SuiGraphQL.js.map +1 -0
- package/dist/services/Tx.d.ts +687 -0
- package/dist/services/Tx.d.ts.map +1 -0
- package/dist/services/Tx.js +1224 -0
- package/dist/services/Tx.js.map +1 -0
- package/dist/testing.d.ts +88 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +163 -0
- package/dist/testing.js.map +1 -0
- package/dist/tx.d.ts +24 -0
- package/dist/tx.d.ts.map +1 -0
- package/dist/tx.js +24 -0
- package/dist/tx.js.map +1 -0
- package/docs/extensions.md +1685 -0
- package/examples/extension-template/README.md +170 -0
- package/examples/extension-template/package.json +44 -0
- package/examples/extension-template/scripts/check-package.ts +147 -0
- package/examples/extension-template/src/Escrow.ts +445 -0
- package/examples/extension-template/src/Platform.ts +136 -0
- package/examples/extension-template/src/errors.ts +61 -0
- package/examples/extension-template/src/extension.ts +63 -0
- package/examples/extension-template/src/index.ts +34 -0
- package/examples/extension-template/src/schema.ts +158 -0
- package/examples/extension-template/src/upstream.ts +66 -0
- package/examples/extension-template/test/escrow.test.ts +559 -0
- package/examples/extension-template/tsconfig.build.json +26 -0
- package/examples/extension-template/tsconfig.json +35 -0
- package/package.json +87 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# `@your-org/example-extension`
|
|
2
|
+
|
|
3
|
+
A copyable skeleton for a sui-effect extension: one Effect service built on
|
|
4
|
+
`Sui` and `Tx`, its errors, its three layers, its tests on the sui-effect
|
|
5
|
+
harness, and the derived Promise face a `client.$extend(...)` consumer sees.
|
|
6
|
+
|
|
7
|
+
`docs/extensions.md` in the sui-effect repository is the authoring guide, and
|
|
8
|
+
every code block in it is copied from this directory.
|
|
9
|
+
|
|
10
|
+
## What is in it
|
|
11
|
+
|
|
12
|
+
| File | What it shows |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `src/schema.ts` | Move layouts through `SuiSchema.bcs`, so an object's type tag is checked before its bytes are parsed |
|
|
15
|
+
| `src/errors.ts` | Two `Schema.TaggedError` classes, each declaring the `outcome` a script's exit code is derived from |
|
|
16
|
+
| `src/Escrow.ts` | The service: a read, a recipe fragment, a submit-on-behalf operation, a nested namespace, and `layer` / `layerConfig` / `layerTest` |
|
|
17
|
+
| `src/upstream.ts` | A stand-in for a third-party Promise SDK, wrapped in `src/Escrow.ts` with `SuiCore.use` and `Effect.tryPromise` |
|
|
18
|
+
| `src/extension.ts` | `SuiExtension.fromService`: the Promise face, derived, never hand-written |
|
|
19
|
+
| `test/escrow.test.ts` | The whole test suite on `layerExtensionTest` and `SuiTest` from `@unconfirmed/sui-effect/testing`. No network, no mocks of its own |
|
|
20
|
+
|
|
21
|
+
## Running it here
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cd examples/extension-template
|
|
25
|
+
bun run check # tsc --noEmit && bun test
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
From the repository root, `bun run check:template` does the same thing.
|
|
29
|
+
|
|
30
|
+
Do **not** run `bun install` in this directory while it lives inside the
|
|
31
|
+
sui-effect repository. It needs no install: `effect` and `@mysten/sui` resolve
|
|
32
|
+
from the repository's own `node_modules`, and `@unconfirmed/sui-effect` resolves through the
|
|
33
|
+
`paths` block in `tsconfig.json`. Installing here would put a second copy of
|
|
34
|
+
`effect` in scope, and two copies of `effect` in one process means two
|
|
35
|
+
`Context.Service` identities and layers that silently do not match.
|
|
36
|
+
|
|
37
|
+
## Consuming it from a separate checkout
|
|
38
|
+
|
|
39
|
+
If you are developing your extension against a sui-effect **checkout** rather
|
|
40
|
+
than a published version, use the packed tarball, not `link:` or `bun link`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cd /path/to/sui-effect && bun run build && npm pack
|
|
44
|
+
mkdir -p vendor && cp /path/to/sui-effect/unconfirmed-sui-effect-*.tgz vendor/
|
|
45
|
+
bun add -d ./vendor/unconfirmed-sui-effect-0.1.0.tgz
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`link:` and `bun link` symlink the checkout, and **module resolution follows the
|
|
49
|
+
symlink's real path**: the linked checkout resolves `effect` and `@mysten/sui`
|
|
50
|
+
from its own `node_modules`, your package resolves them from yours, and the two
|
|
51
|
+
copies are nominally distinct. Every class that crosses the boundary then fails
|
|
52
|
+
to typecheck with `#private` mismatches, and at runtime two `Context.Service`
|
|
53
|
+
identities mean layers that silently do not match. Reserve `link:` for a real
|
|
54
|
+
workspace member, where one `node_modules` serves both.
|
|
55
|
+
|
|
56
|
+
Re-pack whenever the library changes, and **diff before you install**: `tar -tzf`
|
|
57
|
+
the new tarball against the old one, so a file that stopped shipping is caught
|
|
58
|
+
here rather than in a consumer. Record which sui-effect commit or tag the vendor
|
|
59
|
+
copy came from — a line in your README, or the tarball's own filename — so a
|
|
60
|
+
conversion can be re-run against the same library.
|
|
61
|
+
|
|
62
|
+
## Copying it out
|
|
63
|
+
|
|
64
|
+
1. Copy the directory somewhere of your own and rename it in `package.json`
|
|
65
|
+
(`name`, `description`, and the `escrow` property name in `src/extension.ts`).
|
|
66
|
+
2. Delete the `baseUrl` and `paths` blocks from `tsconfig.json` **and
|
|
67
|
+
`tsconfig.build.json`**, and install the dependencies:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
bun add -d @unconfirmed/sui-effect effect@4.0.0-rc.112 @mysten/sui@2.30.0 @mysten/bcs \
|
|
71
|
+
@effect/language-service @types/bun typescript
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Note the `-d`. `@unconfirmed/sui-effect`, `effect` and `@mysten/sui` belong in
|
|
75
|
+
**`peerDependencies` and `devDependencies`**, never in `dependencies` — a
|
|
76
|
+
library that depends on any of them directly puts a second copy in the
|
|
77
|
+
consumer's process, and two copies of `effect` means two `Context.Service`
|
|
78
|
+
identities and layers that silently do not match. The `peerDependencies`
|
|
79
|
+
block this template ships already says so; `devDependencies` is what pins
|
|
80
|
+
the exact versions you build and test against.
|
|
81
|
+
|
|
82
|
+
`effect` is pinned **exactly** (`4.0.0-rc.112`), not to a range: rc.113
|
|
83
|
+
renamed `Config.nonEmptyString`, `Config.string` and `Config.redacted` to
|
|
84
|
+
`Config.NonEmptyString`, `Config.String` and `Config.Redacted`, so the
|
|
85
|
+
neighbouring rcs are not interchangeable. Match whatever `@unconfirmed/sui-effect`'s own
|
|
86
|
+
`peerDependencies` pins.
|
|
87
|
+
|
|
88
|
+
**Until `@unconfirmed/sui-effect` is published**, bun probes the registry for every
|
|
89
|
+
`peerDependencies` entry — even one a local dependency already satisfies —
|
|
90
|
+
and a 404 fails the install. That is what the
|
|
91
|
+
`peerDependenciesMeta["@unconfirmed/sui-effect"].optional: true` block in `package.json` is
|
|
92
|
+
for. Delete that block on the swap to the published package, and make it a
|
|
93
|
+
line on your release checklist: left in, it turns a genuinely missing peer
|
|
94
|
+
into a silent `undefined` at import time.
|
|
95
|
+
3. Rename the service and its identifier. `"example-extension/Escrow"` is a
|
|
96
|
+
runtime key: pick `"<your-package>/<Name>"` once and never change it after
|
|
97
|
+
publishing.
|
|
98
|
+
4. Replace `ESCROW_PACKAGE`, the BCS layouts and the Move call targets with
|
|
99
|
+
yours, and delete `src/upstream.ts` unless you really are wrapping a
|
|
100
|
+
third-party Promise package. Note that every type-shaped value —
|
|
101
|
+
`EscrowContent`, `escrowType`, `receiptType`, `SettlementContent` — is a
|
|
102
|
+
**function of the package id**, because a Move type name contains one:
|
|
103
|
+
configuring a different package has to move the codecs with it. Keep that
|
|
104
|
+
shape.
|
|
105
|
+
5. Keep the shape: reads through `Sui`, writes through `Tx`, contributions as
|
|
106
|
+
recipe fragments, signers as parameters, every error a `Schema.TaggedError`
|
|
107
|
+
with an `outcome`, and the Promise face derived from the service.
|
|
108
|
+
|
|
109
|
+
## Building and publishing
|
|
110
|
+
|
|
111
|
+
`exports` points into `dist`, so the package has to be built before it is
|
|
112
|
+
published or consumed:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
bun run build # tsc -p tsconfig.build.json, emitting dist/ with declarations
|
|
116
|
+
bun run check # typecheck, tests, and the packed-tarball check below
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`bun run check:package` is the step that matters and the one most templates
|
|
120
|
+
lack: it builds, packs the tarball with `bun pm pack`, unpacks it into a
|
|
121
|
+
throwaway `node_modules`, and imports the package the way a consumer will.
|
|
122
|
+
`tsc --noEmit` and `bun test` both import `src/`, so both pass for a package
|
|
123
|
+
whose `dist` is never built and whose `files` list therefore ships nothing —
|
|
124
|
+
which is exactly the state this template was in before. Keep the script.
|
|
125
|
+
|
|
126
|
+
**It works after you copy the template out.** `check-package.ts` resolves
|
|
127
|
+
`@unconfirmed/sui-effect`, `effect` and `@mysten/*` from this package's own `node_modules`
|
|
128
|
+
first, which is what a copied-out package has after `bun install`, and only
|
|
129
|
+
falls back to the sui-effect repository two directories up when that repository
|
|
130
|
+
is really there (it checks the `name` in its `package.json`). Whichever copy of
|
|
131
|
+
`@unconfirmed/sui-effect` it finds has to be **built**, because the consumer imports its
|
|
132
|
+
`exports` map; a published tarball always is.
|
|
133
|
+
|
|
134
|
+
To publish:
|
|
135
|
+
|
|
136
|
+
1. Set `name`, `version` and, for a scoped package, `publishConfig.access`.
|
|
137
|
+
The template is `0.0.0` and deliberately **not** `private`: a package meant
|
|
138
|
+
to be copied and published must not carry a flag that silently refuses to.
|
|
139
|
+
2. `bun run check`.
|
|
140
|
+
3. `npm publish` (or `bun publish`). The `files` list ships `dist` and the
|
|
141
|
+
README and nothing else — no sources, no tests, no tsconfig.
|
|
142
|
+
|
|
143
|
+
## Registering it on a client
|
|
144
|
+
|
|
145
|
+
`src/extension.ts` and `src/Platform.ts` both register `warm` and both thread
|
|
146
|
+
an `options.chainId` through. That is deliberate and it is the rule:
|
|
147
|
+
|
|
148
|
+
- **Every registration on one client gets the same chain id.** The base `Sui`,
|
|
149
|
+
its transport and its **sender-lock map** are shared per client per effective
|
|
150
|
+
chain id. Two registrations that disagree — or one `warm` on a pinned id and
|
|
151
|
+
one lazy with none — get two of everything, and two `Tx.run`s for one address
|
|
152
|
+
stop serializing.
|
|
153
|
+
- **`warm` needs a chain id it can take.** It builds the runtime inside
|
|
154
|
+
`register`, synchronously, so it never asks the node. `mainnet` and `testnet`
|
|
155
|
+
are in the built-in table; `devnet`, `localnet` and any custom network are
|
|
156
|
+
not, and `register` throws without `options.chainId`. `test/escrow.test.ts`
|
|
157
|
+
has that case.
|
|
158
|
+
- **`warm` is what makes synchronous members real.** A recipe builder, a
|
|
159
|
+
package id or a codec read off a lazy registration before its first `await`
|
|
160
|
+
throws `ExtensionNotReady`.
|
|
161
|
+
|
|
162
|
+
## The review checklist
|
|
163
|
+
|
|
164
|
+
The guide's checklist, in short. Reject an extension that has a `Promise` in an
|
|
165
|
+
interface, calls `executeTransaction` directly, holds a consumer signer in a
|
|
166
|
+
layer, has `unknown` in an error channel, maintains a Promise facade by hand,
|
|
167
|
+
or builds its own client instead of requiring `Sui`. Also reject one that
|
|
168
|
+
declares `@unconfirmed/sui-effect` in `dependencies`, hand-builds a `TransportError` instead
|
|
169
|
+
of `TransportError.fromUnknown`, or registers two extensions on one client with
|
|
170
|
+
different chain ids.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@your-org/example-extension",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "A copyable sui-effect extension package: one service, three layers, a derived Promise face.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.build.json",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"test": "bun test",
|
|
22
|
+
"check:package": "bun scripts/check-package.ts",
|
|
23
|
+
"check": "tsc --noEmit && bun test && bun scripts/check-package.ts"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@mysten/bcs": "^2.1.1",
|
|
27
|
+
"@mysten/sui": "^2.28",
|
|
28
|
+
"effect": "4.0.0-rc.112",
|
|
29
|
+
"@unconfirmed/sui-effect": "^0.1.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"@unconfirmed/sui-effect": {
|
|
33
|
+
"optional": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@effect/language-service": "0.87.2",
|
|
38
|
+
"@mysten/bcs": "2.1.1",
|
|
39
|
+
"@mysten/sui": "2.30.0",
|
|
40
|
+
"@types/bun": "1.4.2",
|
|
41
|
+
"effect": "4.0.0-rc.112",
|
|
42
|
+
"typescript": "5.9.3"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The check the template's own tests cannot do: build the package, pack the
|
|
3
|
+
* tarball, install it into a throwaway consumer, and import it.
|
|
4
|
+
*
|
|
5
|
+
* `tsc --noEmit` and `bun test` both import `src/`, so both pass for a package
|
|
6
|
+
* whose `exports` point at a `dist/` that is never built and whose `files` list
|
|
7
|
+
* therefore ships nothing. That is exactly the state this template was in. The
|
|
8
|
+
* only way to catch it is to look at what `npm pack` produces and to load it
|
|
9
|
+
* the way a consumer will.
|
|
10
|
+
*
|
|
11
|
+
* It runs offline, and it works **after you copy the template out**: the
|
|
12
|
+
* consumer's `@unconfirmed/sui-effect`, `effect` and `@mysten/*` are symlinked out of this
|
|
13
|
+
* package's own `node_modules` when it has them, which is what a copied-out
|
|
14
|
+
* package has after `bun install`. Only when neither is there does it fall back
|
|
15
|
+
* to the sui-effect repository two directories up, which is how it runs inside
|
|
16
|
+
* that repository with no install of its own. Keep the script when you copy;
|
|
17
|
+
* you should not have to rewrite it.
|
|
18
|
+
*/
|
|
19
|
+
import { $ } from "bun"
|
|
20
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
21
|
+
import { mkdir, mkdtemp, readdir, rm, symlink, writeFile } from "node:fs/promises"
|
|
22
|
+
import { tmpdir } from "node:os"
|
|
23
|
+
import { join, resolve } from "node:path"
|
|
24
|
+
|
|
25
|
+
const template = resolve(import.meta.dir, "..")
|
|
26
|
+
const templateModules = join(template, "node_modules")
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The sui-effect checkout this template lives inside, or `undefined` when it
|
|
30
|
+
* has been copied out.
|
|
31
|
+
*
|
|
32
|
+
* Two directories up is only the library when it really is: a copied-out
|
|
33
|
+
* template's grandparent is somebody's `projects/` directory, and symlinking
|
|
34
|
+
* that in as `@unconfirmed/sui-effect` is how a copier's first `bun run check` failed with a
|
|
35
|
+
* message about a `dist` that was never going to exist.
|
|
36
|
+
*/
|
|
37
|
+
const repoOf = (): string | undefined => {
|
|
38
|
+
const candidate = resolve(template, "..", "..")
|
|
39
|
+
const manifest = join(candidate, "package.json")
|
|
40
|
+
if (!existsSync(manifest)) return undefined
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(readFileSync(manifest, "utf8")).name === "@unconfirmed/sui-effect" ? candidate : undefined
|
|
43
|
+
} catch {
|
|
44
|
+
return undefined
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const repo = repoOf()
|
|
49
|
+
|
|
50
|
+
const fail = (message: string): never => {
|
|
51
|
+
console.error(`check-package: ${message}`)
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Where the consumer's copy of one package comes from: this template's own
|
|
57
|
+
* `node_modules` first, the sui-effect repository's second.
|
|
58
|
+
*/
|
|
59
|
+
const sourceOf = (name: string): string | undefined => {
|
|
60
|
+
const own = join(templateModules, name)
|
|
61
|
+
if (existsSync(own)) return own
|
|
62
|
+
if (repo === undefined) return undefined
|
|
63
|
+
const inRepo = name === "@unconfirmed/sui-effect" ? repo : join(repo, "node_modules", name)
|
|
64
|
+
return existsSync(inRepo) ? inRepo : undefined
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const suiEffect = sourceOf("@unconfirmed/sui-effect")
|
|
68
|
+
if (suiEffect === undefined) {
|
|
69
|
+
fail(
|
|
70
|
+
"no @unconfirmed/sui-effect to check against: run `bun install` in this package, or run the script " +
|
|
71
|
+
"from inside the sui-effect repository"
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
// Whichever copy it is, the consumer imports its `exports` map, so it must be
|
|
75
|
+
// built. A published tarball always is; a repository checkout may not be.
|
|
76
|
+
if (!existsSync(join(suiEffect!, "dist", "index.js"))) {
|
|
77
|
+
fail(
|
|
78
|
+
`the @unconfirmed/sui-effect at ${suiEffect} is not built; run \`bun run build\` there first`
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await rm(join(template, "dist"), { recursive: true, force: true })
|
|
83
|
+
await $`bun x tsc -p ${join(template, "tsconfig.build.json")}`.cwd(template).quiet()
|
|
84
|
+
|
|
85
|
+
const work = await mkdtemp(join(tmpdir(), "sui-effect-template-"))
|
|
86
|
+
try {
|
|
87
|
+
await $`bun pm pack --destination ${work}`.cwd(template).quiet()
|
|
88
|
+
const packed = (await readdir(work)).filter((name) => name.endsWith(".tgz"))
|
|
89
|
+
const tarball = packed[0]
|
|
90
|
+
if (tarball === undefined) fail("bun pm pack produced no tarball")
|
|
91
|
+
|
|
92
|
+
// Extracted straight into the consumer's `node_modules`, where a real
|
|
93
|
+
// install would put it: a package resolves its own dependencies from where it
|
|
94
|
+
// lives, so unpacking it elsewhere and linking it in would fail on `effect`
|
|
95
|
+
// for reasons that have nothing to do with the package.
|
|
96
|
+
const consumer = join(work, "consumer")
|
|
97
|
+
const modules = join(consumer, "node_modules")
|
|
98
|
+
const name = JSON.parse(readFileSync(join(template, "package.json"), "utf8")).name as string
|
|
99
|
+
const [scope, bare] = name.startsWith("@") ? name.split("/") : [undefined, name]
|
|
100
|
+
const installed = join(modules, ...(scope === undefined ? [bare!] : [scope, bare!]))
|
|
101
|
+
await mkdir(scope === undefined ? modules : join(modules, scope), { recursive: true })
|
|
102
|
+
const extracted = join(work, "extracted")
|
|
103
|
+
await mkdir(extracted, { recursive: true })
|
|
104
|
+
await $`tar -xzf ${join(work, tarball!)} -C ${extracted}`.quiet()
|
|
105
|
+
await $`mv ${join(extracted, "package")} ${installed}`.quiet()
|
|
106
|
+
|
|
107
|
+
// What a consumer actually gets: the files the `files` list shipped, at the
|
|
108
|
+
// paths the `exports` map names.
|
|
109
|
+
for (const required of ["dist/index.js", "dist/index.d.ts", "package.json", "README.md"]) {
|
|
110
|
+
if (!existsSync(join(installed, required))) {
|
|
111
|
+
fail(`the packed tarball has no ${required}; check "files" and the build script`)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const suiEffectScope = join(modules, "@unconfirmed")
|
|
116
|
+
await mkdir(suiEffectScope, { recursive: true })
|
|
117
|
+
await symlink(suiEffect!, join(suiEffectScope, "sui-effect"), "dir")
|
|
118
|
+
for (const peer of ["effect", "@mysten"]) {
|
|
119
|
+
const source = sourceOf(peer)
|
|
120
|
+
if (source === undefined) {
|
|
121
|
+
fail(`no ${peer} to link into the consumer: run \`bun install\` in this package first`)
|
|
122
|
+
}
|
|
123
|
+
await symlink(source!, join(modules, peer), "dir")
|
|
124
|
+
}
|
|
125
|
+
await writeFile(
|
|
126
|
+
join(consumer, "package.json"),
|
|
127
|
+
JSON.stringify({ name: "consumer", private: true, type: "module" }, null, 2)
|
|
128
|
+
)
|
|
129
|
+
await writeFile(
|
|
130
|
+
join(consumer, "consume.ts"),
|
|
131
|
+
[
|
|
132
|
+
`import { Escrow, escrow, receiptType } from "${name}"`,
|
|
133
|
+
`if (typeof Escrow.layerTest !== "function") throw new Error("Escrow.layerTest is missing")`,
|
|
134
|
+
`if (typeof escrow !== "function") throw new Error("the registration factory is missing")`,
|
|
135
|
+
`if (!receiptType("0x2").endsWith("::escrow::Receipt")) throw new Error("receiptType is wrong")`,
|
|
136
|
+
`console.log("ok")`,
|
|
137
|
+
""
|
|
138
|
+
].join("\n")
|
|
139
|
+
)
|
|
140
|
+
const ran = await $`bun run ${join(consumer, "consume.ts")}`.cwd(consumer).quiet().nothrow()
|
|
141
|
+
if (ran.exitCode !== 0) {
|
|
142
|
+
fail(`the packed package did not import in a consumer:\n${ran.stderr.toString()}`)
|
|
143
|
+
}
|
|
144
|
+
console.log("check-package: the packed tarball imports in a fresh consumer")
|
|
145
|
+
} finally {
|
|
146
|
+
await rm(work, { recursive: true, force: true })
|
|
147
|
+
}
|