@powerhousedao/switchboard 6.0.0-dev.1 → 6.0.0-dev.100
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 +905 -0
- package/Dockerfile +63 -37
- package/README.md +92 -0
- package/dist/src/index.js +35 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/metrics.d.ts +7 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +34 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/migrate.d.ts +3 -0
- package/dist/src/migrate.d.ts.map +1 -0
- package/dist/src/migrate.js +65 -0
- package/dist/src/migrate.js.map +1 -0
- package/dist/src/profiler.d.ts +6 -1
- package/dist/src/profiler.d.ts.map +1 -1
- package/dist/src/profiler.js +31 -5
- package/dist/src/profiler.js.map +1 -1
- package/dist/src/renown.d.ts +16 -0
- package/dist/src/renown.d.ts.map +1 -0
- package/dist/src/renown.js +33 -0
- package/dist/src/renown.js.map +1 -0
- package/dist/src/server.d.ts +0 -1
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +163 -78
- package/dist/src/server.js.map +1 -1
- package/dist/src/types.d.ts +19 -6
- package/dist/src/types.d.ts.map +1 -1
- package/dist/test/metrics.test.d.ts +2 -0
- package/dist/test/metrics.test.d.ts.map +1 -0
- package/dist/test/metrics.test.js +121 -0
- package/dist/test/metrics.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +15 -0
- package/dist/vitest.config.js.map +1 -0
- package/entrypoint.sh +11 -16
- package/package.json +35 -23
- package/test/metrics.test.ts +202 -0
- package/tsconfig.json +8 -2
- package/vitest.config.ts +15 -0
- package/dist/src/connect-crypto.d.ts +0 -41
- package/dist/src/connect-crypto.d.ts.map +0 -1
- package/dist/src/connect-crypto.js +0 -127
- package/dist/src/connect-crypto.js.map +0 -1
package/Dockerfile
CHANGED
|
@@ -1,58 +1,84 @@
|
|
|
1
|
-
|
|
1
|
+
# Build stage
|
|
2
|
+
FROM node:24-alpine AS build
|
|
3
|
+
|
|
2
4
|
WORKDIR /app
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
# Install build dependencies
|
|
7
|
+
RUN apk add --no-cache python3 make g++ git bash \
|
|
8
|
+
&& ln -sf /usr/bin/python3 /usr/bin/python
|
|
9
|
+
|
|
10
|
+
# Setup pnpm
|
|
5
11
|
ENV PNPM_HOME="/pnpm"
|
|
6
12
|
ENV PATH="$PNPM_HOME:$PATH"
|
|
7
|
-
RUN corepack enable && corepack
|
|
8
|
-
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
|
13
|
+
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
# Configure JSR registry
|
|
16
|
+
RUN pnpm config set @jsr:registry https://npm.jsr.io
|
|
11
17
|
|
|
12
|
-
#
|
|
13
|
-
|
|
18
|
+
# Build arguments
|
|
19
|
+
ARG TAG=latest
|
|
20
|
+
ARG PH_PACKAGES=""
|
|
14
21
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
ENV NX_DAEMON=false
|
|
22
|
+
# Install ph-cmd, prisma, and prettier
|
|
23
|
+
RUN pnpm add -g ph-cmd@$TAG prisma@5.17.0 prettier
|
|
18
24
|
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
# Initialize project based on tag
|
|
26
|
+
RUN case "$TAG" in \
|
|
27
|
+
*dev*) ph init project --dev --package-manager pnpm ;; \
|
|
28
|
+
*staging*) ph init project --staging --package-manager pnpm ;; \
|
|
29
|
+
*) ph init project --package-manager pnpm ;; \
|
|
30
|
+
esac
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
ENV PH_SWITCHBOARD_DATABASE_URL="dev.db"
|
|
27
|
-
ENV PH_SWITCHBOARD_REDIS_URL=""
|
|
28
|
-
ENV SKIP_DB_MIGRATIONS="false"
|
|
32
|
+
WORKDIR /app/project
|
|
29
33
|
|
|
30
|
-
#
|
|
31
|
-
|
|
34
|
+
# Install PH packages if provided
|
|
35
|
+
RUN if [ -n "$PH_PACKAGES" ]; then \
|
|
36
|
+
IFS=',' ; for pkg in $PH_PACKAGES; do \
|
|
37
|
+
echo "Installing package: $pkg"; \
|
|
38
|
+
ph install "$pkg"; \
|
|
39
|
+
done; \
|
|
40
|
+
fi
|
|
32
41
|
|
|
33
|
-
#
|
|
34
|
-
|
|
42
|
+
# Regenerate Prisma client for Alpine Linux (linux-musl-openssl-3.0.x)
|
|
43
|
+
# The document-drive package ships with darwin-arm64 binaries, we need to regenerate
|
|
44
|
+
RUN prisma generate --schema node_modules/document-drive/dist/prisma/schema.prisma
|
|
35
45
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
# Final stage - slim node image
|
|
47
|
+
FROM node:24-alpine
|
|
48
|
+
|
|
49
|
+
WORKDIR /app
|
|
50
|
+
|
|
51
|
+
# Install runtime dependencies (curl for health checks, openssl for Prisma)
|
|
52
|
+
RUN apk add --no-cache curl openssl
|
|
53
|
+
|
|
54
|
+
# Setup pnpm
|
|
55
|
+
ENV PNPM_HOME="/pnpm"
|
|
56
|
+
ENV PATH="$PNPM_HOME:$PATH"
|
|
57
|
+
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
58
|
+
|
|
59
|
+
# Configure JSR registry
|
|
41
60
|
RUN pnpm config set @jsr:registry https://npm.jsr.io
|
|
61
|
+
|
|
62
|
+
# Install ph-cmd and prisma globally (needed at runtime)
|
|
63
|
+
ARG TAG=latest
|
|
42
64
|
RUN pnpm add -g ph-cmd@$TAG prisma@5.17.0
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*staging*) ph init project --staging --package-manager pnpm ;; \
|
|
47
|
-
*) ph init project --package-manager pnpm ;; \
|
|
48
|
-
esac
|
|
66
|
+
# Copy built project from build stage
|
|
67
|
+
COPY --from=build /app/project /app/project
|
|
49
68
|
|
|
50
69
|
WORKDIR /app/project
|
|
51
70
|
|
|
52
|
-
#
|
|
53
|
-
|
|
71
|
+
# Copy entrypoint
|
|
72
|
+
COPY entrypoint.sh /app/entrypoint.sh
|
|
73
|
+
RUN chmod +x /app/entrypoint.sh
|
|
74
|
+
|
|
75
|
+
# Environment variables
|
|
76
|
+
ENV NODE_ENV=production
|
|
77
|
+
ENV PORT=3000
|
|
78
|
+
ENV DATABASE_URL=""
|
|
79
|
+
ENV SKIP_DB_MIGRATIONS="false"
|
|
54
80
|
|
|
55
|
-
EXPOSE $PORT
|
|
81
|
+
EXPOSE ${PORT}
|
|
56
82
|
|
|
57
83
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
|
|
58
84
|
CMD curl -f http://localhost:${PORT}/health || exit 1
|
package/README.md
CHANGED
|
@@ -40,6 +40,48 @@ pnpm --filter @powerhousedao/switchboard build
|
|
|
40
40
|
pnpm --filter @powerhousedao/switchboard dev
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
### Local Development (PostgreSQL)
|
|
44
|
+
|
|
45
|
+
1. **Start the PostgreSQL database using reactor's Docker Compose:**
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# From the repository root, start the database
|
|
49
|
+
docker compose -f packages/reactor/docker-compose.yml up -d
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This starts:
|
|
53
|
+
- PostgreSQL on port `5433` (mapped from container port 5432)
|
|
54
|
+
- Adminer (database UI) on port `8080`
|
|
55
|
+
|
|
56
|
+
2. **Run database migrations:**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
DATABASE_URL="postgresql://postgres:postgres@localhost:5433/reactor" pnpm migrate
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
3. **Start switchboard with the PostgreSQL database URL:**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
DATABASE_URL="postgresql://postgres:postgres@localhost:5433/reactor" pnpm start
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
4. **(Optional) Access the database UI:**
|
|
69
|
+
- Open http://localhost:8080
|
|
70
|
+
- System: PostgreSQL
|
|
71
|
+
- Server: postgres
|
|
72
|
+
- Username: postgres
|
|
73
|
+
- Password: postgres
|
|
74
|
+
- Database: reactor
|
|
75
|
+
|
|
76
|
+
5. **(Optional) Stop the Database**
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
docker compose -f packages/reactor/docker-compose.yml down
|
|
80
|
+
|
|
81
|
+
# To also remove the data volume:
|
|
82
|
+
docker compose -f packages/reactor/docker-compose.yml down -v
|
|
83
|
+
```
|
|
84
|
+
|
|
43
85
|
### Global Installation
|
|
44
86
|
|
|
45
87
|
```bash
|
|
@@ -52,6 +94,7 @@ pnpm add -g @powerhousedao/switchboard
|
|
|
52
94
|
|
|
53
95
|
## 🏃♂️ Quick Start
|
|
54
96
|
|
|
97
|
+
|
|
55
98
|
## ⚙️ Configuration
|
|
56
99
|
|
|
57
100
|
### Environment Variables
|
|
@@ -60,6 +103,7 @@ pnpm add -g @powerhousedao/switchboard
|
|
|
60
103
|
| ---------------------------- | ---------------------------------- | --------------------- |
|
|
61
104
|
| `PORT` | Server port | `4001` |
|
|
62
105
|
| `DATABASE_URL` | Database connection string | `./.ph/drive-storage` |
|
|
106
|
+
| `PH_REACTOR_DATABASE_URL` | PostgreSQL URL (takes precedence) | - |
|
|
63
107
|
| `REDIS_URL` | Redis connection URL | - |
|
|
64
108
|
| `REDIS_TLS_URL` | Redis TLS connection URL | - |
|
|
65
109
|
| `SENTRY_DSN` | Sentry DSN for error tracking | - |
|
|
@@ -164,6 +208,12 @@ pnpm dev
|
|
|
164
208
|
# Start production server
|
|
165
209
|
pnpm start
|
|
166
210
|
|
|
211
|
+
# Run database migrations (PostgreSQL only)
|
|
212
|
+
pnpm migrate
|
|
213
|
+
|
|
214
|
+
# Check migration status
|
|
215
|
+
pnpm migrate:status
|
|
216
|
+
|
|
167
217
|
# Lint code
|
|
168
218
|
pnpm lint
|
|
169
219
|
|
|
@@ -171,6 +221,48 @@ pnpm lint
|
|
|
171
221
|
pnpm clean
|
|
172
222
|
```
|
|
173
223
|
|
|
224
|
+
### Database Migrations
|
|
225
|
+
|
|
226
|
+
Switchboard uses Kysely for database migrations when running with PostgreSQL. Migrations are handled differently depending on your storage backend:
|
|
227
|
+
|
|
228
|
+
- **PGlite (default)**: Migrations run automatically on startup
|
|
229
|
+
- **PostgreSQL**: Migrations can be run manually or as part of your deployment pipeline
|
|
230
|
+
|
|
231
|
+
#### Running Migrations
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Via pnpm scripts (from apps/switchboard directory)
|
|
235
|
+
DATABASE_URL="postgresql://user:pass@localhost:5432/db" pnpm migrate
|
|
236
|
+
|
|
237
|
+
# Check which migrations have been applied
|
|
238
|
+
DATABASE_URL="postgresql://user:pass@localhost:5432/db" pnpm migrate:status
|
|
239
|
+
|
|
240
|
+
# Via ph CLI (from anywhere)
|
|
241
|
+
ph switchboard --db-path postgresql://user:pass@localhost:5432/db --migrate
|
|
242
|
+
ph switchboard --db-path postgresql://user:pass@localhost:5432/db --migrate-status
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
#### Environment Variables for Migrations
|
|
246
|
+
|
|
247
|
+
The migration commands check for a PostgreSQL URL in this order:
|
|
248
|
+
1. `PH_REACTOR_DATABASE_URL`
|
|
249
|
+
2. `DATABASE_URL`
|
|
250
|
+
3. Config file (`powerhouse.config.json` -> `switchboard.database.url`)
|
|
251
|
+
|
|
252
|
+
If no PostgreSQL URL is found, migrations are skipped with a message (PGlite handles migrations automatically).
|
|
253
|
+
|
|
254
|
+
#### CI/CD Integration
|
|
255
|
+
|
|
256
|
+
For production deployments, run migrations before starting the server:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Run migrations then start
|
|
260
|
+
ph switchboard --migrate && ph switchboard
|
|
261
|
+
|
|
262
|
+
# Or with pnpm
|
|
263
|
+
pnpm migrate && pnpm start
|
|
264
|
+
```
|
|
265
|
+
|
|
174
266
|
### Adding New Features
|
|
175
267
|
|
|
176
268
|
1. **Document Models**: Add new document model modules to the reactor builder
|
package/dist/src/index.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import * as Sentry from "@sentry/node";
|
|
3
|
+
import { childLogger } from "document-drive";
|
|
2
4
|
import { config } from "./config.js";
|
|
5
|
+
import { createMeterProviderFromEnv } from "./metrics.js";
|
|
6
|
+
import { initProfilerFromEnv } from "./profiler.js";
|
|
3
7
|
import { startSwitchboard } from "./server.js";
|
|
4
|
-
|
|
8
|
+
const logger = childLogger(["switchboard"]);
|
|
9
|
+
function ensureNodeVersion(minVersion = "24") {
|
|
5
10
|
const version = process.versions.node;
|
|
6
11
|
if (!version) {
|
|
7
12
|
return;
|
|
@@ -12,6 +17,33 @@ function ensureNodeVersion(minVersion = "22") {
|
|
|
12
17
|
}
|
|
13
18
|
}
|
|
14
19
|
// Ensure minimum Node.js version
|
|
15
|
-
ensureNodeVersion("
|
|
16
|
-
|
|
20
|
+
ensureNodeVersion("24");
|
|
21
|
+
const meterProvider = createMeterProviderFromEnv({
|
|
22
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
23
|
+
OTEL_METRIC_EXPORT_INTERVAL: process.env.OTEL_METRIC_EXPORT_INTERVAL,
|
|
24
|
+
OTEL_SERVICE_NAME: process.env.OTEL_SERVICE_NAME,
|
|
25
|
+
});
|
|
26
|
+
async function shutdown() {
|
|
27
|
+
console.log("\nShutting down...");
|
|
28
|
+
// Flush final metrics before exit. Races against a 5s deadline so an
|
|
29
|
+
// unresponsive OTLP endpoint cannot exhaust terminationGracePeriodSeconds.
|
|
30
|
+
await Promise.race([
|
|
31
|
+
meterProvider?.shutdown().catch(() => undefined),
|
|
32
|
+
new Promise((resolve) => setTimeout(resolve, 5_000)),
|
|
33
|
+
]);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
// SIGINT: Ctrl-C in development; SIGTERM: graceful shutdown in Docker/Kubernetes
|
|
37
|
+
process.on("SIGINT", shutdown);
|
|
38
|
+
process.on("SIGTERM", shutdown);
|
|
39
|
+
if (process.env.PYROSCOPE_SERVER_ADDRESS) {
|
|
40
|
+
try {
|
|
41
|
+
await initProfilerFromEnv(process.env);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
Sentry.captureException(e);
|
|
45
|
+
logger.error("Error starting profiler: @error", e);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
startSwitchboard({ ...config, meterProvider }).catch(console.error);
|
|
17
49
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,SAAS,iBAAiB,CAAC,UAAU,GAAG,IAAI;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CACX,gBAAgB,UAAU,4CAA4C,OAAO,EAAE,CAChF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AACD,iCAAiC;AACjC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExB,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAE5C,SAAS,iBAAiB,CAAC,UAAU,GAAG,IAAI;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CACX,gBAAgB,UAAU,4CAA4C,OAAO,EAAE,CAChF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AACD,iCAAiC;AACjC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAExB,MAAM,aAAa,GAAG,0BAA0B,CAAC;IAC/C,2BAA2B,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B;IACpE,2BAA2B,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B;IACpE,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;CACjD,CAAC,CAAC;AAEH,KAAK,UAAU,QAAQ;IACrB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,qEAAqE;IACrE,2EAA2E;IAC3E,MAAM,OAAO,CAAC,IAAI,CAAC;QACjB,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;QAChD,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;KAC3D,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,iFAAiF;AACjF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEhC,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MeterProvider } from "@opentelemetry/sdk-metrics";
|
|
2
|
+
export declare function createMeterProviderFromEnv(env: {
|
|
3
|
+
OTEL_EXPORTER_OTLP_ENDPOINT?: string;
|
|
4
|
+
OTEL_METRIC_EXPORT_INTERVAL?: string;
|
|
5
|
+
OTEL_SERVICE_NAME?: string;
|
|
6
|
+
}): MeterProvider | undefined;
|
|
7
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EAEd,MAAM,4BAA4B,CAAC;AAKpC,wBAAgB,0BAA0B,CAAC,GAAG,EAAE;IAC9C,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,aAAa,GAAG,SAAS,CA8B5B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
2
|
+
import { Resource } from "@opentelemetry/resources";
|
|
3
|
+
import { MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics";
|
|
4
|
+
import { childLogger } from "document-drive";
|
|
5
|
+
const logger = childLogger(["switchboard", "metrics"]);
|
|
6
|
+
export function createMeterProviderFromEnv(env) {
|
|
7
|
+
const endpoint = env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
8
|
+
if (!endpoint)
|
|
9
|
+
return undefined;
|
|
10
|
+
const parsed = parseInt(env.OTEL_METRIC_EXPORT_INTERVAL ?? "", 10);
|
|
11
|
+
const exportIntervalMillis = Number.isFinite(parsed) && parsed > 0 ? parsed : 5_000;
|
|
12
|
+
const base = endpoint.replace(/\/$/, "");
|
|
13
|
+
const exporterUrl = base.endsWith("/v1/metrics")
|
|
14
|
+
? base
|
|
15
|
+
: `${base}/v1/metrics`;
|
|
16
|
+
logger.info(`Initializing OpenTelemetry metrics exporter at: ${endpoint}`);
|
|
17
|
+
const meterProvider = new MeterProvider({
|
|
18
|
+
resource: new Resource({
|
|
19
|
+
"service.name": env.OTEL_SERVICE_NAME ?? "switchboard",
|
|
20
|
+
}),
|
|
21
|
+
readers: [
|
|
22
|
+
new PeriodicExportingMetricReader({
|
|
23
|
+
exporter: new OTLPMetricExporter({
|
|
24
|
+
url: exporterUrl,
|
|
25
|
+
}),
|
|
26
|
+
exportIntervalMillis,
|
|
27
|
+
exportTimeoutMillis: Math.max(exportIntervalMillis - 250, 1),
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
logger.info(`Metrics export enabled (interval: ${exportIntervalMillis}ms)`);
|
|
32
|
+
return meterProvider;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EACL,aAAa,EACb,6BAA6B,GAC9B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;AAEvD,MAAM,UAAU,0BAA0B,CAAC,GAI1C;IACC,MAAM,QAAQ,GAAG,GAAG,CAAC,2BAA2B,CAAC;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,2BAA2B,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,oBAAoB,GACxB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAEzD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC9C,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,GAAG,IAAI,aAAa,CAAC;IAEzB,MAAM,CAAC,IAAI,CAAC,mDAAmD,QAAQ,EAAE,CAAC,CAAC;IAC3E,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC;QACtC,QAAQ,EAAE,IAAI,QAAQ,CAAC;YACrB,cAAc,EAAE,GAAG,CAAC,iBAAiB,IAAI,aAAa;SACvD,CAAC;QACF,OAAO,EAAE;YACP,IAAI,6BAA6B,CAAC;gBAChC,QAAQ,EAAE,IAAI,kBAAkB,CAAC;oBAC/B,GAAG,EAAE,WAAW;iBACjB,CAAC;gBACF,oBAAoB;gBACpB,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,oBAAoB,GAAG,GAAG,EAAE,CAAC,CAAC;aAC7D,CAAC;SACH;KACF,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CAAC,qCAAqC,oBAAoB,KAAK,CAAC,CAAC;IAC5E,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/migrate.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Kysely, PostgresDialect } from "kysely";
|
|
3
|
+
import { Pool } from "pg";
|
|
4
|
+
import { runMigrations, getMigrationStatus, REACTOR_SCHEMA, } from "@powerhousedao/reactor";
|
|
5
|
+
import { getConfig } from "@powerhousedao/config/node";
|
|
6
|
+
function isPostgresUrl(url) {
|
|
7
|
+
return url.startsWith("postgresql://") || url.startsWith("postgres://");
|
|
8
|
+
}
|
|
9
|
+
async function main() {
|
|
10
|
+
const command = process.argv[2];
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
const dbPath = process.env.PH_REACTOR_DATABASE_URL ??
|
|
13
|
+
process.env.DATABASE_URL ??
|
|
14
|
+
config.switchboard?.database?.url;
|
|
15
|
+
if (!dbPath || !isPostgresUrl(dbPath)) {
|
|
16
|
+
console.log("No PostgreSQL URL configured. Skipping migrations.");
|
|
17
|
+
console.log("(PGlite migrations are handled automatically on startup)");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log(`Database: ${dbPath}`);
|
|
21
|
+
const pool = new Pool({ connectionString: dbPath });
|
|
22
|
+
const db = new Kysely({
|
|
23
|
+
dialect: new PostgresDialect({ pool }),
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
if (command === "status") {
|
|
27
|
+
console.log("\nChecking migration status...");
|
|
28
|
+
const migrations = await getMigrationStatus(db, REACTOR_SCHEMA);
|
|
29
|
+
console.log("\nMigration Status:");
|
|
30
|
+
console.log("=================");
|
|
31
|
+
for (const migration of migrations) {
|
|
32
|
+
const status = migration.executedAt
|
|
33
|
+
? `[OK] Executed at ${migration.executedAt.toISOString()}`
|
|
34
|
+
: "[--] Pending";
|
|
35
|
+
console.log(`${status} - ${migration.name}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log("\nRunning migrations...");
|
|
40
|
+
const result = await runMigrations(db, REACTOR_SCHEMA);
|
|
41
|
+
if (!result.success) {
|
|
42
|
+
console.error("Migration failed:", result.error?.message);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
if (result.migrationsExecuted.length === 0) {
|
|
46
|
+
console.log("No migrations to run - database is up to date");
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log(`Successfully executed ${result.migrationsExecuted.length} migration(s):`);
|
|
50
|
+
for (const name of result.migrationsExecuted) {
|
|
51
|
+
console.log(` - ${name}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await db.destroy();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
void main();
|
|
65
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/migrate.ts"],"names":[],"mappings":"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"}
|
package/dist/src/profiler.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { PyroscopeConfig } from "@pyroscope/nodejs";
|
|
2
2
|
export declare function initProfilerFromEnv(env: typeof process.env): Promise<void>;
|
|
3
|
-
|
|
3
|
+
interface ProfilerFlags {
|
|
4
|
+
wallEnabled?: boolean;
|
|
5
|
+
heapEnabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function initProfiler(options?: PyroscopeConfig, flags?: ProfilerFlags): Promise<void>;
|
|
8
|
+
export {};
|
|
4
9
|
//# sourceMappingURL=profiler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../src/profiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,OAAO,OAAO,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../src/profiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,OAAO,OAAO,CAAC,GAAG,iBAgChE;AAED,UAAU,aAAa;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,YAAY,CAChC,OAAO,CAAC,EAAE,eAAe,EACzB,KAAK,GAAE,aAAyD,iBAqBjE"}
|
package/dist/src/profiler.js
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
export async function initProfilerFromEnv(env) {
|
|
2
|
-
const { PYROSCOPE_SERVER_ADDRESS: serverAddress, PYROSCOPE_APPLICATION_NAME: appName, PYROSCOPE_USER: basicAuthUser, PYROSCOPE_PASSWORD: basicAuthPassword, } = env;
|
|
2
|
+
const { PYROSCOPE_SERVER_ADDRESS: serverAddress, PYROSCOPE_APPLICATION_NAME: appName, PYROSCOPE_USER: basicAuthUser, PYROSCOPE_PASSWORD: basicAuthPassword, PYROSCOPE_WALL_ENABLED: wallEnabled, PYROSCOPE_HEAP_ENABLED: heapEnabled, } = env;
|
|
3
3
|
const options = {
|
|
4
4
|
serverAddress,
|
|
5
5
|
appName,
|
|
6
6
|
basicAuthUser,
|
|
7
7
|
basicAuthPassword,
|
|
8
|
+
// Wall profiling captures wall-clock time (includes async I/O waits)
|
|
9
|
+
// This shows GraphQL resolvers even when waiting for database
|
|
10
|
+
wall: {
|
|
11
|
+
samplingDurationMs: 10000, // 10 second sampling windows
|
|
12
|
+
samplingIntervalMicros: 10000, // 10ms sampling interval (100 samples/sec)
|
|
13
|
+
collectCpuTime: true, // Also collect CPU time alongside wall time
|
|
14
|
+
},
|
|
15
|
+
// Heap profiling for memory allocation tracking
|
|
16
|
+
heap: {
|
|
17
|
+
samplingIntervalBytes: 512 * 1024, // Sample every 512KB allocated
|
|
18
|
+
stackDepth: 64, // Capture deeper stacks for better context
|
|
19
|
+
},
|
|
8
20
|
};
|
|
9
|
-
return initProfiler(options
|
|
21
|
+
return initProfiler(options, {
|
|
22
|
+
wallEnabled: wallEnabled !== "false",
|
|
23
|
+
heapEnabled: heapEnabled === "true",
|
|
24
|
+
});
|
|
10
25
|
}
|
|
11
|
-
export async function initProfiler(options) {
|
|
26
|
+
export async function initProfiler(options, flags = { wallEnabled: true, heapEnabled: false }) {
|
|
12
27
|
console.log("Initializing Pyroscope profiler at:", options?.serverAddress);
|
|
13
|
-
|
|
28
|
+
console.log(" Wall profiling:", flags.wallEnabled ? "enabled" : "disabled");
|
|
29
|
+
console.log(" Heap profiling:", flags.heapEnabled ? "enabled" : "disabled");
|
|
30
|
+
const { default: Pyroscope } = await import("@pyroscope/nodejs");
|
|
14
31
|
Pyroscope.init(options);
|
|
15
|
-
|
|
32
|
+
// Start wall profiling (captures async I/O time - shows resolvers)
|
|
33
|
+
if (flags.wallEnabled) {
|
|
34
|
+
Pyroscope.startWallProfiling();
|
|
35
|
+
}
|
|
36
|
+
// Start CPU profiling (captures CPU-bound work)
|
|
37
|
+
Pyroscope.startCpuProfiling();
|
|
38
|
+
// Optionally start heap profiling (memory allocations)
|
|
39
|
+
if (flags.heapEnabled) {
|
|
40
|
+
Pyroscope.startHeapProfiling();
|
|
41
|
+
}
|
|
16
42
|
}
|
|
17
43
|
//# sourceMappingURL=profiler.js.map
|
package/dist/src/profiler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../src/profiler.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAuB;IAC/D,MAAM,EACJ,wBAAwB,EAAE,aAAa,EACvC,0BAA0B,EAAE,OAAO,EACnC,cAAc,EAAE,aAAa,EAC7B,kBAAkB,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../src/profiler.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAuB;IAC/D,MAAM,EACJ,wBAAwB,EAAE,aAAa,EACvC,0BAA0B,EAAE,OAAO,EACnC,cAAc,EAAE,aAAa,EAC7B,kBAAkB,EAAE,iBAAiB,EACrC,sBAAsB,EAAE,WAAW,EACnC,sBAAsB,EAAE,WAAW,GACpC,GAAG,GAAG,CAAC;IAER,MAAM,OAAO,GAAoB;QAC/B,aAAa;QACb,OAAO;QACP,aAAa;QACb,iBAAiB;QACjB,qEAAqE;QACrE,8DAA8D;QAC9D,IAAI,EAAE;YACJ,kBAAkB,EAAE,KAAK,EAAE,6BAA6B;YACxD,sBAAsB,EAAE,KAAK,EAAE,2CAA2C;YAC1E,cAAc,EAAE,IAAI,EAAE,4CAA4C;SACnE;QACD,gDAAgD;QAChD,IAAI,EAAE;YACJ,qBAAqB,EAAE,GAAG,GAAG,IAAI,EAAE,+BAA+B;YAClE,UAAU,EAAE,EAAE,EAAE,2CAA2C;SAC5D;KACF,CAAC;IACF,OAAO,YAAY,CAAC,OAAO,EAAE;QAC3B,WAAW,EAAE,WAAW,KAAK,OAAO;QACpC,WAAW,EAAE,WAAW,KAAK,MAAM;KACpC,CAAC,CAAC;AACL,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAyB,EACzB,QAAuB,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE;IAEhE,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAE7E,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACjE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAExB,mEAAmE;IACnE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,SAAS,CAAC,kBAAkB,EAAE,CAAC;IACjC,CAAC;IAED,gDAAgD;IAChD,SAAS,CAAC,iBAAiB,EAAE,CAAC;IAE9B,uDAAuD;IACvD,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,SAAS,CAAC,kBAAkB,EAAE,CAAC;IACjC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type IRenown } from "@renown/sdk/node";
|
|
2
|
+
export interface RenownOptions {
|
|
3
|
+
/** Path to the keypair file. Defaults to .ph/.keypair.json in cwd */
|
|
4
|
+
keypairPath?: string;
|
|
5
|
+
/** If true, won't generate a new keypair if none exists */
|
|
6
|
+
requireExisting?: boolean;
|
|
7
|
+
/** Base url of the Renown instance to use */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Initialize Renown for the Switchboard instance.
|
|
12
|
+
* This allows Switchboard to authenticate with remote services
|
|
13
|
+
* using the same identity established during `ph login`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function initRenown(options?: RenownOptions): Promise<IRenown | null>;
|
|
16
|
+
//# sourceMappingURL=renown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renown.d.ts","sourceRoot":"","sources":["../../src/renown.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,OAAO,EACb,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAqCzB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { childLogger } from "document-drive";
|
|
2
|
+
import { DEFAULT_RENOWN_URL, NodeKeyStorage, RenownBuilder, RenownCryptoBuilder, } from "@renown/sdk/node";
|
|
3
|
+
const logger = childLogger(["switchboard", "renown"]);
|
|
4
|
+
/**
|
|
5
|
+
* Initialize Renown for the Switchboard instance.
|
|
6
|
+
* This allows Switchboard to authenticate with remote services
|
|
7
|
+
* using the same identity established during `ph login`.
|
|
8
|
+
*/
|
|
9
|
+
export async function initRenown(options = {}) {
|
|
10
|
+
const { keypairPath, requireExisting = false, baseUrl = DEFAULT_RENOWN_URL, } = options;
|
|
11
|
+
const keyStorage = new NodeKeyStorage(keypairPath, {
|
|
12
|
+
logger,
|
|
13
|
+
});
|
|
14
|
+
// Check if we have an existing keypair
|
|
15
|
+
const existingKeyPair = await keyStorage.loadKeyPair();
|
|
16
|
+
if (!existingKeyPair && requireExisting) {
|
|
17
|
+
throw new Error("No existing keypair found and requireExisting is true. " +
|
|
18
|
+
'Run "ph login" to create one.');
|
|
19
|
+
}
|
|
20
|
+
if (!existingKeyPair) {
|
|
21
|
+
logger.info("No existing keypair found. A new one will be generated.");
|
|
22
|
+
}
|
|
23
|
+
const renownCrypto = await new RenownCryptoBuilder()
|
|
24
|
+
.withKeyPairStorage(keyStorage)
|
|
25
|
+
.build();
|
|
26
|
+
const renown = await new RenownBuilder("switchboard", {})
|
|
27
|
+
.withCrypto(renownCrypto)
|
|
28
|
+
.withBaseUrl(baseUrl)
|
|
29
|
+
.build();
|
|
30
|
+
logger.info("Switchboard identity initialized: @did", renownCrypto.did);
|
|
31
|
+
return renown;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=renown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renown.js","sourceRoot":"","sources":["../../src/renown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,mBAAmB,GAEpB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;AAWtD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,UAAyB,EAAE;IAE3B,MAAM,EACJ,WAAW,EACX,eAAe,GAAG,KAAK,EACvB,OAAO,GAAG,kBAAkB,GAC7B,GAAG,OAAO,CAAC;IAEZ,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,WAAW,EAAE;QACjD,MAAM;KACP,CAAC,CAAC;IAEH,uCAAuC;IACvC,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,CAAC;IAEvD,IAAI,CAAC,eAAe,IAAI,eAAe,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,yDAAyD;YACvD,+BAA+B,CAClC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,IAAI,mBAAmB,EAAE;SACjD,kBAAkB,CAAC,UAAU,CAAC;SAC9B,KAAK,EAAE,CAAC;IAEX,MAAM,MAAM,GAAG,MAAM,IAAI,aAAa,CAAC,aAAa,EAAE,EAAE,CAAC;SACtD,UAAU,CAAC,YAAY,CAAC;SACxB,WAAW,CAAC,OAAO,CAAC;SACpB,KAAK,EAAE,CAAC;IAEX,MAAM,CAAC,IAAI,CAAC,wCAAwC,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IAExE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/src/server.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import type { StartServerOptions, SwitchboardReactor } from "./types.js";
|
|
3
3
|
export declare const startSwitchboard: (options?: StartServerOptions) => Promise<SwitchboardReactor>;
|
|
4
|
-
export { getBearerToken, getConnectCrypto, getConnectDid, } from "./connect-crypto.js";
|
|
5
4
|
export * from "./types.js";
|
|
6
5
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/src/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";AAsDA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAwYzE,eAAO,MAAM,gBAAgB,GAC3B,UAAS,kBAAuB,KAC/B,OAAO,CAAC,kBAAkB,CAiE5B,CAAC;AAEF,cAAc,YAAY,CAAC"}
|