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.
Files changed (110) hide show
  1. package/README.md +19 -46
  2. package/dist/changesets/cli.d.ts +1 -0
  3. package/dist/changesets/cli.js +14 -0
  4. package/dist/changesets/cli.js.map +1 -0
  5. package/dist/{policy/changesets.js → changesets/index.js} +1 -1
  6. package/dist/changesets/index.js.map +1 -0
  7. package/dist/cli.d.ts +2 -6
  8. package/dist/cli.js +3 -7
  9. package/dist/cli.js.map +1 -1
  10. package/dist/email/index.d.ts +1 -2
  11. package/dist/email/index.js +2 -2
  12. package/dist/email/index.js.map +1 -1
  13. package/dist/posthog/index.d.ts +0 -2
  14. package/dist/posthog/index.js +0 -1
  15. package/dist/posthog/index.js.map +1 -1
  16. package/package.json +14 -41
  17. package/config/oxlint/application.json +0 -16
  18. package/config/oxlint/domain.json +0 -29
  19. package/config/oxlint/layers.json +0 -116
  20. package/config/oxlint/tanstack.json +0 -4
  21. package/config/oxlint.json +0 -19
  22. package/config/typescript/base.json +0 -10
  23. package/config/typescript/browser.json +0 -8
  24. package/config/typescript/bundler.json +0 -9
  25. package/config/typescript/library.json +0 -11
  26. package/config/typescript/node-bundler.json +0 -9
  27. package/config/typescript/tanstack.json +0 -6
  28. package/dist/create/index.d.ts +0 -1
  29. package/dist/create/index.js +0 -83
  30. package/dist/create/index.js.map +0 -1
  31. package/dist/create/template/.env.example +0 -16
  32. package/dist/create/template/.oxfmtrc.json +0 -7
  33. package/dist/create/template/Dockerfile +0 -37
  34. package/dist/create/template/Dockerfile.standalone +0 -29
  35. package/dist/create/template/centrifugo.json +0 -14
  36. package/dist/create/template/dockerignore.template +0 -8
  37. package/dist/create/template/drizzle/0000_production_reference.sql +0 -114
  38. package/dist/create/template/drizzle/meta/_journal.json +0 -13
  39. package/dist/create/template/e2e/full-stack.spec.ts +0 -54
  40. package/dist/create/template/gitignore.template +0 -9
  41. package/dist/create/template/oxlint.json +0 -4
  42. package/dist/create/template/package.json +0 -60
  43. package/dist/create/template/playwright.config.ts +0 -7
  44. package/dist/create/template/pnpm-workspace.template.yaml +0 -13
  45. package/dist/create/template/ras-stack.assets.json +0 -4
  46. package/dist/create/template/scripts/containerRuntime.ts +0 -29
  47. package/dist/create/template/scripts/database.test.ts +0 -121
  48. package/dist/create/template/scripts/database.ts +0 -105
  49. package/dist/create/template/src/client/auth.ts +0 -3
  50. package/dist/create/template/src/client/queries.ts +0 -4
  51. package/dist/create/template/src/client/queryClient.ts +0 -1
  52. package/dist/create/template/src/client/useRealtime.ts +0 -20
  53. package/dist/create/template/src/posthog.ts +0 -21
  54. package/dist/create/template/src/routeTree.gen.ts +0 -230
  55. package/dist/create/template/src/router.tsx +0 -17
  56. package/dist/create/template/src/routes/__root.tsx +0 -40
  57. package/dist/create/template/src/routes/api/auth.$.ts +0 -8
  58. package/dist/create/template/src/routes/api/centrifugo.connect.ts +0 -29
  59. package/dist/create/template/src/routes/api/health.ts +0 -6
  60. package/dist/create/template/src/routes/api/live.ts +0 -5
  61. package/dist/create/template/src/routes/api/ready.ts +0 -30
  62. package/dist/create/template/src/routes/api/uploads.$id.ts +0 -40
  63. package/dist/create/template/src/routes/api/uploads.ts +0 -25
  64. package/dist/create/template/src/routes/index.tsx +0 -189
  65. package/dist/create/template/src/server/app.test.ts +0 -24
  66. package/dist/create/template/src/server/app.ts +0 -172
  67. package/dist/create/template/src/server/auth-flow.test.ts +0 -150
  68. package/dist/create/template/src/server/auth.ts +0 -56
  69. package/dist/create/template/src/server/environment.test.ts +0 -43
  70. package/dist/create/template/src/server/environment.ts +0 -67
  71. package/dist/create/template/src/server/fns.ts +0 -38
  72. package/dist/create/template/src/server/messages.test.ts +0 -38
  73. package/dist/create/template/src/server/messages.ts +0 -28
  74. package/dist/create/template/src/server/migration.test.ts +0 -34
  75. package/dist/create/template/src/server/outbox.test.ts +0 -130
  76. package/dist/create/template/src/server/outbox.ts +0 -110
  77. package/dist/create/template/src/server/posthog.test.ts +0 -34
  78. package/dist/create/template/src/server/rate-limit.test.ts +0 -32
  79. package/dist/create/template/src/server/rate-limit.ts +0 -29
  80. package/dist/create/template/src/server/rpc.ts +0 -16
  81. package/dist/create/template/src/server/schema.ts +0 -134
  82. package/dist/create/template/src/server/session.test.ts +0 -56
  83. package/dist/create/template/src/server/session.ts +0 -13
  84. package/dist/create/template/src/server/uploads.test.ts +0 -142
  85. package/dist/create/template/src/server/uploads.ts +0 -199
  86. package/dist/create/template/src/start.ts +0 -12
  87. package/dist/create/template/src/styles.css +0 -42
  88. package/dist/create/template/tsconfig.json +0 -8
  89. package/dist/create/template/vite.config.ts +0 -31
  90. package/dist/create/template/vitest.config.ts +0 -3
  91. package/dist/policy/changesets.js.map +0 -1
  92. package/dist/policy/cli.d.ts +0 -1
  93. package/dist/policy/cli.js +0 -23
  94. package/dist/policy/cli.js.map +0 -1
  95. package/dist/policy/index.d.ts +0 -14
  96. package/dist/policy/index.js +0 -132
  97. package/dist/policy/index.js.map +0 -1
  98. package/dist/policy/init-cli.d.ts +0 -12
  99. package/dist/policy/init-cli.js +0 -75
  100. package/dist/policy/init-cli.js.map +0 -1
  101. package/dist/policy/init.d.ts +0 -24
  102. package/dist/policy/init.js +0 -116
  103. package/dist/policy/init.js.map +0 -1
  104. package/dist/posthog/coverage.d.ts +0 -23
  105. package/dist/posthog/coverage.js +0 -30
  106. package/dist/posthog/coverage.js.map +0 -1
  107. package/dist/tanstack/query.d.ts +0 -3
  108. package/dist/tanstack/query.js +0 -8
  109. package/dist/tanstack/query.js.map +0 -1
  110. /package/dist/{policy/changesets.d.ts → changesets/index.d.ts} +0 -0
