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.
Files changed (115) hide show
  1. package/AGENTS.md +209 -0
  2. package/LICENSE +21 -0
  3. package/LLMS.md +6707 -0
  4. package/README.md +300 -0
  5. package/dist/domain/bcs.d.ts +101 -0
  6. package/dist/domain/bcs.d.ts.map +1 -0
  7. package/dist/domain/bcs.js +183 -0
  8. package/dist/domain/bcs.js.map +1 -0
  9. package/dist/domain/errors.d.ts +595 -0
  10. package/dist/domain/errors.d.ts.map +1 -0
  11. package/dist/domain/errors.js +476 -0
  12. package/dist/domain/errors.js.map +1 -0
  13. package/dist/domain/executed.d.ts +325 -0
  14. package/dist/domain/executed.d.ts.map +1 -0
  15. package/dist/domain/executed.js +253 -0
  16. package/dist/domain/executed.js.map +1 -0
  17. package/dist/domain/journal-entry.d.ts +468 -0
  18. package/dist/domain/journal-entry.d.ts.map +1 -0
  19. package/dist/domain/journal-entry.js +63 -0
  20. package/dist/domain/journal-entry.js.map +1 -0
  21. package/dist/domain/schemas.d.ts +950 -0
  22. package/dist/domain/schemas.d.ts.map +1 -0
  23. package/dist/domain/schemas.js +571 -0
  24. package/dist/domain/schemas.js.map +1 -0
  25. package/dist/domain/sui-schema.d.ts +12 -0
  26. package/dist/domain/sui-schema.d.ts.map +1 -0
  27. package/dist/domain/sui-schema.js +12 -0
  28. package/dist/domain/sui-schema.js.map +1 -0
  29. package/dist/extension.d.ts +7 -0
  30. package/dist/extension.d.ts.map +1 -0
  31. package/dist/extension.js +7 -0
  32. package/dist/extension.js.map +1 -0
  33. package/dist/index.d.ts +31 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +31 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/internal.d.ts +18 -0
  38. package/dist/internal.d.ts.map +1 -0
  39. package/dist/internal.js +18 -0
  40. package/dist/internal.js.map +1 -0
  41. package/dist/journal.d.ts +51 -0
  42. package/dist/journal.d.ts.map +1 -0
  43. package/dist/journal.js +18 -0
  44. package/dist/journal.js.map +1 -0
  45. package/dist/script.d.ts +7 -0
  46. package/dist/script.d.ts.map +1 -0
  47. package/dist/script.js +7 -0
  48. package/dist/script.js.map +1 -0
  49. package/dist/services/Journal.d.ts +76 -0
  50. package/dist/services/Journal.d.ts.map +1 -0
  51. package/dist/services/Journal.js +70 -0
  52. package/dist/services/Journal.js.map +1 -0
  53. package/dist/services/JournalKeyValueStore.d.ts +73 -0
  54. package/dist/services/JournalKeyValueStore.d.ts.map +1 -0
  55. package/dist/services/JournalKeyValueStore.js +155 -0
  56. package/dist/services/JournalKeyValueStore.js.map +1 -0
  57. package/dist/services/Script.d.ts +210 -0
  58. package/dist/services/Script.d.ts.map +1 -0
  59. package/dist/services/Script.js +441 -0
  60. package/dist/services/Script.js.map +1 -0
  61. package/dist/services/Signer.d.ts +132 -0
  62. package/dist/services/Signer.d.ts.map +1 -0
  63. package/dist/services/Signer.js +158 -0
  64. package/dist/services/Signer.js.map +1 -0
  65. package/dist/services/SubmitConfig.d.ts +175 -0
  66. package/dist/services/SubmitConfig.d.ts.map +1 -0
  67. package/dist/services/SubmitConfig.js +52 -0
  68. package/dist/services/SubmitConfig.js.map +1 -0
  69. package/dist/services/Sui.d.ts +295 -0
  70. package/dist/services/Sui.d.ts.map +1 -0
  71. package/dist/services/Sui.js +414 -0
  72. package/dist/services/Sui.js.map +1 -0
  73. package/dist/services/SuiCore.d.ts +227 -0
  74. package/dist/services/SuiCore.d.ts.map +1 -0
  75. package/dist/services/SuiCore.js +400 -0
  76. package/dist/services/SuiCore.js.map +1 -0
  77. package/dist/services/SuiCoreFake.d.ts +278 -0
  78. package/dist/services/SuiCoreFake.d.ts.map +1 -0
  79. package/dist/services/SuiCoreFake.js +1003 -0
  80. package/dist/services/SuiCoreFake.js.map +1 -0
  81. package/dist/services/SuiExtension.d.ts +208 -0
  82. package/dist/services/SuiExtension.d.ts.map +1 -0
  83. package/dist/services/SuiExtension.js +355 -0
  84. package/dist/services/SuiExtension.js.map +1 -0
  85. package/dist/services/SuiGraphQL.d.ts +98 -0
  86. package/dist/services/SuiGraphQL.d.ts.map +1 -0
  87. package/dist/services/SuiGraphQL.js +118 -0
  88. package/dist/services/SuiGraphQL.js.map +1 -0
  89. package/dist/services/Tx.d.ts +687 -0
  90. package/dist/services/Tx.d.ts.map +1 -0
  91. package/dist/services/Tx.js +1224 -0
  92. package/dist/services/Tx.js.map +1 -0
  93. package/dist/testing.d.ts +88 -0
  94. package/dist/testing.d.ts.map +1 -0
  95. package/dist/testing.js +163 -0
  96. package/dist/testing.js.map +1 -0
  97. package/dist/tx.d.ts +24 -0
  98. package/dist/tx.d.ts.map +1 -0
  99. package/dist/tx.js +24 -0
  100. package/dist/tx.js.map +1 -0
  101. package/docs/extensions.md +1685 -0
  102. package/examples/extension-template/README.md +170 -0
  103. package/examples/extension-template/package.json +44 -0
  104. package/examples/extension-template/scripts/check-package.ts +145 -0
  105. package/examples/extension-template/src/Escrow.ts +445 -0
  106. package/examples/extension-template/src/Platform.ts +136 -0
  107. package/examples/extension-template/src/errors.ts +61 -0
  108. package/examples/extension-template/src/extension.ts +63 -0
  109. package/examples/extension-template/src/index.ts +34 -0
  110. package/examples/extension-template/src/schema.ts +158 -0
  111. package/examples/extension-template/src/upstream.ts +66 -0
  112. package/examples/extension-template/test/escrow.test.ts +559 -0
  113. package/examples/extension-template/tsconfig.build.json +26 -0
  114. package/examples/extension-template/tsconfig.json +35 -0
  115. 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 `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 `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/sui-effect-*.tgz vendor/
