@hypersonic-js/core 0.1.2 → 0.2.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 ADDED
@@ -0,0 +1,13 @@
1
+ # @hypersonic-js/core
2
+
3
+ The core of Hypersonic.js — a modern Django-inspired full-stack TypeScript framework
4
+
5
+ 📖 **[Full documentation → hypersonic-js.com](https://hypersonic-js.com)**
6
+
7
+ ## Install
8
+
9
+ npm install @hypersonic-js/core
10
+
11
+ ## License
12
+
13
+ MIT
@@ -4,6 +4,19 @@ export type AuthInstance = ReturnType<typeof betterAuth>;
4
4
  /**
5
5
  * Creates and returns a configured Better Auth instance.
6
6
  * OAuth social providers are only wired in when credentials are supplied.
7
+ * The rateLimit option is only forwarded when explicitly provided, allowing
8
+ * test environments to pass `{ enabled: false }` to suppress the in-process
9
+ * rate limiter and avoid 429s across shared test suites.
10
+ *
11
+ * Three targeted casts remain:
12
+ * - `prisma as PrismaAdapterClient`: our public API keeps `prisma: unknown`
13
+ * to stay agnostic of the generated PrismaClient types; the adapter's own
14
+ * PrismaClient is an empty interface so the cast is safe at runtime.
15
+ * - `socialProviders as BetterAuthOptions['socialProviders']`: our plain record
16
+ * satisfies the runtime contract but TypeScript cannot verify it against the
17
+ * `SocialProviders` mapped type without a cast.
18
+ * - `rateLimit as BetterAuthOptions['rateLimit']`: our `{ enabled?: boolean }`
19
+ * subset is a valid runtime value for Better Auth's rateLimit field.
7
20
  */
8
21
  export declare function createAuth(options: AuthSetupOptions): AuthInstance;
9
22
  //# sourceMappingURL=setup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAKxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;AAExD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,CA2BlE"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;AAUxD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,CA8BlE"}
@@ -1,27 +1,45 @@
1
1
  import { betterAuth } from 'better-auth';
2
2
  import { prismaAdapter } from 'better-auth/adapters/prisma';
3
- import { detectProvider } from '../utils/detect-provider.js';
3
+ import { admin } from 'better-auth/plugins';
4
4
  /**
5
5
  * Creates and returns a configured Better Auth instance.
6
6
  * OAuth social providers are only wired in when credentials are supplied.
7
+ * The rateLimit option is only forwarded when explicitly provided, allowing
8
+ * test environments to pass `{ enabled: false }` to suppress the in-process
9
+ * rate limiter and avoid 429s across shared test suites.
10
+ *
11
+ * Three targeted casts remain:
12
+ * - `prisma as PrismaAdapterClient`: our public API keeps `prisma: unknown`
13
+ * to stay agnostic of the generated PrismaClient types; the adapter's own
14
+ * PrismaClient is an empty interface so the cast is safe at runtime.
15
+ * - `socialProviders as BetterAuthOptions['socialProviders']`: our plain record
16
+ * satisfies the runtime contract but TypeScript cannot verify it against the
17
+ * `SocialProviders` mapped type without a cast.
18
+ * - `rateLimit as BetterAuthOptions['rateLimit']`: our `{ enabled?: boolean }`
19
+ * subset is a valid runtime value for Better Auth's rateLimit field.
7
20
  */
8
21
  export function createAuth(options) {
9
- const provider = detectProvider(options.databaseUrl);
10
22
  const socialProviders = {};
11
23
  if (options.providers?.github !== undefined) {
12
- socialProviders.github = options.providers.github;
24
+ socialProviders['github'] = options.providers.github;
13
25
  }
14
26
  if (options.providers?.google !== undefined) {
15
- socialProviders.google = options.providers.google;
27
+ socialProviders['google'] = options.providers.google;
16
28
  }
17
29
  const hasSocialProviders = Object.keys(socialProviders).length > 0;
18
30
  const authOptions = {
19
31
  secret: options.secret,
20
32
  trustedOrigins: options.trustedOrigins,
21
- database: prismaAdapter(options.prisma, { provider }),
33
+ database: prismaAdapter(options.prisma, { provider: options.provider }),
22
34
  emailAndPassword: { enabled: true },
23
- ...(hasSocialProviders ? { socialProviders } : {}),
35
+ plugins: [admin()],
24
36
  };
37
+ if (hasSocialProviders) {
38
+ authOptions.socialProviders = socialProviders;
39
+ }
40
+ if (options.rateLimit !== undefined) {
41
+ authOptions.rateLimit = options.rateLimit;
42
+ }
25
43
  return betterAuth(authOptions);
26
44
  }
27
45
  //# sourceMappingURL=setup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAK5D;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAyB;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAEpD,MAAM,eAAe,GAAoB,EAAE,CAAA;IAE3C,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,eAAe,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,MAAmC,CAAA;IAChF,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,eAAe,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,MAAmC,CAAA;IAChF,CAAC;IAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAElE,MAAM,WAAW,GAAsB;QACrC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,QAAQ,EAAE,aAAa,CACrB,OAAO,CAAC,MAA6C,EACrD,EAAE,QAAQ,EAAE,CACb;QACD,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnD,CAAA;IAED,OAAO,UAAU,CAAC,WAAW,CAAC,CAAA;AAChC,CAAC"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAc3C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAC,OAAyB;IAClD,MAAM,eAAe,GAA+D,EAAE,CAAA;IAEtF,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,eAAe,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAA;IACtD,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,eAAe,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAA;IACtD,CAAC;IAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAElE,MAAM,WAAW,GAAsB;QACrC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,MAA6B,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC9F,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC;KACnB,CAAA;IAED,IAAI,kBAAkB,EAAE,CAAC;QACvB,WAAW,CAAC,eAAe,GAAG,eAAuD,CAAA;IACvF,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACpC,WAAW,CAAC,SAAS,GAAG,OAAO,CAAC,SAA2C,CAAA;IAC7E,CAAC;IAED,OAAO,UAAU,CAAC,WAAW,CAAiB,CAAA;AAChD,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { DatabaseProvider } from '../config/types.js';
1
2
  export interface SocialProviderCredentials {
2
3
  clientId: string;
3
4
  clientSecret: string;
@@ -5,12 +6,19 @@ export interface SocialProviderCredentials {
5
6
  export interface AuthSetupOptions {
6
7
  secret: string;
7
8
  trustedOrigins: string[];
8
- databaseUrl: string;
9
+ /** Database provider — used to configure the Better Auth Prisma adapter. */
10
+ provider: DatabaseProvider;
9
11
  prisma: unknown;
10
12
  providers?: {
11
13
  github?: SocialProviderCredentials;
12
14
  google?: SocialProviderCredentials;
13
15
  };
16
+ /**
17
+ * Better Auth rate-limit settings.
18
+ */
19
+ rateLimit?: {
20
+ enabled?: boolean;
21
+ };
14
22
  }
15
23
  export type { betterAuth as BetterAuth } from 'better-auth';
16
24
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,yBAAyB,CAAA;QAClC,MAAM,CAAC,EAAE,yBAAyB,CAAA;KACnC,CAAA;CACF;AAGD,YAAY,EAAE,UAAU,IAAI,UAAU,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,4EAA4E;IAC5E,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,yBAAyB,CAAA;QAClC,MAAM,CAAC,EAAE,yBAAyB,CAAA;KACnC,CAAA;IACD;;OAEG;IACH,SAAS,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAClC;AAGD,YAAY,EAAE,UAAU,IAAI,UAAU,EAAE,MAAM,aAAa,CAAA"}
@@ -1,3 +1,7 @@
1
+ export type DatabaseProvider = 'postgresql' | 'sqlite';
2
+ export interface DatabaseConfig {
3
+ provider: DatabaseProvider;
4
+ }
1
5
  export interface ServerConfig {
2
6
  port: number;
3
7
  host: string;
@@ -6,17 +10,45 @@ export interface AuthProviders {
6
10
  github?: boolean;
7
11
  google?: boolean;
8
12
  }
13
+ export interface AuthRateLimit {
14
+ /** Set to false to disable Better Auth's built-in rate limiting (useful in test environments). */
15
+ enabled?: boolean;
16
+ }
9
17
  export interface AuthConfig {
10
18
  trustedOrigins: string[];
11
19
  providers?: AuthProviders;
20
+ /**
21
+ * Better Auth rate-limit settings.
22
+ * Pass `{ enabled: false }` in test environments to prevent the in-process
23
+ * rate limiter from triggering 429 errors across shared test suites.
24
+ */
25
+ rateLimit?: AuthRateLimit;
12
26
  }
13
27
  export interface InertiaConfig {
14
28
  ssr: boolean;
15
29
  version?: string;
16
30
  }
31
+ /**
32
+ * Pino log levels in order of increasing severity.
33
+ * 'silent' disables all output.
34
+ */
35
+ export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent';
36
+ export interface LoggingConfig {
37
+ /**
38
+ * Minimum log level emitted by the framework's Pino logger.
39
+ * Defaults to 'error' when the logging block is omitted.
40
+ */
41
+ level: LogLevel;
42
+ }
17
43
  export interface HypersonicConfig {
18
44
  server: ServerConfig;
19
45
  auth: AuthConfig;
20
46
  inertia: InertiaConfig;
47
+ database: DatabaseConfig;
48
+ /**
49
+ * Server-side logging configuration.
50
+ * Omit to use the framework default (level: 'error').
51
+ */
52
+ logging?: LoggingConfig;
21
53
  }
22
54
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,SAAS,CAAC,EAAE,aAAa,CAAA;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,OAAO,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,aAAa,CAAA;CACvB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,QAAQ,CAAA;AAEtD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,kGAAkG;IAClG,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,OAAO,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEzF,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,KAAK,EAAE,QAAQ,CAAA;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,aAAa,CAAA;IACtB,QAAQ,EAAE,cAAc,CAAA;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB"}
@@ -0,0 +1,13 @@
1
+ import type { DatabaseProvider } from '../config/types.js';
2
+ /**
3
+ * Creates the Prisma v7 driver adapter for the given provider and DATABASE_URL.
4
+ *
5
+ * Adapter packages are dynamic-imported so only the one matching the user's
6
+ * installed driver is loaded at runtime — no unused adapter is bundled.
7
+ *
8
+ * Supported providers and their required packages:
9
+ * - postgresql → @prisma/adapter-pg
10
+ * - sqlite → @prisma/adapter-better-sqlite3 + better-sqlite3
11
+ */
12
+ export declare function createDatabaseAdapter(provider: DatabaseProvider, databaseUrl: string): Promise<unknown>;
13
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/database/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,gBAAgB,EAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAiBlB"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Creates the Prisma v7 driver adapter for the given provider and DATABASE_URL.
3
+ *
4
+ * Adapter packages are dynamic-imported so only the one matching the user's
5
+ * installed driver is loaded at runtime — no unused adapter is bundled.
6
+ *
7
+ * Supported providers and their required packages:
8
+ * - postgresql → @prisma/adapter-pg
9
+ * - sqlite → @prisma/adapter-better-sqlite3 + better-sqlite3
10
+ */
11
+ export async function createDatabaseAdapter(provider, databaseUrl) {
12
+ if (provider === 'postgresql') {
13
+ const { PrismaPg } = await import('@prisma/adapter-pg');
14
+ return new PrismaPg({ connectionString: databaseUrl });
15
+ }
16
+ if (provider === 'sqlite') {
17
+ const { PrismaBetterSqlite3 } = await import('@prisma/adapter-better-sqlite3');
18
+ return new PrismaBetterSqlite3({ url: databaseUrl });
19
+ }
20
+ // TypeScript makes this unreachable for well-typed callers, but keep as a
21
+ // runtime safety net for any JS callers or future provider additions.
22
+ throw new Error(`Hypersonic: unsupported database provider "${provider}". ` +
23
+ `Supported providers are: postgresql, sqlite.`);
24
+ }
25
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/database/adapter.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAA0B,EAC1B,WAAmB;IAEnB,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC9B,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;QACvD,OAAO,IAAI,QAAQ,CAAC,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,CAAA;IACxD,CAAC;IAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAA;QAC9E,OAAO,IAAI,mBAAmB,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAA;IACtD,CAAC;IAED,0EAA0E;IAC1E,sEAAsE;IACtE,MAAM,IAAI,KAAK,CACb,8CAA8C,QAAkB,KAAK;QACnE,8CAA8C,CACjD,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  export { defineConfig } from './config/define-config.js';
2
2
  export { loadConfig, importConfigFile } from './config/loader.js';
3
3
  export { validateEnv, buildEnvSchema } from './config/env.js';
4
- export type { HypersonicConfig, ServerConfig, AuthConfig, InertiaConfig, AuthProviders } from './config/types.js';
4
+ export type { HypersonicConfig, ServerConfig, AuthConfig, InertiaConfig, AuthProviders, DatabaseConfig, DatabaseProvider, } from './config/types.js';
5
5
  export type { Env } from './config/env.js';
6
6
  export type { LoadedConfig } from './config/loader.js';
7
7
  export { createApp } from './server/app.js';
8
8
  export type { CreateAppOptions, HypersonicApp } from './server/types.js';
9
9
  export { getPrismaClient, setPrismaClient, disconnectPrismaClient } from './database/client.js';
10
+ export { createDatabaseAdapter } from './database/adapter.js';
10
11
  export type { PrismaClientLike } from './database/client.js';
11
12
  export { createAuth } from './auth/setup.js';
12
13
  export { mountAuth } from './auth/middleware.js';
@@ -15,6 +16,4 @@ export { createInertiaMiddleware, createInertiaErrorHandler } from './inertia/mi
15
16
  export { createViteSetup } from './inertia/vite.js';
16
17
  export type { InertiaPage, InertiaOptions, ViteSetup } from './inertia/types.js';
17
18
  export { HttpError, NotFoundError, UnauthorizedError, ForbiddenError, ValidationError } from './utils/errors.js';
18
- export { detectProvider } from './utils/detect-provider.js';
19
- export type { DatabaseProvider } from './utils/detect-provider.js';
20
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC7D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjH,YAAY,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGxE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC/F,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAG5D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,YAAY,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA;AAGlF,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGhF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAChH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC7D,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGxE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAG5D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,YAAY,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA;AAGlF,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGhF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { validateEnv, buildEnvSchema } from './config/env.js';
6
6
  export { createApp } from './server/app.js';
7
7
  // Database
8
8
  export { getPrismaClient, setPrismaClient, disconnectPrismaClient } from './database/client.js';
9
+ export { createDatabaseAdapter } from './database/adapter.js';
9
10
  // Auth
10
11
  export { createAuth } from './auth/setup.js';
11
12
  export { mountAuth } from './auth/middleware.js';
@@ -14,5 +15,4 @@ export { createInertiaMiddleware, createInertiaErrorHandler } from './inertia/mi
14
15
  export { createViteSetup } from './inertia/vite.js';
15
16
  // Utils
16
17
  export { HttpError, NotFoundError, UnauthorizedError, ForbiddenError, ValidationError } from './utils/errors.js';
17
- export { detectProvider } from './utils/detect-provider.js';
18
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAK7D,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAG3C,WAAW;AACX,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAG/F,OAAO;AACP,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAGhD,UAAU;AACV,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,QAAQ;AACR,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAChH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAa7D,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAG3C,WAAW;AACX,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,OAAO;AACP,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAGhD,UAAU;AACV,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,QAAQ;AACR,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
@@ -19,6 +19,24 @@ export declare function createInertiaErrorHandler(): (err: unknown, req: Request
19
19
  /**
20
20
  * Mounts the Inertia middleware + Vite integration onto the Express app.
21
21
  * This must be called before routes are registered.
22
+ *
23
+ * Also installs two CSRF middlewares that apply to every route:
24
+ *
25
+ * - **csrfSetter** — sets the `XSRF-TOKEN` cookie only when the incoming
26
+ * request does not already carry one. Skipping rotation on subsequent
27
+ * requests prevents concurrent-tab races where a fresh token issued for
28
+ * Tab B would invalidate an in-flight form submission from Tab A.
29
+ *
30
+ * - **csrfValidator** — on POST/PUT/PATCH/DELETE requests, verifies that the
31
+ * `X-XSRF-TOKEN` request header matches the `XSRF-TOKEN` request cookie.
32
+ * Returns 419 if they are absent or do not match. Exception: when both the
33
+ * cookie AND the header are absent the client has not yet received a CSRF
34
+ * cookie (a completely unauthenticated request with no prior GET). In that
35
+ * case validation is skipped and downstream auth middleware is responsible
36
+ * for redirecting or rejecting the request.
37
+ *
38
+ * Note: `/api/auth/*` routes are handled by Better Auth before reaching this
39
+ * middleware, so they are naturally excluded from CSRF validation.
22
40
  */
23
41
  export declare function createInertiaMiddleware(app: Application, options: InertiaOptions): Promise<void>;
24
42
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/inertia/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAkB,MAAM,SAAS,CAAA;AAC3F,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAA;AA+B7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,IAAI,CAC3C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,KACf,IAAI,CAWR;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAkDf"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/inertia/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAkB,MAAM,SAAS,CAAA;AAC3F,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAA;AAgE7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,IAAI,CAC3C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,KACf,IAAI,CAWR;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAoHf"}
@@ -1,7 +1,41 @@
1
+ import { randomBytes } from 'node:crypto';
1
2
  import { createViteSetup } from './vite.js';
2
3
  import { HttpError } from '../utils/errors.js';
3
4
  const INERTIA_HEADER = 'x-inertia';
4
5
  const INERTIA_VERSION_HEADER = 'x-inertia-version';
6
+ const CSRF_COOKIE = 'XSRF-TOKEN';
7
+ const CSRF_HEADER = 'x-xsrf-token';
8
+ const CSRF_MUTATION_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
9
+ function generateCsrfToken() {
10
+ return randomBytes(32).toString('hex');
11
+ }
12
+ /**
13
+ * Parses the raw Cookie request header into a key→value map.
14
+ * Splits on ';', finds the first '=' in each pair, and URL-decodes the value.
15
+ * Falls back to the raw value if decoding throws a URIError so that a single
16
+ * malformed cookie cannot crash the middleware before CSRF validation runs.
17
+ */
18
+ function parseCookieHeader(cookieHeader) {
19
+ if (!cookieHeader)
20
+ return {};
21
+ const result = {};
22
+ for (const pair of cookieHeader.split(';')) {
23
+ const eqIdx = pair.indexOf('=');
24
+ if (eqIdx === -1)
25
+ continue;
26
+ const key = pair.slice(0, eqIdx).trim();
27
+ const raw = pair.slice(eqIdx + 1).trim();
28
+ let value;
29
+ try {
30
+ value = decodeURIComponent(raw);
31
+ }
32
+ catch {
33
+ value = raw;
34
+ }
35
+ result[key] = value;
36
+ }
37
+ return result;
38
+ }
5
39
  function escapeJson(str) {
6
40
  return str
7
41
  .replace(/&/g, '\\u0026')
@@ -53,18 +87,94 @@ export function createInertiaErrorHandler() {
53
87
  /**
54
88
  * Mounts the Inertia middleware + Vite integration onto the Express app.
55
89
  * This must be called before routes are registered.
90
+ *
91
+ * Also installs two CSRF middlewares that apply to every route:
92
+ *
93
+ * - **csrfSetter** — sets the `XSRF-TOKEN` cookie only when the incoming
94
+ * request does not already carry one. Skipping rotation on subsequent
95
+ * requests prevents concurrent-tab races where a fresh token issued for
96
+ * Tab B would invalidate an in-flight form submission from Tab A.
97
+ *
98
+ * - **csrfValidator** — on POST/PUT/PATCH/DELETE requests, verifies that the
99
+ * `X-XSRF-TOKEN` request header matches the `XSRF-TOKEN` request cookie.
100
+ * Returns 419 if they are absent or do not match. Exception: when both the
101
+ * cookie AND the header are absent the client has not yet received a CSRF
102
+ * cookie (a completely unauthenticated request with no prior GET). In that
103
+ * case validation is skipped and downstream auth middleware is responsible
104
+ * for redirecting or rejecting the request.
105
+ *
106
+ * Note: `/api/auth/*` routes are handled by Better Auth before reaching this
107
+ * middleware, so they are naturally excluded from CSRF validation.
56
108
  */
57
109
  export async function createInertiaMiddleware(app, options) {
58
110
  const version = options.version ?? '1';
59
111
  const vite = await createViteSetup(options.ssr);
60
112
  // Mount Vite dev server or static file serving
61
113
  app.use(vite.middleware);
114
+ // CSRF token setter — writes the XSRF-TOKEN cookie only when the request
115
+ // carries no existing token. This keeps the token stable across multiple
116
+ // concurrent tabs / in-flight requests for the same session.
117
+ // httpOnly must be false so the Inertia JS client can read it.
118
+ const csrfSetter = (req, res, next) => {
119
+ const cookies = parseCookieHeader(req.headers.cookie);
120
+ if (!cookies[CSRF_COOKIE]) {
121
+ res.cookie(CSRF_COOKIE, generateCsrfToken(), {
122
+ httpOnly: false,
123
+ sameSite: 'strict',
124
+ secure: process.env['NODE_ENV'] === 'production',
125
+ path: '/',
126
+ });
127
+ }
128
+ next();
129
+ };
130
+ // CSRF validator — rejects mutation requests where the X-XSRF-TOKEN header
131
+ // does not match the XSRF-TOKEN cookie that was set on a prior response.
132
+ //
133
+ // Special case: when neither token is present the client has not yet
134
+ // received a CSRF cookie (e.g. a completely unauthenticated browser request
135
+ // with no prior GET). Returning 419 in that case would mask the auth-guard
136
+ // redirect to /login with a confusing error. Downstream auth middleware
137
+ // handles these requests. 419 is only appropriate when a cookie exists but
138
+ // the header is wrong or missing — i.e. when there is something concrete to
139
+ // validate against.
140
+ const csrfValidator = (req, res, next) => {
141
+ if (!CSRF_MUTATION_METHODS.has(req.method)) {
142
+ next();
143
+ return;
144
+ }
145
+ const cookies = parseCookieHeader(req.headers.cookie);
146
+ const cookieToken = cookies[CSRF_COOKIE];
147
+ const rawHeaderToken = req.headers[CSRF_HEADER];
148
+ // The header value is always a plain string for custom headers; normalise
149
+ // to string | undefined so the comparison below is type-safe.
150
+ const headerToken = Array.isArray(rawHeaderToken) ? rawHeaderToken[0] : rawHeaderToken;
151
+ const hasCookie = typeof cookieToken === 'string' && cookieToken.length > 0;
152
+ const hasHeader = typeof headerToken === 'string' && headerToken.length > 0;
153
+ // Both absent — no CSRF context; defer to downstream auth middleware.
154
+ if (!hasCookie && !hasHeader) {
155
+ next();
156
+ return;
157
+ }
158
+ // Cookie present but header wrong/missing, or header present but no cookie.
159
+ if (!hasCookie || cookieToken !== headerToken) {
160
+ res.status(419).json({ error: 'CSRF token mismatch' });
161
+ return;
162
+ }
163
+ next();
164
+ };
165
+ app.use(csrfSetter);
166
+ app.use(csrfValidator);
62
167
  // Inertia protocol middleware
63
168
  const inertiaMiddleware = (req, res, next) => {
64
169
  const isInertiaRequest = Boolean(req.headers[INERTIA_HEADER]);
65
- // Asset version mismatch — force a full page reload
170
+ // Asset version mismatch — force a full page reload.
171
+ // Only fires when the client sends X-Inertia-Version AND it doesn't match
172
+ // the server version. Requests without the header (e.g. test clients that
173
+ // set X-Inertia but omit the version) are let through so they receive the
174
+ // normal JSON response rather than a 409.
66
175
  if (isInertiaRequest &&
67
176
  req.method === 'GET' &&
177
+ req.headers[INERTIA_VERSION_HEADER] !== undefined &&
68
178
  req.headers[INERTIA_VERSION_HEADER] !== version) {
69
179
  res.setHeader('X-Inertia-Location', req.url);
70
180
  res.status(409).end();
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/inertia/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/inertia/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type Logger } from 'pino';
2
+ import type { LogLevel } from '../config/types.js';
3
+ export type { Logger };
4
+ /**
5
+ * Creates a configured Pino logger for the Hypersonic server.
6
+ * Defaults to 'error' level so production deployments are quiet by default —
7
+ * only genuine errors reach the log stream unless the developer explicitly
8
+ * lowers the level in hypersonic.config.ts.
9
+ */
10
+ export declare function createLogger(level?: LogLevel): Logger;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logger/index.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAA;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAElD,YAAY,EAAE,MAAM,EAAE,CAAA;AAEtB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAE,QAAkB,GAAG,MAAM,CAE9D"}
@@ -0,0 +1,11 @@
1
+ import pino from 'pino';
2
+ /**
3
+ * Creates a configured Pino logger for the Hypersonic server.
4
+ * Defaults to 'error' level so production deployments are quiet by default —
5
+ * only genuine errors reach the log stream unless the developer explicitly
6
+ * lowers the level in hypersonic.config.ts.
7
+ */
8
+ export function createLogger(level = 'error') {
9
+ return pino({ level });
10
+ }
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logger/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAqB,MAAM,MAAM,CAAA;AAKxC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,OAAO;IACpD,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AACxB,CAAC"}
@@ -3,17 +3,8 @@ import type { CreateAppOptions, HypersonicApp } from './types.js';
3
3
  * Creates and returns a fully wired Hypersonic application.
4
4
  * The auth instance created internally is returned on `app.auth` so
5
5
  * callers can pass it to route registration without creating a second instance.
6
- *
7
- * @example
8
- * ```ts
9
- * import { PrismaClient } from '@prisma/client'
10
- * import { createApp, loadConfig } from '@hypersonic/core'
11
- *
12
- * const { config, env } = await loadConfig()
13
- * const app = await createApp({ config, env, prisma: new PrismaClient() })
14
- * registerRoutes(app.express, prisma, app.auth)
15
- * await app.start()
16
- * ```
6
+ * The Pino logger is returned on `app.logger` and can be passed to mountAdmin
7
+ * or used directly in route handlers.
17
8
  */
18
9
  export declare function createApp(options: CreateAppOptions): Promise<HypersonicApp>;
19
10
  //# sourceMappingURL=app.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA4BjE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC,CA2BjF"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA4BjE;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC,CAsDjF"}
@@ -1,9 +1,12 @@
1
1
  import express from 'express';
2
+ import helmet from 'helmet';
3
+ import { pinoHttp } from 'pino-http';
2
4
  import { setPrismaClient } from '../database/client.js';
3
5
  import { createAuth } from '../auth/setup.js';
4
6
  import { mountAuth } from '../auth/middleware.js';
5
7
  import { createInertiaMiddleware } from '../inertia/middleware.js';
6
8
  import { createLifecycle } from './lifecycle.js';
9
+ import { createLogger } from '../logger/index.js';
7
10
  function resolveProviders(config, env) {
8
11
  const providers = {};
9
12
  const e = env;
@@ -25,30 +28,40 @@ function resolveProviders(config, env) {
25
28
  * Creates and returns a fully wired Hypersonic application.
26
29
  * The auth instance created internally is returned on `app.auth` so
27
30
  * callers can pass it to route registration without creating a second instance.
28
- *
29
- * @example
30
- * ```ts
31
- * import { PrismaClient } from '@prisma/client'
32
- * import { createApp, loadConfig } from '@hypersonic/core'
33
- *
34
- * const { config, env } = await loadConfig()
35
- * const app = await createApp({ config, env, prisma: new PrismaClient() })
36
- * registerRoutes(app.express, prisma, app.auth)
37
- * await app.start()
38
- * ```
31
+ * The Pino logger is returned on `app.logger` and can be passed to mountAdmin
32
+ * or used directly in route handlers.
39
33
  */
40
34
  export async function createApp(options) {
41
35
  const { config, env, prisma } = options;
36
+ if (!config.database) {
37
+ throw new Error('Hypersonic: config.database is required. ' +
38
+ 'Add a database block to your hypersonic.config.ts:\n' +
39
+ ' database: { provider: "yourdbname" }');
40
+ }
41
+ const logger = createLogger(config.logging?.level ?? 'error');
42
42
  const app = express();
43
+ // Security headers.
44
+ // - CSP omitted — requires app-specific configuration; see docs.
45
+ // - referrerPolicy: same-origin preserves the Referer header for
46
+ // same-origin requests so error handlers can redirect back to the
47
+ // originating form. The Helmet default (no-referrer) strips the header
48
+ // entirely, breaking Inertia's redirect-on-error behaviour.
49
+ app.use(helmet({
50
+ contentSecurityPolicy: false,
51
+ referrerPolicy: { policy: 'same-origin' },
52
+ }));
53
+ // HTTP request / response logging via pino-http.
54
+ app.use(pinoHttp({ logger }));
43
55
  app.use(express.json());
44
56
  app.use(express.urlencoded({ extended: true }));
45
57
  setPrismaClient(prisma);
46
58
  const auth = createAuth({
47
59
  secret: env.BETTER_AUTH_SECRET,
48
60
  trustedOrigins: config.auth.trustedOrigins,
49
- databaseUrl: env.DATABASE_URL,
61
+ provider: config.database.provider,
50
62
  prisma,
51
63
  providers: resolveProviders(config, env),
64
+ rateLimit: config.auth.rateLimit,
52
65
  });
53
66
  mountAuth(app, auth);
54
67
  await createInertiaMiddleware(app, {
@@ -56,6 +69,6 @@ export async function createApp(options) {
56
69
  version: config.inertia.version,
57
70
  });
58
71
  const { start, stop } = createLifecycle(app, config);
59
- return { express: app, auth, start, stop };
72
+ return { express: app, auth, logger, start, stop };
60
73
  }
61
74
  //# sourceMappingURL=app.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAKhD,SAAS,gBAAgB,CACvB,MAAwB,EACxB,GAAQ;IAER,MAAM,SAAS,GAA+D,EAAE,CAAA;IAChF,MAAM,CAAC,GAAG,GAAyC,CAAA;IAEnD,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3C,SAAS,CAAC,QAAQ,CAAC,GAAG;YACpB,QAAQ,EAAE,CAAC,CAAC,kBAAkB,CAAW;YACzC,YAAY,EAAE,CAAC,CAAC,sBAAsB,CAAW;SAClD,CAAA;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3C,SAAS,CAAC,QAAQ,CAAC,GAAG;YACpB,QAAQ,EAAE,CAAC,CAAC,kBAAkB,CAAW;YACzC,YAAY,EAAE,CAAC,CAAC,sBAAsB,CAAW;SAClD,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;AAClE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAyB;IACvD,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAEvC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;IAErB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACvB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAE/C,eAAe,CAAC,MAAM,CAAC,CAAA;IAEvB,MAAM,IAAI,GAAG,UAAU,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,kBAAkB;QAC9B,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc;QAC1C,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,MAAM;QACN,SAAS,EAAE,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC;KACzC,CAAC,CAAA;IACF,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAEpB,MAAM,uBAAuB,CAAC,GAAG,EAAE;QACnC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;KAC9B,CAAC,CAAA;IAEF,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAEpD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AAC5C,CAAC"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { Application } from 'express';
2
+ import type { Logger } from '../logger/index.js';
2
3
  import type { HypersonicConfig } from '../config/types.js';
3
4
  import type { Env } from '../config/env.js';
4
5
  import type { PrismaClientLike } from '../database/client.js';
@@ -11,6 +12,8 @@ export interface CreateAppOptions {
11
12
  export interface HypersonicApp {
12
13
  express: Application;
13
14
  auth: AuthInstance;
15
+ /** Pino logger configured from hypersonic.config.ts — defaults to 'error' level. */
16
+ logger: Logger;
14
17
  start: () => Promise<void>;
15
18
  stop: () => Promise<void>;
16
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAA;IACxB,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAA;IACxB,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,EAAE,YAAY,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypersonic-js/core",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "The core of Hypersonic.js — a modern Django-inspired full-stack TypeScript framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,37 +25,50 @@
25
25
  "access": "public"
26
26
  },
27
27
  "engines": {
28
- "node": "^24.0.0"
28
+ "node": ">=24.0.0"
29
29
  },
30
30
  "dependencies": {
31
- "@inertiajs/core": "3.3.0",
32
- "@inertiajs/react": "3.3.0",
33
- "@tailwindcss/vite": "4.3.0",
31
+ "@inertiajs/core": "3.4.0",
32
+ "@inertiajs/react": "3.4.0",
33
+ "@tailwindcss/vite": "4.3.1",
34
34
  "@vitejs/plugin-react": "6.0.2",
35
- "better-auth": "1.6.11",
35
+ "better-auth": "1.6.19",
36
36
  "express": "5.2.1",
37
- "react": "19.2.6",
38
- "react-dom": "19.2.6",
39
- "tailwindcss": "4.3.0",
40
- "vite": "8.0.14",
37
+ "helmet": "8.2.0",
38
+ "pino": "10.3.1",
39
+ "pino-http": "11.0.0",
40
+ "react": "19.2.7",
41
+ "react-dom": "19.2.7",
42
+ "tailwindcss": "4.3.1",
43
+ "vite": "8.0.16",
41
44
  "zod": "4.4.3"
42
45
  },
43
46
  "peerDependencies": {
44
47
  "@prisma/client": "7.8.0",
45
- "prisma": "7.8.0"
48
+ "prisma": "7.8.0",
49
+ "@prisma/adapter-pg": "7.8.0",
50
+ "@prisma/adapter-better-sqlite3": "7.8.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@prisma/adapter-pg": {
54
+ "optional": true
55
+ },
56
+ "@prisma/adapter-better-sqlite3": {
57
+ "optional": true
58
+ }
46
59
  },
47
60
  "devDependencies": {
48
61
  "@prisma/client": "7.8.0",
49
62
  "@types/express": "5.0.6",
50
- "@types/node": "25.9.1",
51
- "@types/react": "19.2.15",
63
+ "@types/node": "25.9.3",
64
+ "@types/react": "19.2.17",
52
65
  "@types/react-dom": "19.2.3",
53
66
  "@types/supertest": "7.2.0",
54
- "@vitest/coverage-v8": "4.1.7",
67
+ "@vitest/coverage-v8": "4.1.9",
55
68
  "prisma": "7.8.0",
56
69
  "supertest": "7.2.2",
57
70
  "typescript": "6.0.3",
58
- "vitest": "4.1.7"
71
+ "vitest": "4.1.9"
59
72
  },
60
73
  "scripts": {
61
74
  "build": "tsc",
package/Readme.md DELETED
@@ -1,30 +0,0 @@
1
- # @hypersonic-js/complete
2
-
3
- **Hypersonic.js** — everything in one installation. This package re-exports the full public API of every Hypersonic package so you don't have to manage individual package versions.
4
-
5
- 📖 **[hypersonic-js.com](https://hypersonic-js.com)**
6
-
7
- ## Install
8
-
9
- ```bash
10
- npm install @hypersonic-js/complete
11
- npm install --save-dev prisma @prisma/client
12
- ```
13
-
14
- ## When to use this
15
-
16
- Use `@hypersonic-js/complete` if you want a single dependency that tracks the full framework. Use the individual packages (e.g. `@hypersonic-js/core`) if you need fine-grained control over which parts of the framework you include.
17
-
18
- ## Quick start
19
-
20
- ```ts
21
- import { defineConfig, createApp, loadConfig } from '@hypersonic-js/complete'
22
- ```
23
-
24
- Everything exported by `@hypersonic-js/complete` is identical to the same export from its source package — no wrappers, no overhead.
25
-
26
- Full documentation at **[hypersonic-js.com](https://hypersonic-js.com)**.
27
-
28
- ## License
29
-
30
- MIT © [Joaquim Dalton-Pereira](https://github.com/Zesuperaker)