ras-stack 0.47.0 → 0.47.2
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/LICENSE +21 -661
- package/README.md +12 -16
- package/dist/create/index.js +16 -2
- package/dist/create/index.js.map +1 -1
- package/{examples/full-stack → dist/create/template}/Dockerfile +9 -9
- package/{examples/full-stack → dist/create/template}/Dockerfile.standalone +3 -2
- package/{examples/full-stack → dist/create/template}/package.json +4 -3
- package/dist/runtime/dev.js +1 -1
- package/dist/runtime/dev.js.map +1 -1
- package/package.json +10 -13
- /package/{examples/full-stack → dist/create/template}/.env.example +0 -0
- /package/{examples/full-stack → dist/create/template}/.oxfmtrc.json +0 -0
- /package/{examples/full-stack → dist/create/template}/centrifugo.json +0 -0
- /package/{examples/full-stack → dist/create/template}/dockerignore.template +0 -0
- /package/{examples/full-stack → dist/create/template}/drizzle/0000_production_reference.sql +0 -0
- /package/{examples/full-stack → dist/create/template}/drizzle/meta/_journal.json +0 -0
- /package/{examples/full-stack → dist/create/template}/e2e/full-stack.spec.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/gitignore.template +0 -0
- /package/{examples/full-stack → dist/create/template}/oxlint.json +0 -0
- /package/{examples/full-stack → dist/create/template}/playwright.config.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/pnpm-workspace.template.yaml +0 -0
- /package/{examples/full-stack → dist/create/template}/ras-stack.assets.json +0 -0
- /package/{examples/full-stack → dist/create/template}/scripts/containerRuntime.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/scripts/database.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/scripts/database.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/client/auth.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/client/queries.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/client/queryClient.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/client/useRealtime.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/posthog.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routeTree.gen.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/router.tsx +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/__root.tsx +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/auth.$.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/centrifugo.connect.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/health.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/live.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/ready.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/uploads.$id.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/api/uploads.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/routes/index.tsx +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/app.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/app.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/auth-flow.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/auth.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/environment.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/environment.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/fns.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/messages.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/messages.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/migration.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/outbox.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/outbox.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/posthog.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/rate-limit.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/rate-limit.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/rpc.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/schema.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/session.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/session.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/uploads.test.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/server/uploads.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/start.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/src/styles.css +0 -0
- /package/{examples/full-stack → dist/create/template}/tsconfig.json +0 -0
- /package/{examples/full-stack → dist/create/template}/vite.config.ts +0 -0
- /package/{examples/full-stack → dist/create/template}/vitest.config.ts +0 -0
package/README.md
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
1
|
# 🧱 ras-stack
|
|
4
2
|
|
|
5
3
|
**A practical TypeScript stack with strong defaults and room to make it yours.**
|
|
6
4
|
|
|
7
5
|
TanStack Start · React · Better Auth · Drizzle · SQLite/PostgreSQL · Centrifugo · Caddy · PostHog
|
|
8
6
|
|
|
9
|
-
[](https://www.npmjs.com/package/ras-stack) [](https://github.com/richardsolomou/ras-stack/actions/workflows/ci.yml) [](LICENSE)
|
|
10
|
-
|
|
11
|
-
</div>
|
|
7
|
+
[](https://www.npmjs.com/package/ras-stack) [](https://github.com/richardsolomou/ras-stack/actions/workflows/ci.yml) [](https://github.com/richardsolomou/ras-stack/blob/main/packages/ras-stack/LICENSE)
|
|
12
8
|
|
|
13
9
|
I kept rebuilding the same boring parts: secure sessions, origin checks, database startup, realtime connections, process shutdown, CI, previews, and releases. `ras-stack` solves them once with the libraries I would choose anyway.
|
|
14
10
|
|
|
@@ -54,7 +50,7 @@ Applications still configure every upstream library directly. This table describ
|
|
|
54
50
|
|
|
55
51
|
The application keeps schemas, migrations, repositories, routes, authorization, templates, upload rules, realtime payloads, storage, deployment topology, and UI. There is no shared application factory or giant configuration object.
|
|
56
52
|
|
|
57
|
-
The [`examples/full-stack`](examples/full-stack) workspace shows the boundaries together and tests them through `workspace:*`. It is the repository's integration contract and the canonical source for the generated starter; once generated, the application owns its copied code and normal semver dependency.
|
|
53
|
+
The [`examples/full-stack`](https://github.com/richardsolomou/ras-stack/tree/main/examples/full-stack) workspace shows the boundaries together and tests them through `workspace:*`. It is the repository's integration contract and the canonical source for the generated starter; once generated, the application owns its copied code and normal semver dependency.
|
|
58
54
|
|
|
59
55
|
## Pick what you need 🧩
|
|
60
56
|
|
|
@@ -103,17 +99,17 @@ Three reusable workflows provide the standard pull-request preview lifecycle:
|
|
|
103
99
|
- `deploy-dokploy-preview.yml` publishes, resolves, deploys, reports, and removes previews.
|
|
104
100
|
- `prune-dokploy-previews.yml` cleans up applications and images left behind by interrupted runs.
|
|
105
101
|
|
|
106
|
-
Applications supply only their package, application prefix, port, environment template, and optional product hook. They can provide a custom HTTPS domain, optionally manage a prefixed Cloudflare-proxied record for origins that reject direct traffic, or let Dokploy generate an HTTP `sslip.io` address. The shared `DOKPLOY_URL`, `DOKPLOY_API_KEY`, and staging-only `DOKPLOY_ENVIRONMENT_ID` secrets can be configured once at organization level. See [Repository tooling](docs/repository-tooling.md) for the caller contract, private-registry options, and lifecycle hooks.
|
|
102
|
+
Applications supply only their package, application prefix, port, environment template, and optional product hook. They can provide a custom HTTPS domain, optionally manage a prefixed Cloudflare-proxied record for origins that reject direct traffic, or let Dokploy generate an HTTP `sslip.io` address. The shared `DOKPLOY_URL`, `DOKPLOY_API_KEY`, and staging-only `DOKPLOY_ENVIRONMENT_ID` secrets can be configured once at organization level. See [Repository tooling](https://github.com/richardsolomou/ras-stack/blob/main/docs/repository-tooling.md) for the caller contract, private-registry options, and lifecycle hooks.
|
|
107
103
|
|
|
108
104
|
## Guides 📚
|
|
109
105
|
|
|
110
|
-
| Guide
|
|
111
|
-
|
|
|
112
|
-
| [Application primitives](docs/application-primitives.md) | Authentication, request security, databases, realtime clients, email, uploads, and stateful development resources |
|
|
113
|
-
| [Repository tooling](docs/repository-tooling.md) | TypeScript and Oxlint configuration, generated policy, GitHub Actions, previews, releases, and production runtime composition |
|
|
114
|
-
| [PostHog integration](docs/posthog.md) | Browser/server setup, identity and session correlation, ingest proxying, shutdown, coverage declarations, and source-map responsibility |
|
|
115
|
-
| [Full-stack example](docs/full-stack-example.md) | The `workspace:*` integration contract, local development, production container, and two-browser journey |
|
|
116
|
-
| [Production operations](docs/production-reference-operations.md) | Migration, backup/restore, rollback, configuration, proxy, shutdown, and supply-chain boundaries |
|
|
106
|
+
| Guide | What it covers |
|
|
107
|
+
| ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| [Application primitives](https://github.com/richardsolomou/ras-stack/blob/main/docs/application-primitives.md) | Authentication, request security, databases, realtime clients, email, uploads, and stateful development resources |
|
|
109
|
+
| [Repository tooling](https://github.com/richardsolomou/ras-stack/blob/main/docs/repository-tooling.md) | TypeScript and Oxlint configuration, generated policy, GitHub Actions, previews, releases, and production runtime composition |
|
|
110
|
+
| [PostHog integration](https://github.com/richardsolomou/ras-stack/blob/main/docs/posthog.md) | Browser/server setup, identity and session correlation, ingest proxying, shutdown, coverage declarations, and source-map responsibility |
|
|
111
|
+
| [Full-stack example](https://github.com/richardsolomou/ras-stack/blob/main/docs/full-stack-example.md) | The `workspace:*` integration contract, local development, production container, and two-browser journey |
|
|
112
|
+
| [Production operations](https://github.com/richardsolomou/ras-stack/blob/main/docs/production-reference-operations.md) | Migration, backup/restore, rollback, configuration, proxy, shutdown, and supply-chain boundaries |
|
|
117
113
|
|
|
118
114
|
## Development 🛠️
|
|
119
115
|
|
|
@@ -124,8 +120,8 @@ just install
|
|
|
124
120
|
just check
|
|
125
121
|
```
|
|
126
122
|
|
|
127
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for release instructions. Report vulnerabilities privately as described in [SECURITY.md](SECURITY.md).
|
|
123
|
+
See [CONTRIBUTING.md](https://github.com/richardsolomou/ras-stack/blob/main/CONTRIBUTING.md) for release instructions. Report vulnerabilities privately as described in [SECURITY.md](https://github.com/richardsolomou/ras-stack/blob/main/SECURITY.md).
|
|
128
124
|
|
|
129
125
|
## License
|
|
130
126
|
|
|
131
|
-
[
|
|
127
|
+
[MIT](https://github.com/richardsolomou/ras-stack/blob/main/packages/ras-stack/LICENSE).
|
package/dist/create/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export async function runCreateCli(arguments_) {
|
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
const destination = path.resolve(positional[0]);
|
|
12
|
-
const source =
|
|
12
|
+
const source = await starterSource();
|
|
13
13
|
await assertSource(source);
|
|
14
14
|
await assertEmptyDestination(destination);
|
|
15
15
|
if (dryRun) {
|
|
@@ -31,10 +31,24 @@ export async function runCreateCli(arguments_) {
|
|
|
31
31
|
const packageManifest = JSON.parse(await readFile(path.resolve(import.meta.dirname, '../../package.json'), 'utf8'));
|
|
32
32
|
manifest.name = packageName(path.basename(destination));
|
|
33
33
|
manifest.dependencies['ras-stack'] = `^${packageManifest.version}`;
|
|
34
|
-
manifest.scripts.build = manifest.scripts.build.replaceAll('node ../../dist/cli.js', 'ras');
|
|
34
|
+
manifest.scripts.build = manifest.scripts.build.replaceAll('node ../../packages/ras-stack/dist/cli.js', 'ras');
|
|
35
35
|
await writeFile(packageFile, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
36
36
|
console.log(destination);
|
|
37
37
|
}
|
|
38
|
+
async function starterSource() {
|
|
39
|
+
const bundled = path.resolve(import.meta.dirname, 'template');
|
|
40
|
+
try {
|
|
41
|
+
await assertSource(bundled);
|
|
42
|
+
return bundled;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error.code !== 'ENOENT')
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
const workspace = path.resolve(import.meta.dirname, '../../../../examples/full-stack');
|
|
49
|
+
await assertSource(workspace);
|
|
50
|
+
return workspace;
|
|
51
|
+
}
|
|
38
52
|
async function materializeTemplate(directory, template, output) {
|
|
39
53
|
const source = path.join(directory, template);
|
|
40
54
|
await copyFile(source, path.join(directory, output));
|
package/dist/create/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/create/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC9F,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAoB;IACrD,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC/C,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAA;IAC5E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAA;QAC1D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC,CAAA;IAChD,MAAM,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/create/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { copyFile, cp, mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nexport async function runCreateCli(arguments_: string[]) {\n const dryRun = arguments_.includes('--dry-run')\n const positional = arguments_.filter((argument) => argument !== '--dry-run')\n if (positional.length !== 1) {\n console.error('usage: ras create <directory> [--dry-run]')\n process.exitCode = 2\n return\n }\n const destination = path.resolve(positional[0]!)\n const source = await starterSource()\n await assertSource(source)\n await assertEmptyDestination(destination)\n if (dryRun) {\n console.log(destination)\n return\n }\n await mkdir(destination, { recursive: true })\n await cp(source, destination, {\n recursive: true,\n filter: (entry) => !excluded(path.relative(source, entry)),\n })\n await materializeTemplate(destination, 'gitignore.template', '.gitignore')\n await materializeTemplate(destination, 'dockerignore.template', '.dockerignore')\n await materializeTemplate(destination, 'pnpm-workspace.template.yaml', 'pnpm-workspace.yaml')\n await copyFile(path.join(destination, 'Dockerfile.standalone'), path.join(destination, 'Dockerfile'))\n await rm(path.join(destination, 'Dockerfile.standalone'))\n const packageFile = path.join(destination, 'package.json')\n const manifest = JSON.parse(await readFile(packageFile, 'utf8')) as {\n name: string\n dependencies: Record<string, string>\n scripts: Record<string, string>\n }\n const packageManifest = JSON.parse(await readFile(path.resolve(import.meta.dirname, '../../package.json'), 'utf8')) as { version: string }\n manifest.name = packageName(path.basename(destination))\n manifest.dependencies['ras-stack'] = `^${packageManifest.version}`\n manifest.scripts.build = manifest.scripts.build!.replaceAll('node ../../packages/ras-stack/dist/cli.js', 'ras')\n await writeFile(packageFile, `${JSON.stringify(manifest, null, 2)}\\n`)\n console.log(destination)\n}\n\nasync function starterSource() {\n const bundled = path.resolve(import.meta.dirname, 'template')\n try {\n await assertSource(bundled)\n return bundled\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n const workspace = path.resolve(import.meta.dirname, '../../../../examples/full-stack')\n await assertSource(workspace)\n return workspace\n}\n\nasync function materializeTemplate(directory: string, template: string, output: string) {\n const source = path.join(directory, template)\n await copyFile(source, path.join(directory, output))\n await rm(source)\n}\n\nfunction excluded(relative: string) {\n const [root] = relative.split(path.sep)\n return ['.output', '.data', 'node_modules', 'test-results'].includes(root ?? '')\n}\n\nasync function assertSource(source: string) {\n if (!(await stat(path.join(source, 'package.json'))).isFile()) throw new Error('The packaged full-stack starter is missing')\n}\n\nasync function assertEmptyDestination(destination: string) {\n try {\n const info = await stat(destination)\n if (!info.isDirectory() || (await readdir(destination)).length > 0)\n throw new Error(`Destination must be an empty directory: ${destination}`)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n}\n\nfunction packageName(name: string) {\n const normalized = name\n .toLowerCase()\n .replaceAll(/[^a-z\\d._-]/g, '-')\n .replaceAll(/^-+|-+$/g, '')\n return normalized || 'ras-stack-app'\n}\n"]}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# syntax=docker/dockerfile:1
|
|
2
|
-
ARG RUNTIME_BINARIES_IMAGE=ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.
|
|
2
|
+
ARG RUNTIME_BINARIES_IMAGE=ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.2@sha256:311119db377ac80e87b3116e634912eeca2059b16c170a4d342923de3fd90ba9
|
|
3
3
|
FROM node:24-alpine AS build
|
|
4
4
|
WORKDIR /app
|
|
5
5
|
RUN apk add --no-cache python3 make g++
|
|
6
6
|
RUN corepack enable && corepack install --global pnpm@11.15.0
|
|
7
7
|
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
8
|
+
COPY packages/ras-stack/package.json ./packages/ras-stack/package.json
|
|
9
|
+
COPY packages/create-ras-app/package.json ./packages/create-ras-app/package.json
|
|
10
|
+
COPY apps/web/package.json ./apps/web/package.json
|
|
8
11
|
COPY examples/full-stack/package.json ./examples/full-stack/package.json
|
|
9
12
|
RUN pnpm fetch --frozen-lockfile
|
|
10
|
-
COPY
|
|
11
|
-
COPY dist ./dist
|
|
12
|
-
COPY src ./src
|
|
13
|
-
COPY scripts ./scripts
|
|
14
|
-
COPY tsconfig.json tsconfig.build.json LICENSE README.md ./
|
|
13
|
+
COPY packages/ras-stack ./packages/ras-stack
|
|
15
14
|
COPY examples/full-stack ./examples/full-stack
|
|
16
15
|
RUN pnpm install --offline --frozen-lockfile
|
|
17
|
-
RUN pnpm build && pnpm --filter @ras-stack/example-full-stack build
|
|
16
|
+
RUN pnpm --filter ras-stack build && pnpm --filter @ras-stack/example-full-stack build
|
|
18
17
|
|
|
19
18
|
FROM ${RUNTIME_BINARIES_IMAGE} AS runtime-binaries
|
|
20
19
|
|
|
21
20
|
FROM node:24-alpine
|
|
22
21
|
WORKDIR /app
|
|
23
|
-
RUN apk
|
|
22
|
+
RUN apk upgrade --no-cache \
|
|
23
|
+
&& apk add --no-cache tini \
|
|
24
24
|
&& rm -rf /usr/local/lib/node_modules/corepack /usr/local/lib/node_modules/npm /opt/yarn-v1.22.22 \
|
|
25
25
|
&& rm -f /usr/local/bin/corepack /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
26
26
|
&& mkdir -p /data \
|
|
@@ -29,7 +29,7 @@ COPY --from=build --chown=node:node /app/examples/full-stack/.output ./.output
|
|
|
29
29
|
COPY --from=runtime-binaries /usr/local/bin/centrifugo /usr/local/bin/centrifugo
|
|
30
30
|
COPY --from=runtime-binaries /usr/local/bin/caddy /usr/local/bin/caddy
|
|
31
31
|
COPY --chown=node:node examples/full-stack/centrifugo.json ./centrifugo.json
|
|
32
|
-
COPY --chown=node:node LICENSE ./
|
|
32
|
+
COPY --chown=node:node packages/ras-stack/LICENSE ./
|
|
33
33
|
ENV NODE_ENV=production DATA_DIR=/data TRUST_PROXY=false CENTRIFUGO_CONFIG=/app/centrifugo.json CENTRIFUGO_API_URL=http://127.0.0.1:8100/api CENTRIFUGO_HTTP_SERVER_PORT=8100
|
|
34
34
|
EXPOSE 3100
|
|
35
35
|
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=3 CMD wget -q --spider http://127.0.0.1:3100/api/ready || exit 1
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# syntax=docker/dockerfile:1
|
|
2
|
-
ARG RUNTIME_BINARIES_IMAGE=ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.
|
|
2
|
+
ARG RUNTIME_BINARIES_IMAGE=ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.2@sha256:311119db377ac80e87b3116e634912eeca2059b16c170a4d342923de3fd90ba9
|
|
3
3
|
FROM node:24-alpine AS build
|
|
4
4
|
WORKDIR /app
|
|
5
5
|
RUN apk add --no-cache python3 make g++
|
|
@@ -12,7 +12,8 @@ FROM ${RUNTIME_BINARIES_IMAGE} AS runtime-binaries
|
|
|
12
12
|
|
|
13
13
|
FROM node:24-alpine
|
|
14
14
|
WORKDIR /app
|
|
15
|
-
RUN apk
|
|
15
|
+
RUN apk upgrade --no-cache \
|
|
16
|
+
&& apk add --no-cache tini \
|
|
16
17
|
&& rm -rf /usr/local/lib/node_modules/corepack /usr/local/lib/node_modules/npm /opt/yarn-v1.22.22 \
|
|
17
18
|
&& rm -f /usr/local/bin/corepack /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
18
19
|
&& mkdir -p /data \
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"build": "vite build && node ../../dist/cli.js assets sync && esbuild scripts/containerRuntime.ts scripts/database.ts --bundle --platform=node --format=esm --target=node24 --external:better-sqlite3 --outdir=.output/server --out-extension:.js=.mjs --log-level=warning && node ../../dist/cli.js assets check",
|
|
6
|
+
"build": "vite build && node ../../packages/ras-stack/dist/cli.js assets sync && esbuild scripts/containerRuntime.ts scripts/database.ts --bundle --platform=node --format=esm --target=node24 --external:better-sqlite3 --outdir=.output/server --out-extension:.js=.mjs --log-level=warning && node ../../packages/ras-stack/dist/cli.js assets check",
|
|
7
7
|
"dev": "vite dev",
|
|
8
8
|
"format": "oxfmt --write .",
|
|
9
9
|
"format:check": "oxfmt --check .",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@tanstack/react-start": "^1.168.32",
|
|
30
30
|
"better-auth": "1.7.1",
|
|
31
31
|
"better-sqlite3": "12.11.1",
|
|
32
|
-
"centrifuge": "5.7.
|
|
32
|
+
"centrifuge": "5.7.1",
|
|
33
33
|
"drizzle-orm": "0.45.2",
|
|
34
34
|
"nodemailer": "^9.0.3",
|
|
35
35
|
"posthog-js": "^1.414.0",
|
|
@@ -49,8 +49,9 @@
|
|
|
49
49
|
"@vitejs/plugin-react": "^6.0.5",
|
|
50
50
|
"esbuild": "0.28.2",
|
|
51
51
|
"nitro": "3.0.260610-beta",
|
|
52
|
-
"oxfmt": "^0.
|
|
52
|
+
"oxfmt": "^0.63.0",
|
|
53
53
|
"oxlint": "^1.74.0",
|
|
54
|
+
"oxlint-tsgolint": "^7.0.2001",
|
|
54
55
|
"typescript": "^7.0.2",
|
|
55
56
|
"vite": "8.2.1",
|
|
56
57
|
"vitest": "^4.1.10"
|
package/dist/runtime/dev.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { access } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
const runtimeImage = 'ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.
|
|
4
|
+
const runtimeImage = 'ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.2@sha256:311119db377ac80e87b3116e634912eeca2059b16c170a4d342923de3fd90ba9';
|
|
5
5
|
export async function runRealtimeDev(options, dependencies = {}) {
|
|
6
6
|
const configPath = path.resolve(options.configPath);
|
|
7
7
|
try {
|
package/dist/runtime/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/runtime/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from 'node:child_process'\nimport { access } from 'node:fs/promises'\nimport path from 'node:path'\n\nconst runtimeImage =\n 'ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.1@sha256:581a691b59a603685bee8ba9576e80d419b967b63017f82d778fce39ca6f0c0b'\n\nexport type RealtimeDevOptions = {\n configPath: string\n containerName: string\n port: number\n bindAddress?: string\n origin: string\n secret: string\n detached?: boolean\n connectProxyEndpoint?: string\n}\n\ntype CommandResult = { code: number }\ntype RunCommand = (command: string, args: readonly string[]) => Promise<CommandResult>\ntype RealtimeDevDependencies = { remove?: (containerName: string) => Promise<void>; run?: RunCommand }\n\nexport async function runRealtimeDev(options: RealtimeDevOptions, dependencies: RealtimeDevDependencies = {}) {\n const configPath = path.resolve(options.configPath)\n try {\n await access(configPath)\n } catch (error) {\n throw new Error(`realtime config is unavailable: ${configPath}`, { cause: error })\n }\n const containerName = dockerName(options.containerName)\n const publicPort = tcpPort(options.port)\n const bindAddress = dockerBindAddress(options.bindAddress ?? '127.0.0.1')\n const origin = httpUrl(options.origin, 'origin')\n const secret = required(options.secret, 'secret')\n const connectProxyEndpoint = options.connectProxyEndpoint ? httpEndpoint(options.connectProxyEndpoint) : undefined\n const run = dependencies.run ?? runCommand\n const remove = dependencies.remove ?? removeContainer\n\n try {\n if (options.detached) await remove(containerName)\n const result = await run('docker', [\n 'run',\n '--rm',\n ...(options.detached ? ['-d'] : []),\n '--name',\n containerName,\n '--add-host',\n 'host.docker.internal:host-gateway',\n '-p',\n `${bindAddress}:${publicPort}:8000`,\n '-e',\n `CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY=${secret}`,\n '-e',\n 'CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_ENABLED=true',\n '-e',\n `CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_HMAC_SECRET_KEY=${secret}`,\n '-e',\n `CENTRIFUGO_HTTP_API_KEY=${secret}`,\n '-e',\n `CENTRIFUGO_CLIENT_ALLOWED_ORIGINS=${origin}`,\n '-e',\n `CENTRIFUGO_VAR_PROXY_SECRET=${secret}`,\n ...(connectProxyEndpoint ? ['-e', `CENTRIFUGO_CLIENT_PROXY_CONNECT_ENDPOINT=${connectProxyEndpoint}`] : []),\n '-v',\n `${configPath}:/centrifugo/config.json:ro`,\n runtimeImage,\n '/usr/local/bin/centrifugo',\n '--config=/centrifugo/config.json',\n '--health.enabled',\n ])\n if (result.code !== 0) throw new Error(`Docker exited with status ${result.code}`)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error('Docker is required but was not found', { cause: error })\n }\n throw error\n }\n}\n\nexport function parseRealtimeDevArguments(arguments_: readonly string[]): RealtimeDevOptions {\n const values = new Map<string, string>()\n let detached = false\n for (let index = 0; index < arguments_.length; index += 1) {\n const argument = arguments_[index]!\n if (argument === '--detach') {\n detached = true\n continue\n }\n if (!['--config', '--name', '--port', '--bind-address', '--origin', '--secret', '--connect-proxy-endpoint'].includes(argument)) {\n throw new Error(`unknown argument: ${argument}`)\n }\n const value = arguments_[index + 1]\n if (!value || value.startsWith('--')) throw new Error(`${argument} requires a value`)\n values.set(argument, value)\n index += 1\n }\n const connectProxyEndpoint = values.get('--connect-proxy-endpoint')\n const bindAddress = values.get('--bind-address')\n return {\n configPath: required(values.get('--config'), '--config'),\n containerName: required(values.get('--name'), '--name'),\n port: Number(required(values.get('--port'), '--port')),\n ...(bindAddress ? { bindAddress } : {}),\n origin: required(values.get('--origin'), '--origin'),\n secret: required(values.get('--secret'), '--secret'),\n ...(detached ? { detached: true } : {}),\n ...(connectProxyEndpoint ? { connectProxyEndpoint } : {}),\n }\n}\n\nasync function runCommand(command: string, args: readonly string[]) {\n return new Promise<CommandResult>((resolve, reject) => {\n const child = spawn(command, [...args], { stdio: 'inherit' })\n child.once('error', reject)\n child.once('exit', (code) => resolve({ code: code ?? 1 }))\n })\n}\n\nasync function removeContainer(containerName: string) {\n await new Promise<void>((resolve, reject) => {\n const child = spawn('docker', ['rm', '--force', containerName], { stdio: 'ignore' })\n child.once('error', reject)\n child.once('exit', () => resolve())\n })\n}\n\nfunction required(value: string | undefined, name: string) {\n const normalized = value?.trim()\n if (!normalized) throw new Error(`${name} is required`)\n return normalized\n}\n\nfunction dockerName(value: string) {\n const normalized = required(value, 'containerName')\n if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(normalized)) throw new Error('containerName is invalid')\n return normalized\n}\n\nfunction tcpPort(value: number) {\n if (!Number.isInteger(value) || value < 1 || value > 65_535) throw new Error('port must be a valid TCP port')\n return value\n}\n\nfunction dockerBindAddress(value: string) {\n if (value !== '127.0.0.1' && value !== '0.0.0.0') throw new Error('bindAddress must be 127.0.0.1 or 0.0.0.0')\n return value\n}\n\nfunction httpUrl(value: string, name: string) {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error(`${name} must be an HTTP URL`)\n }\n if (\n !['http:', 'https:'].includes(parsed.protocol) ||\n parsed.username ||\n parsed.password ||\n parsed.pathname !== '/' ||\n parsed.search ||\n parsed.hash\n ) {\n throw new Error(`${name} must be an HTTP origin`)\n }\n return parsed.origin\n}\n\nfunction httpEndpoint(value: string) {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error('connectProxyEndpoint must be an HTTP URL')\n }\n if (!['http:', 'https:'].includes(parsed.protocol) || parsed.username || parsed.password || parsed.search || parsed.hash) {\n throw new Error('connectProxyEndpoint must be an HTTP URL without credentials, query, or fragment')\n }\n return parsed.toString()\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/runtime/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,YAAY,GAChB,0IAA0I,CAAA;AAiB5I,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA2B,EAAE,YAAY,GAA4B,EAAE;IAC1G,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACnD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,mCAAmC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;IACpF,CAAC;IACD,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,WAAW,IAAI,WAAW,CAAC,CAAA;IACzE,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IACjD,MAAM,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAClH,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,IAAI,UAAU,CAAA;IAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,eAAe,CAAA;IAErD,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ;YAAE,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QACjD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,EAAE;YACjC,KAAK;YACL,MAAM;YACN,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnC,QAAQ;YACR,aAAa;YACb,YAAY;YACZ,mCAAmC;YACnC,IAAI;YACJ,GAAG,WAAW,IAAI,UAAU,OAAO;YACnC,IAAI;YACJ,2CAA2C,MAAM,EAAE;YACnD,IAAI;YACJ,mDAAmD;YACnD,IAAI;YACJ,wDAAwD,MAAM,EAAE;YAChE,IAAI;YACJ,2BAA2B,MAAM,EAAE;YACnC,IAAI;YACJ,qCAAqC,MAAM,EAAE;YAC7C,IAAI;YACJ,+BAA+B,MAAM,EAAE;YACvC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,4CAA4C,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3G,IAAI;YACJ,GAAG,UAAU,6BAA6B;YAC1C,YAAY;YACZ,2BAA2B;YAC3B,kCAAkC;YAClC,kBAAkB;SACnB,CAAC,CAAA;QACF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IACpF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,sCAAsC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;QAC3E,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,UAA6B;IACrE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IACxC,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAE,CAAA;QACnC,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC5B,QAAQ,GAAG,IAAI,CAAA;YACf,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/H,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAA;QAClD,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,mBAAmB,CAAC,CAAA;QACrF,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QAC3B,KAAK,IAAI,CAAC,CAAA;IACZ,CAAC;IACD,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;IACnE,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChD,OAAO;QACL,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;QACxD,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACvD,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QACtD,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;QACpD,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;QACpD,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1D,CAAA;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,IAAuB;IAChE,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QAC7D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC3B,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,aAAqB;IAClD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QACpF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC3B,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB,EAAE,IAAY;IACvD,MAAM,UAAU,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;IAChC,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,cAAc,CAAC,CAAA;IACvD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAA;IACnD,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IACjG,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,KAAa;IAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAC7G,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7G,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,OAAO,CAAC,KAAa,EAAE,IAAY;IAC1C,IAAI,MAAW,CAAA;IACf,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,CAAA;IAChD,CAAC;IACD,IACE,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC9C,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,QAAQ,KAAK,GAAG;QACvB,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,IAAI,EACX,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yBAAyB,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,MAAW,CAAA;IACf,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACzH,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAA;IACrG,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAA;AAC1B,CAAC","sourcesContent":["import { spawn } from 'node:child_process'\nimport { access } from 'node:fs/promises'\nimport path from 'node:path'\n\nconst runtimeImage =\n 'ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.2@sha256:311119db377ac80e87b3116e634912eeca2059b16c170a4d342923de3fd90ba9'\n\nexport type RealtimeDevOptions = {\n configPath: string\n containerName: string\n port: number\n bindAddress?: string\n origin: string\n secret: string\n detached?: boolean\n connectProxyEndpoint?: string\n}\n\ntype CommandResult = { code: number }\ntype RunCommand = (command: string, args: readonly string[]) => Promise<CommandResult>\ntype RealtimeDevDependencies = { remove?: (containerName: string) => Promise<void>; run?: RunCommand }\n\nexport async function runRealtimeDev(options: RealtimeDevOptions, dependencies: RealtimeDevDependencies = {}) {\n const configPath = path.resolve(options.configPath)\n try {\n await access(configPath)\n } catch (error) {\n throw new Error(`realtime config is unavailable: ${configPath}`, { cause: error })\n }\n const containerName = dockerName(options.containerName)\n const publicPort = tcpPort(options.port)\n const bindAddress = dockerBindAddress(options.bindAddress ?? '127.0.0.1')\n const origin = httpUrl(options.origin, 'origin')\n const secret = required(options.secret, 'secret')\n const connectProxyEndpoint = options.connectProxyEndpoint ? httpEndpoint(options.connectProxyEndpoint) : undefined\n const run = dependencies.run ?? runCommand\n const remove = dependencies.remove ?? removeContainer\n\n try {\n if (options.detached) await remove(containerName)\n const result = await run('docker', [\n 'run',\n '--rm',\n ...(options.detached ? ['-d'] : []),\n '--name',\n containerName,\n '--add-host',\n 'host.docker.internal:host-gateway',\n '-p',\n `${bindAddress}:${publicPort}:8000`,\n '-e',\n `CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY=${secret}`,\n '-e',\n 'CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_ENABLED=true',\n '-e',\n `CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_HMAC_SECRET_KEY=${secret}`,\n '-e',\n `CENTRIFUGO_HTTP_API_KEY=${secret}`,\n '-e',\n `CENTRIFUGO_CLIENT_ALLOWED_ORIGINS=${origin}`,\n '-e',\n `CENTRIFUGO_VAR_PROXY_SECRET=${secret}`,\n ...(connectProxyEndpoint ? ['-e', `CENTRIFUGO_CLIENT_PROXY_CONNECT_ENDPOINT=${connectProxyEndpoint}`] : []),\n '-v',\n `${configPath}:/centrifugo/config.json:ro`,\n runtimeImage,\n '/usr/local/bin/centrifugo',\n '--config=/centrifugo/config.json',\n '--health.enabled',\n ])\n if (result.code !== 0) throw new Error(`Docker exited with status ${result.code}`)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error('Docker is required but was not found', { cause: error })\n }\n throw error\n }\n}\n\nexport function parseRealtimeDevArguments(arguments_: readonly string[]): RealtimeDevOptions {\n const values = new Map<string, string>()\n let detached = false\n for (let index = 0; index < arguments_.length; index += 1) {\n const argument = arguments_[index]!\n if (argument === '--detach') {\n detached = true\n continue\n }\n if (!['--config', '--name', '--port', '--bind-address', '--origin', '--secret', '--connect-proxy-endpoint'].includes(argument)) {\n throw new Error(`unknown argument: ${argument}`)\n }\n const value = arguments_[index + 1]\n if (!value || value.startsWith('--')) throw new Error(`${argument} requires a value`)\n values.set(argument, value)\n index += 1\n }\n const connectProxyEndpoint = values.get('--connect-proxy-endpoint')\n const bindAddress = values.get('--bind-address')\n return {\n configPath: required(values.get('--config'), '--config'),\n containerName: required(values.get('--name'), '--name'),\n port: Number(required(values.get('--port'), '--port')),\n ...(bindAddress ? { bindAddress } : {}),\n origin: required(values.get('--origin'), '--origin'),\n secret: required(values.get('--secret'), '--secret'),\n ...(detached ? { detached: true } : {}),\n ...(connectProxyEndpoint ? { connectProxyEndpoint } : {}),\n }\n}\n\nasync function runCommand(command: string, args: readonly string[]) {\n return new Promise<CommandResult>((resolve, reject) => {\n const child = spawn(command, [...args], { stdio: 'inherit' })\n child.once('error', reject)\n child.once('exit', (code) => resolve({ code: code ?? 1 }))\n })\n}\n\nasync function removeContainer(containerName: string) {\n await new Promise<void>((resolve, reject) => {\n const child = spawn('docker', ['rm', '--force', containerName], { stdio: 'ignore' })\n child.once('error', reject)\n child.once('exit', () => resolve())\n })\n}\n\nfunction required(value: string | undefined, name: string) {\n const normalized = value?.trim()\n if (!normalized) throw new Error(`${name} is required`)\n return normalized\n}\n\nfunction dockerName(value: string) {\n const normalized = required(value, 'containerName')\n if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(normalized)) throw new Error('containerName is invalid')\n return normalized\n}\n\nfunction tcpPort(value: number) {\n if (!Number.isInteger(value) || value < 1 || value > 65_535) throw new Error('port must be a valid TCP port')\n return value\n}\n\nfunction dockerBindAddress(value: string) {\n if (value !== '127.0.0.1' && value !== '0.0.0.0') throw new Error('bindAddress must be 127.0.0.1 or 0.0.0.0')\n return value\n}\n\nfunction httpUrl(value: string, name: string) {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error(`${name} must be an HTTP URL`)\n }\n if (\n !['http:', 'https:'].includes(parsed.protocol) ||\n parsed.username ||\n parsed.password ||\n parsed.pathname !== '/' ||\n parsed.search ||\n parsed.hash\n ) {\n throw new Error(`${name} must be an HTTP origin`)\n }\n return parsed.origin\n}\n\nfunction httpEndpoint(value: string) {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error('connectProxyEndpoint must be an HTTP URL')\n }\n if (!['http:', 'https:'].includes(parsed.protocol) || parsed.username || parsed.password || parsed.search || parsed.hash) {\n throw new Error('connectProxyEndpoint must be an HTTP URL without credentials, query, or fragment')\n }\n return parsed.toString()\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ras-stack",
|
|
3
|
-
"version": "0.47.
|
|
3
|
+
"version": "0.47.2",
|
|
4
4
|
"description": "Composable full-stack primitives shared across Richard Solomou's applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authentication",
|
|
@@ -9,20 +9,20 @@
|
|
|
9
9
|
"tanstack",
|
|
10
10
|
"tus"
|
|
11
11
|
],
|
|
12
|
-
"homepage": "https://github.com/richardsolomou/ras-stack#readme",
|
|
12
|
+
"homepage": "https://github.com/richardsolomou/ras-stack/tree/main/packages/ras-stack#readme",
|
|
13
13
|
"bugs": "https://github.com/richardsolomou/ras-stack/issues",
|
|
14
|
-
"license": "
|
|
14
|
+
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/richardsolomou/ras-stack.git"
|
|
17
|
+
"url": "git+https://github.com/richardsolomou/ras-stack.git",
|
|
18
|
+
"directory": "packages/ras-stack"
|
|
18
19
|
},
|
|
19
20
|
"bin": {
|
|
20
21
|
"ras": "./dist/cli.js"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"dist",
|
|
24
|
-
"config"
|
|
25
|
-
"examples/full-stack"
|
|
25
|
+
"config"
|
|
26
26
|
],
|
|
27
27
|
"type": "module",
|
|
28
28
|
"sideEffects": false,
|
|
@@ -154,12 +154,10 @@
|
|
|
154
154
|
"yaml": "^2.8.2"
|
|
155
155
|
},
|
|
156
156
|
"devDependencies": {
|
|
157
|
-
"@changesets/cli": "^2.31.1",
|
|
158
157
|
"@opentelemetry/api-logs": "^0.221.0",
|
|
159
158
|
"@opentelemetry/exporter-logs-otlp-http": "^0.221.0",
|
|
160
159
|
"@opentelemetry/resources": "^2.10.0",
|
|
161
160
|
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
162
|
-
"@playwright/test": "1.62.1",
|
|
163
161
|
"@posthog/react": "^1.10.3",
|
|
164
162
|
"@tanstack/react-query": "^5.101.4",
|
|
165
163
|
"@tanstack/react-start": "^1.168.32",
|
|
@@ -170,10 +168,10 @@
|
|
|
170
168
|
"@types/react-test-renderer": "19.1.0",
|
|
171
169
|
"@vitest/coverage-v8": "^4.1.10",
|
|
172
170
|
"better-sqlite3": "12.11.1",
|
|
173
|
-
"centrifuge": "5.7.
|
|
171
|
+
"centrifuge": "5.7.1",
|
|
174
172
|
"drizzle-orm": "0.45.2",
|
|
175
173
|
"nodemailer": "^9.0.3",
|
|
176
|
-
"oxfmt": "^0.
|
|
174
|
+
"oxfmt": "^0.63.0",
|
|
177
175
|
"oxlint": "^1.74.0",
|
|
178
176
|
"oxlint-tsgolint": "^7.0.2001",
|
|
179
177
|
"postgres": "3.4.9",
|
|
@@ -258,7 +256,7 @@
|
|
|
258
256
|
"node": ">=24 <25"
|
|
259
257
|
},
|
|
260
258
|
"scripts": {
|
|
261
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
259
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/copyStarter.mjs",
|
|
262
260
|
"config:check": "tsc -p test/config-consumer/tsconfig.json && tsc -p test/config-consumer/tsconfig-bundler.json && tsc -p test/config-consumer/tsconfig-node-bundler.json && tsc -p test/config-consumer/tsconfig-library.json && oxlint --config config/oxlint/application.json --print-config > /dev/null && oxlint --config config/oxlint/tanstack.json --print-config > /dev/null",
|
|
263
261
|
"typecheck": "tsc --noEmit",
|
|
264
262
|
"lint": "oxlint --type-aware --deny-warnings .",
|
|
@@ -267,7 +265,6 @@
|
|
|
267
265
|
"test": "vitest run --config vitest.config.ts",
|
|
268
266
|
"package:check": "node scripts/checkPackedPackage.mjs",
|
|
269
267
|
"peer:floor": "node scripts/checkPeerFloor.mjs",
|
|
270
|
-
"check": "pnpm format:check && pnpm lint && pnpm config:check && pnpm typecheck && pnpm test && pnpm build && pnpm package:check
|
|
271
|
-
"version-packages": "changeset version"
|
|
268
|
+
"check": "pnpm format:check && pnpm lint && pnpm config:check && pnpm typecheck && pnpm test && pnpm build && pnpm package:check"
|
|
272
269
|
}
|
|
273
270
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|