package/README.md CHANGED
@@ -18,10 +18,11 @@ A helper belongs here when it removes a repeated decision or failure mode withou
18
18
 
19
19
  ## What you get 📦
20
20
 
21
- It ships in four forms:
21
+ It ships as independently versioned packages and deployment tooling:
22
22
 
23
23
  - **TypeScript modules** under narrow import paths such as `ras-stack/database/sqlite`, `ras-stack/realtime/react`, and `ras-stack/tanstack/server`.
24
- - **Command-line tools** for generated policy, production assets, preview status, and a local Centrifugo container.
24
+ - **Configuration presets** in the dependency-free `ras-stack-config` package for TypeScript and Oxlint.
25
+ - **Command-line tools** for changeset validation, production assets, preview status, and a local Centrifugo container.
25
26
  - **GitHub Actions and reusable workflows** for toolchain setup, checks, browser tests, previews, and Changesets releases.
26
27
  - **A separate OCI image** containing verified Caddy and Centrifugo binaries for production images.
27
28
 
@@ -31,13 +32,13 @@ An application can use one surface without adopting the others. The npm package
31
32
 
32
33
  | Layer | Supported technology | What `ras-stack` centralizes |
33
34
  | ------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
34
- | Runtime and tooling | Node, ESM TypeScript, pnpm, Just, Oxlint | Compiler/linter bases, setup actions, and version synchronization |
35
- | Web application | TanStack Start, React, TanStack Query | Request binding, mutation-origin checks, canonical hosts, health handlers, and Query defaults |
35
+ | Runtime and tooling | Node, ESM TypeScript, pnpm, Just, Oxlint | Setup actions and version synchronization |
36
+ | Web application | TanStack Start, React | Request binding, mutation-origin checks, canonical hosts, health handlers |
36
37
  | Authentication | Better Auth | Secure option builders, origins, secrets, redirects, failure classification, and React action state |
37
38
  | Data | Drizzle, `better-sqlite3`, Postgres.js | Connection lifecycle, safety defaults, migrations, target selection, and conformance checks |
38
39
  | Realtime | Centrifuge, Centrifugo, Caddy | Publishing, tokens, browser/React lifecycle, presence, proxy configuration, binaries, and supervision |
39
- | Email and uploads | Nodemailer, `tus-js-client` | SMTP configuration/delivery, auth callbacks, and promise-based resumable uploads |
40
- | Observability | PostHog JS, React, Node, and OpenTelemetry | Analytics, replay, errors, logs, metrics, tracing, correlation, proxying, shutdown, and coverage |
40
+ | Email and uploads | Nodemailer 9/10, `tus-js-client` | SMTP configuration/delivery, auth callbacks, and promise-based resumable uploads |
41
+ | Observability | PostHog JS, React, Node, and OpenTelemetry | Analytics, replay, errors, logs, metrics, tracing, correlation, proxying, and shutdown |
41
42
  | Delivery | GitHub Actions, Changesets, Dokploy, Docker | Checks, releases, preview lifecycle/status, production assets, and runtime binaries |
42
43
 
43
44
  Applications still configure every upstream library directly. This table describes what is tested together, not a replacement API.
@@ -48,46 +49,18 @@ Applications still configure every upstream library directly. This table describ
48
49
 
49
50
  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.
50
51
 
51
- 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.
52
+ 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 fixture; applications own their integration code and dependency versions.
52
53
 
53
- ## Pick what you need 🧩
54
+ ## Installation
54
55
 
55
- `ras-stack` requires Node 24.
56
+ `ras-stack` requires Node 24. Install the runtime package for application helpers and the configuration package for compiler/linter presets:
56
57
 
57
58
  ```sh
58
59
  pnpm add ras-stack
60
+ pnpm add -D ras-stack-config
59
61
  ```
60
62
 
61
- Nodemailer, Centrifuge, `better-sqlite3`, Drizzle, Postgres.js, and `tus-js-client` are optional peer dependencies. Install them only when using their integrations:
62
-
63
- ```sh
64
- pnpm add nodemailer
65
- pnpm add centrifuge
66
- pnpm add tus-js-client
67
- pnpm add better-auth @better-auth/drizzle-adapter better-sqlite3 drizzle-orm
68
- pnpm add postgres drizzle-orm
69
- ```
70
-
71
- Start with the narrowest public entrypoint that owns the repeated mechanic:
72
-
73
- | Need | Entrypoint or command | The application still owns |
74
- | --------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------- |
75
- | Authentication defaults and browser action state | `ras-stack/auth`, `ras-stack/auth/client`, `ras-stack/auth/react` | Better Auth configuration, forms, policy, and navigation |
76
- | RPC, mutation-origin, health, and canonical-host handling | `ras-stack/server`, `ras-stack/tanstack/server`, `ras-stack/tanstack/middleware` | Routes, authorization, logging, and health work |
77
- | SQLite or PostgreSQL lifecycle | `ras-stack/database/*` | Schemas, migrations, repositories, and transactions |
78
- | Realtime publication and browser lifecycle | `ras-stack/realtime/*` | Channels, tickets, payloads, presence models, and invalidation |
79
- | Email, uploads, and production assets | `ras-stack/email`, `ras-stack/uploads`, `ras assets` | Templates, metadata, quotas, storage, and asset contents |
80
- | Production or development realtime runtime | `ras-stack/runtime`, `ras realtime` | Images, ports, secrets, volumes, and distributed policy |
81
- | Compiler, lint, CI, release, and preview mechanics | `ras-stack/config/*`, `actions/*`, `.github/workflows/*`, `ras-stack/preview/*` | Triggers, permissions, services, deployment, and verification |
82
- | Generated repository policy files | `ras policy` | Which policies apply and every declared override |
83
-
84
- To start from the production reference instead of assembling entrypoints individually:
85
-
86
- ```sh
87
- pnpm create ras-app my-app
88
- ```
89
-
90
- The `create-ras-app` command delegates to the same scaffold implementation available through `pnpm dlx ras-stack create my-app`. The scaffold includes Better Auth, checked-in migrations, durable uploads, SMTP flows, a transactional realtime outbox, production health/lifecycle behavior, and its tests. It remains ordinary application code rather than a second framework API.
63
+ Import helpers from their narrow entrypoints and install the upstream peer libraries required by the integrations you use. Configuration-only repositories need just `ras-stack-config`.
91
64
 
