ras-stack 2.0.2 → 3.0.1
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 +19 -46
- package/dist/changesets/cli.d.ts +1 -0
- package/dist/changesets/cli.js +14 -0
- package/dist/changesets/cli.js.map +1 -0
- package/dist/{policy/changesets.js → changesets/index.js} +1 -1
- package/dist/changesets/index.js.map +1 -0
- package/dist/cli.d.ts +2 -6
- package/dist/cli.js +3 -7
- package/dist/cli.js.map +1 -1
- package/dist/email/index.d.ts +1 -2
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/posthog/index.d.ts +0 -2
- package/dist/posthog/index.js +0 -1
- package/dist/posthog/index.js.map +1 -1
- package/package.json +14 -41
- package/config/oxlint/application.json +0 -16
- package/config/oxlint/domain.json +0 -29
- package/config/oxlint/layers.json +0 -116
- package/config/oxlint/tanstack.json +0 -4
- package/config/oxlint.json +0 -19
- package/config/typescript/base.json +0 -10
- package/config/typescript/browser.json +0 -8
- package/config/typescript/bundler.json +0 -9
- package/config/typescript/library.json +0 -11
- package/config/typescript/node-bundler.json +0 -9
- package/config/typescript/tanstack.json +0 -6
- package/dist/create/index.d.ts +0 -1
- package/dist/create/index.js +0 -83
- package/dist/create/index.js.map +0 -1
- package/dist/create/template/.env.example +0 -16
- package/dist/create/template/.oxfmtrc.json +0 -7
- package/dist/create/template/Dockerfile +0 -37
- package/dist/create/template/Dockerfile.standalone +0 -29
- package/dist/create/template/centrifugo.json +0 -14
- package/dist/create/template/dockerignore.template +0 -8
- package/dist/create/template/drizzle/0000_production_reference.sql +0 -114
- package/dist/create/template/drizzle/meta/_journal.json +0 -13
- package/dist/create/template/e2e/full-stack.spec.ts +0 -54
- package/dist/create/template/gitignore.template +0 -9
- package/dist/create/template/oxlint.json +0 -4
- package/dist/create/template/package.json +0 -60
- package/dist/create/template/playwright.config.ts +0 -7
- package/dist/create/template/pnpm-workspace.template.yaml +0 -13
- package/dist/create/template/ras-stack.assets.json +0 -4
- package/dist/create/template/scripts/containerRuntime.ts +0 -29
- package/dist/create/template/scripts/database.test.ts +0 -121
- package/dist/create/template/scripts/database.ts +0 -105
- package/dist/create/template/src/client/auth.ts +0 -3
- package/dist/create/template/src/client/queries.ts +0 -4
- package/dist/create/template/src/client/queryClient.ts +0 -1
- package/dist/create/template/src/client/useRealtime.ts +0 -20
- package/dist/create/template/src/posthog.ts +0 -21
- package/dist/create/template/src/routeTree.gen.ts +0 -230
- package/dist/create/template/src/router.tsx +0 -17
- package/dist/create/template/src/routes/__root.tsx +0 -40
- package/dist/create/template/src/routes/api/auth.$.ts +0 -8
- package/dist/create/template/src/routes/api/centrifugo.connect.ts +0 -29
- package/dist/create/template/src/routes/api/health.ts +0 -6
- package/dist/create/template/src/routes/api/live.ts +0 -5
- package/dist/create/template/src/routes/api/ready.ts +0 -30
- package/dist/create/template/src/routes/api/uploads.$id.ts +0 -40
- package/dist/create/template/src/routes/api/uploads.ts +0 -25
- package/dist/create/template/src/routes/index.tsx +0 -189
- package/dist/create/template/src/server/app.test.ts +0 -24
- package/dist/create/template/src/server/app.ts +0 -172
- package/dist/create/template/src/server/auth-flow.test.ts +0 -150
- package/dist/create/template/src/server/auth.ts +0 -56
- package/dist/create/template/src/server/environment.test.ts +0 -43
- package/dist/create/template/src/server/environment.ts +0 -67
- package/dist/create/template/src/server/fns.ts +0 -38
- package/dist/create/template/src/server/messages.test.ts +0 -38
- package/dist/create/template/src/server/messages.ts +0 -28
- package/dist/create/template/src/server/migration.test.ts +0 -34
- package/dist/create/template/src/server/outbox.test.ts +0 -130
- package/dist/create/template/src/server/outbox.ts +0 -110
- package/dist/create/template/src/server/posthog.test.ts +0 -34
- package/dist/create/template/src/server/rate-limit.test.ts +0 -32
- package/dist/create/template/src/server/rate-limit.ts +0 -29
- package/dist/create/template/src/server/rpc.ts +0 -16
- package/dist/create/template/src/server/schema.ts +0 -134
- package/dist/create/template/src/server/session.test.ts +0 -56
- package/dist/create/template/src/server/session.ts +0 -13
- package/dist/create/template/src/server/uploads.test.ts +0 -142
- package/dist/create/template/src/server/uploads.ts +0 -199
- package/dist/create/template/src/start.ts +0 -12
- package/dist/create/template/src/styles.css +0 -42
- package/dist/create/template/tsconfig.json +0 -8
- package/dist/create/template/vite.config.ts +0 -31
- package/dist/create/template/vitest.config.ts +0 -3
- package/dist/policy/changesets.js.map +0 -1
- package/dist/policy/cli.d.ts +0 -1
- package/dist/policy/cli.js +0 -23
- package/dist/policy/cli.js.map +0 -1
- package/dist/policy/index.d.ts +0 -14
- package/dist/policy/index.js +0 -132
- package/dist/policy/index.js.map +0 -1
- package/dist/policy/init-cli.d.ts +0 -12
- package/dist/policy/init-cli.js +0 -75
- package/dist/policy/init-cli.js.map +0 -1
- package/dist/policy/init.d.ts +0 -24
- package/dist/policy/init.js +0 -116
- package/dist/policy/init.js.map +0 -1
- package/dist/posthog/coverage.d.ts +0 -23
- package/dist/posthog/coverage.js +0 -30
- package/dist/posthog/coverage.js.map +0 -1
- package/dist/tanstack/query.d.ts +0 -3
- package/dist/tanstack/query.js +0 -8
- package/dist/tanstack/query.js.map +0 -1
- /package/dist/{policy/changesets.d.ts → changesets/index.d.ts} +0 -0
package/config/oxlint.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"plugins": ["typescript", "unicorn", "oxc", "react", "jsx-a11y", "import", "vitest"],
|
|
3
|
-
"categories": {
|
|
4
|
-
"correctness": "error",
|
|
5
|
-
"suspicious": "warn",
|
|
6
|
-
"perf": "warn"
|
|
7
|
-
},
|
|
8
|
-
"rules": {
|
|
9
|
-
"import/no-unassigned-import": "off",
|
|
10
|
-
"react/react-in-jsx-scope": "off",
|
|
11
|
-
"typescript/consistent-return": "off",
|
|
12
|
-
"typescript/no-unsafe-type-assertion": "off",
|
|
13
|
-
"unicorn/filename-case": "off",
|
|
14
|
-
"vitest/require-mock-type-parameters": "off"
|
|
15
|
-
},
|
|
16
|
-
"env": {
|
|
17
|
-
"builtin": true
|
|
18
|
-
}
|
|
19
|
-
}
|
package/dist/create/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function runCreateCli(arguments_: string[]): Promise<void>;
|
package/dist/create/index.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { copyFile, cp, mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
export async function runCreateCli(arguments_) {
|
|
4
|
-
const dryRun = arguments_.includes('--dry-run');
|
|
5
|
-
const positional = arguments_.filter((argument) => argument !== '--dry-run');
|
|
6
|
-
if (positional.length !== 1) {
|
|
7
|
-
console.error('usage: ras create <directory> [--dry-run]');
|
|
8
|
-
process.exitCode = 2;
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
const destination = path.resolve(positional[0]);
|
|
12
|
-
const source = await starterSource();
|
|
13
|
-
await assertSource(source);
|
|
14
|
-
await assertEmptyDestination(destination);
|
|
15
|
-
if (dryRun) {
|
|
16
|
-
console.log(destination);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
await mkdir(destination, { recursive: true });
|
|
20
|
-
await cp(source, destination, {
|
|
21
|
-
recursive: true,
|
|
22
|
-
filter: (entry) => !excluded(path.relative(source, entry)),
|
|
23
|
-
});
|
|
24
|
-
await materializeTemplate(destination, 'gitignore.template', '.gitignore');
|
|
25
|
-
await materializeTemplate(destination, 'dockerignore.template', '.dockerignore');
|
|
26
|
-
await materializeTemplate(destination, 'pnpm-workspace.template.yaml', 'pnpm-workspace.yaml');
|
|
27
|
-
await copyFile(path.join(destination, 'Dockerfile.standalone'), path.join(destination, 'Dockerfile'));
|
|
28
|
-
await rm(path.join(destination, 'Dockerfile.standalone'));
|
|
29
|
-
const packageFile = path.join(destination, 'package.json');
|
|
30
|
-
const manifest = JSON.parse(await readFile(packageFile, 'utf8'));
|
|
31
|
-
const packageManifest = JSON.parse(await readFile(path.resolve(import.meta.dirname, '../../package.json'), 'utf8'));
|
|
32
|
-
manifest.name = packageName(path.basename(destination));
|
|
33
|
-
manifest.dependencies['ras-stack'] = `^${packageManifest.version}`;
|
|
34
|
-
manifest.scripts.build = manifest.scripts.build.replaceAll('node ../../packages/ras-stack/dist/cli.js', 'ras');
|
|
35
|
-
await writeFile(packageFile, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
36
|
-
console.log(destination);
|
|
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
|
-
}
|
|
52
|
-
async function materializeTemplate(directory, template, output) {
|
|
53
|
-
const source = path.join(directory, template);
|
|
54
|
-
await copyFile(source, path.join(directory, output));
|
|
55
|
-
await rm(source);
|
|
56
|
-
}
|
|
57
|
-
function excluded(relative) {
|
|
58
|
-
const [root] = relative.split(path.sep);
|
|
59
|
-
return ['.output', '.data', 'node_modules', 'test-results'].includes(root ?? '');
|
|
60
|
-
}
|
|
61
|
-
async function assertSource(source) {
|
|
62
|
-
if (!(await stat(path.join(source, 'package.json'))).isFile())
|
|
63
|
-
throw new Error('The packaged full-stack starter is missing');
|
|
64
|
-
}
|
|
65
|
-
async function assertEmptyDestination(destination) {
|
|
66
|
-
try {
|
|
67
|
-
const info = await stat(destination);
|
|
68
|
-
if (!info.isDirectory() || (await readdir(destination)).length > 0)
|
|
69
|
-
throw new Error(`Destination must be an empty directory: ${destination}`);
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
if (error.code !== 'ENOENT')
|
|
73
|
-
throw error;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
function packageName(name) {
|
|
77
|
-
const normalized = name
|
|
78
|
-
.toLowerCase()
|
|
79
|
-
.replaceAll(/[^a-z\d._-]/g, '-')
|
|
80
|
-
.replaceAll(/^-+|-+$/g, '');
|
|
81
|
-
return normalized || 'ras-stack-app';
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=index.js.map
|
package/dist/create/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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,16 +0,0 @@
|
|
|
1
|
-
APP_URL=http://localhost:3100
|
|
2
|
-
DATA_DIR=.data/example-full-stack
|
|
3
|
-
TRUST_PROXY=false
|
|
4
|
-
CENTRIFUGO_API_URL=http://127.0.0.1:8100/api
|
|
5
|
-
CENTRIFUGO_API_KEY=replace-for-local-development
|
|
6
|
-
CENTRIFUGO_PROXY_SECRET=replace-for-local-development
|
|
7
|
-
BETTER_AUTH_SECRET=replace-with-at-least-32-random-characters
|
|
8
|
-
SMTP_HOST=127.0.0.1
|
|
9
|
-
SMTP_PORT=1025
|
|
10
|
-
SMTP_SECURE=false
|
|
11
|
-
EMAIL_FROM=ras-stack@example.test
|
|
12
|
-
EMAIL_REQUIRE_VERIFICATION=true
|
|
13
|
-
UPLOAD_MAX_BYTES=1000000
|
|
14
|
-
UPLOAD_QUOTA_BYTES=5000000
|
|
15
|
-
UPLOAD_GLOBAL_QUOTA_BYTES=100000000
|
|
16
|
-
UPLOAD_GLOBAL_MAX_FILES=1024
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1
|
|
2
|
-
ARG RUNTIME_BINARIES_IMAGE=ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.4@sha256:183261400ef822d3dfb7ae9391dc3836d343e01de41ab131df6a42751f87288e
|
|
3
|
-
FROM node:24-alpine AS build
|
|
4
|
-
WORKDIR /app
|
|
5
|
-
RUN apk add --no-cache python3 make g++
|
|
6
|
-
RUN corepack enable && corepack install --global pnpm@11.15.0
|
|
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
|
|
11
|
-
COPY examples/full-stack/package.json ./examples/full-stack/package.json
|
|
12
|
-
RUN pnpm fetch --frozen-lockfile
|
|
13
|
-
COPY packages/ras-stack ./packages/ras-stack
|
|
14
|
-
COPY examples/full-stack ./examples/full-stack
|
|
15
|
-
RUN pnpm install --offline --frozen-lockfile
|
|
16
|
-
RUN pnpm --filter ras-stack build && pnpm --filter @ras-stack/example-full-stack build
|
|
17
|
-
|
|
18
|
-
FROM ${RUNTIME_BINARIES_IMAGE} AS runtime-binaries
|
|
19
|
-
|
|
20
|
-
FROM node:24-alpine
|
|
21
|
-
WORKDIR /app
|
|
22
|
-
RUN apk upgrade --no-cache \
|
|
23
|
-
&& apk add --no-cache tini \
|
|
24
|
-
&& rm -rf /usr/local/lib/node_modules/corepack /usr/local/lib/node_modules/npm /opt/yarn-v1.22.22 \
|
|
25
|
-
&& rm -f /usr/local/bin/corepack /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
26
|
-
&& mkdir -p /data \
|
|
27
|
-
&& chown -R node:node /app /data
|
|
28
|
-
COPY --from=build --chown=node:node /app/examples/full-stack/.output ./.output
|
|
29
|
-
COPY --from=runtime-binaries /usr/local/bin/centrifugo /usr/local/bin/centrifugo
|
|
30
|
-
COPY --from=runtime-binaries /usr/local/bin/caddy /usr/local/bin/caddy
|
|
31
|
-
COPY --chown=node:node examples/full-stack/centrifugo.json ./centrifugo.json
|
|
32
|
-
COPY --chown=node:node packages/ras-stack/LICENSE ./
|
|
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
|
-
EXPOSE 3100
|
|
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
|
|
36
|
-
USER node
|
|
37
|
-
ENTRYPOINT ["/sbin/tini", "-g", "--", "node", ".output/server/containerRuntime.mjs"]
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1
|
|
2
|
-
ARG RUNTIME_BINARIES_IMAGE=ghcr.io/richardsolomou/ras-stack-runtime-binaries:runtime-v1.0.4@sha256:183261400ef822d3dfb7ae9391dc3836d343e01de41ab131df6a42751f87288e
|
|
3
|
-
FROM node:24-alpine AS build
|
|
4
|
-
WORKDIR /app
|
|
5
|
-
RUN apk add --no-cache python3 make g++
|
|
6
|
-
RUN corepack enable && corepack install --global pnpm@11.15.0
|
|
7
|
-
COPY . .
|
|
8
|
-
RUN pnpm install --no-frozen-lockfile
|
|
9
|
-
RUN pnpm build
|
|
10
|
-
|
|
11
|
-
FROM ${RUNTIME_BINARIES_IMAGE} AS runtime-binaries
|
|
12
|
-
|
|
13
|
-
FROM node:24-alpine
|
|
14
|
-
WORKDIR /app
|
|
15
|
-
RUN apk upgrade --no-cache \
|
|
16
|
-
&& apk add --no-cache tini \
|
|
17
|
-
&& rm -rf /usr/local/lib/node_modules/corepack /usr/local/lib/node_modules/npm /opt/yarn-v1.22.22 \
|
|
18
|
-
&& rm -f /usr/local/bin/corepack /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
19
|
-
&& mkdir -p /data \
|
|
20
|
-
&& chown -R node:node /app /data
|
|
21
|
-
COPY --from=build --chown=node:node /app/.output ./.output
|
|
22
|
-
COPY --from=runtime-binaries /usr/local/bin/centrifugo /usr/local/bin/centrifugo
|
|
23
|
-
COPY --from=runtime-binaries /usr/local/bin/caddy /usr/local/bin/caddy
|
|
24
|
-
COPY --chown=node:node centrifugo.json ./centrifugo.json
|
|
25
|
-
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
|
|
26
|
-
EXPOSE 3100
|
|
27
|
-
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=3 CMD wget -q --spider http://127.0.0.1:3100/api/ready || exit 1
|
|
28
|
-
USER node
|
|
29
|
-
ENTRYPOINT ["/sbin/tini", "-g", "--", "node", ".output/server/containerRuntime.mjs"]
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"client": {
|
|
3
|
-
"proxy": {
|
|
4
|
-
"connect": {
|
|
5
|
-
"enabled": true,
|
|
6
|
-
"endpoint": "http://127.0.0.1:3101/api/centrifugo/connect",
|
|
7
|
-
"http_headers": ["Cookie", "Origin", "X-Forwarded-Host", "X-Forwarded-Proto"],
|
|
8
|
-
"http": { "static_headers": { "X-Proxy-Secret": "${CENTRIFUGO_VAR_PROXY_SECRET}" } }
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
"channel": { "namespaces": [{ "name": "messages", "allow_subscribe_for_client": true }] },
|
|
13
|
-
"health": { "enabled": true }
|
|
14
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
CREATE TABLE `user` (
|
|
2
|
-
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
-
`name` text NOT NULL,
|
|
4
|
-
`email` text NOT NULL,
|
|
5
|
-
`email_verified` integer DEFAULT false NOT NULL,
|
|
6
|
-
`image` text,
|
|
7
|
-
`created_at` integer NOT NULL,
|
|
8
|
-
`updated_at` integer NOT NULL
|
|
9
|
-
);
|
|
10
|
-
--> statement-breakpoint
|
|
11
|
-
CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);
|
|
12
|
-
--> statement-breakpoint
|
|
13
|
-
CREATE TABLE `session` (
|
|
14
|
-
`id` text PRIMARY KEY NOT NULL,
|
|
15
|
-
`expires_at` integer NOT NULL,
|
|
16
|
-
`token` text NOT NULL,
|
|
17
|
-
`created_at` integer NOT NULL,
|
|
18
|
-
`updated_at` integer NOT NULL,
|
|
19
|
-
`ip_address` text,
|
|
20
|
-
`user_agent` text,
|
|
21
|
-
`user_id` text NOT NULL,
|
|
22
|
-
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
23
|
-
);
|
|
24
|
-
--> statement-breakpoint
|
|
25
|
-
CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);
|
|
26
|
-
--> statement-breakpoint
|
|
27
|
-
CREATE INDEX `session_user_id_idx` ON `session` (`user_id`);
|
|
28
|
-
--> statement-breakpoint
|
|
29
|
-
CREATE TABLE `account` (
|
|
30
|
-
`id` text PRIMARY KEY NOT NULL,
|
|
31
|
-
`account_id` text NOT NULL,
|
|
32
|
-
`issuer` text NOT NULL,
|
|
33
|
-
`provider_id` text NOT NULL,
|
|
34
|
-
`user_id` text NOT NULL,
|
|
35
|
-
`access_token` text,
|
|
36
|
-
`refresh_token` text,
|
|
37
|
-
`id_token` text,
|
|
38
|
-
`access_token_expires_at` integer,
|
|
39
|
-
`refresh_token_expires_at` integer,
|
|
40
|
-
`scope` text,
|
|
41
|
-
`password` text,
|
|
42
|
-
`created_at` integer NOT NULL,
|
|
43
|
-
`updated_at` integer NOT NULL,
|
|
44
|
-
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
45
|
-
);
|
|
46
|
-
--> statement-breakpoint
|
|
47
|
-
CREATE INDEX `account_user_id_idx` ON `account` (`user_id`);
|
|
48
|
-
--> statement-breakpoint
|
|
49
|
-
CREATE UNIQUE INDEX `account_issuer_account_id_unique` ON `account` (`issuer`,`account_id`);
|
|
50
|
-
--> statement-breakpoint
|
|
51
|
-
CREATE TABLE `verification` (
|
|
52
|
-
`id` text PRIMARY KEY NOT NULL,
|
|
53
|
-
`identifier` text NOT NULL,
|
|
54
|
-
`value` text NOT NULL,
|
|
55
|
-
`expires_at` integer NOT NULL,
|
|
56
|
-
`created_at` integer NOT NULL,
|
|
57
|
-
`updated_at` integer NOT NULL
|
|
58
|
-
);
|
|
59
|
-
--> statement-breakpoint
|
|
60
|
-
CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`);
|
|
61
|
-
--> statement-breakpoint
|
|
62
|
-
CREATE TABLE `rate_limit` (
|
|
63
|
-
`id` text PRIMARY KEY NOT NULL,
|
|
64
|
-
`key` text NOT NULL,
|
|
65
|
-
`count` integer NOT NULL,
|
|
66
|
-
`last_request` integer NOT NULL
|
|
67
|
-
);
|
|
68
|
-
--> statement-breakpoint
|
|
69
|
-
CREATE UNIQUE INDEX `rate_limit_key_unique` ON `rate_limit` (`key`);
|
|
70
|
-
--> statement-breakpoint
|
|
71
|
-
CREATE TABLE `app_rate_limit` (
|
|
72
|
-
`key` text PRIMARY KEY NOT NULL,
|
|
73
|
-
`count` integer NOT NULL,
|
|
74
|
-
`reset_at` integer NOT NULL
|
|
75
|
-
);
|
|
76
|
-
--> statement-breakpoint
|
|
77
|
-
CREATE TABLE `messages` (
|
|
78
|
-
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
79
|
-
`author_id` text NOT NULL,
|
|
80
|
-
`author` text NOT NULL,
|
|
81
|
-
`body` text NOT NULL,
|
|
82
|
-
`created_at` integer NOT NULL,
|
|
83
|
-
FOREIGN KEY (`author_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
84
|
-
);
|
|
85
|
-
--> statement-breakpoint
|
|
86
|
-
CREATE INDEX `messages_author_id_idx` ON `messages` (`author_id`);
|
|
87
|
-
--> statement-breakpoint
|
|
88
|
-
CREATE TABLE `uploads` (
|
|
89
|
-
`id` text PRIMARY KEY NOT NULL,
|
|
90
|
-
`owner_id` text NOT NULL,
|
|
91
|
-
`filename` text NOT NULL,
|
|
92
|
-
`media_type` text NOT NULL,
|
|
93
|
-
`length` integer NOT NULL,
|
|
94
|
-
`offset` integer DEFAULT 0 NOT NULL,
|
|
95
|
-
`state` text DEFAULT 'active' NOT NULL,
|
|
96
|
-
`created_at` integer NOT NULL,
|
|
97
|
-
`updated_at` integer NOT NULL,
|
|
98
|
-
FOREIGN KEY (`owner_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
99
|
-
);
|
|
100
|
-
--> statement-breakpoint
|
|
101
|
-
CREATE INDEX `uploads_owner_id_state_idx` ON `uploads` (`owner_id`,`state`);
|
|
102
|
-
--> statement-breakpoint
|
|
103
|
-
CREATE TABLE `outbox` (
|
|
104
|
-
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
105
|
-
`channel` text NOT NULL,
|
|
106
|
-
`payload` text NOT NULL,
|
|
107
|
-
`attempts` integer DEFAULT 0 NOT NULL,
|
|
108
|
-
`available_at` integer NOT NULL,
|
|
109
|
-
`created_at` integer NOT NULL,
|
|
110
|
-
`failed_at` integer,
|
|
111
|
-
`last_error` text
|
|
112
|
-
);
|
|
113
|
-
--> statement-breakpoint
|
|
114
|
-
CREATE INDEX `outbox_available_at_idx` ON `outbox` (`available_at`,`id`);
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { expect, test } from '@playwright/test'
|
|
2
|
-
|
|
3
|
-
test('keeps authentication submission disabled before hydration', async ({ browser }) => {
|
|
4
|
-
const context = await browser.newContext({ javaScriptEnabled: false })
|
|
5
|
-
const page = await context.newPage()
|
|
6
|
-
await page.goto('/')
|
|
7
|
-
|
|
8
|
-
await expect(page.getByRole('button', { name: 'Create account', exact: true })).toBeDisabled()
|
|
9
|
-
await context.close()
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test('signs up, authorizes resources, persists an upload, and receives an outbox publication', async ({ browser, request }, testInfo) => {
|
|
13
|
-
const run = Date.now()
|
|
14
|
-
const firstMessage = `first message ${run}`
|
|
15
|
-
const realtimeMessage = `realtime message ${run}`
|
|
16
|
-
const origin = testInfo.project.use.baseURL!
|
|
17
|
-
expect((await request.get('/api/live')).status()).toBe(200)
|
|
18
|
-
expect((await request.get('/api/ready')).status()).toBe(200)
|
|
19
|
-
expect((await request.get('/')).headers()['x-content-type-options']).toBe('nosniff')
|
|
20
|
-
expect((await request.post('/api/uploads', { headers: { Origin: origin, 'Upload-Length': '1' } })).status()).toBe(401)
|
|
21
|
-
expect((await request.head('/api/uploads/missing')).status()).toBe(401)
|
|
22
|
-
|
|
23
|
-
const alice = await browser.newPage()
|
|
24
|
-
await alice.goto('/')
|
|
25
|
-
await signUp(alice, 'Alice', 'alice@example.test')
|
|
26
|
-
await alice.getByLabel('Message').fill(firstMessage)
|
|
27
|
-
await alice.getByRole('button', { name: 'Add message' }).click()
|
|
28
|
-
await expect(alice.getByText(`Alice: ${firstMessage}`)).toBeVisible()
|
|
29
|
-
|
|
30
|
-
await alice.getByLabel('Upload').setInputFiles({ name: 'proof.txt', mimeType: 'text/plain', buffer: Buffer.from('workspace proof') })
|
|
31
|
-
const upload = alice.getByText(/Uploaded to .*\/api\/uploads\//)
|
|
32
|
-
await expect(upload).toBeVisible()
|
|
33
|
-
const uploadUrl = (await upload.textContent())!.replace('Uploaded to ', '')
|
|
34
|
-
|
|
35
|
-
const bob = await browser.newPage()
|
|
36
|
-
await bob.goto('/')
|
|
37
|
-
await signUp(bob, 'Bob', 'bob@example.test')
|
|
38
|
-
expect(await bob.evaluate((url) => fetch(url, { method: 'HEAD' }).then((response) => response.status), uploadUrl)).toBe(404)
|
|
39
|
-
await expect(bob.getByText(`Alice: ${firstMessage}`)).toBeVisible()
|
|
40
|
-
await bob.getByLabel('Message').fill(realtimeMessage)
|
|
41
|
-
await bob.getByRole('button', { name: 'Add message' }).click()
|
|
42
|
-
await expect(alice.getByText(`Bob: ${realtimeMessage}`)).toBeVisible()
|
|
43
|
-
await alice.getByRole('button', { name: 'Sign out' }).click()
|
|
44
|
-
await expect(alice.getByRole('heading', { name: 'Create account' })).toBeVisible()
|
|
45
|
-
await alice.screenshot({ path: testInfo.outputPath('example.png'), fullPage: true })
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
async function signUp(page: import('@playwright/test').Page, name: string, email: string) {
|
|
49
|
-
await page.getByLabel('Name').fill(name)
|
|
50
|
-
await page.getByLabel('Email').fill(email)
|
|
51
|
-
await page.getByLabel('Password').fill('correct horse battery staple')
|
|
52
|
-
await page.getByRole('button', { name: 'Create account', exact: true }).click()
|
|
53
|
-
await expect(page.getByRole('heading', { name: `Hello, ${name}` })).toBeVisible()
|
|
54
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ras-stack/example-full-stack",
|
|
3
|
-
"private": true,
|
|
4
|
-
"type": "module",
|
|
5
|
-
"scripts": {
|
|
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
|
-
"dev": "vite dev",
|
|
8
|
-
"format": "oxfmt --write .",
|
|
9
|
-
"format:check": "oxfmt --check .",
|
|
10
|
-
"lint": "oxlint --config oxlint.json --type-aware --deny-warnings .",
|
|
11
|
-
"realtime": "ras realtime --config centrifugo.json --name ras-stack-example-realtime --port 8100 --origin http://localhost:3100 --secret example-development-secret --connect-proxy-endpoint http://host.docker.internal:3100/api/centrifugo/connect",
|
|
12
|
-
"e2e": "playwright test",
|
|
13
|
-
"test": "vitest run --config vitest.config.ts",
|
|
14
|
-
"typecheck": "tsc --noEmit",
|
|
15
|
-
"db:backup": "node .output/server/database.mjs backup",
|
|
16
|
-
"db:restore": "node .output/server/database.mjs restore",
|
|
17
|
-
"check": "pnpm format:check && pnpm lint && pnpm build && pnpm typecheck && pnpm test"
|
|
18
|
-
},
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"@better-auth/core": "1.7.1",
|
|
21
|
-
"@better-auth/drizzle-adapter": "1.7.1",
|
|
22
|
-
"@opentelemetry/api-logs": "^0.221.0",
|
|
23
|
-
"@opentelemetry/exporter-logs-otlp-http": "^0.221.0",
|
|
24
|
-
"@opentelemetry/resources": "^2.10.0",
|
|
25
|
-
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
26
|
-
"@posthog/react": "^1.10.6",
|
|
27
|
-
"@tanstack/react-query": "^5.101.4",
|
|
28
|
-
"@tanstack/react-router": "^1.170.18",
|
|
29
|
-
"@tanstack/react-router-ssr-query": "^1.167.1",
|
|
30
|
-
"@tanstack/react-start": "^1.168.32",
|
|
31
|
-
"better-auth": "1.7.1",
|
|
32
|
-
"better-sqlite3": "12.11.1",
|
|
33
|
-
"centrifuge": "5.7.1",
|
|
34
|
-
"drizzle-orm": "0.45.2",
|
|
35
|
-
"nodemailer": "^9.0.3",
|
|
36
|
-
"posthog-js": "^1.430.3",
|
|
37
|
-
"posthog-node": "^5.52.1",
|
|
38
|
-
"ras-stack": "workspace:*",
|
|
39
|
-
"react": "19.2.8",
|
|
40
|
-
"react-dom": "19.2.8",
|
|
41
|
-
"tus-js-client": "^4.3.1",
|
|
42
|
-
"zod": "4.4.3"
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@playwright/test": "1.62.1",
|
|
46
|
-
"@types/better-sqlite3": "9.6.0",
|
|
47
|
-
"@types/node": "^26.2.0",
|
|
48
|
-
"@types/react": "19.2.18",
|
|
49
|
-
"@types/react-dom": "19.2.3",
|
|
50
|
-
"@vitejs/plugin-react": "^6.0.5",
|
|
51
|
-
"esbuild": "0.28.2",
|
|
52
|
-
"nitro": "3.0.260610-beta",
|
|
53
|
-
"oxfmt": "^0.63.0",
|
|
54
|
-
"oxlint": "^1.74.0",
|
|
55
|
-
"oxlint-tsgolint": "^7.0.2001",
|
|
56
|
-
"typescript": "^7.0.2",
|
|
57
|
-
"vite": "8.2.1",
|
|
58
|
-
"vitest": "^4.1.10"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { defineConfig, devices } from '@playwright/test'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
testDir: './e2e',
|
|
5
|
-
timeout: 30_000,
|
|
6
|
-
use: { ...devices['Desktop Chrome'], baseURL: process.env.EXAMPLE_BASE_URL ?? 'http://127.0.0.1:3110', trace: 'retain-on-failure' },
|
|
7
|
-
})
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { runRealtimeStack } from 'ras-stack/runtime'
|
|
2
|
-
|
|
3
|
-
const required = (name: string) => {
|
|
4
|
-
const value = process.env[name]?.trim()
|
|
5
|
-
if (!value) throw new Error(`${name} is required`)
|
|
6
|
-
return value
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const apiKey = required('CENTRIFUGO_API_KEY')
|
|
10
|
-
const proxySecret = required('CENTRIFUGO_PROXY_SECRET')
|
|
11
|
-
const realtime: NodeJS.ProcessEnv = { ...process.env, CENTRIFUGO_VAR_PROXY_SECRET: proxySecret }
|
|
12
|
-
delete realtime.CENTRIFUGO_API_KEY
|
|
13
|
-
delete realtime.CENTRIFUGO_PROXY_SECRET
|
|
14
|
-
delete realtime.CENTRIFUGO_API_URL
|
|
15
|
-
delete realtime.CENTRIFUGO_CONFIG
|
|
16
|
-
|
|
17
|
-
process.exitCode = await runRealtimeStack({
|
|
18
|
-
app: { command: process.execPath, args: ['.output/server/index.mjs'], env: { ...process.env, PORT: '3101' } },
|
|
19
|
-
centrifugo: {
|
|
20
|
-
configPath: process.env.CENTRIFUGO_CONFIG ?? '/app/centrifugo.json',
|
|
21
|
-
env: realtime,
|
|
22
|
-
environment: { apiKey, allowedOrigins: process.env.APP_URL ?? 'http://localhost:3100' },
|
|
23
|
-
},
|
|
24
|
-
caddy: {
|
|
25
|
-
configPath: '/tmp/ras-stack-example-Caddyfile',
|
|
26
|
-
env: process.env,
|
|
27
|
-
proxy: { publicPort: 3100, appPort: 3101, realtimePort: 8100 },
|
|
28
|
-
},
|
|
29
|
-
})
|