45
+ bun add -d ./vendor/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 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`. `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 `sui-effect`'s own
86
+ `peerDependencies` pins.
87
+
88
+ **Until `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.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
+ `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
+ `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 `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
+ "sui-effect": "^0.1.0"
30
+ },
31
+ "peerDependenciesMeta": {
32
+ "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,145 @@
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 `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 `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 === "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 === "sui-effect" ? repo : join(repo, "node_modules", name)
64
+ return existsSync(inRepo) ? inRepo : undefined
65
+ }
66
+
67
+ const suiEffect = sourceOf("sui-effect")
68
+ if (suiEffect === undefined) {
69
+ fail(
70
+ "no 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 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
+ await symlink(suiEffect!, join(modules, "sui-effect"), "dir")
116
+ for (const peer of ["effect", "@mysten"]) {
117
+ const source = sourceOf(peer)
118
+ if (source === undefined) {
119
+ fail(`no ${peer} to link into the consumer: run \`bun install\` in this package first`)
120
+ }
121
+ await symlink(source!, join(modules, peer), "dir")
122
+ }
123
+ await writeFile(
124
+ join(consumer, "package.json"),
125
+ JSON.stringify({ name: "consumer", private: true, type: "module" }, null, 2)
126
+ )
127
+ await writeFile(
128
+ join(consumer, "consume.ts"),
129
+ [
130
+ `import { Escrow, escrow, receiptType } from "${name}"`,
131
+ `if (typeof Escrow.layerTest !== "function") throw new Error("Escrow.layerTest is missing")`,
132
+ `if (typeof escrow !== "function") throw new Error("the registration factory is missing")`,
133
+ `if (!receiptType("0x2").endsWith("::escrow::Receipt")) throw new Error("receiptType is wrong")`,
134
+ `console.log("ok")`,
135
+ ""
136
+ ].join("\n")
137
+ )
138
+ const ran = await $`bun run ${join(consumer, "consume.ts")}`.cwd(consumer).quiet().nothrow()
139
+ if (ran.exitCode !== 0) {
140
+ fail(`the packed package did not import in a consumer:\n${ran.stderr.toString()}`)
141
+ }
142
+ console.log("check-package: the packed tarball imports in a fresh consumer")
143
+ } finally {
144
+ await rm(work, { recursive: true, force: true })
145
+ }