92
65
  ## Dokploy previews 🚀
93
66
 
@@ -101,13 +74,13 @@ Applications supply only their package, application prefix, port, environment te
101
74
 
102
75
  ## Guides 📚
103
76
 
104
- | Guide | What it covers |
105
- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
106
- | [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 |
107
- | [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 |
108
- | [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 |
109
- | [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 |
110
- | [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 |
77
+ | Guide | What it covers |
78
+ | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
79
+ | [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 |
80
+ | [Repository tooling](https://github.com/richardsolomou/ras-stack/blob/main/docs/repository-tooling.md) | TypeScript and Oxlint configuration, changeset validation, GitHub Actions, previews, releases, and production runtime composition |
81
+ | [PostHog integration](https://github.com/richardsolomou/ras-stack/blob/main/docs/posthog.md) | Browser/server setup, identity and session correlation, ingest proxying, shutdown and source-map responsibility |
82
+ | [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 |
83
+ | [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 |
111
84
 
112
85
  ## Development 🛠️
113
86
 
@@ -0,0 +1 @@
1
+ export declare function runChangesetsCli(arguments_: string[]): Promise<void>;
@@ -0,0 +1,14 @@
1
+ import { checkChangesets } from './index.js';
2
+ export async function runChangesetsCli(arguments_) {
3
+ if (arguments_.length !== 1 || arguments_[0] !== 'check') {
4
+ console.error('usage: ras changesets check');
5
+ process.exitCode = 2;
6
+ return;
7
+ }
8
+ const errors = await checkChangesets(process.cwd());
9
+ for (const message of errors)
10
+ console.error(message);
11
+ if (errors.length > 0)
12
+ process.exitCode = 1;
13
+ }
14
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/changesets/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAoB;IACzD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;QAC5C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IACnD,KAAK,MAAM,OAAO,IAAI,MAAM;QAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACpD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;AAC7C,CAAC","sourcesContent":["import { checkChangesets } from './index.js'\n\nexport async function runChangesetsCli(arguments_: string[]): Promise<void> {\n if (arguments_.length !== 1 || arguments_[0] !== 'check') {\n console.error('usage: ras changesets check')\n process.exitCode = 2\n return\n }\n const errors = await checkChangesets(process.cwd())\n for (const message of errors) console.error(message)\n if (errors.length > 0) process.exitCode = 1\n}\n"]}
@@ -34,4 +34,4 @@ export async function checkChangesets(root) {
34
34
  }
35
35
  return errors;
36
36
  }
37
- //# sourceMappingURL=changesets.js.map
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/changesets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAA4B,EAAE,EAAE;QAC3F,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAA;QACtC,MAAM,KAAK,CAAA;IACb,CAAC,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAA;IAClG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,cAAc,IAAI,EAAE,CAAA;QACjC,iFAAiF;QACjF,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAA;QACzD,IAAI,QAAQ,CAAA;QACZ,IAAI,CAAC;YACH,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAA;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,kCAAkC,CAAC,CAAA;YACtD,SAAQ;QACV,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,qBAAqB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACvF,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { parseChangesetFile } from '@changesets/parse'\nimport { getPackages } from '@manypkg/get-packages'\nimport { readdir, readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\n\nexport async function checkChangesets(root: string): Promise<string[]> {\n const files = await readdir(join(root, '.changeset')).catch((error: NodeJS.ErrnoException) => {\n if (error.code === 'ENOENT') return []\n throw error\n })\n const changesets = files.filter((file) => file.endsWith('.md') && file !== 'README.md').toSorted()\n if (changesets.length === 0) return []\n const { packages } = await getPackages(root)\n const names = new Set(packages.map(({ packageJson }) => packageJson.name))\n const errors: string[] = []\n for (const file of changesets) {\n const path = `.changeset/${file}`\n // Read serially so a large changeset directory does not open every file at once.\n // oxlint-disable-next-line no-await-in-loop\n const contents = await readFile(join(root, path), 'utf8')\n let releases\n try {\n releases = parseChangesetFile(contents).releases\n } catch {\n errors.push(`${path}: missing or invalid frontmatter`)\n continue\n }\n for (const { name } of releases) {\n if (!names.has(name)) errors.push(`${path}: unknown package ${JSON.stringify(name)}`)\n }\n }\n return errors\n}\n"]}
package/dist/cli.d.ts CHANGED
@@ -1,15 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { runAssetsCli } from './build/cli.js';
3
- import { runCreateCli } from './create/index.js';
4
- import { runInitCli } from './policy/init-cli.js';
5
- import { runPolicyCli } from './policy/cli.js';
3
+ import { runChangesetsCli } from './changesets/cli.js';
6
4
  import { runPreviewCli } from './preview/cli.js';
7
5
  import { runRealtimeCli } from './runtime/dev-cli.js';
8
6
  declare const commands: {
9
7
  readonly assets: typeof runAssetsCli;
10
- readonly create: typeof runCreateCli;
11
- readonly init: typeof runInitCli;
12
- readonly policy: typeof runPolicyCli;
8
+ readonly changesets: typeof runChangesetsCli;
13
9
  readonly preview: typeof runPreviewCli;
14
10
  readonly realtime: typeof runRealtimeCli;
15
11
  };
package/dist/cli.js CHANGED
@@ -1,15 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { runAssetsCli } from './build/cli.js';
3
- import { runCreateCli } from './create/index.js';
4
- import { runInitCli } from './policy/init-cli.js';
5
- import { runPolicyCli } from './policy/cli.js';
3
+ import { runChangesetsCli } from './changesets/cli.js';
6
4
  import { runPreviewCli } from './preview/cli.js';
7
5
  import { runRealtimeCli } from './runtime/dev-cli.js';
8
6
  const commands = {
9
7
  assets: runAssetsCli,
10
- create: runCreateCli,
11
- init: runInitCli,
12
- policy: runPolicyCli,
8
+ changesets: runChangesetsCli,
13
9
  preview: runPreviewCli,
14
10
  realtime: runRealtimeCli,
15
11
  };
@@ -22,7 +18,7 @@ export function parseRasCommand(arguments_) {
22
18
  export async function runRasCli(arguments_) {
23
19
  const parsed = parseRasCommand(arguments_);
24
20
  if (!parsed) {
25
- console.error('usage: ras <assets|create|init|policy|preview|realtime> [arguments]');
21
+ console.error('usage: ras <assets|changesets|preview|realtime> [arguments]');
26
22
  process.exitCode = 2;
27
23
  return;
28
24
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,QAAQ,GAAG;IACf,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,IAAI,EAAE,UAAU;IAChB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,cAAc;CAChB,CAAA;AAIV,MAAM,UAAU,eAAe,CAAC,UAAoB;IAClD,MAAM,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,GAAG,UAAU,CAAA;IAC9C,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IACpE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,OAAqB,EAAE,CAAA;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,UAAoB;IAClD,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAA;QACpF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IACD,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAClD,CAAC;AAED,IAAI,OAAO,IAAI,CAAC,IAAI;IAAE,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA","sourcesContent":["#!/usr/bin/env node\nimport { runAssetsCli } from './build/cli.js'\nimport { runCreateCli } from './create/index.js'\nimport { runInitCli } from './policy/init-cli.js'\nimport { runPolicyCli } from './policy/cli.js'\nimport { runPreviewCli } from './preview/cli.js'\nimport { runRealtimeCli } from './runtime/dev-cli.js'\n\nconst commands = {\n assets: runAssetsCli,\n create: runCreateCli,\n init: runInitCli,\n policy: runPolicyCli,\n preview: runPreviewCli,\n realtime: runRealtimeCli,\n} as const\n\nexport type RasCommand = keyof typeof commands\n\nexport function parseRasCommand(arguments_: string[]): { arguments: string[]; command: RasCommand } | undefined {\n const [command, ...argumentsRest] = arguments_\n if (!(command && Object.hasOwn(commands, command))) return undefined\n return { arguments: argumentsRest, command: command as RasCommand }\n}\n\nexport async function runRasCli(arguments_: string[]): Promise<void> {\n const parsed = parseRasCommand(arguments_)\n if (!parsed) {\n console.error('usage: ras <assets|create|init|policy|preview|realtime> [arguments]')\n process.exitCode = 2\n return\n }\n await commands[parsed.command](parsed.arguments)\n}\n\nif (import.meta.main) await runRasCli(process.argv.slice(2))\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,QAAQ,GAAG;IACf,MAAM,EAAE,YAAY;IACpB,UAAU,EAAE,gBAAgB;IAC5B,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,cAAc;CAChB,CAAA;AAIV,MAAM,UAAU,eAAe,CAAC,UAAoB;IAClD,MAAM,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,GAAG,UAAU,CAAA;IAC9C,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IACpE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,OAAqB,EAAE,CAAA;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,UAAoB;IAClD,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAA;QAC5E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IACD,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAClD,CAAC;AAED,IAAI,OAAO,IAAI,CAAC,IAAI;IAAE,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA","sourcesContent":["#!/usr/bin/env node\nimport { runAssetsCli } from './build/cli.js'\nimport { runChangesetsCli } from './changesets/cli.js'\nimport { runPreviewCli } from './preview/cli.js'\nimport { runRealtimeCli } from './runtime/dev-cli.js'\n\nconst commands = {\n assets: runAssetsCli,\n changesets: runChangesetsCli,\n preview: runPreviewCli,\n realtime: runRealtimeCli,\n} as const\n\nexport type RasCommand = keyof typeof commands\n\nexport function parseRasCommand(arguments_: string[]): { arguments: string[]; command: RasCommand } | undefined {\n const [command, ...argumentsRest] = arguments_\n if (!(command && Object.hasOwn(commands, command))) return undefined\n return { arguments: argumentsRest, command: command as RasCommand }\n}\n\nexport async function runRasCli(arguments_: string[]): Promise<void> {\n const parsed = parseRasCommand(arguments_)\n if (!parsed) {\n console.error('usage: ras <assets|changesets|preview|realtime> [arguments]')\n process.exitCode = 2\n return\n }\n await commands[parsed.command](parsed.arguments)\n}\n\nif (import.meta.main) await runRasCli(process.argv.slice(2))\n"]}
@@ -1,4 +1,3 @@
1
- import nodemailer from 'nodemailer';
2
1
  export type EmailMessage = {
3
2
  to: string;
4
3
  subject: string;
@@ -46,7 +45,7 @@ export declare function createAuthEmailHandler<User extends {
46
45
  }>(delivery: EmailDelivery, message: AuthEmailMessageFactory<User>): (input: AuthEmailInput<User>, request?: Request) => Promise<void>;
47
46
  export declare function smtpConfigFromEnvironment(environment?: NodeJS.ProcessEnv, keys?: SmtpEnvironmentOptions): SmtpConfig | undefined;
48
47
  export declare function createSmtpDelivery(config: SmtpConfig): EmailDelivery;
49
- export declare function createSmtpTransport(config: SmtpConfig): nodemailer.Transporter<import("nodemailer/lib/smtp-transport/index.js").SentMessageInfo, import("nodemailer/lib/smtp-transport/index.js").Options>;
48
+ export declare function createSmtpTransport(config: SmtpConfig): import("nodemailer").Mail<import("nodemailer").SMTPSentMessageInfo, import("nodemailer").SMTPTransportOptions>;
50
49
  export type StandardAuthEmailOptions = {
51
50
  productName: string;
52
51
  };
@@ -1,4 +1,4 @@
1
- import nodemailer from 'nodemailer';
1
+ import { createTransport } from 'nodemailer';
2
2
  export function createAuthEmailHandler(delivery, message) {
3
3
  return async (input, request) => delivery.send(await message(input, request));
4
4
  }
@@ -37,7 +37,7 @@ export function createSmtpDelivery(config) {
37
37
  };
38
38
  }
39
39
  export function createSmtpTransport(config) {
40
- return nodemailer.createTransport({
40
+ return createTransport({
41
41
  host: config.host,
42
42
  port: config.port,
43
43
  secure: config.secure,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/email/index.ts"],"names":[],"mappings":"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","sourcesContent":["import nodemailer from 'nodemailer'\n\nexport type EmailMessage = { to: string; subject: string; text: string; html?: string }\n\nexport type SmtpConfig = {\n from: string\n host: string\n port: number\n secure: boolean\n user?: string\n password?: string\n}\n\nexport type SmtpEnvironmentOptions = {\n host?: string\n port?: string\n secure?: string\n user?: string\n password?: string\n from?: string\n}\n\nexport type EmailDelivery = {\n send(message: EmailMessage): Promise<void>\n verify(): Promise<void>\n}\n\nexport type AuthEmailInput<User extends { email: string } = { email: string }> = {\n user: User\n url: string\n token: string\n}\n\nexport type AuthEmailMessageFactory<User extends { email: string } = { email: string }> = (\n input: AuthEmailInput<User>,\n request?: Request,\n) => EmailMessage | Promise<EmailMessage>\n\nexport function createAuthEmailHandler<User extends { email: string } = { email: string }>(\n delivery: EmailDelivery,\n message: AuthEmailMessageFactory<User>,\n) {\n return async (input: AuthEmailInput<User>, request?: Request) => delivery.send(await message(input, request))\n}\n\nexport function smtpConfigFromEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n keys: SmtpEnvironmentOptions = {},\n): SmtpConfig | undefined {\n const host = environment[keys.host ?? 'SMTP_HOST']?.trim()\n const from = environment[keys.from ?? 'EMAIL_FROM']?.trim()\n if (!host && !from) return undefined\n if (!host) throw new Error(`${keys.host ?? 'SMTP_HOST'} is required for SMTP email`)\n if (!from) throw new Error(`${keys.from ?? 'EMAIL_FROM'} is required for SMTP email`)\n\n const portKey = keys.port ?? 'SMTP_PORT'\n const port = Number(environment[portKey] ?? 587)\n if (!Number.isInteger(port) || port < 1 || port > 65_535) throw new Error(`${portKey} must be a valid TCP port`)\n\n const userKey = keys.user ?? 'SMTP_USER'\n const passwordKey = keys.password ?? 'SMTP_PASSWORD'\n const user = environment[userKey]?.trim()\n const password = environment[passwordKey]\n if (Boolean(user) !== Boolean(password)) throw new Error(`${userKey} and ${passwordKey} must be configured together`)\n\n return {\n from,\n host,\n port,\n secure: environment[keys.secure ?? 'SMTP_SECURE']?.trim().toLowerCase() === 'true',\n ...(user && password ? { user, password } : {}),\n }\n}\n\nexport function createSmtpDelivery(config: SmtpConfig): EmailDelivery {\n const transport = createSmtpTransport(config)\n return {\n send: async (message) => transport.sendMail({ from: config.from, ...message }).then(() => undefined),\n verify: async () => transport.verify().then(() => undefined),\n }\n}\n\nexport function createSmtpTransport(config: SmtpConfig) {\n return nodemailer.createTransport({\n host: config.host,\n port: config.port,\n secure: config.secure,\n auth: config.user ? { user: config.user, pass: config.password } : undefined,\n })\n}\n\nexport type StandardAuthEmailOptions = { productName: string }\n\nexport function standardAuthEmails<User extends { email: string } = { email: string }>(\n delivery: EmailDelivery,\n options: StandardAuthEmailOptions,\n) {\n const expiry = 'This link expires in one hour.'\n const message =\n (subject: string, label: string): AuthEmailMessageFactory<User> =>\n ({ user, url }) => ({\n to: user.email,\n subject,\n text: `${subject} using this link: ${url}\\n\\n${expiry}`,\n html: `<p>${escapeHtml(subject)} using the link below.</p><p><a href=\"${escapeHtml(url)}\">${label}</a></p><p>${expiry}</p>`,\n })\n return {\n sendResetPassword: createAuthEmailHandler(delivery, message(`Reset your ${options.productName} password`, 'Reset password')),\n sendVerificationEmail: createAuthEmailHandler(\n delivery,\n message(`Verify your ${options.productName} email address`, 'Verify email address'),\n ),\n }\n}\n\nfunction escapeHtml(value: string) {\n return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\"', '&quot;')\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/email/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAsC5C,MAAM,UAAU,sBAAsB,CACpC,QAAuB,EACvB,OAAsC;IAEtC,OAAO,KAAK,EAAE,KAA2B,EAAE,OAAiB,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;AAC/G,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,WAAW,GAAsB,OAAO,CAAC,GAAG,EAC5C,IAAI,GAA2B,EAAE;IAEjC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,EAAE,IAAI,EAAE,CAAA;IAC1D,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC,EAAE,IAAI,EAAE,CAAA;IAC3D,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IACpC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,6BAA6B,CAAC,CAAA;IACpF,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,6BAA6B,CAAC,CAAA;IAErF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,CAAA;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAA;IAChD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,2BAA2B,CAAC,CAAA;IAEhH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,CAAA;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAA;IACpD,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAA;IACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;IACzC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,QAAQ,WAAW,8BAA8B,CAAC,CAAA;IAErH,OAAO;QACL,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM;QAClF,GAAG,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAkB;IACnD,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;IAC7C,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;QACpG,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;KAC7D,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAkB;IACpD,OAAO,eAAe,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;KAC7E,CAAC,CAAA;AACJ,CAAC;AAID,MAAM,UAAU,kBAAkB,CAChC,QAAuB,EACvB,OAAiC;IAEjC,MAAM,MAAM,GAAG,gCAAgC,CAAA;IAC/C,MAAM,OAAO,GACX,CAAC,OAAe,EAAE,KAAa,EAAiC,EAAE,CAClE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QAClB,EAAE,EAAE,IAAI,CAAC,KAAK;QACd,OAAO;QACP,IAAI,EAAE,GAAG,OAAO,qBAAqB,GAAG,OAAO,MAAM,EAAE;QACvD,IAAI,EAAE,MAAM,UAAU,CAAC,OAAO,CAAC,yCAAyC,UAAU,CAAC,GAAG,CAAC,KAAK,KAAK,cAAc,MAAM,MAAM;KAC5H,CAAC,CAAA;IACJ,OAAO;QACL,iBAAiB,EAAE,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,cAAc,OAAO,CAAC,WAAW,WAAW,EAAE,gBAAgB,CAAC,CAAC;QAC5H,qBAAqB,EAAE,sBAAsB,CAC3C,QAAQ,EACR,OAAO,CAAC,eAAe,OAAO,CAAC,WAAW,gBAAgB,EAAE,sBAAsB,CAAC,CACpF;KACF,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;AACjH,CAAC","sourcesContent":["import { createTransport } from 'nodemailer'\n\nexport type EmailMessage = { to: string; subject: string; text: string; html?: string }\n\nexport type SmtpConfig = {\n from: string\n host: string\n port: number\n secure: boolean\n user?: string\n password?: string\n}\n\nexport type SmtpEnvironmentOptions = {\n host?: string\n port?: string\n secure?: string\n user?: string\n password?: string\n from?: string\n}\n\nexport type EmailDelivery = {\n send(message: EmailMessage): Promise<void>\n verify(): Promise<void>\n}\n\nexport type AuthEmailInput<User extends { email: string } = { email: string }> = {\n user: User\n url: string\n token: string\n}\n\nexport type AuthEmailMessageFactory<User extends { email: string } = { email: string }> = (\n input: AuthEmailInput<User>,\n request?: Request,\n) => EmailMessage | Promise<EmailMessage>\n\nexport function createAuthEmailHandler<User extends { email: string } = { email: string }>(\n delivery: EmailDelivery,\n message: AuthEmailMessageFactory<User>,\n) {\n return async (input: AuthEmailInput<User>, request?: Request) => delivery.send(await message(input, request))\n}\n\nexport function smtpConfigFromEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n keys: SmtpEnvironmentOptions = {},\n): SmtpConfig | undefined {\n const host = environment[keys.host ?? 'SMTP_HOST']?.trim()\n const from = environment[keys.from ?? 'EMAIL_FROM']?.trim()\n if (!host && !from) return undefined\n if (!host) throw new Error(`${keys.host ?? 'SMTP_HOST'} is required for SMTP email`)\n if (!from) throw new Error(`${keys.from ?? 'EMAIL_FROM'} is required for SMTP email`)\n\n const portKey = keys.port ?? 'SMTP_PORT'\n const port = Number(environment[portKey] ?? 587)\n if (!Number.isInteger(port) || port < 1 || port > 65_535) throw new Error(`${portKey} must be a valid TCP port`)\n\n const userKey = keys.user ?? 'SMTP_USER'\n const passwordKey = keys.password ?? 'SMTP_PASSWORD'\n const user = environment[userKey]?.trim()\n const password = environment[passwordKey]\n if (Boolean(user) !== Boolean(password)) throw new Error(`${userKey} and ${passwordKey} must be configured together`)\n\n return {\n from,\n host,\n port,\n secure: environment[keys.secure ?? 'SMTP_SECURE']?.trim().toLowerCase() === 'true',\n ...(user && password ? { user, password } : {}),\n }\n}\n\nexport function createSmtpDelivery(config: SmtpConfig): EmailDelivery {\n const transport = createSmtpTransport(config)\n return {\n send: async (message) => transport.sendMail({ from: config.from, ...message }).then(() => undefined),\n verify: async () => transport.verify().then(() => undefined),\n }\n}\n\nexport function createSmtpTransport(config: SmtpConfig) {\n return createTransport({\n host: config.host,\n port: config.port,\n secure: config.secure,\n auth: config.user ? { user: config.user, pass: config.password } : undefined,\n })\n}\n\nexport type StandardAuthEmailOptions = { productName: string }\n\nexport function standardAuthEmails<User extends { email: string } = { email: string }>(\n delivery: EmailDelivery,\n options: StandardAuthEmailOptions,\n) {\n const expiry = 'This link expires in one hour.'\n const message =\n (subject: string, label: string): AuthEmailMessageFactory<User> =>\n ({ user, url }) => ({\n to: user.email,\n subject,\n text: `${subject} using this link: ${url}\\n\\n${expiry}`,\n html: `<p>${escapeHtml(subject)} using the link below.</p><p><a href=\"${escapeHtml(url)}\">${label}</a></p><p>${expiry}</p>`,\n })\n return {\n sendResetPassword: createAuthEmailHandler(delivery, message(`Reset your ${options.productName} password`, 'Reset password')),\n sendVerificationEmail: createAuthEmailHandler(\n delivery,\n message(`Verify your ${options.productName} email address`, 'Verify email address'),\n ),\n }\n}\n\nfunction escapeHtml(value: string) {\n return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\"', '&quot;')\n}\n"]}
@@ -1,6 +1,4 @@
1
1
  export { postHogEnvironment, postHogHttpUrl } from './config.js';
2
2
  export type { PostHogBrowserService, PostHogEnvironment } from './config.js';
3
- export { definePostHogCoverage } from './coverage.js';
4
- export type { PostHogCoverage, PostHogCoverageDecision } from './coverage.js';
5
3
  export { POSTHOG_DISTINCT_ID_HEADER, POSTHOG_SESSION_ID_HEADER, postHogRequestContext } from './request.js';
6
4
  export type { PostHogRequestContext, PostHogRequestContextOptions } from './request.js';
@@ -1,4 +1,3 @@
1
1
  export { postHogEnvironment, postHogHttpUrl } from './config.js';
2
- export { definePostHogCoverage } from './coverage.js';
3
2
  export { POSTHOG_DISTINCT_ID_HEADER, POSTHOG_SESSION_ID_HEADER, postHogRequestContext } from './request.js';
4
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/posthog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA","sourcesContent":["export { postHogEnvironment, postHogHttpUrl } from './config.js'\nexport type { PostHogBrowserService, PostHogEnvironment } from './config.js'\nexport { definePostHogCoverage } from './coverage.js'\nexport type { PostHogCoverage, PostHogCoverageDecision } from './coverage.js'\nexport { POSTHOG_DISTINCT_ID_HEADER, POSTHOG_SESSION_ID_HEADER, postHogRequestContext } from './request.js'\nexport type { PostHogRequestContext, PostHogRequestContextOptions } from './request.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/posthog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEhE,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA","sourcesContent":["export { postHogEnvironment, postHogHttpUrl } from './config.js'\nexport type { PostHogBrowserService, PostHogEnvironment } from './config.js'\nexport { POSTHOG_DISTINCT_ID_HEADER, POSTHOG_SESSION_ID_HEADER, postHogRequestContext } from './request.js'\nexport type { PostHogRequestContext, PostHogRequestContextOptions } from './request.js'\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ras-stack",
3
- "version": "2.0.2",
3
+ "version": "3.0.1",
4
4
  "description": "Composable full-stack primitives shared across Richard Solomou's applications.",
5
5
  "keywords": [
6
6
  "authentication",
@@ -21,8 +21,7 @@
21
21
  "ras": "./dist/cli.js"
22
22
  },
23
23
  "files": [
24
- "dist",
25
- "config"
24
+ "dist"
26
25
  ],
27
26
  "type": "module",
28
27
  "sideEffects": false,
@@ -63,14 +62,6 @@
63
62
  "types": "./dist/conformance/index.d.ts",
64
63
  "default": "./dist/conformance/index.js"
65
64
  },
66
- "./create": {
67
- "types": "./dist/create/index.d.ts",
68
- "default": "./dist/create/index.js"
69
- },
70
- "./policy": {
71
- "types": "./dist/policy/index.d.ts",
72
- "default": "./dist/policy/index.js"
73
- },
74
65
  "./posthog": {
75
66
  "types": "./dist/posthog/index.d.ts",
76
67
  "default": "./dist/posthog/index.js"
@@ -119,10 +110,6 @@
119
110
  "types": "./dist/runtime/index.d.ts",
120
111
  "default": "./dist/runtime/index.js"
121
112
  },
122
- "./tanstack/query": {
123
- "types": "./dist/tanstack/query.d.ts",
124
- "default": "./dist/tanstack/query.js"
125
- },
126
113
  "./tanstack/middleware": {
127
114
  "types": "./dist/tanstack/middleware.d.ts",
128
115
  "default": "./dist/tanstack/middleware.js"
@@ -135,27 +122,17 @@
135
122
  "types": "./dist/uploads/index.d.ts",
136
123
  "default": "./dist/uploads/index.js"
137
124
  },
138
- "./config/oxlint": "./config/oxlint.json",
139
- "./config/oxlint/application": "./config/oxlint/application.json",
140
- "./config/oxlint/tanstack": "./config/oxlint/tanstack.json",
141
- "./config/typescript/base": "./config/typescript/base.json",
142
- "./config/typescript/browser": "./config/typescript/browser.json",
143
- "./config/typescript/bundler": "./config/typescript/bundler.json",
144
- "./config/typescript/library": "./config/typescript/library.json",
145
- "./config/typescript/node-bundler": "./config/typescript/node-bundler.json",
146
- "./config/typescript/tanstack": "./config/typescript/tanstack.json",
147
- "./config/oxlint/domain": "./config/oxlint/domain.json",
148
- "./config/oxlint/layers": "./config/oxlint/layers.json"
125
+ "./changesets": {
126
+ "types": "./dist/changesets/index.d.ts",
127
+ "default": "./dist/changesets/index.js"
128
+ }
149
129
  },
150
130
  "publishConfig": {
151
131
  "access": "public"
152
132
  },
153
133
  "dependencies": {
154
134
  "@changesets/parse": "1.0.0",
155
- "@inquirer/confirm": "^6.1.1",
156
- "@inquirer/select": "^5.2.1",
157
- "@manypkg/get-packages": "3.1.0",
158
- "yaml": "^2.8.2"
135
+ "@manypkg/get-packages": "3.1.0"
159
136
  },
160
137
  "devDependencies": {
161
138
  "@opentelemetry/api-logs": "^0.221.0",
@@ -163,7 +140,6 @@
163
140
  "@opentelemetry/resources": "^2.10.0",
164
141
  "@opentelemetry/sdk-logs": "^0.221.0",
165
142
  "@posthog/react": "1.10.6",
166
- "@tanstack/react-query": "^5.101.4",
167
143
  "@tanstack/react-start": "^1.168.32",
168
144
  "@types/better-sqlite3": "9.6.0",
169
145
  "@types/node": "^26.2.0",
@@ -174,7 +150,7 @@
174
150
  "better-sqlite3": "12.11.1",
175
151
  "centrifuge": "5.7.1",
176
152
  "drizzle-orm": "0.45.2",
177
- "nodemailer": "^9.0.3",
153
+ "nodemailer": "^10.0.11",
178
154
  "oxfmt": "^0.63.0",
179
155
  "oxlint": "^1.74.0",
180
156
  "oxlint-tsgolint": "^7.0.2001",
@@ -186,7 +162,9 @@
186
162
  "tus-js-client": "^4.3.1",
187
163
  "typescript": "^7.0.2",
188
164
  "vite": "8.2.1",
189
- "vitest": "^4.1.10"
165
+ "vitest": "^4.1.10",
166
+ "yaml": "^2.8.2",
167
+ "ras-stack-config": "1.0.0"
190
168
  },
191
169
  "peerDependencies": {
192
170
  "@opentelemetry/api-logs": "^0.221.0",
@@ -194,12 +172,11 @@
194
172
  "@opentelemetry/resources": "^2.10.0",
195
173
  "@opentelemetry/sdk-logs": "^0.221.0",
196
174
  "@posthog/react": ">=1.1 <2",
197
- "@tanstack/react-query": ">=5.62.8 <6",
198
175
  "@tanstack/react-start": ">=1.168.10 <2",
199
176
  "better-sqlite3": ">=12 <14",
200
177
  "centrifuge": ">=5 <6",
201
178
  "drizzle-orm": ">=0.45 <1",
202
- "nodemailer": ">=9 <10",
179
+ "nodemailer": ">=9 <11",
203
180
  "postgres": ">=3.4 <4",
204
181
  "posthog-js": ">=1.430.3 <2",
205
182
  "posthog-node": ">=5.52 <6",
@@ -222,9 +199,6 @@
222
199
  "@posthog/react": {
223
200
  "optional": true
224
201
  },
225
- "@tanstack/react-query": {
226
- "optional": true
227
- },
228
202
  "@tanstack/react-start": {
229
203
  "optional": true
230
204
  },
@@ -260,8 +234,7 @@
260
234
  "node": ">=24 <25"
261
235
  },
262
236
  "scripts": {
263
- "build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/copyStarter.mjs",
264
- "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",
237
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
265
238
  "typecheck": "tsc --noEmit",
266
239
  "lint": "oxlint --type-aware --deny-warnings .",
267
240
  "format": "oxfmt --write .",
@@ -270,6 +243,6 @@
270
243
  "package:check": "node scripts/checkPackedPackage.mjs",
271
244
  "peer:floor": "node scripts/checkPeerFloor.mjs",
272
245
  "runtime:pin": "node scripts/checkRuntimePin.mjs",
273
- "check": "pnpm format:check && pnpm lint && pnpm config:check && pnpm typecheck && pnpm test && pnpm build && pnpm package:check"
246
+ "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test && pnpm build && pnpm package:check"
274
247
  }
275
248
  }
@@ -1,16 +0,0 @@
1
- {
2
- "extends": ["../oxlint.json"],
3
- "rules": {
4
- "no-console": "off",
5
- "no-await-in-loop": "off",
6
- "no-underscore-dangle": "off",
7
- "unicorn/require-post-message-target-origin": "off",
8
- "vitest/require-to-throw-message": "off",
9
- "vitest/no-conditional-expect": "off",
10
- "unicorn/no-array-sort": "off",
11
- "oxc/no-map-spread": "off",
12
- "unicorn/consistent-function-scoping": "off",
13
- "unicorn/prefer-add-event-listener": "off",
14
- "typescript/no-unnecessary-type-parameters": "off"
15
- }
16
- }
@@ -1,29 +0,0 @@
1
- {
2
- "overrides": [
3
- {
4
- "files": ["src/core/**", "src/geometry/**"],
5
- "rules": {
6
- "no-restricted-imports": [
7
- "error",
8
- {
9
- "patterns": [
10
- {
11
- "regex": "^(?:node:|(?:assert|async_hooks|buffer|child_process|cluster|console|constants|crypto|dgram|diagnostics_channel|dns|domain|events|fs|http|http2|https|inspector|module|net|os|path|perf_hooks|process|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|trace_events|tty|url|util|v8|vm|wasi|worker_threads|zlib)(?:/|$))",
12
- "message": "Domain modules must not import Node builtins."
13
- },
14
- {
15
- "regex": "^(@tanstack/|react(?:/|-|$)|@testing-library/|drizzle-orm(?:/|$)|postgres(?:/|$)|iovalkey(?:/|$)|ioredis(?:/|$)|@electric-sql/|better-auth(?:/|$)|cheerio(?:/|$)|html-to-text(?:/|$)|centrifuge(?:/|$)|posthog-(?:js|node)(?:/|$))",
16
- "message": "Domain modules must not import framework or persistence dependencies."
17
- },
18
- {
19
- "regex": "^(?:(?:\\.\\.?/)+|@/)(?:adapters|client|components|db|lib|routes|server)/",
20
- "message": "Domain modules must not import application layers."
21
- }
22
- ]
23
- }
24
- ]
25
- },
26
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
27
- }
28
- ]
29
- }
@@ -1,116 +0,0 @@
1
- {
2
- "overrides": [
3
- {
4
- "files": ["src/routes/**"],
5
- "rules": {
6
- "no-restricted-imports": [
7
- "error",
8
- {
9
- "patterns": [
10
- {
11
- "regex": "^(?:\\./[^.]|(?:\\.\\./)+routes/|@/routes/)",
12
- "message": "Route modules must not import sibling route modules."
13
- }
14
- ]
15
- }
16
- ]
17
- },
18
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
19
- },
20
- {
21
- "files": ["src/server/**"],
22
- "rules": {
23
- "no-restricted-imports": [
24
- "error",
25
- {
26
- "patterns": [
27
- {
28
- "regex": "^(?:(?:\\.\\.?/)+|@/)(?:client|routes)/",
29
- "message": "Server modules must not import client or route modules."
30
- }
31
- ]
32
- }
33
- ]
34
- },
35
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
36
- },
37
- {
38
- "files": ["src/client/**"],
39
- "rules": {
40
- "no-restricted-imports": [
41
- "error",
42
- {
43
- "patterns": [
44
- {
45
- "group": [
46
- "**/adapters/**",
47
- "**/db/**",
48
- "**/routes/**",
49
- "**/server/**",
50
- "!**/server/functions",
51
- "!**/server/functions.*",
52
- "!**/server/functions/**",
53
- "!**/server/fns",
54
- "!**/server/fns.*"
55
- ],
56
- "message": "Client modules may import server functions, but not server implementations."
57
- }
58
- ]
59
- }
60
- ]
61
- },
62
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
63
- },
64
- {
65
- "files": ["src/contracts/**"],
66
- "rules": {
67
- "no-restricted-imports": [
68
- "error",
69
- {
70
- "patterns": [
71
- {
72
- "regex": "^(?:(?:\\.\\.?/)+|@/)(?:adapters|client|components|db|lib|routes|server)/",
73
- "message": "Shared contracts must not import application layers."
74
- }
75
- ]
76
- }
77
- ]
78
- },
79
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
80
- },
81
- {
82
- "files": ["src/adapters/**"],
83
- "rules": {
84
- "no-restricted-imports": [
85
- "error",
86
- {
87
- "patterns": [
88
- {
89
- "regex": "^(?:(?:\\.\\.?/)+|@/)(?:client|db|routes|server)/",
90
- "message": "Adapters must not import application layers."
91
- }
92
- ]
93
- }
94
- ]
95
- },
96
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
97
- },
98
- {
99
- "files": ["src/db/**"],
100
- "rules": {
101
- "no-restricted-imports": [
102
- "error",
103
- {
104
- "patterns": [
105
- {
106
- "regex": "^(?:(?:\\.\\.?/)+|@/)(?:adapters|client|routes|server)/",
107
- "message": "Database modules must not import application layers."
108
- }
109
- ]
110
- }
111
- ]
112
- },
113
- "excludeFiles": ["**/*.test.*", "**/*.spec.*"]
114
- }
115
- ]
116
- }
@@ -1,4 +0,0 @@
1
- {
2
- "extends": ["../oxlint.json"],
3
- "ignorePatterns": ["src/routeTree.gen.ts", ".output/**", "node_modules/**"]
4
- }