Skip to content

Commit dbaf5c8

Browse files
chore: WiP - still need to test explicit imports from 'bare' (non node: prefixed) builtins in deps
But it appears to be alive
1 parent 37ec46b commit dbaf5c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+462
-52
lines changed

packages/libs/lit-action-bundler/src/lib/shims/buffer.ts renamed to packages/libs/lit-action-bundler/buffer.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,4 @@
22
// @ts-nocheck
33
export * from 'node:buffer';
44
import { default as buffer } from 'node:buffer';
5-
export const kMaxLength = 4294967296;
6-
buffer.kMaxLength = kMaxLength;
75
export default buffer;

packages/libs/lit-action-bundler/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@
2929
"!**/*.tsbuildinfo"
3030
],
3131
"dependencies": {
32+
"@lit-protocol/auth-helpers": "^7.2.0",
33+
"@lit-protocol/constants": "^7.2.0",
34+
"@lit-protocol/lit-node-client": "^7.2.0",
3235
"esbuild": "^0.25.5",
3336
"ethers": "5.8.0",
3437
"ipfs-only-hash": "^4.0.0",
3538
"tslib": "^2.8.1"
39+
},
40+
"devDependencies": {
41+
"@lit-protocol/types": "^7.2.0"
3642
}
3743
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import type { LIT_NETWORKS_KEYS } from '@lit-protocol/types';
2+
3+
import { LitNodeClient } from '@lit-protocol/lit-node-client';
4+
5+
export class LitNodeClientInstance {
6+
private readonly litNodeClientInstance: LitNodeClient;
7+
8+
private isConnected = false;
9+
10+
private connectHandle: Promise<boolean> | null = null;
11+
12+
constructor({ network }: { network: LIT_NETWORKS_KEYS }) {
13+
this.litNodeClientInstance = new LitNodeClient({
14+
debug: true,
15+
litNetwork: network,
16+
});
17+
}
18+
19+
async connect(): Promise<boolean> {
20+
if (!this.isConnected) {
21+
// Coalesce concurrent calls
22+
if (this.connectHandle) {
23+
return this.connectHandle;
24+
}
25+
26+
// Stash a handle so concurrent calls to connect are coaelesced into 1
27+
this.connectHandle = this.litNodeClientInstance.connect().then(() => true);
28+
29+
try {
30+
// Don't return until we know the result of pending connect attempt
31+
await this.connectHandle;
32+
this.isConnected = true;
33+
} catch (e) {
34+
// We allow multiple calls to (retries!) to `connect()` even in case where one succeeded
35+
// if `isConnected` is false (e.g. a prior attempt failed)
36+
this.isConnected = false;
37+
throw e;
38+
} finally {
39+
this.connectHandle = null;
40+
}
41+
return this.isConnected;
42+
}
43+
44+
return true;
45+
}
46+
47+
async disconnect(): Promise<void> {
48+
if (!this.isConnected && this.connectHandle) {
49+
// Wait for connect attempt to finish so we don't end up just re-adding the listener when it finishes.
50+
try {
51+
await this.connectHandle;
52+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
53+
} catch (e) {
54+
/* Ignore errors on connect; we're disconnecting! */
55+
}
56+
}
57+
58+
try {
59+
await this.litNodeClientInstance.disconnect();
60+
} catch (e) {
61+
/* We did our best */
62+
console.log('Failed to disconnect from LitNodeClientInstance.', (e as Error).message);
63+
} finally {
64+
this.isConnected = false;
65+
}
66+
}
67+
68+
get litNodeClient(): LitNodeClient {
69+
return this.litNodeClientInstance;
70+
}
71+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// src/toolClient/execute/generateVincentToolSessionSigs.ts
2+
3+
import type { ethers } from 'ethers';
4+
5+
import type { LitNodeClient } from '@lit-protocol/lit-node-client';
6+
7+
import {
8+
createSiweMessageWithRecaps,
9+
generateAuthSig,
10+
LitActionResource,
11+
LitPKPResource,
12+
} from '@lit-protocol/auth-helpers';
13+
import { LIT_ABILITY } from '@lit-protocol/constants';
14+
15+
/** @hidden */
16+
export const generateVincentToolSessionSigs = async ({
17+
litNodeClient,
18+
ethersSigner,
19+
}: {
20+
litNodeClient: LitNodeClient;
21+
ethersSigner: ethers.Signer;
22+
}) => {
23+
return litNodeClient.getSessionSigs({
24+
chain: 'ethereum',
25+
resourceAbilityRequests: [
26+
{ resource: new LitPKPResource('*'), ability: LIT_ABILITY.PKPSigning },
27+
{ resource: new LitActionResource('*'), ability: LIT_ABILITY.LitActionExecution },
28+
],
29+
authNeededCallback: async ({ resourceAbilityRequests, uri }) => {
30+
const [walletAddress, nonce] = await Promise.all([
31+
ethersSigner.getAddress(),
32+
litNodeClient.getLatestBlockhash(),
33+
]);
34+
35+
const toSign = await createSiweMessageWithRecaps({
36+
uri: uri || 'http://localhost:3000',
37+
expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(),
38+
resources: resourceAbilityRequests || [],
39+
walletAddress,
40+
nonce,
41+
litNodeClient,
42+
});
43+
44+
return await generateAuthSig({ signer: ethersSigner, toSign });
45+
},
46+
});
47+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { LitNodeClient } from '@lit-protocol/lit-node-client';
2+
import type { LIT_NETWORKS_KEYS } from '@lit-protocol/types';
3+
4+
import { LitNodeClientInstance } from './LitNodeClientInstance';
5+
6+
let instance: LitNodeClientInstance | null = null;
7+
8+
export async function getLitNodeClientInstance({
9+
network,
10+
}: {
11+
network: LIT_NETWORKS_KEYS;
12+
}): Promise<LitNodeClient> {
13+
if (instance) {
14+
// connect() is idempotent; if we're retrying from outside, attempt to connect again
15+
// This is a no-op if already connected 🎉 but if a prior attempt fails, it'll try again.
16+
await instance.connect();
17+
return instance.litNodeClient;
18+
}
19+
20+
instance = new LitNodeClientInstance({ network });
21+
await instance.connect();
22+
23+
return instance.litNodeClient;
24+
}
25+
26+
export async function disconnectLitNodeClientInstance() {
27+
if (instance) {
28+
await instance.disconnect();
29+
instance = null;
30+
}
31+
return true;
32+
}

packages/libs/lit-action-bundler/src/bundleTest.spec.ts

Whitespace-only changes.

packages/libs/lit-action-bundler/src/lib/esbuild/esbuild.ts

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,37 @@ import type { BuildResult } from 'esbuild';
22

33
import path from 'path';
44

5-
import esbuild from 'esbuild';
5+
import { build } from 'esbuild';
66

77
import type { BuildLitActionOptions } from './types';
88

99
import { aliasFetch } from './plugins/aliasFetch';
1010
import { createBundledFile } from './plugins/createBundledFile';
11+
import { nodeBuiltinDenoShims } from './plugins/nodeBuiltinDenoShims';
1112
import { wrapIIFEInStringPlugin } from './plugins/wrapIIFEInString';
1213
import { assertOutputFiles } from './utils';
1314

15+
export function getCompatPluginCreators() {
16+
return {
17+
aliasFetch: aliasFetch,
18+
nodeBuiltinDenoShims: nodeBuiltinDenoShims,
19+
wrapIIFEInStringPlugin: wrapIIFEInStringPlugin,
20+
createBundledFile: createBundledFile,
21+
};
22+
}
23+
24+
export const esbuildConfigDefaults = {
25+
bundle: true,
26+
minify: false,
27+
sourcemap: false,
28+
treeShaking: true,
29+
metafile: true,
30+
// inject: [path.resolve(__dirname, './plugins/node-global-shims.ts')],
31+
platform: 'browser' as const,
32+
write: false,
33+
external: ['node:*'],
34+
};
35+
1436
/** Builds a Lit Action
1537
*/
1638
export async function buildLitAction({
@@ -21,35 +43,34 @@ export async function buildLitAction({
2143
}: BuildLitActionOptions) {
2244
const sourceDir = path.dirname(entryPoint);
2345

24-
await esbuild
25-
.build({
26-
outdir,
27-
tsconfig: tsconfigPath,
28-
entryPoints: [entryPoint],
29-
bundle: true,
30-
minify: false,
31-
sourcemap: false,
32-
treeShaking: true,
33-
metafile: true,
34-
plugins: [
35-
aliasFetch(),
36-
await wrapIIFEInStringPlugin(),
37-
await createBundledFile({ sourceDir: sourceDir, getLitActionHandler: getLitActionHandler }),
38-
],
39-
platform: 'browser',
40-
write: false,
41-
})
42-
.then((result: BuildResult) => {
43-
assertOutputFiles(result);
44-
45-
result.outputFiles.forEach((file) => {
46-
const bytes = file.text.length;
47-
const mbInDecimal = (bytes / 1_000_000).toFixed(4);
48-
49-
const filePathArr = file.path.split('/');
50-
console.log(
51-
`✅ ${filePathArr.slice(filePathArr.length - 2, filePathArr.length - 1)} - ${mbInDecimal} MB`,
52-
);
53-
});
46+
const plugins = [aliasFetch(), await nodeBuiltinDenoShims(), await wrapIIFEInStringPlugin()];
47+
48+
if (getLitActionHandler) {
49+
plugins.push(
50+
await createBundledFile({
51+
sourceDir: sourceDir,
52+
getLitActionHandler: getLitActionHandler,
53+
}),
54+
);
55+
}
56+
57+
await build({
58+
outdir,
59+
tsconfig: tsconfigPath,
60+
entryPoints: [entryPoint],
61+
plugins,
62+
...esbuildConfigDefaults,
63+
}).then((result: BuildResult) => {
64+
assertOutputFiles(result);
65+
66+
result.outputFiles.forEach((file) => {
67+
const bytes = file.text.length;
68+
const mbInDecimal = (bytes / 1_000_000).toFixed(4);
69+
70+
const filePathArr = file.path.split('/');
71+
console.log(
72+
`✅ ${filePathArr.slice(filePathArr.length - 2, filePathArr.length - 1)} - ${mbInDecimal} MB`,
73+
);
5474
});
75+
});
5576
}

packages/libs/lit-action-bundler/src/lib/esbuild/plugins/createBundledFile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import path from 'path';
66
/** @ts-expect-error No types for this pkg */
77
import Hash from 'ipfs-only-hash';
88

9-
import type { GetLitActionHandlerFunc } from '../types';
9+
import type { GetLitActionWrapperContentFunc } from '../types';
1010

1111
import { getMetadataJsonFileContent } from '../templates';
1212
import { assertOutputFiles, ensureDirectoryExistence } from '../utils';
@@ -16,7 +16,7 @@ export async function createBundledFile({
1616
getLitActionHandler,
1717
}: {
1818
sourceDir: string;
19-
getLitActionHandler: GetLitActionHandlerFunc;
19+
getLitActionHandler: GetLitActionWrapperContentFunc;
2020
}): Promise<Plugin> {
2121
return {
2222
name: `create-bundled-lit-action-file`,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// shims/node-globals.ts
2+
export { Buffer } from 'node:buffer';
3+
export { setTimeout, clearTimeout } from 'node:timers';
4+
export const process = {
5+
env: {
6+
NODE_ENV: 'production',
7+
},
8+
};
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import type { Plugin } from 'esbuild';
2+
3+
import path from 'path';
4+
5+
// Path to the shims directory relative to this file
6+
const SHIMS_DIR = '../../shims';
7+
8+
export function nodeBuiltinDenoShims(): Plugin {
9+
return {
10+
name: 'node-builtin-deno-shims',
11+
setup(build) {
12+
// Handle top-level modules
13+
build.onResolve(
14+
{
15+
filter:
16+
/^(node:)?(assert|async_hooks|console|constants|crypto|dgram|dns|events|http|http2|https|net|os|path|querystring|readline|stream|string_decoder|timers|url|util|zlib)$/,
17+
},
18+
(args) => {
19+
const moduleName = args.path.replace(/^node:/, '');
20+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${moduleName}.js`));
21+
return { path: shimPath };
22+
},
23+
);
24+
25+
// Handle stream submodules
26+
build.onResolve(
27+
{ filter: /^(node:)?_stream_(duplex|passthrough|readable|transform|writable)$/ },
28+
(args) => {
29+
const moduleName = args.path.replace(/^node:/, '');
30+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${moduleName}.js`));
31+
return { path: shimPath };
32+
},
33+
);
34+
35+
// Handle path submodules
36+
build.onResolve({ filter: /^(node:)?path\/(posix|win32)$/ }, (args) => {
37+
const modulePath = args.path.replace(/^node:/, '');
38+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
39+
return { path: shimPath };
40+
});
41+
42+
// Handle assert submodules
43+
build.onResolve({ filter: /^(node:)?assert\/(strict)$/ }, (args) => {
44+
const modulePath = args.path.replace(/^node:/, '');
45+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
46+
return { path: shimPath };
47+
});
48+
49+
// Handle readline submodules
50+
build.onResolve({ filter: /^(node:)?readline\/(promises)$/ }, (args) => {
51+
const modulePath = args.path.replace(/^node:/, '');
52+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
53+
return { path: shimPath };
54+
});
55+
56+
// Handle stream submodules
57+
build.onResolve({ filter: /^(node:)?stream\/(consumers|promises|web)$/ }, (args) => {
58+
const modulePath = args.path.replace(/^node:/, '');
59+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
60+
return { path: shimPath };
61+
});
62+
63+
// Handle timers submodules
64+
build.onResolve({ filter: /^(node:)?timers\/(promises)$/ }, (args) => {
65+
const modulePath = args.path.replace(/^node:/, '');
66+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
67+
return { path: shimPath };
68+
});
69+
70+
// Handle dns submodules
71+
build.onResolve({ filter: /^(node:)?dns\/(promises)$/ }, (args) => {
72+
const modulePath = args.path.replace(/^node:/, '');
73+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
74+
return { path: shimPath };
75+
});
76+
77+
// Handle util submodules
78+
build.onResolve({ filter: /^(node:)?util\/(types)$/ }, (args) => {
79+
const modulePath = args.path.replace(/^node:/, '');
80+
const shimPath = path.resolve(__dirname, path.join(SHIMS_DIR, `${modulePath}.js`));
81+
return { path: shimPath };
82+
});
83+
},
84+
};
85+
}

0 commit comments

Comments
 (0)