@ariestools/aries-chain-serve 0.1.14
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/README.md +25 -0
- package/dist/bin/chainServer.mjs +152 -0
- package/dist/node/ChainBacking.d.ts +21 -0
- package/dist/node/ChainBacking.d.ts.map +1 -0
- package/dist/node/bin/chainServer.d.ts +11 -0
- package/dist/node/bin/chainServer.d.ts.map +1 -0
- package/dist/node/index.d.ts +5 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.mjs +85 -0
- package/dist/node/index.mjs.map +7 -0
- package/dist/node/startChainServer.d.ts +38 -0
- package/dist/node/startChainServer.d.ts.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @ariestools/aries-chain-serve
|
|
2
|
+
|
|
3
|
+
> **Dev only.** This package is a local development fixture — it accepts any
|
|
4
|
+
> S3 credentials, carries no auth or metrics, and only ships an ephemeral
|
|
5
|
+
> in-memory backing. It is not meant for production at this time; production
|
|
6
|
+
> chains are published to real object storage (S3/R2) behind the standard
|
|
7
|
+
> sub-domain layout.
|
|
8
|
+
|
|
9
|
+
Serves an XL1/XYO published-chain layout from a single origin using
|
|
10
|
+
subfolders (`/blocks`, `/state`, `/indexes`) instead of the production
|
|
11
|
+
sub-domains. The subfolders are S3 buckets on an embedded S3-compatible
|
|
12
|
+
server ([s3rver](https://www.npmjs.com/package/s3rver)), so the existing
|
|
13
|
+
`ariesi xyo s3 ...` publish commands write into it unchanged while readers
|
|
14
|
+
(`RestBlockViewer`, `curl`) fetch the same layout paths over plain HTTP.
|
|
15
|
+
The server also accepts an explicit TLS certificate and key. The `aries chain
|
|
16
|
+
up --ssl auto` command configures those inputs with a locally trusted macOS
|
|
17
|
+
development certificate and advertises `https://chain.aries.test:8791`.
|
|
18
|
+
|
|
19
|
+
Backings (`CHAIN_BACKING`): `memory` (ephemeral temp directory, wiped on
|
|
20
|
+
shutdown). `disk` and `s3` are planned.
|
|
21
|
+
|
|
22
|
+
The daemon bin (`dist/bin/chainServer.mjs`) is spawned by `aries chain up`;
|
|
23
|
+
env config: `CHAIN_PORT` (default 8791), `HOST` (default 127.0.0.1),
|
|
24
|
+
`CHAIN_BACKING` (default `memory`), `CHAIN_PUBLIC_HOST`, `CHAIN_TLS_CERT`, and
|
|
25
|
+
`CHAIN_TLS_KEY`.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import S3rver from "s3rver";
|
|
7
|
+
//#region src/ChainBacking.ts
|
|
8
|
+
const CHAIN_BACKINGS = ["memory"];
|
|
9
|
+
function isChainBackingKind(value) {
|
|
10
|
+
return CHAIN_BACKINGS.includes(value);
|
|
11
|
+
}
|
|
12
|
+
function createMemoryBacking() {
|
|
13
|
+
let dir;
|
|
14
|
+
return {
|
|
15
|
+
description: "memory (ephemeral temp directory)",
|
|
16
|
+
get directory() {
|
|
17
|
+
if (dir === void 0) throw new Error("Memory backing not prepared");
|
|
18
|
+
return dir;
|
|
19
|
+
},
|
|
20
|
+
async prepare() {
|
|
21
|
+
dir ??= await mkdtemp(path.join(tmpdir(), "aries-chain-"));
|
|
22
|
+
},
|
|
23
|
+
async cleanup() {
|
|
24
|
+
if (dir !== void 0) await rm(dir, {
|
|
25
|
+
recursive: true,
|
|
26
|
+
force: true
|
|
27
|
+
});
|
|
28
|
+
dir = void 0;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function resolveBacking(kind) {
|
|
33
|
+
switch (kind) {
|
|
34
|
+
case "memory": return createMemoryBacking();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/startChainServer.ts
|
|
39
|
+
/**
|
|
40
|
+
* The bucket-per-role split of the published chain layout. Path-style
|
|
41
|
+
* addressing turns each bucket into a subfolder of the one origin —
|
|
42
|
+
* `/blocks`, `/state`, `/indexes` — replacing the production sub-domains.
|
|
43
|
+
*/
|
|
44
|
+
const CHAIN_BUCKETS = [
|
|
45
|
+
"blocks",
|
|
46
|
+
"state",
|
|
47
|
+
"indexes"
|
|
48
|
+
];
|
|
49
|
+
const DEFAULT_HOST = "127.0.0.1";
|
|
50
|
+
const DEFAULT_PORT = 8791;
|
|
51
|
+
/** Allow browser RestBlockViewer clients to read the layout cross-origin. */
|
|
52
|
+
const CORS_ALLOW_READS = `<CORSConfiguration>
|
|
53
|
+
<CORSRule>
|
|
54
|
+
<AllowedOrigin>*</AllowedOrigin>
|
|
55
|
+
<AllowedMethod>GET</AllowedMethod>
|
|
56
|
+
<AllowedMethod>HEAD</AllowedMethod>
|
|
57
|
+
<AllowedHeader>*</AllowedHeader>
|
|
58
|
+
</CORSRule>
|
|
59
|
+
</CORSConfiguration>`;
|
|
60
|
+
/**
|
|
61
|
+
* Boots an S3-compatible server (s3rver) pre-configured with the three chain
|
|
62
|
+
* layout buckets. Writers use the S3 API (any credentials are accepted);
|
|
63
|
+
* readers fetch `/{bucket}/{layout-path}` over HTTP or optional TLS.
|
|
64
|
+
*
|
|
65
|
+
* DEV ONLY — this server is a local development fixture, not a production
|
|
66
|
+
* chain host. It intentionally skips the production concerns the datalake
|
|
67
|
+
* and signing-pool planes carry (auth, metrics, durable multi-instance
|
|
68
|
+
* storage): any S3 credentials are accepted and the only backing is an
|
|
69
|
+
* ephemeral temp directory. Production chains stay on the real sub-domain
|
|
70
|
+
* layout (blocks/state/indexes origins backed by S3/R2).
|
|
71
|
+
*/
|
|
72
|
+
async function startChainServer(options) {
|
|
73
|
+
const host = options.host ?? DEFAULT_HOST;
|
|
74
|
+
const publicHost = options.publicHost ?? host;
|
|
75
|
+
await options.backing.prepare();
|
|
76
|
+
const server = new S3rver({
|
|
77
|
+
address: host,
|
|
78
|
+
allowMismatchedSignatures: true,
|
|
79
|
+
cert: options.tls?.cert,
|
|
80
|
+
configureBuckets: CHAIN_BUCKETS.map((name) => ({
|
|
81
|
+
name,
|
|
82
|
+
configs: [CORS_ALLOW_READS]
|
|
83
|
+
})),
|
|
84
|
+
directory: options.backing.directory,
|
|
85
|
+
key: options.tls?.key,
|
|
86
|
+
port: options.port ?? DEFAULT_PORT,
|
|
87
|
+
silent: options.silent ?? false,
|
|
88
|
+
vhostBuckets: false
|
|
89
|
+
});
|
|
90
|
+
try {
|
|
91
|
+
const { port } = await server.run();
|
|
92
|
+
return {
|
|
93
|
+
baseUrl: `${options.tls === void 0 ? "http" : "https"}://${publicHost}:${port}`,
|
|
94
|
+
port,
|
|
95
|
+
close: async () => {
|
|
96
|
+
await server.close();
|
|
97
|
+
await options.backing.cleanup();
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
await options.backing.cleanup();
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/bin/chainServer.ts
|
|
107
|
+
/**
|
|
108
|
+
* Chain REST server daemon: serves an XL1/XYO published-chain layout from a
|
|
109
|
+
* single origin using subfolders (/blocks, /state, /indexes) instead of the
|
|
110
|
+
* production sub-domains. The subfolders are S3 buckets on an embedded
|
|
111
|
+
* S3-compatible server, so the existing `xyo s3 ...` publish commands write
|
|
112
|
+
* into it unchanged while readers (RestBlockViewer, curl) fetch the same
|
|
113
|
+
* layout paths over HTTP or optional TLS.
|
|
114
|
+
*/
|
|
115
|
+
const PORT = Number(process.env.CHAIN_PORT ?? 8791);
|
|
116
|
+
const HOST = process.env.HOST ?? "127.0.0.1";
|
|
117
|
+
const BACKING = process.env.CHAIN_BACKING ?? "memory";
|
|
118
|
+
const PUBLIC_HOST = process.env.CHAIN_PUBLIC_HOST;
|
|
119
|
+
const TLS_CERT_PATH = process.env.CHAIN_TLS_CERT;
|
|
120
|
+
const TLS_KEY_PATH = process.env.CHAIN_TLS_KEY;
|
|
121
|
+
async function main() {
|
|
122
|
+
if (!isChainBackingKind(BACKING)) throw new Error(`Unsupported CHAIN_BACKING '${BACKING}' (supported: ${CHAIN_BACKINGS.join(", ")})`);
|
|
123
|
+
const backing = resolveBacking(BACKING);
|
|
124
|
+
if (TLS_CERT_PATH === void 0 !== (TLS_KEY_PATH === void 0)) throw new Error("CHAIN_TLS_CERT and CHAIN_TLS_KEY must be provided together");
|
|
125
|
+
const server = await startChainServer({
|
|
126
|
+
backing,
|
|
127
|
+
host: HOST,
|
|
128
|
+
port: PORT,
|
|
129
|
+
publicHost: PUBLIC_HOST,
|
|
130
|
+
tls: TLS_CERT_PATH === void 0 || TLS_KEY_PATH === void 0 ? void 0 : {
|
|
131
|
+
cert: readFileSync(TLS_CERT_PATH),
|
|
132
|
+
key: readFileSync(TLS_KEY_PATH)
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
console.log(`chain server listening at ${server.baseUrl}\n` + CHAIN_BUCKETS.map((bucket) => ` /${bucket.padEnd(7)} ${server.baseUrl}/${bucket}`).join("\n") + `\nbacking: ${backing.description} — ${backing.directory}`);
|
|
136
|
+
const shutdown = async () => {
|
|
137
|
+
await server.close();
|
|
138
|
+
process.exit(0);
|
|
139
|
+
};
|
|
140
|
+
process.on("SIGINT", () => {
|
|
141
|
+
shutdown();
|
|
142
|
+
});
|
|
143
|
+
process.on("SIGTERM", () => {
|
|
144
|
+
shutdown();
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
main().catch((error) => {
|
|
148
|
+
console.error(error);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
});
|
|
151
|
+
//#endregion
|
|
152
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const CHAIN_BACKINGS: readonly ["memory"];
|
|
2
|
+
export type ChainBackingKind = typeof CHAIN_BACKINGS[number];
|
|
3
|
+
export declare function isChainBackingKind(value: string): value is ChainBackingKind;
|
|
4
|
+
/**
|
|
5
|
+
* Where the served chain layout's objects live. v1 ships only `memory` (an
|
|
6
|
+
* ephemeral temp directory wiped on shutdown); a `disk` kind (caller-owned
|
|
7
|
+
* directory, no-op cleanup) is the natural next addition. An `s3` kind will
|
|
8
|
+
* proxy a remote bucket instead of running a local store, so it will lift
|
|
9
|
+
* this seam up to the server level rather than fit this interface.
|
|
10
|
+
*/
|
|
11
|
+
export interface ChainBacking {
|
|
12
|
+
/** Human-readable label for banners and status output. */
|
|
13
|
+
readonly description: string;
|
|
14
|
+
/** Directory the S3-compatible server persists bucket objects under. Only valid after prepare(). */
|
|
15
|
+
readonly directory: string;
|
|
16
|
+
cleanup(): Promise<void>;
|
|
17
|
+
prepare(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createMemoryBacking(): ChainBacking;
|
|
20
|
+
export declare function resolveBacking(kind: ChainBackingKind): ChainBacking;
|
|
21
|
+
//# sourceMappingURL=ChainBacking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChainBacking.d.ts","sourceRoot":"","sources":["../../src/ChainBacking.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,qBAAsB,CAAA;AACjD,MAAM,MAAM,gBAAgB,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAA;AAE5D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CAE3E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,oGAAoG;IACpG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,wBAAgB,mBAAmB,IAAI,YAAY,CAgBlD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAMnE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Chain REST server daemon: serves an XL1/XYO published-chain layout from a
|
|
4
|
+
* single origin using subfolders (/blocks, /state, /indexes) instead of the
|
|
5
|
+
* production sub-domains. The subfolders are S3 buckets on an embedded
|
|
6
|
+
* S3-compatible server, so the existing `xyo s3 ...` publish commands write
|
|
7
|
+
* into it unchanged while readers (RestBlockViewer, curl) fetch the same
|
|
8
|
+
* layout paths over HTTP or optional TLS.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=chainServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chainServer.d.ts","sourceRoot":"","sources":["../../../src/bin/chainServer.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { ChainBacking, ChainBackingKind } from './ChainBacking.ts';
|
|
2
|
+
export { CHAIN_BACKINGS, createMemoryBacking, isChainBackingKind, resolveBacking, } from './ChainBacking.ts';
|
|
3
|
+
export type { ChainBucket, ChainServerOptions, RunningChainServer, } from './startChainServer.ts';
|
|
4
|
+
export { CHAIN_BUCKETS, startChainServer } from './startChainServer.ts';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACvE,OAAO,EACL,cAAc,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,GACxE,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,WAAW,EAAE,kBAAkB,EAAE,kBAAkB,GACpD,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/ChainBacking.ts
|
|
2
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
var CHAIN_BACKINGS = ["memory"];
|
|
6
|
+
function isChainBackingKind(value) {
|
|
7
|
+
return CHAIN_BACKINGS.includes(value);
|
|
8
|
+
}
|
|
9
|
+
function createMemoryBacking() {
|
|
10
|
+
let dir;
|
|
11
|
+
return {
|
|
12
|
+
description: "memory (ephemeral temp directory)",
|
|
13
|
+
get directory() {
|
|
14
|
+
if (dir === void 0) throw new Error("Memory backing not prepared");
|
|
15
|
+
return dir;
|
|
16
|
+
},
|
|
17
|
+
async prepare() {
|
|
18
|
+
dir ??= await mkdtemp(path.join(tmpdir(), "aries-chain-"));
|
|
19
|
+
},
|
|
20
|
+
async cleanup() {
|
|
21
|
+
if (dir !== void 0) await rm(dir, { recursive: true, force: true });
|
|
22
|
+
dir = void 0;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function resolveBacking(kind) {
|
|
27
|
+
switch (kind) {
|
|
28
|
+
case "memory": {
|
|
29
|
+
return createMemoryBacking();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/startChainServer.ts
|
|
35
|
+
import S3rver from "s3rver";
|
|
36
|
+
var CHAIN_BUCKETS = ["blocks", "state", "indexes"];
|
|
37
|
+
var DEFAULT_HOST = "127.0.0.1";
|
|
38
|
+
var DEFAULT_PORT = 8791;
|
|
39
|
+
var CORS_ALLOW_READS = `<CORSConfiguration>
|
|
40
|
+
<CORSRule>
|
|
41
|
+
<AllowedOrigin>*</AllowedOrigin>
|
|
42
|
+
<AllowedMethod>GET</AllowedMethod>
|
|
43
|
+
<AllowedMethod>HEAD</AllowedMethod>
|
|
44
|
+
<AllowedHeader>*</AllowedHeader>
|
|
45
|
+
</CORSRule>
|
|
46
|
+
</CORSConfiguration>`;
|
|
47
|
+
async function startChainServer(options) {
|
|
48
|
+
const host = options.host ?? DEFAULT_HOST;
|
|
49
|
+
const publicHost = options.publicHost ?? host;
|
|
50
|
+
await options.backing.prepare();
|
|
51
|
+
const server = new S3rver({
|
|
52
|
+
address: host,
|
|
53
|
+
allowMismatchedSignatures: true,
|
|
54
|
+
cert: options.tls?.cert,
|
|
55
|
+
configureBuckets: CHAIN_BUCKETS.map((name) => ({ name, configs: [CORS_ALLOW_READS] })),
|
|
56
|
+
directory: options.backing.directory,
|
|
57
|
+
key: options.tls?.key,
|
|
58
|
+
port: options.port ?? DEFAULT_PORT,
|
|
59
|
+
silent: options.silent ?? false,
|
|
60
|
+
vhostBuckets: false
|
|
61
|
+
});
|
|
62
|
+
try {
|
|
63
|
+
const { port } = await server.run();
|
|
64
|
+
return {
|
|
65
|
+
baseUrl: `${options.tls === void 0 ? "http" : "https"}://${publicHost}:${port}`,
|
|
66
|
+
port,
|
|
67
|
+
close: async () => {
|
|
68
|
+
await server.close();
|
|
69
|
+
await options.backing.cleanup();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
} catch (error) {
|
|
73
|
+
await options.backing.cleanup();
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
CHAIN_BACKINGS,
|
|
79
|
+
CHAIN_BUCKETS,
|
|
80
|
+
createMemoryBacking,
|
|
81
|
+
isChainBackingKind,
|
|
82
|
+
resolveBacking,
|
|
83
|
+
startChainServer
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ChainBacking.ts", "../../src/startChainServer.ts"],
|
|
4
|
+
"sourcesContent": ["import { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport path from 'node:path'\n\nexport const CHAIN_BACKINGS = ['memory'] as const\nexport type ChainBackingKind = typeof CHAIN_BACKINGS[number]\n\nexport function isChainBackingKind(value: string): value is ChainBackingKind {\n return (CHAIN_BACKINGS as readonly string[]).includes(value)\n}\n\n/**\n * Where the served chain layout's objects live. v1 ships only `memory` (an\n * ephemeral temp directory wiped on shutdown); a `disk` kind (caller-owned\n * directory, no-op cleanup) is the natural next addition. An `s3` kind will\n * proxy a remote bucket instead of running a local store, so it will lift\n * this seam up to the server level rather than fit this interface.\n */\nexport interface ChainBacking {\n /** Human-readable label for banners and status output. */\n readonly description: string\n /** Directory the S3-compatible server persists bucket objects under. Only valid after prepare(). */\n readonly directory: string\n cleanup(): Promise<void>\n prepare(): Promise<void>\n}\n\nexport function createMemoryBacking(): ChainBacking {\n let dir: string | undefined\n return {\n description: 'memory (ephemeral temp directory)',\n get directory(): string {\n if (dir === undefined) throw new Error('Memory backing not prepared')\n return dir\n },\n async prepare(): Promise<void> {\n dir ??= await mkdtemp(path.join(tmpdir(), 'aries-chain-'))\n },\n async cleanup(): Promise<void> {\n if (dir !== undefined) await rm(dir, { recursive: true, force: true })\n dir = undefined\n },\n }\n}\n\nexport function resolveBacking(kind: ChainBackingKind): ChainBacking {\n switch (kind) {\n case 'memory': {\n return createMemoryBacking()\n }\n }\n}\n", "import S3rver from 's3rver'\n\nimport type { ChainBacking } from './ChainBacking.ts'\n\n/**\n * The bucket-per-role split of the published chain layout. Path-style\n * addressing turns each bucket into a subfolder of the one origin \u2014\n * `/blocks`, `/state`, `/indexes` \u2014 replacing the production sub-domains.\n */\nexport const CHAIN_BUCKETS = ['blocks', 'state', 'indexes'] as const\nexport type ChainBucket = typeof CHAIN_BUCKETS[number]\n\nconst DEFAULT_HOST = '127.0.0.1'\nconst DEFAULT_PORT = 8791\n\n/** Allow browser RestBlockViewer clients to read the layout cross-origin. */\nconst CORS_ALLOW_READS = `<CORSConfiguration>\n <CORSRule>\n <AllowedOrigin>*</AllowedOrigin>\n <AllowedMethod>GET</AllowedMethod>\n <AllowedMethod>HEAD</AllowedMethod>\n <AllowedHeader>*</AllowedHeader>\n </CORSRule>\n</CORSConfiguration>`\n\nexport interface ChainServerOptions {\n backing: ChainBacking\n host?: string\n port?: number\n publicHost?: string\n silent?: boolean\n tls?: {\n cert: string | Buffer\n key: string | Buffer\n }\n}\n\nexport interface RunningChainServer {\n baseUrl: string\n port: number\n close(): Promise<void>\n}\n\n/**\n * Boots an S3-compatible server (s3rver) pre-configured with the three chain\n * layout buckets. Writers use the S3 API (any credentials are accepted);\n * readers fetch `/{bucket}/{layout-path}` over HTTP or optional TLS.\n *\n * DEV ONLY \u2014 this server is a local development fixture, not a production\n * chain host. It intentionally skips the production concerns the datalake\n * and signing-pool planes carry (auth, metrics, durable multi-instance\n * storage): any S3 credentials are accepted and the only backing is an\n * ephemeral temp directory. Production chains stay on the real sub-domain\n * layout (blocks/state/indexes origins backed by S3/R2).\n */\nexport async function startChainServer(options: ChainServerOptions): Promise<RunningChainServer> {\n const host = options.host ?? DEFAULT_HOST\n const publicHost = options.publicHost ?? host\n await options.backing.prepare()\n const server = new S3rver({\n address: host,\n allowMismatchedSignatures: true,\n cert: options.tls?.cert,\n configureBuckets: CHAIN_BUCKETS.map(name => ({ name, configs: [CORS_ALLOW_READS] })),\n directory: options.backing.directory,\n key: options.tls?.key,\n port: options.port ?? DEFAULT_PORT,\n silent: options.silent ?? false,\n vhostBuckets: false,\n })\n try {\n const { port } = await server.run()\n return {\n baseUrl: `${options.tls === undefined ? 'http' : 'https'}://${publicHost}:${port}`,\n port,\n close: async (): Promise<void> => {\n await server.close()\n await options.backing.cleanup()\n },\n }\n } catch (error) {\n await options.backing.cleanup()\n throw error\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,SAAS,UAAU;AAC5B,SAAS,cAAc;AACvB,OAAO,UAAU;AAEV,IAAM,iBAAiB,CAAC,QAAQ;AAGhC,SAAS,mBAAmB,OAA0C;AAC3E,SAAQ,eAAqC,SAAS,KAAK;AAC7D;AAkBO,SAAS,sBAAoC;AAClD,MAAI;AACJ,SAAO;AAAA,IACL,aAAa;AAAA,IACb,IAAI,YAAoB;AACtB,UAAI,QAAQ,OAAW,OAAM,IAAI,MAAM,6BAA6B;AACpE,aAAO;AAAA,IACT;AAAA,IACA,MAAM,UAAyB;AAC7B,cAAQ,MAAM,QAAQ,KAAK,KAAK,OAAO,GAAG,cAAc,CAAC;AAAA,IAC3D;AAAA,IACA,MAAM,UAAyB;AAC7B,UAAI,QAAQ,OAAW,OAAM,GAAG,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACrE,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,eAAe,MAAsC;AACnE,UAAQ,MAAM;AAAA,IACZ,KAAK,UAAU;AACb,aAAO,oBAAoB;AAAA,IAC7B;AAAA,EACF;AACF;;;ACnDA,OAAO,YAAY;AASZ,IAAM,gBAAgB,CAAC,UAAU,SAAS,SAAS;AAG1D,IAAM,eAAe;AACrB,IAAM,eAAe;AAGrB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuCzB,eAAsB,iBAAiB,SAA0D;AAC/F,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAM,SAAS,IAAI,OAAO;AAAA,IACxB,SAAS;AAAA,IACT,2BAA2B;AAAA,IAC3B,MAAM,QAAQ,KAAK;AAAA,IACnB,kBAAkB,cAAc,IAAI,WAAS,EAAE,MAAM,SAAS,CAAC,gBAAgB,EAAE,EAAE;AAAA,IACnF,WAAW,QAAQ,QAAQ;AAAA,IAC3B,KAAK,QAAQ,KAAK;AAAA,IAClB,MAAM,QAAQ,QAAQ;AAAA,IACtB,QAAQ,QAAQ,UAAU;AAAA,IAC1B,cAAc;AAAA,EAChB,CAAC;AACD,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,OAAO,IAAI;AAClC,WAAO;AAAA,MACL,SAAS,GAAG,QAAQ,QAAQ,SAAY,SAAS,OAAO,MAAM,UAAU,IAAI,IAAI;AAAA,MAChF;AAAA,MACA,OAAO,YAA2B;AAChC,cAAM,OAAO,MAAM;AACnB,cAAM,QAAQ,QAAQ,QAAQ;AAAA,MAChC;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,QAAQ,QAAQ,QAAQ;AAC9B,UAAM;AAAA,EACR;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ChainBacking } from './ChainBacking.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The bucket-per-role split of the published chain layout. Path-style
|
|
4
|
+
* addressing turns each bucket into a subfolder of the one origin —
|
|
5
|
+
* `/blocks`, `/state`, `/indexes` — replacing the production sub-domains.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CHAIN_BUCKETS: readonly ["blocks", "state", "indexes"];
|
|
8
|
+
export type ChainBucket = typeof CHAIN_BUCKETS[number];
|
|
9
|
+
export interface ChainServerOptions {
|
|
10
|
+
backing: ChainBacking;
|
|
11
|
+
host?: string;
|
|
12
|
+
port?: number;
|
|
13
|
+
publicHost?: string;
|
|
14
|
+
silent?: boolean;
|
|
15
|
+
tls?: {
|
|
16
|
+
cert: string | Buffer;
|
|
17
|
+
key: string | Buffer;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface RunningChainServer {
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
port: number;
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Boots an S3-compatible server (s3rver) pre-configured with the three chain
|
|
27
|
+
* layout buckets. Writers use the S3 API (any credentials are accepted);
|
|
28
|
+
* readers fetch `/{bucket}/{layout-path}` over HTTP or optional TLS.
|
|
29
|
+
*
|
|
30
|
+
* DEV ONLY — this server is a local development fixture, not a production
|
|
31
|
+
* chain host. It intentionally skips the production concerns the datalake
|
|
32
|
+
* and signing-pool planes carry (auth, metrics, durable multi-instance
|
|
33
|
+
* storage): any S3 credentials are accepted and the only backing is an
|
|
34
|
+
* ephemeral temp directory. Production chains stay on the real sub-domain
|
|
35
|
+
* layout (blocks/state/indexes origins backed by S3/R2).
|
|
36
|
+
*/
|
|
37
|
+
export declare function startChainServer(options: ChainServerOptions): Promise<RunningChainServer>;
|
|
38
|
+
//# sourceMappingURL=startChainServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startChainServer.d.ts","sourceRoot":"","sources":["../../src/startChainServer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;GAIG;AACH,eAAO,MAAM,aAAa,yCAA0C,CAAA;AACpE,MAAM,MAAM,WAAW,GAAG,OAAO,aAAa,CAAC,MAAM,CAAC,CAAA;AAetD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE;QACJ,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;QACrB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KACrB,CAAA;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA6B/F"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ariestools/aries-chain-serve",
|
|
3
|
+
"version": "0.1.14",
|
|
4
|
+
"description": "Aries chain REST server: serves the XL1 published-chain S3 layout from one origin with /blocks, /state, /indexes subfolders",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ariestools",
|
|
7
|
+
"xl1",
|
|
8
|
+
"xyo",
|
|
9
|
+
"chain",
|
|
10
|
+
"blockviewer",
|
|
11
|
+
"s3",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://ariestools.ai",
|
|
15
|
+
"license": "LGPL-3.0-only",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "Arie Trouw",
|
|
18
|
+
"email": "support@ariestools.ai",
|
|
19
|
+
"url": "https://ariestools.ai"
|
|
20
|
+
},
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/node/index.d.ts",
|
|
26
|
+
"default": "./dist/node/index.mjs"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"bin": {
|
|
31
|
+
"aries-chain-serve": "dist/bin/chainServer.mjs"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"s3rver": "~3.7.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@ariestools/toolchain": "~8.7.22",
|
|
45
|
+
"@ariestools/tsconfig": "~8.7.22",
|
|
46
|
+
"@aws-sdk/client-s3": "~3.1091.0",
|
|
47
|
+
"@types/node": "~26.1.1",
|
|
48
|
+
"@types/s3rver": "~3.7.4",
|
|
49
|
+
"rolldown": "~1.2.0",
|
|
50
|
+
"typescript": "~6.0.3",
|
|
51
|
+
"vite": "~8.1.5",
|
|
52
|
+
"vitest": "~4.1.10"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.17.1"
|
|
56
|
+
},
|
|
57
|
+
"engineStrict": true,
|
|
58
|
+
"scripts": {
|
|
59
|
+
"package-compile": "package-compile-only && rolldown -c rolldown.config.ts"
|
|
60
|
+
}
|
|
61
|
+
}
|