ras-stack 0.43.0 → 0.45.0

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.
@@ -1,9 +1,9 @@
1
1
  export { acceptedOrigins, forwardedOrigin, parseOrigin, requireSameOrigin, trustedOrigins, validSameOriginRequest } from './origins.js';
2
2
  export type { OriginOptions } from './origins.js';
3
3
  export { configuredProviderOptions, configuredProviders, providerCredentials } from './providers.js';
4
- export type { ProviderCredentials } from './providers.js';
4
+ export type { ProviderCredentials, ProviderEnvironmentOptions } from './providers.js';
5
5
  export { randomId, randomToken } from './random.js';
6
6
  export { persistedSecret } from './secret.js';
7
7
  export type { PersistedSecretOptions } from './secret.js';
8
- export { standardRateLimitOptions, standardSessionOptions } from './settings.js';
9
- export type { RateLimitRule } from './settings.js';
8
+ export { standardAccountOptions, standardRateLimitOptions, standardSessionOptions } from './settings.js';
9
+ export type { RateLimitRule, SessionOptions, StandardAccountOptions } from './settings.js';
@@ -2,5 +2,5 @@ export { acceptedOrigins, forwardedOrigin, parseOrigin, requireSameOrigin, trust
2
2
  export { configuredProviderOptions, configuredProviders, providerCredentials } from './providers.js';
3
3
  export { randomId, randomToken } from './random.js';
4
4
  export { persistedSecret } from './secret.js';
5
- export { standardRateLimitOptions, standardSessionOptions } from './settings.js';
5
+ export { standardAccountOptions, standardRateLimitOptions, standardSessionOptions } from './settings.js';
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAEvI,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAEpG,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA","sourcesContent":["export { acceptedOrigins, forwardedOrigin, parseOrigin, requireSameOrigin, trustedOrigins, validSameOriginRequest } from './origins.js'\nexport type { OriginOptions } from './origins.js'\nexport { configuredProviderOptions, configuredProviders, providerCredentials } from './providers.js'\nexport type { ProviderCredentials } from './providers.js'\nexport { randomId, randomToken } from './random.js'\nexport { persistedSecret } from './secret.js'\nexport type { PersistedSecretOptions } from './secret.js'\nexport { standardRateLimitOptions, standardSessionOptions } from './settings.js'\nexport type { RateLimitRule } from './settings.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAEvI,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAEpG,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA","sourcesContent":["export { acceptedOrigins, forwardedOrigin, parseOrigin, requireSameOrigin, trustedOrigins, validSameOriginRequest } from './origins.js'\nexport type { OriginOptions } from './origins.js'\nexport { configuredProviderOptions, configuredProviders, providerCredentials } from './providers.js'\nexport type { ProviderCredentials, ProviderEnvironmentOptions } from './providers.js'\nexport { randomId, randomToken } from './random.js'\nexport { persistedSecret } from './secret.js'\nexport type { PersistedSecretOptions } from './secret.js'\nexport { standardAccountOptions, standardRateLimitOptions, standardSessionOptions } from './settings.js'\nexport type { RateLimitRule, SessionOptions, StandardAccountOptions } from './settings.js'\n"]}
@@ -2,6 +2,10 @@ export type ProviderCredentials = {
2
2
  clientId: string;
3
3
  clientSecret: string;
4
4
  };
5
- export declare function configuredProviders<const Provider extends string>(providers: readonly Provider[], environment?: NodeJS.ProcessEnv): Provider[];
6
- export declare function providerCredentials(provider: string, environment?: NodeJS.ProcessEnv): ProviderCredentials | undefined;
7
- export declare function configuredProviderOptions<const Provider extends string>(providers: readonly Provider[], environment?: NodeJS.ProcessEnv): Partial<Record<Provider, ProviderCredentials>>;
5
+ export type ProviderEnvironmentOptions = {
6
+ prefix?: string;
7
+ rejectPartial?: boolean;
8
+ };
9
+ export declare function configuredProviders<const Provider extends string>(providers: readonly Provider[], environment?: NodeJS.ProcessEnv, options?: ProviderEnvironmentOptions): Provider[];
10
+ export declare function providerCredentials(provider: string, environment?: NodeJS.ProcessEnv, options?: ProviderEnvironmentOptions): ProviderCredentials | undefined;
11
+ export declare function configuredProviderOptions<const Provider extends string>(providers: readonly Provider[], environment?: NodeJS.ProcessEnv, environmentOptions?: ProviderEnvironmentOptions): Partial<Record<Provider, ProviderCredentials>>;
@@ -1,22 +1,26 @@
1
- export function configuredProviders(providers, environment = process.env) {
2
- return providers.filter((provider) => {
3
- const prefix = provider.toUpperCase().replaceAll('-', '_');
4
- return Boolean(environment[`${prefix}_CLIENT_ID`]?.trim() && environment[`${prefix}_CLIENT_SECRET`]?.trim());
5
- });
1
+ function providerEnvironmentKeys(provider, prefix = '') {
2
+ const name = provider.toUpperCase().replaceAll('-', '_');
3
+ return { clientId: `${prefix}${name}_CLIENT_ID`, clientSecret: `${prefix}${name}_CLIENT_SECRET` };
6
4
  }
7
- export function providerCredentials(provider, environment = process.env) {
8
- const prefix = provider.toUpperCase().replaceAll('-', '_');
9
- const clientId = environment[`${prefix}_CLIENT_ID`]?.trim();
10
- const clientSecret = environment[`${prefix}_CLIENT_SECRET`]?.trim();
5
+ export function configuredProviders(providers, environment = process.env, options = {}) {
6
+ return providers.filter((provider) => Boolean(providerCredentials(provider, environment, options)));
7
+ }
8
+ export function providerCredentials(provider, environment = process.env, options = {}) {
9
+ const keys = providerEnvironmentKeys(provider, options.prefix);
10
+ const clientId = environment[keys.clientId]?.trim();
11
+ const clientSecret = environment[keys.clientSecret]?.trim();
12
+ if (options.rejectPartial && Boolean(clientId) !== Boolean(clientSecret)) {
13
+ throw new Error(`${keys.clientId} and ${keys.clientSecret} must be configured together`);
14
+ }
11
15
  return clientId && clientSecret ? { clientId, clientSecret } : undefined;
12
16
  }
13
- export function configuredProviderOptions(providers, environment = process.env) {
14
- const options = {};
17
+ export function configuredProviderOptions(providers, environment = process.env, environmentOptions = {}) {
18
+ const providerOptions = {};
15
19
  for (const provider of providers) {
16
- const credentials = providerCredentials(provider, environment);
20
+ const credentials = providerCredentials(provider, environment, environmentOptions);
17
21
  if (credentials)
18
- options[provider] = credentials;
22
+ providerOptions[provider] = credentials;
19
23
  }
20
- return options;
24
+ return providerOptions;
21
25
  }
22
26
  //# sourceMappingURL=providers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/auth/providers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CACjC,SAA8B,EAC9B,WAAW,GAAsB,OAAO,CAAC,GAAG;IAE5C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAC1D,OAAO,OAAO,CAAC,WAAW,CAAC,GAAG,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,WAAW,CAAC,GAAG,MAAM,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9G,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAW,GAAsB,OAAO,CAAC,GAAG;IAChG,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAC1D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,CAAA;IAC3D,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,MAAM,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAA;IACnE,OAAO,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1E,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,SAA8B,EAC9B,WAAW,GAAsB,OAAO,CAAC,GAAG;IAE5C,MAAM,OAAO,GAAmD,EAAE,CAAA;IAClE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,mBAAmB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;QAC9D,IAAI,WAAW;YAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAA;IAClD,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["export type ProviderCredentials = { clientId: string; clientSecret: string }\n\nexport function configuredProviders<const Provider extends string>(\n providers: readonly Provider[],\n environment: NodeJS.ProcessEnv = process.env,\n) {\n return providers.filter((provider) => {\n const prefix = provider.toUpperCase().replaceAll('-', '_')\n return Boolean(environment[`${prefix}_CLIENT_ID`]?.trim() && environment[`${prefix}_CLIENT_SECRET`]?.trim())\n })\n}\n\nexport function providerCredentials(provider: string, environment: NodeJS.ProcessEnv = process.env): ProviderCredentials | undefined {\n const prefix = provider.toUpperCase().replaceAll('-', '_')\n const clientId = environment[`${prefix}_CLIENT_ID`]?.trim()\n const clientSecret = environment[`${prefix}_CLIENT_SECRET`]?.trim()\n return clientId && clientSecret ? { clientId, clientSecret } : undefined\n}\n\nexport function configuredProviderOptions<const Provider extends string>(\n providers: readonly Provider[],\n environment: NodeJS.ProcessEnv = process.env,\n): Partial<Record<Provider, ProviderCredentials>> {\n const options: Partial<Record<Provider, ProviderCredentials>> = {}\n for (const provider of providers) {\n const credentials = providerCredentials(provider, environment)\n if (credentials) options[provider] = credentials\n }\n return options\n}\n"]}
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/auth/providers.ts"],"names":[],"mappings":"AAGA,SAAS,uBAAuB,CAAC,QAAgB,EAAE,MAAM,GAAG,EAAE;IAC5D,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACxD,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,IAAI,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAA;AACnG,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAA8B,EAC9B,WAAW,GAAsB,OAAO,CAAC,GAAG,EAC5C,OAAO,GAA+B,EAAE;IAExC,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;AACrG,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,WAAW,GAAsB,OAAO,CAAC,GAAG,EAC5C,OAAO,GAA+B,EAAE;IAExC,MAAM,IAAI,GAAG,uBAAuB,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAA;IACnD,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAA;IAC3D,IAAI,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,YAAY,8BAA8B,CAAC,CAAA;IAC1F,CAAC;IACD,OAAO,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1E,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,SAA8B,EAC9B,WAAW,GAAsB,OAAO,CAAC,GAAG,EAC5C,kBAAkB,GAA+B,EAAE;IAEnD,MAAM,eAAe,GAAmD,EAAE,CAAA;IAC1E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAA;QAClF,IAAI,WAAW;YAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAA;IAC1D,CAAC;IACD,OAAO,eAAe,CAAA;AACxB,CAAC","sourcesContent":["export type ProviderCredentials = { clientId: string; clientSecret: string }\nexport type ProviderEnvironmentOptions = { prefix?: string; rejectPartial?: boolean }\n\nfunction providerEnvironmentKeys(provider: string, prefix = '') {\n const name = provider.toUpperCase().replaceAll('-', '_')\n return { clientId: `${prefix}${name}_CLIENT_ID`, clientSecret: `${prefix}${name}_CLIENT_SECRET` }\n}\n\nexport function configuredProviders<const Provider extends string>(\n providers: readonly Provider[],\n environment: NodeJS.ProcessEnv = process.env,\n options: ProviderEnvironmentOptions = {},\n) {\n return providers.filter((provider) => Boolean(providerCredentials(provider, environment, options)))\n}\n\nexport function providerCredentials(\n provider: string,\n environment: NodeJS.ProcessEnv = process.env,\n options: ProviderEnvironmentOptions = {},\n): ProviderCredentials | undefined {\n const keys = providerEnvironmentKeys(provider, options.prefix)\n const clientId = environment[keys.clientId]?.trim()\n const clientSecret = environment[keys.clientSecret]?.trim()\n if (options.rejectPartial && Boolean(clientId) !== Boolean(clientSecret)) {\n throw new Error(`${keys.clientId} and ${keys.clientSecret} must be configured together`)\n }\n return clientId && clientSecret ? { clientId, clientSecret } : undefined\n}\n\nexport function configuredProviderOptions<const Provider extends string>(\n providers: readonly Provider[],\n environment: NodeJS.ProcessEnv = process.env,\n environmentOptions: ProviderEnvironmentOptions = {},\n): Partial<Record<Provider, ProviderCredentials>> {\n const providerOptions: Partial<Record<Provider, ProviderCredentials>> = {}\n for (const provider of providers) {\n const credentials = providerCredentials(provider, environment, environmentOptions)\n if (credentials) providerOptions[provider] = credentials\n }\n return providerOptions\n}\n"]}
@@ -2,10 +2,20 @@ export type RateLimitRule = {
2
2
  window: number;
3
3
  max: number;
4
4
  };
5
- export declare function standardSessionOptions(): {
5
+ export type SessionOptions = {
6
+ expiresIn?: number | undefined;
7
+ updateAge?: number | undefined;
8
+ };
9
+ export type StandardAccountOptions = {
10
+ encryptOAuthTokens?: boolean;
11
+ };
12
+ export declare function standardSessionOptions<const Options extends object>(overrides?: Options & SessionOptions): Options & {
6
13
  expiresIn: number;
7
14
  updateAge: number;
8
15
  };
16
+ export declare function standardAccountOptions<const Options extends object>(overrides?: Options & StandardAccountOptions): Options & {
17
+ encryptOAuthTokens: boolean;
18
+ };
9
19
  export declare function standardRateLimitOptions(customRules?: Record<string, RateLimitRule>): {
10
20
  enabled: boolean;
11
21
  storage: 'database';
@@ -24,5 +34,9 @@ export declare function standardRateLimitOptions(customRules?: Record<string, Ra
24
34
  window: number;
25
35
  max: number;
26
36
  };
37
+ '/admin/set-user-password': {
38
+ window: number;
39
+ max: number;
40
+ };
27
41
  };
28
42
  };
@@ -1,5 +1,15 @@
1
- export function standardSessionOptions() {
2
- return { expiresIn: 60 * 60 * 24 * 90, updateAge: 60 * 60 * 24 };
1
+ export function standardSessionOptions(overrides = {}) {
2
+ return {
3
+ ...overrides,
4
+ expiresIn: overrides.expiresIn ?? 60 * 60 * 24 * 90,
5
+ updateAge: overrides.updateAge ?? 60 * 60 * 24,
6
+ };
7
+ }
8
+ export function standardAccountOptions(overrides = {}) {
9
+ return {
10
+ ...overrides,
11
+ encryptOAuthTokens: overrides.encryptOAuthTokens ?? true,
12
+ };
3
13
  }
4
14
  export function standardRateLimitOptions(customRules = {}) {
5
15
  return {
@@ -11,6 +21,7 @@ export function standardRateLimitOptions(customRules = {}) {
11
21
  '/sign-in/email': { window: 60, max: 20 },
12
22
  '/sign-up/email': { window: 60, max: 15 },
13
23
  '/request-password-reset': { window: 60, max: 5 },
24
+ '/admin/set-user-password': { window: 60, max: 10 },
14
25
  ...customRules,
15
26
  },
16
27
  };
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/auth/settings.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,sBAAsB;IACpC,OAAO,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,WAAW,GAAkC,EAAE;IACtF,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,UAAmB;QAC5B,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,GAAG;QACR,WAAW,EAAE;YACX,gBAAgB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACzC,gBAAgB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACzC,yBAAyB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE;YACjD,GAAG,WAAW;SACf;KACF,CAAA;AACH,CAAC","sourcesContent":["export type RateLimitRule = { window: number; max: number }\n\nexport function standardSessionOptions() {\n return { expiresIn: 60 * 60 * 24 * 90, updateAge: 60 * 60 * 24 }\n}\n\nexport function standardRateLimitOptions(customRules: Record<string, RateLimitRule> = {}) {\n return {\n enabled: true,\n storage: 'database' as const,\n window: 60,\n max: 120,\n customRules: {\n '/sign-in/email': { window: 60, max: 20 },\n '/sign-up/email': { window: 60, max: 15 },\n '/request-password-reset': { window: 60, max: 5 },\n ...customRules,\n },\n }\n}\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/auth/settings.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,sBAAsB,CAA+B,SAAS,GAA6B,EAA8B;IACvI,OAAO;QACL,GAAG,SAAS;QACZ,SAAS,EAAE,SAAS,CAAC,SAAS,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACnD,SAAS,EAAE,SAAS,CAAC,SAAS,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;KAC/C,CAAA;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,SAAS,GAAqC,EAAsC;IAEpF,OAAO;QACL,GAAG,SAAS;QACZ,kBAAkB,EAAE,SAAS,CAAC,kBAAkB,IAAI,IAAI;KACzD,CAAA;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,WAAW,GAAkC,EAAE;IACtF,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,UAAmB;QAC5B,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,GAAG;QACR,WAAW,EAAE;YACX,gBAAgB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACzC,gBAAgB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACzC,yBAAyB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE;YACjD,0BAA0B,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACnD,GAAG,WAAW;SACf;KACF,CAAA;AACH,CAAC","sourcesContent":["export type RateLimitRule = { window: number; max: number }\n\nexport type SessionOptions = { expiresIn?: number | undefined; updateAge?: number | undefined }\nexport type StandardAccountOptions = { encryptOAuthTokens?: boolean }\n\nexport function standardSessionOptions<const Options extends object>(overrides: Options & SessionOptions = {} as Options & SessionOptions) {\n return {\n ...overrides,\n expiresIn: overrides.expiresIn ?? 60 * 60 * 24 * 90,\n updateAge: overrides.updateAge ?? 60 * 60 * 24,\n }\n}\n\nexport function standardAccountOptions<const Options extends object>(\n overrides: Options & StandardAccountOptions = {} as Options & StandardAccountOptions,\n) {\n return {\n ...overrides,\n encryptOAuthTokens: overrides.encryptOAuthTokens ?? true,\n }\n}\n\nexport function standardRateLimitOptions(customRules: Record<string, RateLimitRule> = {}) {\n return {\n enabled: true,\n storage: 'database' as const,\n window: 60,\n max: 120,\n customRules: {\n '/sign-in/email': { window: 60, max: 20 },\n '/sign-up/email': { window: 60, max: 15 },\n '/request-password-reset': { window: 60, max: 5 },\n '/admin/set-user-password': { window: 60, max: 10 },\n ...customRules,\n },\n }\n}\n"]}
@@ -4,20 +4,16 @@ type ViteProxyTarget = {
4
4
  changeOrigin: true;
5
5
  rewrite: (path: string) => string;
6
6
  };
7
- export declare function postHogIngestProxy(input: Pick<PostHogEnvironment, 'host' | 'assetsHost'>): {
7
+ export declare const POSTHOG_DEFAULT_INGEST_PATH = "/ingest";
8
+ export declare function postHogIngestProxy(input: Pick<PostHogEnvironment, 'host' | 'assetsHost'>, options?: {
9
+ path?: string;
10
+ }): {
11
+ path: string;
8
12
  vite: {
9
- '/ingest/static': ViteProxyTarget;
10
- '/ingest/array': ViteProxyTarget;
11
- '/ingest': ViteProxyTarget;
13
+ [x: string]: ViteProxyTarget;
12
14
  };
13
15
  nitro: {
14
- '/ingest/static/**': {
15
- proxy: string;
16
- };
17
- '/ingest/array/**': {
18
- proxy: string;
19
- };
20
- '/ingest/**': {
16
+ [x: string]: {
21
17
  proxy: string;
22
18
  };
23
19
  };
@@ -1,24 +1,34 @@
1
1
  import { postHogHttpUrl } from './config.js';
2
- function viteTarget(host) {
2
+ function viteTarget(host, ingestPath) {
3
+ const prefix = new RegExp(`^${ingestPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`);
3
4
  return {
4
5
  target: host,
5
6
  changeOrigin: true,
6
- rewrite: (path) => path.replace(/^\/ingest/, ''),
7
+ rewrite: (path) => path.replace(prefix, ''),
7
8
  };
8
9
  }
9
- export function postHogIngestProxy(input) {
10
+ export const POSTHOG_DEFAULT_INGEST_PATH = '/ingest';
11
+ function normalizedIngestPath(path) {
12
+ if (!path.startsWith('/') || path.endsWith('/') || path.includes('?') || path.includes('#')) {
13
+ throw new Error('PostHog ingest path must start with "/", have no trailing slash, and carry no query or fragment');
14
+ }
15
+ return path;
16
+ }
17
+ export function postHogIngestProxy(input, options = {}) {
10
18
  const ingestionHost = postHogHttpUrl(input.host, 'host');
11
19
  const assetsHost = postHogHttpUrl(input.assetsHost, 'assetsHost');
20
+ const path = normalizedIngestPath(options.path ?? POSTHOG_DEFAULT_INGEST_PATH);
12
21
  return {
22
+ path,
13
23
  vite: {
14
- '/ingest/static': viteTarget(assetsHost),
15
- '/ingest/array': viteTarget(assetsHost),
16
- '/ingest': viteTarget(ingestionHost),
24
+ [`${path}/static`]: viteTarget(assetsHost, path),
25
+ [`${path}/array`]: viteTarget(assetsHost, path),
26
+ [path]: viteTarget(ingestionHost, path),
17
27
  },
18
28
  nitro: {
19
- '/ingest/static/**': { proxy: `${assetsHost}/static/**` },
20
- '/ingest/array/**': { proxy: `${assetsHost}/array/**` },
21
- '/ingest/**': { proxy: `${ingestionHost}/**` },
29
+ [`${path}/static/**`]: { proxy: `${assetsHost}/static/**` },
30
+ [`${path}/array/**`]: { proxy: `${assetsHost}/array/**` },
31
+ [`${path}/**`]: { proxy: `${ingestionHost}/**` },
22
32
  },
23
33
  };
24
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/posthog/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAS5C,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;KACjD,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAsD;IACvF,MAAM,aAAa,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACxD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IACjE,OAAO;QACL,IAAI,EAAE;YACJ,gBAAgB,EAAE,UAAU,CAAC,UAAU,CAAC;YACxC,eAAe,EAAE,UAAU,CAAC,UAAU,CAAC;YACvC,SAAS,EAAE,UAAU,CAAC,aAAa,CAAC;SACrC;QACD,KAAK,EAAE;YACL,mBAAmB,EAAE,EAAE,KAAK,EAAE,GAAG,UAAU,YAAY,EAAE;YACzD,kBAAkB,EAAE,EAAE,KAAK,EAAE,GAAG,UAAU,WAAW,EAAE;YACvD,YAAY,EAAE,EAAE,KAAK,EAAE,GAAG,aAAa,KAAK,EAAE;SAC/C;KACF,CAAA;AACH,CAAC","sourcesContent":["import { postHogHttpUrl } from './config.js'\nimport type { PostHogEnvironment } from './config.js'\n\ntype ViteProxyTarget = {\n target: string\n changeOrigin: true\n rewrite: (path: string) => string\n}\n\nfunction viteTarget(host: string): ViteProxyTarget {\n return {\n target: host,\n changeOrigin: true,\n rewrite: (path) => path.replace(/^\\/ingest/, ''),\n }\n}\n\nexport function postHogIngestProxy(input: Pick<PostHogEnvironment, 'host' | 'assetsHost'>) {\n const ingestionHost = postHogHttpUrl(input.host, 'host')\n const assetsHost = postHogHttpUrl(input.assetsHost, 'assetsHost')\n return {\n vite: {\n '/ingest/static': viteTarget(assetsHost),\n '/ingest/array': viteTarget(assetsHost),\n '/ingest': viteTarget(ingestionHost),\n },\n nitro: {\n '/ingest/static/**': { proxy: `${assetsHost}/static/**` },\n '/ingest/array/**': { proxy: `${assetsHost}/array/**` },\n '/ingest/**': { proxy: `${ingestionHost}/**` },\n },\n }\n}\n"]}
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/posthog/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAS5C,SAAS,UAAU,CAAC,IAAY,EAAE,UAAkB;IAClD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;IAClF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;KAC5C,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,SAAS,CAAA;AAEpD,SAAS,oBAAoB,CAAC,IAAY;IACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAA;IACpH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAsD,EAAE,OAAO,GAAsB,EAAE;IACxH,MAAM,aAAa,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACxD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IACjE,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,IAAI,IAAI,2BAA2B,CAAC,CAAA;IAC9E,OAAO;QACL,IAAI;QACJ,IAAI,EAAE;YACJ,CAAC,GAAG,IAAI,SAAS,CAAC,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC;YAChD,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC;YAC/C,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC;SACxC;QACD,KAAK,EAAE;YACL,CAAC,GAAG,IAAI,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,UAAU,YAAY,EAAE;YAC3D,CAAC,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,UAAU,WAAW,EAAE;YACzD,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,aAAa,KAAK,EAAE;SACjD;KACF,CAAA;AACH,CAAC","sourcesContent":["import { postHogHttpUrl } from './config.js'\nimport type { PostHogEnvironment } from './config.js'\n\ntype ViteProxyTarget = {\n target: string\n changeOrigin: true\n rewrite: (path: string) => string\n}\n\nfunction viteTarget(host: string, ingestPath: string): ViteProxyTarget {\n const prefix = new RegExp(`^${ingestPath.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`)\n return {\n target: host,\n changeOrigin: true,\n rewrite: (path) => path.replace(prefix, ''),\n }\n}\n\nexport const POSTHOG_DEFAULT_INGEST_PATH = '/ingest'\n\nfunction normalizedIngestPath(path: string): string {\n if (!path.startsWith('/') || path.endsWith('/') || path.includes('?') || path.includes('#')) {\n throw new Error('PostHog ingest path must start with \"/\", have no trailing slash, and carry no query or fragment')\n }\n return path\n}\n\nexport function postHogIngestProxy(input: Pick<PostHogEnvironment, 'host' | 'assetsHost'>, options: { path?: string } = {}) {\n const ingestionHost = postHogHttpUrl(input.host, 'host')\n const assetsHost = postHogHttpUrl(input.assetsHost, 'assetsHost')\n const path = normalizedIngestPath(options.path ?? POSTHOG_DEFAULT_INGEST_PATH)\n return {\n path,\n vite: {\n [`${path}/static`]: viteTarget(assetsHost, path),\n [`${path}/array`]: viteTarget(assetsHost, path),\n [path]: viteTarget(ingestionHost, path),\n },\n nitro: {\n [`${path}/static/**`]: { proxy: `${assetsHost}/static/**` },\n [`${path}/array/**`]: { proxy: `${assetsHost}/array/**` },\n [`${path}/**`]: { proxy: `${ingestionHost}/**` },\n },\n }\n}\n"]}
@@ -1,10 +1,11 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { PostHogConfig, Properties } from 'posthog-js';
3
3
  import type { PostHogEnvironment } from './config.js';
4
- export declare function PostHogIntegration({ children, environment, fallback, options, }: {
4
+ export declare function PostHogIntegration({ children, environment, fallback, ingestPath, options, }: {
5
5
  children?: ReactNode;
6
6
  environment: PostHogEnvironment | undefined;
7
7
  fallback?: ReactNode;
8
+ ingestPath?: string;
8
9
  options?: Partial<PostHogConfig>;
9
10
  }): string | number | bigint | boolean | import("react").FunctionComponentElement<({
10
11
  client: import("posthog-js").PostHog;
@@ -1,14 +1,15 @@
1
1
  import { PostHogErrorBoundary, PostHogProvider, usePostHog } from '@posthog/react';
2
2
  import { createElement, useEffect, useRef } from 'react';
3
3
  import { postHogBrowserOptions } from './client.js';
4
- export function PostHogIntegration({ children, environment, fallback = createElement('main', null, 'Something went wrong. Refresh the page to try again.'), options, }) {
4
+ import { POSTHOG_DEFAULT_INGEST_PATH } from './proxy.js';
5
+ export function PostHogIntegration({ children, environment, fallback = createElement('main', null, 'Something went wrong. Refresh the page to try again.'), ingestPath = POSTHOG_DEFAULT_INGEST_PATH, options, }) {
5
6
  if (!environment)
6
7
  return children;
7
8
  const tracingHostnames = typeof window === 'undefined' ? undefined : [window.location.hostname];
8
9
  return createElement(PostHogProvider, {
9
10
  apiKey: environment.projectToken,
10
11
  options: postHogBrowserOptions({
11
- apiHost: '/ingest',
12
+ apiHost: ingestPath,
12
13
  uiHost: environment.uiHost,
13
14
  ...(tracingHostnames ? { tracingHostnames } : {}),
14
15
  ...(options ? { options } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/posthog/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAClF,OAAO,EAAE,aAAa,EAAkB,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAExE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAGnD,MAAM,UAAU,kBAAkB,CAAC,EACjC,QAAQ,EACR,WAAW,EACX,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,sDAAsD,CAAC,EAC9F,OAAO,GAMR;IACC,IAAI,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAA;IACjC,MAAM,gBAAgB,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC/F,OAAO,aAAa,CAClB,eAAe,EACf;QACE,MAAM,EAAE,WAAW,CAAC,YAAY;QAChC,OAAO,EAAE,qBAAqB,CAAC;YAC7B,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC,CAAC;KACH,EACD,aAAa,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAC5D,CAAA;AACH,CAAC;AAaD,MAAM,UAAU,yBAAyB,CAA8B,EACrE,UAAU,EACV,UAAU,GAIX;IACC,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,EAAE,CAAA;IACvC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,UAAU,GAAG,MAAM,CAAqB,SAAS,CAAC,CAAA;IACxD,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;IACxC,aAAa,CAAC,OAAO,GAAG,UAAU,CAAA;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAAE,OAAM;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAA;QAC/B,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;YACxD,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAA;QAC9B,CAAC;aAAM,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,UAAU,CAAC,OAAO,GAAG,SAAS,CAAA;QAChC,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;IAEnE,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { PostHogErrorBoundary, PostHogProvider, usePostHog } from '@posthog/react'\nimport { createElement, type ReactNode, useEffect, useRef } from 'react'\nimport type { PostHogConfig, Properties } from 'posthog-js'\nimport { postHogBrowserOptions } from './client.js'\nimport type { PostHogEnvironment } from './config.js'\n\nexport function PostHogIntegration({\n children,\n environment,\n fallback = createElement('main', null, 'Something went wrong. Refresh the page to try again.'),\n options,\n}: {\n children?: ReactNode\n environment: PostHogEnvironment | undefined\n fallback?: ReactNode\n options?: Partial<PostHogConfig>\n}) {\n if (!environment) return children\n const tracingHostnames = typeof window === 'undefined' ? undefined : [window.location.hostname]\n return createElement(\n PostHogProvider,\n {\n apiKey: environment.projectToken,\n options: postHogBrowserOptions({\n apiHost: '/ingest',\n uiHost: environment.uiHost,\n ...(tracingHostnames ? { tracingHostnames } : {}),\n ...(options ? { options } : {}),\n }),\n },\n createElement(PostHogErrorBoundary, { fallback }, children),\n )\n}\n\nexport type BetterAuthUser = { id: string }\nexport type BetterAuthSession<User extends BetterAuthUser = BetterAuthUser> = { user: User }\nexport type BetterAuthSessionState<User extends BetterAuthUser = BetterAuthUser> = {\n data?: BetterAuthSession<User> | null\n error?: unknown\n isPending: boolean\n}\nexport type BetterAuthReactClient<User extends BetterAuthUser = BetterAuthUser> = {\n useSession: () => BetterAuthSessionState<User>\n}\n\nexport function PostHogBetterAuthIdentity<User extends BetterAuthUser>({\n authClient,\n properties,\n}: {\n authClient: BetterAuthReactClient<User>\n properties?: (user: User) => Properties\n}) {\n const session = authClient.useSession()\n const posthog = usePostHog()\n const identified = useRef<string | undefined>(undefined)\n const propertiesRef = useRef(properties)\n propertiesRef.current = properties\n\n useEffect(() => {\n if (session.isPending || session.error) return\n const user = session.data?.user\n if (user) {\n posthog.identify(user.id, propertiesRef.current?.(user))\n identified.current = user.id\n } else if (identified.current) {\n posthog.reset()\n identified.current = undefined\n }\n }, [posthog, session.data?.user, session.error, session.isPending])\n\n return null\n}\n"]}
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/posthog/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAClF,OAAO,EAAE,aAAa,EAAkB,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAExE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AAExD,MAAM,UAAU,kBAAkB,CAAC,EACjC,QAAQ,EACR,WAAW,EACX,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,sDAAsD,CAAC,EAC9F,UAAU,GAAG,2BAA2B,EACxC,OAAO,GAOR;IACC,IAAI,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAA;IACjC,MAAM,gBAAgB,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC/F,OAAO,aAAa,CAClB,eAAe,EACf;QACE,MAAM,EAAE,WAAW,CAAC,YAAY;QAChC,OAAO,EAAE,qBAAqB,CAAC;YAC7B,OAAO,EAAE,UAAU;YACnB,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC,CAAC;KACH,EACD,aAAa,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAC5D,CAAA;AACH,CAAC;AAaD,MAAM,UAAU,yBAAyB,CAA8B,EACrE,UAAU,EACV,UAAU,GAIX;IACC,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,EAAE,CAAA;IACvC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,UAAU,GAAG,MAAM,CAAqB,SAAS,CAAC,CAAA;IACxD,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;IACxC,aAAa,CAAC,OAAO,GAAG,UAAU,CAAA;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAAE,OAAM;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAA;QAC/B,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;YACxD,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAA;QAC9B,CAAC;aAAM,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,UAAU,CAAC,OAAO,GAAG,SAAS,CAAA;QAChC,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;IAEnE,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { PostHogErrorBoundary, PostHogProvider, usePostHog } from '@posthog/react'\nimport { createElement, type ReactNode, useEffect, useRef } from 'react'\nimport type { PostHogConfig, Properties } from 'posthog-js'\nimport { postHogBrowserOptions } from './client.js'\nimport type { PostHogEnvironment } from './config.js'\nimport { POSTHOG_DEFAULT_INGEST_PATH } from './proxy.js'\n\nexport function PostHogIntegration({\n children,\n environment,\n fallback = createElement('main', null, 'Something went wrong. Refresh the page to try again.'),\n ingestPath = POSTHOG_DEFAULT_INGEST_PATH,\n options,\n}: {\n children?: ReactNode\n environment: PostHogEnvironment | undefined\n fallback?: ReactNode\n ingestPath?: string\n options?: Partial<PostHogConfig>\n}) {\n if (!environment) return children\n const tracingHostnames = typeof window === 'undefined' ? undefined : [window.location.hostname]\n return createElement(\n PostHogProvider,\n {\n apiKey: environment.projectToken,\n options: postHogBrowserOptions({\n apiHost: ingestPath,\n uiHost: environment.uiHost,\n ...(tracingHostnames ? { tracingHostnames } : {}),\n ...(options ? { options } : {}),\n }),\n },\n createElement(PostHogErrorBoundary, { fallback }, children),\n )\n}\n\nexport type BetterAuthUser = { id: string }\nexport type BetterAuthSession<User extends BetterAuthUser = BetterAuthUser> = { user: User }\nexport type BetterAuthSessionState<User extends BetterAuthUser = BetterAuthUser> = {\n data?: BetterAuthSession<User> | null\n error?: unknown\n isPending: boolean\n}\nexport type BetterAuthReactClient<User extends BetterAuthUser = BetterAuthUser> = {\n useSession: () => BetterAuthSessionState<User>\n}\n\nexport function PostHogBetterAuthIdentity<User extends BetterAuthUser>({\n authClient,\n properties,\n}: {\n authClient: BetterAuthReactClient<User>\n properties?: (user: User) => Properties\n}) {\n const session = authClient.useSession()\n const posthog = usePostHog()\n const identified = useRef<string | undefined>(undefined)\n const propertiesRef = useRef(properties)\n propertiesRef.current = properties\n\n useEffect(() => {\n if (session.isPending || session.error) return\n const user = session.data?.user\n if (user) {\n posthog.identify(user.id, propertiesRef.current?.(user))\n identified.current = user.id\n } else if (identified.current) {\n posthog.reset()\n identified.current = undefined\n }\n }, [posthog, session.data?.user, session.error, session.isPending])\n\n return null\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { drizzleAdapter } from '@better-auth/drizzle-adapter'
2
2
  import { betterAuth } from 'better-auth'
3
3
  import { tanstackStartCookies } from 'better-auth/tanstack-start'
4
- import { standardRateLimitOptions, standardSessionOptions } from 'ras-stack/auth'
4
+ import { standardAccountOptions, standardRateLimitOptions, standardSessionOptions } from 'ras-stack/auth'
5
5
  import type { EmailDelivery } from 'ras-stack/email'
6
6
  import type { AppEnvironment } from './environment'
7
7
  import * as schema from './schema'
@@ -31,6 +31,7 @@ export function createAuth(options: { database: Database; email?: EmailDelivery;
31
31
  secret: options.secret,
32
32
  trustedOrigins: [options.environment.appUrl],
33
33
  database: drizzleAdapter(options.database, { provider: 'sqlite', schema }),
34
+ account: standardAccountOptions(),
34
35
  emailAndPassword: {
35
36
  enabled: true,
36
37
  requireEmailVerification: Boolean(email) && options.environment.requireEmailVerification,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ras-stack",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "description": "Composable full-stack primitives shared across Richard Solomou's applications.",
5
5
  "keywords": [
6
6
  "authentication",