@farmslot/adapter-node 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/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/dependencies.d.ts +35 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +104 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/node-adapter.d.ts +63 -0
- package/dist/node-adapter.d.ts.map +1 -0
- package/dist/node-adapter.js +125 -0
- package/dist/node-adapter.js.map +1 -0
- package/dist/workspace-tsconfig.d.ts +36 -0
- package/dist/workspace-tsconfig.d.ts.map +1 -0
- package/dist/workspace-tsconfig.js +80 -0
- package/dist/workspace-tsconfig.js.map +1 -0
- package/package.json +69 -0
- package/scripts/cleanup.sh +53 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@farmslot/adapter-node` are tracked here.
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
- Active-development baseline; add user-facing changes here before release or package publication.
|
|
8
|
+
|
|
9
|
+
## 0.1.0 - 2026-10-06
|
|
10
|
+
|
|
11
|
+
- Add the headless Node platform adapter, moved from the metamask-harness `core` adapter. `createNodeAdapter(config)` builds a `PlatformAdapter` with no ports, dev server, logs or launch; the host supplies the id, detection, hints, wording, action set and overlay leaves. `nodeDependencyBlock` checks a Yarn PnP or node_modules install, the bins the actions run (found through the host's `resolveBin`, so readiness asks what execution asks; no bin is required by default) and runtime dependencies, and `runtimeStatus` applies the same check, so doctor reports a checkout whose actions cannot run; `workspaceTsconfigEnv` points tsx at each workspace package's `src`, built or not, so a stale `dist` never runs, and `checkoutWorkspacePackages` takes the package list from the checkout's `workspaces`; `scripts/cleanup.sh --adapter <id>` removes the adapter's overlay.
|
|
12
|
+
- Publish with adapter-sdk 0.5.0 and recipe-runner 0.25.0.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arthur Breton
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @farmslot/adapter-node
|
|
2
|
+
|
|
3
|
+
A headless Node platform adapter for recipe harnesses, built on `@farmslot/adapter-sdk`. It has
|
|
4
|
+
no app, ports, dev server, logs or launch: installed dependencies are its only runtime signal.
|
|
5
|
+
The host supplies the adapter id, detection, hints and wording, its action set and overlay
|
|
6
|
+
leaves; product checks stay in the host.
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { checkoutWorkspacePackages, createNodeAdapter } from '@farmslot/adapter-node';
|
|
10
|
+
|
|
11
|
+
export const core = createNodeAdapter({
|
|
12
|
+
id: 'core',
|
|
13
|
+
detect: { files: (target) => hasFile(target, 'packages/my-controller') },
|
|
14
|
+
hints: {
|
|
15
|
+
launch: 'my-harness run <recipe>',
|
|
16
|
+
relaunch: 'my-harness verify',
|
|
17
|
+
runtimeProbeRecovery: (target) => `my-harness verify --target ${target}`,
|
|
18
|
+
},
|
|
19
|
+
wording: { ready: 'Core is headless; dependencies are installed.' },
|
|
20
|
+
dependencies: { runtimeDeps: ['immer'], requiredFor: (_target, use) => usesController(use) },
|
|
21
|
+
workspacePackages: checkoutWorkspacePackages, // or a fixed map: { '@acme/messenger': 'packages/messenger' }
|
|
22
|
+
actions,
|
|
23
|
+
harness,
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A host adds its own members by spreading the result: `{ ...createNodeAdapter(config), readiness }`.
|
|
28
|
+
|
|
29
|
+
`runtimeStatus` reads the install through recipe-runner's `depsCheck`, which tracks Yarn's install
|
|
30
|
+
state, so it reports `deps-missing` for an npm or pnpm checkout even after `installCommand` ran.
|
|
31
|
+
Such a host overrides `runtimeStatus` with its own check: `{ ...createNodeAdapter(config), runtimeStatus }`.
|
|
32
|
+
|
|
33
|
+
Docs: https://farmslot.io/docs/reference/adapter-node
|
|
34
|
+
|
|
35
|
+
## Source layout
|
|
36
|
+
|
|
37
|
+
| path | owns |
|
|
38
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
39
|
+
| `src/node-adapter.ts` | `createNodeAdapter`, its config and wording types, `HEADLESS_FORBIDDEN_FIELDS` |
|
|
40
|
+
| `src/dependencies.ts` | `nodeDependencyBlock` (Yarn PnP, node_modules, bins via `resolveBin`, runtime deps), `pnpNodeOptions` |
|
|
41
|
+
| `src/workspace-tsconfig.ts` | `checkoutWorkspacePackages`, `workspaceTsconfig`/`workspaceTsconfigEnv`: tsx paths to each workspace package's `src` |
|
|
42
|
+
| `scripts/cleanup.sh` | `cleanup.sh --adapter <id> [--target <dir>]`: removes the adapter's overlay directory |
|
|
43
|
+
|
|
44
|
+
`scripts/cleanup.sh` is exported by path (`@farmslot/adapter-node/scripts/cleanup.sh`, also
|
|
45
|
+
`NODE_CLEANUP_SCRIPT`). It honours `RECIPE_HARNESS_ROOT` (default `temp/recipe/harness`) and
|
|
46
|
+
refuses an absolute value or one with `.`/`..` components.
|
|
47
|
+
|
|
48
|
+
## Maintenance rules
|
|
49
|
+
|
|
50
|
+
- No product names. Every line the adapter prints can be replaced through `wording` or `hints`.
|
|
51
|
+
- Dependency codes and messages derive from the adapter id (`<ID>_DEPS_MISSING`), so a host keeps
|
|
52
|
+
its codes by keeping its id.
|
|
53
|
+
- Recipe actions, readiness checks and install scripts stay in the host.
|
|
54
|
+
|
|
55
|
+
## Local quality
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
yarn workspace @farmslot/adapter-node quality
|
|
59
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AdapterDependencyBlock } from '@farmslot/adapter-sdk';
|
|
2
|
+
/** Options for {@link nodeDependencyBlock}. */
|
|
3
|
+
export interface NodeDependencyOptions {
|
|
4
|
+
/** Packages the checkout must resolve at runtime. Default: none. */
|
|
5
|
+
runtimeDeps?: readonly string[];
|
|
6
|
+
/** Executables the actions run (e.g. `tsx`). Default: none. */
|
|
7
|
+
bins?: readonly string[];
|
|
8
|
+
/**
|
|
9
|
+
* Finds `bin` for the checkout, or returns null. Pass the resolver execution
|
|
10
|
+
* uses, so the check and the run agree. Default: `<target>/node_modules/.bin/<bin>`.
|
|
11
|
+
*/
|
|
12
|
+
resolveBin?(target: string, bin: string): string | null;
|
|
13
|
+
/** Names the checkout in messages ("<label> dependencies are …"). Default: `node`. */
|
|
14
|
+
label?: string;
|
|
15
|
+
/** Code prefix: `<prefix>_DEPS_MISSING`, `<prefix>_DEPS_INCOMPLETE`. Default: the label, upper-cased. */
|
|
16
|
+
codePrefix?: string;
|
|
17
|
+
/** The block's next step. Default: {@link yarnInstallCommand}. */
|
|
18
|
+
installCommand?(target: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* The next step when `bin` cannot be found. Default: the install command. A host
|
|
21
|
+
* whose `resolveBin` looks outside the checkout says how to provide the bin.
|
|
22
|
+
*/
|
|
23
|
+
missingBinAction?(target: string, bin: string): string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Why the checkout at `target` cannot run yet, or null when it can. Under Yarn PnP
|
|
27
|
+
* the install marker `.pnp.cjs` is the whole check; otherwise node_modules, each
|
|
28
|
+
* bin, then each runtime dependency.
|
|
29
|
+
*/
|
|
30
|
+
export declare function nodeDependencyBlock(target: string, options?: NodeDependencyOptions): AdapterDependencyBlock | null;
|
|
31
|
+
/** `current` plus `--require <target>/.pnp.cjs` when the checkout is a Yarn PnP install. */
|
|
32
|
+
export declare function pnpNodeOptions(target: string, current: string | undefined): string | undefined;
|
|
33
|
+
/** `cd '<target>' && yarn install --immutable`. */
|
|
34
|
+
export declare function yarnInstallCommand(target: string): string;
|
|
35
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../src/dependencies.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAIpE,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACxD,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yGAAyG;IACzG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxC;;;OAGG;IACH,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACxD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,sBAAsB,GAAG,IAAI,CAmD/B;AAED,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM9F;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// The headless dependency check: a Node checkout can run recipes once Yarn
|
|
2
|
+
// installed it (PnP or node_modules), the tools its actions run are found, and the
|
|
3
|
+
// packages its live scripts import resolve from the checkout.
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
const requireFromPackage = createRequire(import.meta.url);
|
|
8
|
+
/**
|
|
9
|
+
* Why the checkout at `target` cannot run yet, or null when it can. Under Yarn PnP
|
|
10
|
+
* the install marker `.pnp.cjs` is the whole check; otherwise node_modules, each
|
|
11
|
+
* bin, then each runtime dependency.
|
|
12
|
+
*/
|
|
13
|
+
export function nodeDependencyBlock(target, options = {}) {
|
|
14
|
+
const resolved = path.resolve(target);
|
|
15
|
+
const label = options.label ?? 'node';
|
|
16
|
+
const prefix = options.codePrefix ?? label.toUpperCase().replace(/[^A-Z0-9]+/gu, '_');
|
|
17
|
+
const missing = `${prefix}_DEPS_MISSING`;
|
|
18
|
+
const incomplete = `${prefix}_DEPS_INCOMPLETE`;
|
|
19
|
+
const userAction = (options.installCommand ?? yarnInstallCommand)(resolved);
|
|
20
|
+
const nodeLinker = readYarnNodeLinker(resolved);
|
|
21
|
+
if (nodeLinker === 'pnp') {
|
|
22
|
+
if (fs.existsSync(path.join(resolved, '.pnp.cjs')))
|
|
23
|
+
return null;
|
|
24
|
+
return {
|
|
25
|
+
code: missing,
|
|
26
|
+
message: `${label} dependencies are not installed for Yarn PnP (.pnp.cjs is missing).`,
|
|
27
|
+
userAction,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (!fs.existsSync(path.join(resolved, 'node_modules'))) {
|
|
31
|
+
return {
|
|
32
|
+
code: missing,
|
|
33
|
+
message: nodeLinker === 'node-modules'
|
|
34
|
+
? `${label} dependencies are not installed (nodeLinker requires node_modules, but node_modules is missing).`
|
|
35
|
+
: `${label} dependencies are not installed (node_modules is missing).`,
|
|
36
|
+
userAction,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
for (const bin of options.bins ?? []) {
|
|
40
|
+
if (options.resolveBin ? options.resolveBin(resolved, bin) : localBin(resolved, bin))
|
|
41
|
+
continue;
|
|
42
|
+
return {
|
|
43
|
+
code: incomplete,
|
|
44
|
+
message: options.resolveBin
|
|
45
|
+
? `${label} dependencies are incomplete (no ${bin} runtime found for the checkout).`
|
|
46
|
+
: `${label} dependencies are incomplete (node_modules/.bin/${bin} is missing).`,
|
|
47
|
+
userAction: options.missingBinAction ? options.missingBinAction(resolved, bin) : userAction,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
for (const dependency of options.runtimeDeps ?? []) {
|
|
51
|
+
if (!canResolveFromTarget(dependency, resolved)) {
|
|
52
|
+
return {
|
|
53
|
+
code: incomplete,
|
|
54
|
+
message: `${label} dependencies are incomplete (cannot resolve ${dependency} from the target checkout).`,
|
|
55
|
+
userAction,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
/** `current` plus `--require <target>/.pnp.cjs` when the checkout is a Yarn PnP install. */
|
|
62
|
+
export function pnpNodeOptions(target, current) {
|
|
63
|
+
if (readYarnNodeLinker(target) !== 'pnp')
|
|
64
|
+
return current;
|
|
65
|
+
const pnp = path.join(path.resolve(target), '.pnp.cjs');
|
|
66
|
+
if (!fs.existsSync(pnp))
|
|
67
|
+
return current;
|
|
68
|
+
const pnpOption = `--require ${pnp}`;
|
|
69
|
+
return current ? `${current} ${pnpOption}` : pnpOption;
|
|
70
|
+
}
|
|
71
|
+
/** `cd '<target>' && yarn install --immutable`. */
|
|
72
|
+
export function yarnInstallCommand(target) {
|
|
73
|
+
return `cd ${shellQuote(path.resolve(target))} && yarn install --immutable`;
|
|
74
|
+
}
|
|
75
|
+
function canResolveFromTarget(specifier, target) {
|
|
76
|
+
try {
|
|
77
|
+
requireFromPackage.resolve(specifier, { paths: [target] });
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const code = error.code;
|
|
82
|
+
// Not found from the checkout is the answer this check asks for.
|
|
83
|
+
if (code === 'MODULE_NOT_FOUND')
|
|
84
|
+
return false;
|
|
85
|
+
// Installed, but its exports offer no require() entry (ESM-only): present.
|
|
86
|
+
if (code === 'ERR_PACKAGE_PATH_NOT_EXPORTED')
|
|
87
|
+
return true;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function localBin(target, bin) {
|
|
92
|
+
const file = path.join(target, 'node_modules/.bin', bin);
|
|
93
|
+
return fs.existsSync(file) ? file : null;
|
|
94
|
+
}
|
|
95
|
+
function readYarnNodeLinker(target) {
|
|
96
|
+
const yarnrc = path.join(target, '.yarnrc.yml');
|
|
97
|
+
if (!fs.existsSync(yarnrc))
|
|
98
|
+
return undefined;
|
|
99
|
+
return /^nodeLinker:\s*["']?([^"'\s#]+)["']?/mu.exec(fs.readFileSync(yarnrc, 'utf8'))?.[1];
|
|
100
|
+
}
|
|
101
|
+
function shellQuote(value) {
|
|
102
|
+
return `'${value.replace(/'/gu, `'\\''`)}'`;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../src/dependencies.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { nodeDependencyBlock, type NodeDependencyOptions, pnpNodeOptions, yarnInstallCommand, } from './dependencies.js';
|
|
2
|
+
export { createNodeAdapter, HEADLESS_FORBIDDEN_FIELDS, NODE_CLEANUP_SCRIPT, type NodeAdapterConfig, type NodeAdapterDependencies, type NodeAdapterNotice, type NodeAdapterWording, type NodeDependencyUse, } from './node-adapter.js';
|
|
3
|
+
export { checkoutWorkspacePackages, type WorkspacePackageMap, type WorkspacePackages, type WorkspaceTsconfig, workspaceTsconfig, workspaceTsconfigEnv, type WorkspaceTsconfigEnvOptions, } from './workspace-tsconfig.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,2BAA2B,GACjC,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { nodeDependencyBlock, pnpNodeOptions, yarnInstallCommand, } from './dependencies.js';
|
|
2
|
+
export { createNodeAdapter, HEADLESS_FORBIDDEN_FIELDS, NODE_CLEANUP_SCRIPT, } from './node-adapter.js';
|
|
3
|
+
export { checkoutWorkspacePackages, workspaceTsconfig, workspaceTsconfigEnv, } from './workspace-tsconfig.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EAEnB,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,GAMpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,yBAAyB,EAIzB,iBAAiB,EACjB,oBAAoB,GAErB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type AdapterActions, type AdapterDetect, type AdapterHarness, type AdapterHints, type AdapterRun, type AdapterRuntimeContextSpec, type PlatformAdapter } from '@farmslot/adapter-sdk';
|
|
2
|
+
import { type WorkspacePackages } from './workspace-tsconfig.js';
|
|
3
|
+
/** Absolute path of the shipped overlay cleanup leaf (`cleanup.sh --adapter <id>`). */
|
|
4
|
+
export declare const NODE_CLEANUP_SCRIPT: string;
|
|
5
|
+
/** Runtime-context fields a headless checkout never records: it has no ports or device. */
|
|
6
|
+
export declare const HEADLESS_FORBIDDEN_FIELDS: readonly string[];
|
|
7
|
+
/** A refusal a headless platform prints instead of acting. */
|
|
8
|
+
export interface NodeAdapterNotice {
|
|
9
|
+
message: string;
|
|
10
|
+
userAction: string;
|
|
11
|
+
}
|
|
12
|
+
/** Every line the adapter prints. Defaults name the adapter id and its `hints`. */
|
|
13
|
+
export interface NodeAdapterWording {
|
|
14
|
+
/** `runtimeStatus` reason when dependencies are installed. */
|
|
15
|
+
ready: string;
|
|
16
|
+
/** `runtimeStatus` reason otherwise. */
|
|
17
|
+
notReady: string;
|
|
18
|
+
/** `devServer.stop`: there is no dev server. */
|
|
19
|
+
devServerStop: NodeAdapterNotice;
|
|
20
|
+
/** `launch`: there is nothing to launch. */
|
|
21
|
+
launch: NodeAdapterNotice;
|
|
22
|
+
}
|
|
23
|
+
/** What a run or one action is about to use, as `run.dependencyBlock` receives it. */
|
|
24
|
+
export type NodeDependencyUse = Parameters<NonNullable<AdapterRun['dependencyBlock']>>[1];
|
|
25
|
+
/** The dependency check `run` and `call` apply before they start. */
|
|
26
|
+
export interface NodeAdapterDependencies {
|
|
27
|
+
/** Packages the checkout must resolve at runtime. Default: none. */
|
|
28
|
+
runtimeDeps?: readonly string[];
|
|
29
|
+
/** Executables the actions run (e.g. `tsx`). Default: none. */
|
|
30
|
+
bins?: readonly string[];
|
|
31
|
+
/** Finds a bin for the checkout; pass the resolver execution uses. Default: `<target>/node_modules/.bin`. */
|
|
32
|
+
resolveBin?(target: string, bin: string): string | null;
|
|
33
|
+
/** Next step when a bin cannot be found. Default: the install command. */
|
|
34
|
+
missingBinAction?(target: string, bin: string): string;
|
|
35
|
+
/** Whether this run or action needs the checkout's dependencies. Default: always. */
|
|
36
|
+
requiredFor?(target: string, use: NodeDependencyUse): boolean | Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
export interface NodeAdapterConfig {
|
|
39
|
+
/** Registry key and the value of `--adapter`. */
|
|
40
|
+
id: string;
|
|
41
|
+
hints: AdapterHints;
|
|
42
|
+
actions: AdapterActions;
|
|
43
|
+
harness: AdapterHarness;
|
|
44
|
+
detect?: AdapterDetect;
|
|
45
|
+
/** Host run members. A host `dependencyBlock` replaces the built-in check. */
|
|
46
|
+
run?: AdapterRun;
|
|
47
|
+
wording?: Partial<NodeAdapterWording>;
|
|
48
|
+
dependencies?: NodeAdapterDependencies;
|
|
49
|
+
/**
|
|
50
|
+
* Workspace packages live adapter scripts import from src: a map, or
|
|
51
|
+
* `checkoutWorkspacePackages` to take every package the checkout declares.
|
|
52
|
+
* When set and `actions.tsxLiveScripts` is absent, scripts run under tsx with
|
|
53
|
+
* `workspaceTsconfigEnv` (`<id>-adapter.tsconfig.json`).
|
|
54
|
+
*/
|
|
55
|
+
workspacePackages?: WorkspacePackages;
|
|
56
|
+
/** Next step when dependencies are missing. Default: `yarnInstallCommand`. */
|
|
57
|
+
installCommand?(target: string): string;
|
|
58
|
+
/** Default: `HEADLESS_FORBIDDEN_FIELDS`. */
|
|
59
|
+
runtimeContext?: AdapterRuntimeContextSpec;
|
|
60
|
+
}
|
|
61
|
+
/** A headless `PlatformAdapter`; spread it to add host members. */
|
|
62
|
+
export declare function createNodeAdapter(config: NodeAdapterConfig): PlatformAdapter;
|
|
63
|
+
//# sourceMappingURL=node-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.d.ts","sourceRoot":"","sources":["../src/node-adapter.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,yBAAyB,EAE9B,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,yBAAyB,CAAC;AAEvF,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,QAAmE,CAAC;AAEpG,2FAA2F;AAC3F,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAStD,CAAC;AAEF,8DAA8D;AAC9D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,aAAa,EAAE,iBAAiB,CAAC;IACjC,4CAA4C;IAC5C,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1F,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,6GAA6G;IAC7G,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACxD,0EAA0E;IAC1E,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACvD,qFAAqF;IACrF,WAAW,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClF;AAED,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtC,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,8EAA8E;IAC9E,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,yBAAyB,CAAC;CAC5C;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CA+G5E"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// A headless Node platform: no app, ports, dev server, logs or launch. Installed
|
|
2
|
+
// dependencies are the only runtime signal, and lifecycle commands teach the
|
|
3
|
+
// headless path. The host supplies identity, detection, wording and its action
|
|
4
|
+
// set; product checks stay in the host.
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { defineAdapter, } from '@farmslot/adapter-sdk';
|
|
8
|
+
import { depsCheck } from '@farmslot/recipe-runner/runtime/deps-readiness';
|
|
9
|
+
import { nodeDependencyBlock, yarnInstallCommand } from './dependencies.js';
|
|
10
|
+
import { workspaceTsconfigEnv } from './workspace-tsconfig.js';
|
|
11
|
+
/** Absolute path of the shipped overlay cleanup leaf (`cleanup.sh --adapter <id>`). */
|
|
12
|
+
export const NODE_CLEANUP_SCRIPT = fileURLToPath(new URL('../scripts/cleanup.sh', import.meta.url));
|
|
13
|
+
/** Runtime-context fields a headless checkout never records: it has no ports or device. */
|
|
14
|
+
export const HEADLESS_FORBIDDEN_FIELDS = [
|
|
15
|
+
'cdpPort',
|
|
16
|
+
'watcherPort',
|
|
17
|
+
'metroPort',
|
|
18
|
+
'devServerPort',
|
|
19
|
+
'simulator',
|
|
20
|
+
'simulatorUdid',
|
|
21
|
+
'adbSerial',
|
|
22
|
+
'extensionId',
|
|
23
|
+
];
|
|
24
|
+
/** A headless `PlatformAdapter`; spread it to add host members. */
|
|
25
|
+
export function createNodeAdapter(config) {
|
|
26
|
+
const { id, hints } = config;
|
|
27
|
+
const installCommand = config.installCommand ?? yarnInstallCommand;
|
|
28
|
+
const wording = {
|
|
29
|
+
ready: `${id} is headless; dependencies are installed.`,
|
|
30
|
+
notReady: `${id} is headless; dependencies are not fully installed.`,
|
|
31
|
+
devServerStop: {
|
|
32
|
+
message: `${id} is headless; no dev server runs for a ${id} checkout`,
|
|
33
|
+
userAction: hints.relaunch,
|
|
34
|
+
},
|
|
35
|
+
launch: {
|
|
36
|
+
message: `${id} is headless; there is nothing to launch.`,
|
|
37
|
+
userAction: hints.relaunch,
|
|
38
|
+
},
|
|
39
|
+
...config.wording,
|
|
40
|
+
};
|
|
41
|
+
const dependencies = config.dependencies ?? {};
|
|
42
|
+
const dependencyBlockFor = (target) => nodeDependencyBlock(target, {
|
|
43
|
+
runtimeDeps: dependencies.runtimeDeps,
|
|
44
|
+
bins: dependencies.bins,
|
|
45
|
+
resolveBin: dependencies.resolveBin,
|
|
46
|
+
missingBinAction: dependencies.missingBinAction,
|
|
47
|
+
label: id,
|
|
48
|
+
installCommand,
|
|
49
|
+
});
|
|
50
|
+
const workspacePackages = config.workspacePackages;
|
|
51
|
+
return defineAdapter({
|
|
52
|
+
id,
|
|
53
|
+
sdkVersion: 1,
|
|
54
|
+
headless: true,
|
|
55
|
+
resolveSlotPorts() {
|
|
56
|
+
// Headless: no ports or device to resolve.
|
|
57
|
+
},
|
|
58
|
+
async runtimeStatus(target) {
|
|
59
|
+
const deps = depsCheck(path.resolve(target));
|
|
60
|
+
if (deps.status !== 'current') {
|
|
61
|
+
return {
|
|
62
|
+
decision: 'install',
|
|
63
|
+
reasonCode: `deps-${deps.status}`,
|
|
64
|
+
reasons: [wording.notReady],
|
|
65
|
+
nextAction: installCommand(target),
|
|
66
|
+
deps: deps.status,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Installed is not enough: the actions must find their runtime too, so
|
|
70
|
+
// doctor and verify report what run and call would refuse.
|
|
71
|
+
const block = dependencyBlockFor(target);
|
|
72
|
+
if (block) {
|
|
73
|
+
return {
|
|
74
|
+
decision: 'install',
|
|
75
|
+
reasonCode: 'deps-incomplete',
|
|
76
|
+
reasons: [wording.notReady, block.message],
|
|
77
|
+
nextAction: block.userAction,
|
|
78
|
+
deps: deps.status,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
decision: 'ready',
|
|
83
|
+
reasonCode: 'deps-present',
|
|
84
|
+
reasons: [wording.ready],
|
|
85
|
+
nextAction: undefined,
|
|
86
|
+
deps: deps.status,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
devServer: {
|
|
90
|
+
label: 'dev-server',
|
|
91
|
+
describe: () => 'no dev server (headless)',
|
|
92
|
+
stop: () => ({ kind: 'headless', ...wording.devServerStop }),
|
|
93
|
+
},
|
|
94
|
+
logSources: () => [],
|
|
95
|
+
appLogSource: () => null,
|
|
96
|
+
hints,
|
|
97
|
+
detect: config.detect,
|
|
98
|
+
launch: async ({ usage }) => usage(wording.launch.message, wording.launch.userAction),
|
|
99
|
+
actions: workspacePackages && !config.actions.tsxLiveScripts
|
|
100
|
+
? {
|
|
101
|
+
...config.actions,
|
|
102
|
+
tsxLiveScripts: {
|
|
103
|
+
env: (projectRoot, tempDir) => workspaceTsconfigEnv(projectRoot, tempDir, {
|
|
104
|
+
packages: workspacePackages,
|
|
105
|
+
fileName: `${id}-adapter.tsconfig.json`,
|
|
106
|
+
}),
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
: config.actions,
|
|
110
|
+
harness: config.harness,
|
|
111
|
+
runtimeContext: config.runtimeContext ?? { forbiddenFields: HEADLESS_FORBIDDEN_FIELDS },
|
|
112
|
+
run: {
|
|
113
|
+
async dependencyBlock(target, use) {
|
|
114
|
+
const required = dependencies.requiredFor
|
|
115
|
+
? await dependencies.requiredFor(target, use)
|
|
116
|
+
: true;
|
|
117
|
+
if (!required)
|
|
118
|
+
return null;
|
|
119
|
+
return dependencyBlockFor(target);
|
|
120
|
+
},
|
|
121
|
+
...config.run,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=node-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.js","sourceRoot":"","sources":["../src/node-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Package name → its directory, relative to the checkout root. */
|
|
2
|
+
export type WorkspacePackageMap = Readonly<Record<string, string>>;
|
|
3
|
+
/** A fixed map, or one read from the checkout (see {@link checkoutWorkspacePackages}). */
|
|
4
|
+
export type WorkspacePackages = WorkspacePackageMap | ((projectRoot: string) => WorkspacePackageMap);
|
|
5
|
+
/** The tsconfig tsx loads through `TSX_TSCONFIG_PATH`. */
|
|
6
|
+
export interface WorkspaceTsconfig {
|
|
7
|
+
compilerOptions: {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
paths: Record<string, string[]>;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Options for {@link workspaceTsconfigEnv}. */
|
|
13
|
+
export interface WorkspaceTsconfigEnvOptions {
|
|
14
|
+
packages: WorkspacePackages;
|
|
15
|
+
/** File name written under the temp dir. Default: `node-adapter.tsconfig.json`. */
|
|
16
|
+
fileName?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Every package the checkout's root `package.json` declares in `workspaces` (an
|
|
20
|
+
* array or `{ packages }`), by name. A monorepo that moves a dependency into its
|
|
21
|
+
* workspace (core's `@metamask/utils`) needs no host change. Patterns are literal
|
|
22
|
+
* directories or `<dir>/*`; any other pattern throws.
|
|
23
|
+
*/
|
|
24
|
+
export declare function checkoutWorkspacePackages(projectRoot: string): WorkspacePackageMap;
|
|
25
|
+
/**
|
|
26
|
+
* Paths for every package that has `src/index.ts`, built or not; null when no
|
|
27
|
+
* package has one.
|
|
28
|
+
*/
|
|
29
|
+
export declare function workspaceTsconfig(projectRoot: string, packages: WorkspacePackages): WorkspaceTsconfig | null;
|
|
30
|
+
/**
|
|
31
|
+
* Write {@link workspaceTsconfig} under `tempDir` and return the environment tsx
|
|
32
|
+
* runs with: `TSX_TSCONFIG_PATH`, and `NODE_OPTIONS` with the checkout's PnP
|
|
33
|
+
* loader when it has one. Empty when no package needs mapping.
|
|
34
|
+
*/
|
|
35
|
+
export declare function workspaceTsconfigEnv(projectRoot: string, tempDir: string, options: WorkspaceTsconfigEnvOptions): Promise<NodeJS.ProcessEnv>;
|
|
36
|
+
//# sourceMappingURL=workspace-tsconfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-tsconfig.d.ts","sourceRoot":"","sources":["../src/workspace-tsconfig.ts"],"names":[],"mappings":"AAYA,mEAAmE;AACnE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnE,0FAA0F;AAC1F,MAAM,MAAM,iBAAiB,GACzB,mBAAmB,GACnB,CAAC,CAAC,WAAW,EAAE,MAAM,KAAK,mBAAmB,CAAC,CAAC;AAEnD,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC;CACvE;AAED,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,CA6BlF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,GAC1B,iBAAiB,GAAG,IAAI,CAW1B;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAS5B"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Live adapter scripts import a checkout's workspace packages as runtime values.
|
|
2
|
+
// Their package "exports" point at dist/, which an unbuilt checkout lacks and a
|
|
3
|
+
// built one may hold from an older source or build layout. A generated tsconfig
|
|
4
|
+
// paths map points tsx at each package's src instead, so a script always runs the
|
|
5
|
+
// checkout's current code, without building or modifying the checkout.
|
|
6
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { writeFile } from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { pnpNodeOptions } from './dependencies.js';
|
|
10
|
+
/**
|
|
11
|
+
* Every package the checkout's root `package.json` declares in `workspaces` (an
|
|
12
|
+
* array or `{ packages }`), by name. A monorepo that moves a dependency into its
|
|
13
|
+
* workspace (core's `@metamask/utils`) needs no host change. Patterns are literal
|
|
14
|
+
* directories or `<dir>/*`; any other pattern throws.
|
|
15
|
+
*/
|
|
16
|
+
export function checkoutWorkspacePackages(projectRoot) {
|
|
17
|
+
const manifest = JSON.parse(readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
|
|
18
|
+
const patterns = Array.isArray(manifest.workspaces)
|
|
19
|
+
? manifest.workspaces
|
|
20
|
+
: (manifest.workspaces?.packages ?? []);
|
|
21
|
+
const dirs = patterns.flatMap((pattern) => {
|
|
22
|
+
const parent = pattern.endsWith('/*') ? pattern.slice(0, -2) : undefined;
|
|
23
|
+
if (/[*!?{[]/u.test(parent ?? pattern)) {
|
|
24
|
+
throw new Error(`workspace pattern "${pattern}" is not supported; pass workspacePackages as a map.`);
|
|
25
|
+
}
|
|
26
|
+
if (parent === undefined)
|
|
27
|
+
return [pattern];
|
|
28
|
+
const parentDir = path.join(projectRoot, parent);
|
|
29
|
+
if (!existsSync(parentDir))
|
|
30
|
+
return [];
|
|
31
|
+
return readdirSync(parentDir, { withFileTypes: true })
|
|
32
|
+
.filter((entry) => entry.isDirectory())
|
|
33
|
+
.map((entry) => path.posix.join(parent, entry.name));
|
|
34
|
+
});
|
|
35
|
+
const packages = {};
|
|
36
|
+
for (const dir of dirs) {
|
|
37
|
+
const packageJson = path.join(projectRoot, dir, 'package.json');
|
|
38
|
+
if (!existsSync(packageJson))
|
|
39
|
+
continue;
|
|
40
|
+
const { name } = JSON.parse(readFileSync(packageJson, 'utf8'));
|
|
41
|
+
if (name)
|
|
42
|
+
packages[name] = dir;
|
|
43
|
+
}
|
|
44
|
+
return packages;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Paths for every package that has `src/index.ts`, built or not; null when no
|
|
48
|
+
* package has one.
|
|
49
|
+
*/
|
|
50
|
+
export function workspaceTsconfig(projectRoot, packages) {
|
|
51
|
+
const map = typeof packages === 'function' ? packages(projectRoot) : packages;
|
|
52
|
+
const paths = {};
|
|
53
|
+
for (const [name, dir] of Object.entries(map)) {
|
|
54
|
+
const srcDir = path.join(projectRoot, dir, 'src');
|
|
55
|
+
if (!existsSync(path.join(srcDir, 'index.ts')))
|
|
56
|
+
continue;
|
|
57
|
+
paths[name] = [path.join(srcDir, 'index.ts')];
|
|
58
|
+
paths[`${name}/*`] = [path.join(srcDir, '*')];
|
|
59
|
+
}
|
|
60
|
+
if (Object.keys(paths).length === 0)
|
|
61
|
+
return null;
|
|
62
|
+
return { compilerOptions: { baseUrl: projectRoot, paths } };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Write {@link workspaceTsconfig} under `tempDir` and return the environment tsx
|
|
66
|
+
* runs with: `TSX_TSCONFIG_PATH`, and `NODE_OPTIONS` with the checkout's PnP
|
|
67
|
+
* loader when it has one. Empty when no package needs mapping.
|
|
68
|
+
*/
|
|
69
|
+
export async function workspaceTsconfigEnv(projectRoot, tempDir, options) {
|
|
70
|
+
const tsconfig = workspaceTsconfig(projectRoot, options.packages);
|
|
71
|
+
if (!tsconfig)
|
|
72
|
+
return {};
|
|
73
|
+
const tsconfigPath = path.join(tempDir, options.fileName ?? 'node-adapter.tsconfig.json');
|
|
74
|
+
await writeFile(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
|
|
75
|
+
return {
|
|
76
|
+
TSX_TSCONFIG_PATH: tsconfigPath,
|
|
77
|
+
NODE_OPTIONS: pnpNodeOptions(projectRoot, process.env.NODE_OPTIONS),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=workspace-tsconfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-tsconfig.js","sourceRoot":"","sources":["../src/workspace-tsconfig.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@farmslot/adapter-node",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./scripts/cleanup.sh": "./scripts/cleanup.sh",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"typecheck": "tsc --noEmit --project tsconfig.json",
|
|
18
|
+
"test": "node ../../scripts/quality/run-tsx-tests.mjs --cwd . --tsconfig tsconfig.json test",
|
|
19
|
+
"format": "prettier --write --ignore-path ../../.prettierignore .",
|
|
20
|
+
"format:check": "prettier --check --ignore-path ../../.prettierignore .",
|
|
21
|
+
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
22
|
+
"lint:fix": "eslint \"src/**/*.ts\" \"test/**/*.ts\" --fix",
|
|
23
|
+
"quality": "prettier --check --ignore-path ../../.prettierignore . && eslint \"src/**/*.ts\" \"test/**/*.ts\" && tsc --noEmit --project tsconfig.json && yarn build && yarn test",
|
|
24
|
+
"build": "yarn workspace @farmslot/adapter-sdk build && rm -rf dist && tsc --project tsconfig.build.json",
|
|
25
|
+
"prepack": "cd ../.. && node scripts/quality/check-farmslot-package-readiness.mjs --require-changelog --packages @farmslot/adapter-node && yarn workspace @farmslot/adapter-node build",
|
|
26
|
+
"prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/adapter-node"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@farmslot/adapter-sdk": "0.5.0",
|
|
30
|
+
"@farmslot/recipe-runner": "0.25.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"eslint": "^10.3.0",
|
|
35
|
+
"prettier": "^3.8.3",
|
|
36
|
+
"tsx": "^4.19.0",
|
|
37
|
+
"typescript": "^5.6.0"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/deeeed/farmslot.git",
|
|
42
|
+
"directory": "packages/adapter-node"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/deeeed/farmslot/issues"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"homepage": "https://farmslot.io/docs/reference/adapter-node",
|
|
49
|
+
"keywords": [
|
|
50
|
+
"farmslot",
|
|
51
|
+
"recipe",
|
|
52
|
+
"adapter",
|
|
53
|
+
"node",
|
|
54
|
+
"headless",
|
|
55
|
+
"agentic-engineering"
|
|
56
|
+
],
|
|
57
|
+
"files": [
|
|
58
|
+
"README.md",
|
|
59
|
+
"LICENSE",
|
|
60
|
+
"dist/**/*.js",
|
|
61
|
+
"dist/**/*.d.ts",
|
|
62
|
+
"dist/**/*.d.ts.map",
|
|
63
|
+
"dist/**/*.js.map",
|
|
64
|
+
"scripts/*.sh"
|
|
65
|
+
],
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# cleanup.sh: remove a headless adapter's recipe-harness overlay.
|
|
3
|
+
#
|
|
4
|
+
# Inputs: --adapter <id> (required); --target <checkout> (default $PWD);
|
|
5
|
+
# env RECIPE_HARNESS_ROOT (checkout-relative, default temp/recipe/harness).
|
|
6
|
+
# Outputs: removes <target>/<harness root>/<id>.
|
|
7
|
+
# Exit: 0 cleaned (idempotent); 1 invalid RECIPE_HARNESS_ROOT; 2 bad args.
|
|
8
|
+
# Never touches: product files. A headless install patches nothing in the
|
|
9
|
+
# checkout, so there are no backups to restore; a missing overlay is a success.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
ADAPTER=""
|
|
13
|
+
TARGET="$PWD"
|
|
14
|
+
while [ "$#" -gt 0 ]; do
|
|
15
|
+
case "$1" in
|
|
16
|
+
--adapter|--target)
|
|
17
|
+
[ "$#" -ge 2 ] || { echo "cleanup.sh: $1 needs a value" >&2; exit 2; }
|
|
18
|
+
if [ "$1" = --adapter ]; then ADAPTER="$2"; else TARGET="$2"; fi
|
|
19
|
+
shift 2 ;;
|
|
20
|
+
-h|--help) echo "Usage: cleanup.sh --adapter <id> [--target <checkout>]"; exit 0 ;;
|
|
21
|
+
*) echo "Unknown arg: $1" >&2; exit 2 ;;
|
|
22
|
+
esac
|
|
23
|
+
done
|
|
24
|
+
|
|
25
|
+
case "$ADAPTER" in
|
|
26
|
+
"") echo "cleanup.sh: --adapter <id> is required" >&2; exit 2 ;;
|
|
27
|
+
.|..|*[!A-Za-z0-9._-]*) echo "cleanup.sh: invalid adapter id: '$ADAPTER'" >&2; exit 2 ;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
# The checkout-relative overlay root. An empty value falls back to the default;
|
|
31
|
+
# a set value must be relative, use a safe charset and have no '.'/'..'
|
|
32
|
+
# components, so a hostile or mistyped value can't make rm -rf leave the target.
|
|
33
|
+
harness_root() {
|
|
34
|
+
local root="${RECIPE_HARNESS_ROOT:-temp/recipe/harness}"
|
|
35
|
+
case "$root" in
|
|
36
|
+
/*) echo "RECIPE_HARNESS_ROOT must be a non-empty relative path: '$root'" >&2; return 1 ;;
|
|
37
|
+
*[!A-Za-z0-9._/-]*) echo "RECIPE_HARNESS_ROOT may only contain A-Za-z0-9 and . _ / - : '$root'" >&2; return 1 ;;
|
|
38
|
+
esac
|
|
39
|
+
local IFS=/ part
|
|
40
|
+
for part in $root; do
|
|
41
|
+
case "$part" in
|
|
42
|
+
.|..) echo "RECIPE_HARNESS_ROOT must not contain '.' or '..' path components: '$root'" >&2; return 1 ;;
|
|
43
|
+
esac
|
|
44
|
+
done
|
|
45
|
+
printf '%s' "$root"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
TARGET="$(cd "$TARGET" && pwd)"
|
|
49
|
+
HARNESS_ROOT="$(harness_root)"
|
|
50
|
+
HARNESS_DIR="$TARGET/$HARNESS_ROOT/$ADAPTER"
|
|
51
|
+
|
|
52
|
+
rm -rf "$HARNESS_DIR"
|
|
53
|
+
echo "Cleaned $ADAPTER recipe harness from $TARGET"
|