@eminuckan/spine 0.2.2 → 0.3.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.
- package/CHANGELOG.md +42 -0
- package/CODE_OF_CONDUCT.md +39 -0
- package/CONTRIBUTING.md +78 -0
- package/MAINTAINERS.md +43 -0
- package/README.md +111 -55
- package/ROADMAP.md +58 -0
- package/SECURITY.md +37 -0
- package/dist/access/evaluator.d.ts +3 -0
- package/dist/access/evaluator.d.ts.map +1 -0
- package/dist/access/index.d.ts +3 -0
- package/dist/access/index.d.ts.map +1 -0
- package/dist/access/index.js +4 -0
- package/dist/access/types.d.ts +38 -0
- package/dist/access/types.d.ts.map +1 -0
- package/dist/access-CGrsDMwu.js +61 -0
- package/dist/access-CGrsDMwu.js.map +1 -0
- package/dist/api-client/api-config.server.d.ts +27 -0
- package/dist/api-client/api-config.server.d.ts.map +1 -1
- package/dist/api-client/error-codes.d.ts +6 -31
- package/dist/api-client/error-codes.d.ts.map +1 -1
- package/dist/api-client/index.js +3 -3
- package/dist/api-client/server.d.ts +1 -1
- package/dist/api-client/server.d.ts.map +1 -1
- package/dist/api-client/server.js +4 -4
- package/dist/{api-client-DsrxK05Z.js → api-client-CgZUMukO.js} +9 -26
- package/dist/api-client-CgZUMukO.js.map +1 -0
- package/dist/auth/auth.server.d.ts +21 -16
- package/dist/auth/auth.server.d.ts.map +1 -1
- package/dist/auth/authorization-parameters.d.ts +5 -0
- package/dist/auth/authorization-parameters.d.ts.map +1 -0
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/redis-session-storage.server.d.ts +18 -1
- package/dist/auth/redis-session-storage.server.d.ts.map +1 -1
- package/dist/auth/route-protection.server.d.ts +20 -4
- package/dist/auth/route-protection.server.d.ts.map +1 -1
- package/dist/auth/server.d.ts +1 -1
- package/dist/auth/server.d.ts.map +1 -1
- package/dist/auth/server.js +5 -5
- package/dist/auth/types.d.ts +88 -21
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth.server-D5oiz9aF.js +1066 -0
- package/dist/auth.server-D5oiz9aF.js.map +1 -0
- package/dist/auth.server-lC94lmlx.js +5 -0
- package/dist/identity/identity-context.server.d.ts +2 -0
- package/dist/identity/identity-context.server.d.ts.map +1 -1
- package/dist/identity/identity-store.d.ts +19 -2
- package/dist/identity/identity-store.d.ts.map +1 -1
- package/dist/identity/index.js +2 -2
- package/dist/identity/server.js +3 -3
- package/dist/identity/types.d.ts +3 -1
- package/dist/identity/types.d.ts.map +1 -1
- package/dist/{identity-CFa1txoj.js → identity-C5un-xAs.js} +104 -60
- package/dist/identity-C5un-xAs.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/logging/index.js +1 -1
- package/dist/{logging-_h2mi3L9.js → logging-DviiAkLx.js} +2 -2
- package/dist/{logging-_h2mi3L9.js.map → logging-DviiAkLx.js.map} +1 -1
- package/dist/permission-service-CvGpwI0d.js +95 -0
- package/dist/permission-service-CvGpwI0d.js.map +1 -0
- package/dist/permissions/constants.d.ts +3 -0
- package/dist/permissions/constants.d.ts.map +1 -1
- package/dist/permissions/index.js +2 -1
- package/dist/permissions/permission-store.d.ts +1 -1
- package/dist/permissions/types.d.ts +1 -1
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/{permissions-D5ScGGnd.js → permissions-_n1hIG7Q.js} +8 -106
- package/dist/permissions-_n1hIG7Q.js.map +1 -0
- package/dist/query-client/index.js +1 -1
- package/dist/query-client/types.d.ts +9 -9
- package/dist/query-client/types.d.ts.map +1 -1
- package/dist/{query-client-Bpe08pk9.js → query-client-Bh3TyB8W.js} +2 -2
- package/dist/query-client-Bh3TyB8W.js.map +1 -0
- package/dist/react-router/index.js +12 -10
- package/dist/react-router/server.js +19 -17
- package/dist/redis-session-storage.server-v2VcpFsQ.js +500 -0
- package/dist/redis-session-storage.server-v2VcpFsQ.js.map +1 -0
- package/dist/{server-BHfKHKF_.js → server-B6PCxc-T.js} +39 -87
- package/dist/server-B6PCxc-T.js.map +1 -0
- package/dist/{server-DZmcd2Lr.js → server-C96NMFBy.js} +18 -10
- package/dist/server-C96NMFBy.js.map +1 -0
- package/dist/{server-BxvRxjCK.js → server-Ca-3DJf2.js} +44 -11
- package/dist/server-Ca-3DJf2.js.map +1 -0
- package/dist/{server-C3L8J7iE.js → server-Dxsww9v9.js} +6 -5
- package/dist/server-Dxsww9v9.js.map +1 -0
- package/dist/{server-CouYoZiw.js → server-hGrElJMG.js} +2 -2
- package/dist/{server-CouYoZiw.js.map → server-hGrElJMG.js.map} +1 -1
- package/dist/server.js +19 -17
- package/dist/signalr/index.js +1 -1
- package/dist/signalr/types.d.ts +1 -1
- package/dist/{signalr-SJ-1sIxw.js → signalr-k-70VHKo.js} +3 -2
- package/dist/signalr-k-70VHKo.js.map +1 -0
- package/dist/tenant/index.js +2 -2
- package/dist/tenant/server.js +4 -4
- package/dist/tenant/tenant-context.d.ts +17 -1
- package/dist/tenant/tenant-context.d.ts.map +1 -1
- package/dist/tenant/tenant-cookie.server.d.ts.map +1 -1
- package/dist/tenant/tenant-store.d.ts +54 -9
- package/dist/tenant/tenant-store.d.ts.map +1 -1
- package/dist/tenant/tenant.server.d.ts +20 -1
- package/dist/tenant/tenant.server.d.ts.map +1 -1
- package/dist/tenant/types.d.ts +29 -9
- package/dist/tenant/types.d.ts.map +1 -1
- package/dist/tenant-DfLemb6n.js +384 -0
- package/dist/tenant-DfLemb6n.js.map +1 -0
- package/dist/{types-BnKaWdfe.js → types-BaaE6wjY.js} +1 -1
- package/dist/{types-BnKaWdfe.js.map → types-BaaE6wjY.js.map} +1 -1
- package/docs/adapters.md +87 -0
- package/docs/architecture.md +193 -0
- package/docs/backend-adaptation.md +249 -0
- package/docs/codex-for-oss-application.md +31 -0
- package/docs/codex-maintenance.md +47 -0
- package/docs/installation.md +213 -0
- package/docs/module-reference.md +207 -0
- package/docs/releasing.md +92 -0
- package/package.json +27 -4
- package/dist/api-client-DsrxK05Z.js.map +0 -1
- package/dist/auth.server-BPiCtlJE.js +0 -5
- package/dist/auth.server-Cx2h2qu3.js +0 -724
- package/dist/auth.server-Cx2h2qu3.js.map +0 -1
- package/dist/identity-CFa1txoj.js.map +0 -1
- package/dist/permissions-D5ScGGnd.js.map +0 -1
- package/dist/query-client-Bpe08pk9.js.map +0 -1
- package/dist/redis-session-storage.server-BR_0y-QO.js +0 -250
- package/dist/redis-session-storage.server-BR_0y-QO.js.map +0 -1
- package/dist/server-BHfKHKF_.js.map +0 -1
- package/dist/server-BxvRxjCK.js.map +0 -1
- package/dist/server-C3L8J7iE.js.map +0 -1
- package/dist/server-DZmcd2Lr.js.map +0 -1
- package/dist/signalr-SJ-1sIxw.js.map +0 -1
- package/dist/tenant-C6KPaSCX.js +0 -256
- package/dist/tenant-C6KPaSCX.js.map +0 -1
- /package/dist/{src-CJ2RLi94.js → src-B9rDUgSb.js} +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { PermissionCode } from '../permissions/types';
|
|
2
|
+
export type AccessOperator = 'AND' | 'OR';
|
|
3
|
+
export interface EntitlementAccessSnapshot {
|
|
4
|
+
exists?: boolean;
|
|
5
|
+
status?: string | null;
|
|
6
|
+
planCode?: string | null;
|
|
7
|
+
featureKeys?: readonly string[] | null;
|
|
8
|
+
limits?: Record<string, unknown> | null;
|
|
9
|
+
}
|
|
10
|
+
/** @deprecated Use EntitlementAccessSnapshot instead. */
|
|
11
|
+
export type SubscriptionAccessSnapshot = EntitlementAccessSnapshot;
|
|
12
|
+
export interface AccessSubject {
|
|
13
|
+
permissions?: readonly PermissionCode[] | null;
|
|
14
|
+
entitlement?: EntitlementAccessSnapshot | null;
|
|
15
|
+
/** @deprecated Use entitlement instead. */
|
|
16
|
+
subscription?: SubscriptionAccessSnapshot | null;
|
|
17
|
+
isInternalUser?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface AccessRequirement {
|
|
20
|
+
permissions?: readonly PermissionCode[];
|
|
21
|
+
permissionOperator?: AccessOperator;
|
|
22
|
+
features?: readonly string[];
|
|
23
|
+
featureOperator?: AccessOperator;
|
|
24
|
+
requireActiveEntitlement?: boolean;
|
|
25
|
+
/** @deprecated Use requireActiveEntitlement instead. */
|
|
26
|
+
requireActiveSubscription?: boolean;
|
|
27
|
+
internalOnly?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export type AccessDeniedReason = 'internal-only' | 'inactive-entitlement'
|
|
30
|
+
/** @deprecated Use inactive-entitlement instead. */
|
|
31
|
+
| 'inactive-subscription' | 'missing-permissions' | 'missing-features';
|
|
32
|
+
export interface AccessDecision {
|
|
33
|
+
allowed: boolean;
|
|
34
|
+
reasons: AccessDeniedReason[];
|
|
35
|
+
missingPermissions: PermissionCode[];
|
|
36
|
+
missingFeatures: string[];
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/access/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,IAAI,CAAC;AAE1C,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACzC;AAED,yDAAyD;AACzD,MAAM,MAAM,0BAA0B,GAAG,yBAAyB,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC/C,2CAA2C;IAC3C,YAAY,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IACjD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACxC,kBAAkB,CAAC,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,wDAAwD;IACxD,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,kBAAkB,GAC1B,eAAe,GACf,sBAAsB;AACxB,oDAAoD;GAClD,uBAAuB,GACvB,qBAAqB,GACrB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,kBAAkB,EAAE,cAAc,EAAE,CAAC;IACrC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { PermissionChecker } from "./permission-service-CvGpwI0d.js";
|
|
2
|
+
|
|
3
|
+
//#region src/access/evaluator.ts
|
|
4
|
+
const ACTIVE_ENTITLEMENT_STATUSES = new Set(["active", "trialing"]);
|
|
5
|
+
const EMPTY_DECISION = Object.freeze({
|
|
6
|
+
allowed: true,
|
|
7
|
+
reasons: [],
|
|
8
|
+
missingPermissions: [],
|
|
9
|
+
missingFeatures: []
|
|
10
|
+
});
|
|
11
|
+
function normalizeFeature(value) {
|
|
12
|
+
return value.trim().toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
function hasActiveEntitlement(entitlement) {
|
|
15
|
+
if (!entitlement?.exists) return false;
|
|
16
|
+
return ACTIVE_ENTITLEMENT_STATUSES.has(entitlement.status?.toLowerCase() ?? "");
|
|
17
|
+
}
|
|
18
|
+
function checkFeatureSet(grantedFeatures, requiredFeatures, operator) {
|
|
19
|
+
if (requiredFeatures.length === 0) return [];
|
|
20
|
+
const granted = new Set(grantedFeatures.map(normalizeFeature));
|
|
21
|
+
const normalizedRequired = requiredFeatures.map(normalizeFeature).filter(Boolean);
|
|
22
|
+
if (operator === "OR") return normalizedRequired.some((feature) => granted.has(feature)) ? [] : normalizedRequired;
|
|
23
|
+
return normalizedRequired.filter((feature) => !granted.has(feature));
|
|
24
|
+
}
|
|
25
|
+
function evaluateAccessRequirement(requirement, subject) {
|
|
26
|
+
if (!requirement) return EMPTY_DECISION;
|
|
27
|
+
const reasons = [];
|
|
28
|
+
const permissions = requirement.permissions ?? [];
|
|
29
|
+
const features = requirement.features ?? [];
|
|
30
|
+
const entitlement = subject.entitlement ?? subject.subscription;
|
|
31
|
+
let missingPermissions = [];
|
|
32
|
+
let missingFeatures = [];
|
|
33
|
+
if (requirement.internalOnly && !subject.isInternalUser) reasons.push("internal-only");
|
|
34
|
+
if (requirement.requireActiveEntitlement && !hasActiveEntitlement(entitlement)) reasons.push("inactive-entitlement");
|
|
35
|
+
else if (requirement.requireActiveSubscription && !hasActiveEntitlement(entitlement)) reasons.push("inactive-subscription");
|
|
36
|
+
if (permissions.length > 0) {
|
|
37
|
+
const checker = new PermissionChecker([...subject.permissions ?? []]);
|
|
38
|
+
const result = checker.hasPermissions([...permissions], {
|
|
39
|
+
operator: requirement.permissionOperator ?? "AND",
|
|
40
|
+
wildcard: true
|
|
41
|
+
});
|
|
42
|
+
if (!result.hasPermission) {
|
|
43
|
+
missingPermissions = result.missingPermissions;
|
|
44
|
+
reasons.push("missing-permissions");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (features.length > 0) {
|
|
48
|
+
missingFeatures = checkFeatureSet(entitlement?.featureKeys ?? [], features, requirement.featureOperator ?? "AND");
|
|
49
|
+
if (missingFeatures.length > 0) reasons.push("missing-features");
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
allowed: reasons.length === 0,
|
|
53
|
+
reasons,
|
|
54
|
+
missingPermissions,
|
|
55
|
+
missingFeatures
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { evaluateAccessRequirement };
|
|
61
|
+
//# sourceMappingURL=access-CGrsDMwu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-CGrsDMwu.js","names":["EMPTY_DECISION: AccessDecision","value: string","entitlement?: EntitlementAccessSnapshot | null","grantedFeatures: readonly string[]","requiredFeatures: readonly string[]","operator: AccessOperator","requirement: AccessRequirement | null | undefined","subject: AccessSubject","reasons: AccessDeniedReason[]","missingPermissions: string[]","missingFeatures: string[]"],"sources":["../src/access/evaluator.ts"],"sourcesContent":["import { PermissionChecker } from '../permissions/permission-service';\nimport type {\n AccessDecision,\n AccessDeniedReason,\n AccessOperator,\n AccessRequirement,\n AccessSubject,\n EntitlementAccessSnapshot,\n} from './types';\n\nconst ACTIVE_ENTITLEMENT_STATUSES = new Set(['active', 'trialing']);\n\nconst EMPTY_DECISION: AccessDecision = Object.freeze({\n allowed: true,\n reasons: [],\n missingPermissions: [],\n missingFeatures: [],\n});\n\nfunction normalizeFeature(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction hasActiveEntitlement(entitlement?: EntitlementAccessSnapshot | null): boolean {\n if (!entitlement?.exists) {\n return false;\n }\n\n return ACTIVE_ENTITLEMENT_STATUSES.has(entitlement.status?.toLowerCase() ?? '');\n}\n\nfunction checkFeatureSet(\n grantedFeatures: readonly string[],\n requiredFeatures: readonly string[],\n operator: AccessOperator,\n): string[] {\n if (requiredFeatures.length === 0) {\n return [];\n }\n\n const granted = new Set(grantedFeatures.map(normalizeFeature));\n const normalizedRequired = requiredFeatures.map(normalizeFeature).filter(Boolean);\n\n if (operator === 'OR') {\n return normalizedRequired.some((feature) => granted.has(feature)) ? [] : normalizedRequired;\n }\n\n return normalizedRequired.filter((feature) => !granted.has(feature));\n}\n\nexport function evaluateAccessRequirement(\n requirement: AccessRequirement | null | undefined,\n subject: AccessSubject,\n): AccessDecision {\n if (!requirement) {\n return EMPTY_DECISION;\n }\n\n const reasons: AccessDeniedReason[] = [];\n const permissions = requirement.permissions ?? [];\n const features = requirement.features ?? [];\n const entitlement = subject.entitlement ?? subject.subscription;\n let missingPermissions: string[] = [];\n let missingFeatures: string[] = [];\n\n if (requirement.internalOnly && !subject.isInternalUser) {\n reasons.push('internal-only');\n }\n\n if (requirement.requireActiveEntitlement && !hasActiveEntitlement(entitlement)) {\n reasons.push('inactive-entitlement');\n } else if (requirement.requireActiveSubscription && !hasActiveEntitlement(entitlement)) {\n reasons.push('inactive-subscription');\n }\n\n if (permissions.length > 0) {\n const checker = new PermissionChecker([...(subject.permissions ?? [])]);\n const result = checker.hasPermissions([...permissions], {\n operator: requirement.permissionOperator ?? 'AND',\n wildcard: true,\n });\n\n if (!result.hasPermission) {\n missingPermissions = result.missingPermissions;\n reasons.push('missing-permissions');\n }\n }\n\n if (features.length > 0) {\n missingFeatures = checkFeatureSet(\n entitlement?.featureKeys ?? [],\n features,\n requirement.featureOperator ?? 'AND',\n );\n\n if (missingFeatures.length > 0) {\n reasons.push('missing-features');\n }\n }\n\n return {\n allowed: reasons.length === 0,\n reasons,\n missingPermissions,\n missingFeatures,\n };\n}\n"],"mappings":";;;AAUA,MAAM,8BAA8B,IAAI,IAAI,CAAC,UAAU,UAAW;AAElE,MAAMA,iBAAiC,OAAO,OAAO;CACnD,SAAS;CACT,SAAS,CAAE;CACX,oBAAoB,CAAE;CACtB,iBAAiB,CAAE;AACpB,EAAC;AAEF,SAAS,iBAAiBC,OAAuB;AAC/C,QAAO,MAAM,MAAM,CAAC,aAAa;AAClC;AAED,SAAS,qBAAqBC,aAAyD;AACrF,MAAK,aAAa,OAChB,QAAO;AAGT,QAAO,4BAA4B,IAAI,YAAY,QAAQ,aAAa,IAAI,GAAG;AAChF;AAED,SAAS,gBACPC,iBACAC,kBACAC,UACU;AACV,KAAI,iBAAiB,WAAW,EAC9B,QAAO,CAAE;CAGX,MAAM,UAAU,IAAI,IAAI,gBAAgB,IAAI,iBAAiB;CAC7D,MAAM,qBAAqB,iBAAiB,IAAI,iBAAiB,CAAC,OAAO,QAAQ;AAEjF,KAAI,aAAa,KACf,QAAO,mBAAmB,KAAK,CAAC,YAAY,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAE,IAAG;AAG3E,QAAO,mBAAmB,OAAO,CAAC,aAAa,QAAQ,IAAI,QAAQ,CAAC;AACrE;AAED,SAAgB,0BACdC,aACAC,SACgB;AAChB,MAAK,YACH,QAAO;CAGT,MAAMC,UAAgC,CAAE;CACxC,MAAM,cAAc,YAAY,eAAe,CAAE;CACjD,MAAM,WAAW,YAAY,YAAY,CAAE;CAC3C,MAAM,cAAc,QAAQ,eAAe,QAAQ;CACnD,IAAIC,qBAA+B,CAAE;CACrC,IAAIC,kBAA4B,CAAE;AAElC,KAAI,YAAY,iBAAiB,QAAQ,eACvC,SAAQ,KAAK,gBAAgB;AAG/B,KAAI,YAAY,6BAA6B,qBAAqB,YAAY,CAC5E,SAAQ,KAAK,uBAAuB;UAC3B,YAAY,8BAA8B,qBAAqB,YAAY,CACpF,SAAQ,KAAK,wBAAwB;AAGvC,KAAI,YAAY,SAAS,GAAG;EAC1B,MAAM,UAAU,IAAI,kBAAkB,CAAC,GAAI,QAAQ,eAAe,CAAE,CAAE;EACtE,MAAM,SAAS,QAAQ,eAAe,CAAC,GAAG,WAAY,GAAE;GACtD,UAAU,YAAY,sBAAsB;GAC5C,UAAU;EACX,EAAC;AAEF,OAAK,OAAO,eAAe;AACzB,wBAAqB,OAAO;AAC5B,WAAQ,KAAK,sBAAsB;EACpC;CACF;AAED,KAAI,SAAS,SAAS,GAAG;AACvB,oBAAkB,gBAChB,aAAa,eAAe,CAAE,GAC9B,UACA,YAAY,mBAAmB,MAChC;AAED,MAAI,gBAAgB,SAAS,EAC3B,SAAQ,KAAK,mBAAmB;CAEnC;AAED,QAAO;EACL,SAAS,QAAQ,WAAW;EAC5B;EACA;EACA;CACD;AACF"}
|
|
@@ -25,6 +25,33 @@ export interface APIConfigFactoryOptions {
|
|
|
25
25
|
* Default timeout in milliseconds
|
|
26
26
|
*/
|
|
27
27
|
timeout?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Header name used for bearer-style auth. Set to null when buildHeaders owns auth.
|
|
30
|
+
* @default 'Authorization'
|
|
31
|
+
*/
|
|
32
|
+
authHeaderName?: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Build an auth header value from the resolved access token.
|
|
35
|
+
* @default token => `Bearer ${token}`
|
|
36
|
+
*/
|
|
37
|
+
authHeaderValue?: (accessToken: string) => string;
|
|
38
|
+
/**
|
|
39
|
+
* Header name used for tenant context. Set to null when buildHeaders owns tenancy.
|
|
40
|
+
* @default 'X-Tenant-Id'
|
|
41
|
+
*/
|
|
42
|
+
tenantHeaderName?: string | null;
|
|
43
|
+
/**
|
|
44
|
+
* Final app-specific header hook. Returned headers are merged last.
|
|
45
|
+
*/
|
|
46
|
+
buildHeaders?: (context: APIHeaderStrategyContext) => Record<string, string>;
|
|
47
|
+
}
|
|
48
|
+
export interface APIHeaderStrategyContext {
|
|
49
|
+
request: Request;
|
|
50
|
+
options: CreateAPIConfigOptions;
|
|
51
|
+
accessToken?: string;
|
|
52
|
+
tenantId: string | null;
|
|
53
|
+
includeAuth: boolean;
|
|
54
|
+
requireTenant: boolean;
|
|
28
55
|
}
|
|
29
56
|
/**
|
|
30
57
|
* Create API Config Factory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-config.server.d.ts","sourceRoot":"","sources":["../../src/api-client/api-config.server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAiBlH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"api-config.server.d.ts","sourceRoot":"","sources":["../../src/api-client/api-config.server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAiBlH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9E;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,sBAAsB,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,gBAAgB,EAChC,gBAAgB,EAAE,kBAAkB,EACpC,MAAM,CAAC,EAAE,SAAS,EAClB,cAAc,GAAE,uBAA4B;+BAmEjC,OAAO,YACP,sBAAsB,KAC9B,OAAO,CAAC,SAAS,CAAC;yBA+EK,MAAM;EAQjC;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Error Codes
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Generic error codes that apps can use as a starter vocabulary.
|
|
5
|
+
* Domain-specific codes should live in the consuming app.
|
|
5
6
|
*/
|
|
6
7
|
export declare const ErrorCodes: {
|
|
7
8
|
readonly Validation: {
|
|
@@ -17,41 +18,15 @@ export declare const ErrorCodes: {
|
|
|
17
18
|
readonly UserNotFound: "UserNotFound";
|
|
18
19
|
readonly EmailAlreadyExists: "EmailAlreadyExists";
|
|
19
20
|
};
|
|
20
|
-
readonly
|
|
21
|
-
readonly
|
|
22
|
-
readonly
|
|
23
|
-
readonly SystemLocked: "SystemLocked";
|
|
24
|
-
readonly AccountsDuplicate: "AccountsDuplicate";
|
|
25
|
-
readonly AccountNotFound: "AccountNotFound";
|
|
26
|
-
};
|
|
27
|
-
readonly Subscription: {
|
|
28
|
-
readonly SubscriptionRequired: "SubscriptionRequired";
|
|
29
|
-
readonly SubscriptionExpired: "SubscriptionExpired";
|
|
21
|
+
readonly Access: {
|
|
22
|
+
readonly EntitlementRequired: "EntitlementRequired";
|
|
23
|
+
readonly EntitlementExpired: "EntitlementExpired";
|
|
30
24
|
readonly FeatureNotAvailable: "FeatureNotAvailable";
|
|
31
|
-
|
|
32
|
-
readonly PropertyManagement: {
|
|
33
|
-
readonly PropertyNotFound: "PropertyNotFound";
|
|
34
|
-
readonly UnitNotFound: "UnitNotFound";
|
|
35
|
-
readonly DuplicateProperty: "DuplicateProperty";
|
|
36
|
-
readonly DuplicateUnit: "DuplicateUnit";
|
|
37
|
-
};
|
|
38
|
-
readonly Leasing: {
|
|
39
|
-
readonly LeaseNotFound: "LeaseNotFound";
|
|
40
|
-
readonly LeaseConflict: "LeaseConflict";
|
|
41
|
-
readonly TenantNotFound: "TenantNotFound";
|
|
42
|
-
readonly LateFeeValidationError: "LateFeeValidationError";
|
|
25
|
+
readonly TenantContextMissing: "TenantContextMissing";
|
|
43
26
|
};
|
|
44
27
|
readonly NotFound: "NotFound";
|
|
45
28
|
readonly Unauthorized: "Unauthorized";
|
|
46
29
|
readonly Forbidden: "Forbidden";
|
|
47
30
|
readonly InternalError: "InternalError";
|
|
48
31
|
};
|
|
49
|
-
/**
|
|
50
|
-
* Check if error code is from PropertyManagement module
|
|
51
|
-
*/
|
|
52
|
-
export declare function isPropertyManagementError(code: string): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Check if error code is from Leasing module
|
|
55
|
-
*/
|
|
56
|
-
export declare function isLeasingError(code: string): boolean;
|
|
57
32
|
//# sourceMappingURL=error-codes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/api-client/error-codes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/api-client/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;CA+Bb,CAAC"}
|
package/dist/api-client/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../logging-
|
|
2
|
-
import { isApiClientError } from "../types-
|
|
3
|
-
import { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isRetryableError, withRetry } from "../api-client-
|
|
1
|
+
import "../logging-DviiAkLx.js";
|
|
2
|
+
import { isApiClientError } from "../types-BaaE6wjY.js";
|
|
3
|
+
import { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isRetryableError, withRetry } from "../api-client-CgZUMukO.js";
|
|
4
4
|
|
|
5
5
|
export { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isApiClientError, isRetryableError, withRetry };
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Server-side exports for API client module.
|
|
5
5
|
*/
|
|
6
6
|
export * from './index';
|
|
7
|
-
export { createAPIConfigFactory, type APIConfigFactory, type APIConfigFactoryOptions, } from './api-config.server';
|
|
7
|
+
export { createAPIConfigFactory, type APIConfigFactory, type APIConfigFactoryOptions, type APIHeaderStrategyContext, } from './api-config.server';
|
|
8
8
|
export { createFetchMiddleware, createApiClient, type FetchSetupOptions, type CreateApiClientOptions, } from './fetch-client.server';
|
|
9
9
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api-client/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api-client/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../logging-
|
|
2
|
-
import { isApiClientError } from "../types-
|
|
3
|
-
import { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isRetryableError, withRetry } from "../api-client-
|
|
4
|
-
import { createAPIConfigFactory, createApiClient, createFetchMiddleware } from "../server-
|
|
1
|
+
import "../logging-DviiAkLx.js";
|
|
2
|
+
import { isApiClientError } from "../types-BaaE6wjY.js";
|
|
3
|
+
import { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isRetryableError, withRetry } from "../api-client-CgZUMukO.js";
|
|
4
|
+
import { createAPIConfigFactory, createApiClient, createFetchMiddleware } from "../server-C96NMFBy.js";
|
|
5
5
|
|
|
6
6
|
export { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createAPIConfigFactory, createApiClient, createFetchMiddleware, createRetryFetch, fetchWithTimeout, handleApiError, isApiClientError, isRetryableError, withRetry };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { logger } from "./logging-
|
|
1
|
+
import { logger } from "./logging-DviiAkLx.js";
|
|
2
2
|
|
|
3
3
|
//#region src/api-client/error-codes.ts
|
|
4
4
|
/**
|
|
5
5
|
* Error Codes
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Generic error codes that apps can use as a starter vocabulary.
|
|
8
|
+
* Domain-specific codes should live in the consuming app.
|
|
8
9
|
*/
|
|
9
10
|
const ErrorCodes = {
|
|
10
11
|
Validation: { Failed: "ValidationFailed" },
|
|
@@ -18,29 +19,11 @@ const ErrorCodes = {
|
|
|
18
19
|
UserNotFound: "UserNotFound",
|
|
19
20
|
EmailAlreadyExists: "EmailAlreadyExists"
|
|
20
21
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
AccountNotFound: "AccountNotFound"
|
|
27
|
-
},
|
|
28
|
-
Subscription: {
|
|
29
|
-
SubscriptionRequired: "SubscriptionRequired",
|
|
30
|
-
SubscriptionExpired: "SubscriptionExpired",
|
|
31
|
-
FeatureNotAvailable: "FeatureNotAvailable"
|
|
32
|
-
},
|
|
33
|
-
PropertyManagement: {
|
|
34
|
-
PropertyNotFound: "PropertyNotFound",
|
|
35
|
-
UnitNotFound: "UnitNotFound",
|
|
36
|
-
DuplicateProperty: "DuplicateProperty",
|
|
37
|
-
DuplicateUnit: "DuplicateUnit"
|
|
38
|
-
},
|
|
39
|
-
Leasing: {
|
|
40
|
-
LeaseNotFound: "LeaseNotFound",
|
|
41
|
-
LeaseConflict: "LeaseConflict",
|
|
42
|
-
TenantNotFound: "TenantNotFound",
|
|
43
|
-
LateFeeValidationError: "LateFeeValidationError"
|
|
22
|
+
Access: {
|
|
23
|
+
EntitlementRequired: "EntitlementRequired",
|
|
24
|
+
EntitlementExpired: "EntitlementExpired",
|
|
25
|
+
FeatureNotAvailable: "FeatureNotAvailable",
|
|
26
|
+
TenantContextMissing: "TenantContextMissing"
|
|
44
27
|
},
|
|
45
28
|
NotFound: "NotFound",
|
|
46
29
|
Unauthorized: "Unauthorized",
|
|
@@ -209,4 +192,4 @@ function createRetryFetch(config) {
|
|
|
209
192
|
|
|
210
193
|
//#endregion
|
|
211
194
|
export { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isRetryableError, withRetry };
|
|
212
|
-
//# sourceMappingURL=api-client-
|
|
195
|
+
//# sourceMappingURL=api-client-CgZUMukO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client-CgZUMukO.js","names":["problemDetails: ProblemDetails","response: Response","config: ErrorHandlerConfig","error: ApiError","message: string","type: 'error' | 'success' | 'info'","DEFAULT_RETRY_CONFIG: Required<RetryConfig>","error: unknown","attempt: number","baseDelay: number","maxDelay: number","fn: () => Promise<T>","config?: RetryConfig","lastError: unknown","input: RequestInfo | URL","init?: RequestInit & { timeout?: number }","init?: RequestInit"],"sources":["../src/api-client/error-codes.ts","../src/api-client/error-handler.ts","../src/api-client/retry-handler.ts"],"sourcesContent":["/**\n * Error Codes\n * \n * Generic error codes that apps can use as a starter vocabulary.\n * Domain-specific codes should live in the consuming app.\n */\n\nexport const ErrorCodes = {\n // Validation\n Validation: {\n Failed: 'ValidationFailed',\n },\n\n // Identity\n Identity: {\n InvalidCredentials: 'InvalidCredentials',\n UserInactive: 'UserInactive',\n TenantContextMissing: 'TenantContextMissing',\n InvalidCurrentPassword: 'InvalidCurrentPassword',\n OwnerCannotDisableMembership: 'OwnerCannotDisableMembership',\n CurrentUserMissing: 'CurrentUserMissing',\n UserNotFound: 'UserNotFound',\n EmailAlreadyExists: 'EmailAlreadyExists',\n },\n\n // Access and entitlement\n Access: {\n EntitlementRequired: 'EntitlementRequired',\n EntitlementExpired: 'EntitlementExpired',\n FeatureNotAvailable: 'FeatureNotAvailable',\n TenantContextMissing: 'TenantContextMissing',\n },\n\n // General\n NotFound: 'NotFound',\n Unauthorized: 'Unauthorized',\n Forbidden: 'Forbidden',\n InternalError: 'InternalError',\n} as const;\n","/**\n * Error Handler\n * \n * Centralized error handling with ProblemDetails parsing.\n */\n\nimport type { ProblemDetails, ValidationError } from './types';\nimport { ErrorCodes } from './error-codes';\nimport { logger } from '../logging';\n\n/**\n * API Error Class\n */\nexport class ApiError extends Error {\n constructor(\n public problemDetails: ProblemDetails,\n public response: Response\n ) {\n super(problemDetails.detail);\n this.name = 'ApiError';\n }\n\n get code(): string {\n return this.problemDetails.title;\n }\n\n get status(): number {\n return this.problemDetails.status;\n }\n\n get isValidationError(): boolean {\n return this.code === ErrorCodes.Validation.Failed;\n }\n\n get validationErrors(): ValidationError[] {\n return this.problemDetails.meta?.errors ?? [];\n }\n\n get traceId(): string {\n return this.problemDetails.traceId;\n }\n}\n\n/**\n * Parse API error response\n */\nexport async function handleApiError(response: Response): Promise<never> {\n let problemDetails: ProblemDetails;\n\n try {\n problemDetails = await response.json();\n } catch {\n problemDetails = {\n type: `https://httpstatuses.com/${response.status}`,\n title: 'UnknownError',\n status: response.status,\n detail: response.statusText || 'An unknown error occurred',\n traceId: response.headers.get('x-trace-id') ?? 'unknown',\n };\n }\n\n logger.error('API request failed', undefined, {\n code: problemDetails.title,\n status: problemDetails.status,\n detail: problemDetails.detail,\n traceId: problemDetails.traceId,\n });\n\n throw new ApiError(problemDetails, response);\n}\n\n/**\n * Error Handler Configuration\n */\nexport interface ErrorHandlerConfig {\n handlers?: Partial<Record<string, (error: ApiError) => void>>;\n showToast?: boolean;\n toastMessages?: Partial<Record<string, string>>;\n onError?: (error: ApiError) => void;\n toast?: (message: string, type: 'error' | 'success' | 'info') => void;\n}\n\n/**\n * Error Handler Class\n */\nexport class ErrorHandler {\n private config: ErrorHandlerConfig;\n\n constructor(config: ErrorHandlerConfig = {}) {\n this.config = {\n showToast: true,\n ...config,\n };\n }\n\n handle(error: ApiError): void {\n const code = error.code;\n\n logger.error('Handling API Error', undefined, {\n code,\n status: error.status,\n traceId: error.traceId,\n });\n\n // Try custom handler first\n if (this.config.handlers?.[code]) {\n this.config.handlers[code]!(error);\n return;\n }\n\n // Fallback\n if (this.config.onError) {\n this.config.onError(error);\n } else {\n this.showDefaultToast(error);\n }\n }\n\n private showToast(message: string, type: 'error' | 'success' | 'info'): void {\n if (this.config.showToast && this.config.toast) {\n this.config.toast(message, type);\n }\n }\n\n private showDefaultToast(error: ApiError): void {\n const message =\n this.config.toastMessages?.[error.code] ||\n error.problemDetails.detail ||\n 'An error occurred';\n this.showToast(message, 'error');\n }\n}\n\n/**\n * Create global error handler\n */\nexport function createErrorHandler(config?: ErrorHandlerConfig): ErrorHandler {\n return new ErrorHandler(config);\n}\n\n/**\n * Map validation errors to form fields\n */\nexport function mapValidationErrors(errors: ValidationError[]): Record<string, string> {\n const mapped: Record<string, string> = {};\n for (const error of errors) {\n const fieldName = error.field.charAt(0).toLowerCase() + error.field.slice(1);\n mapped[fieldName] = error.message;\n }\n return mapped;\n}\n","/**\n * Retry Handler\n * \n * Retry logic for API requests.\n */\n\nimport type { RetryConfig } from './types';\n\nconst DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n retryCondition: (error: unknown) => {\n if (error instanceof Response) {\n return error.status >= 500 || error.status === 429;\n }\n return false;\n },\n};\n\n/**\n * Calculate backoff delay\n */\nexport function calculateBackoffDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number\n): number {\n const delay = baseDelay * Math.pow(2, attempt);\n const jitter = Math.random() * 0.3 * delay;\n return Math.min(delay + jitter, maxDelay);\n}\n\n/**\n * Check if error is retryable\n */\nexport function isRetryableError(error: unknown): boolean {\n if (error instanceof Response) {\n return error.status >= 500 || error.status === 429;\n }\n if (error instanceof TypeError) {\n // Network errors\n return true;\n }\n return false;\n}\n\n/**\n * Execute function with retry logic\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n config?: RetryConfig\n): Promise<T> {\n const { maxRetries, baseDelay, maxDelay, retryCondition } = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n if (attempt === maxRetries || !retryCondition(error)) {\n throw error;\n }\n\n const delay = calculateBackoffDelay(attempt, baseDelay, maxDelay);\n console.log(`Retry attempt ${attempt + 1}/${maxRetries} after ${delay}ms`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw lastError;\n}\n\n/**\n * Fetch with timeout\n */\nexport async function fetchWithTimeout(\n input: RequestInfo | URL,\n init?: RequestInit & { timeout?: number }\n): Promise<Response> {\n const { timeout = 30000, ...fetchInit } = init || {};\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(input, {\n ...fetchInit,\n signal: controller.signal,\n });\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Create fetch function with retry\n */\nexport function createRetryFetch(config?: RetryConfig) {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n return withRetry(() => fetch(input, init), config);\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* OpenID Connect Authentication Server Module
|
|
3
3
|
*
|
|
4
4
|
* Handles:
|
|
5
5
|
* - Login flow (PKCE)
|
|
@@ -81,25 +81,30 @@ export declare function login(request: Request, returnUrlOrOptions?: string | Lo
|
|
|
81
81
|
*/
|
|
82
82
|
export declare function handleCallback(request: Request): Promise<Response>;
|
|
83
83
|
/**
|
|
84
|
-
* Logout user
|
|
84
|
+
* Logout user.
|
|
85
85
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
* Default logout follows OIDC RP-Initiated Logout and ends the identity
|
|
87
|
+
* provider session. Automatic/session-expiry cleanup can request
|
|
88
|
+
* `/auth/logout?logout=local` to clear only this app's Redis session without
|
|
89
|
+
* bouncing the browser through the identity provider or revoking SSO tokens.
|
|
90
|
+
*/
|
|
91
|
+
export declare function logout(request: Request): Promise<Response>;
|
|
92
|
+
/**
|
|
93
|
+
* Handle an OIDC Back-Channel Logout request from Keycloak or another OP.
|
|
92
94
|
*
|
|
93
|
-
*
|
|
94
|
-
* -
|
|
95
|
-
*
|
|
96
|
-
*
|
|
95
|
+
* Configure the client Backchannel logout URL to this endpoint. The logout
|
|
96
|
+
* token is signature-verified against the provider JWKS, issuer/audience are
|
|
97
|
+
* checked, and all matching local Redis sessions are destroyed by `sid` first,
|
|
98
|
+
* falling back to `sub` when the OP omits a session id.
|
|
99
|
+
*/
|
|
100
|
+
export declare function handleBackChannelLogout(request: Request): Promise<Response>;
|
|
101
|
+
/**
|
|
102
|
+
* Handle OIDC Front-Channel Logout iframe/browser requests.
|
|
97
103
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* - Query param `sso_logout=true` - override for full logout
|
|
104
|
+
* Front-channel logout cannot carry a signed logout token, so this validates the
|
|
105
|
+
* issuer and applies local cleanup only when a `sid` is present.
|
|
101
106
|
*/
|
|
102
|
-
export declare function
|
|
107
|
+
export declare function handleFrontChannelLogout(request: Request): Promise<Response>;
|
|
103
108
|
/**
|
|
104
109
|
* Get current user from session
|
|
105
110
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.server.d.ts","sourceRoot":"","sources":["../../src/auth/auth.server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"auth.server.d.ts","sourceRoot":"","sources":["../../src/auth/auth.server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAKL,cAAc,EASf,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAEV,gBAAgB,EAChB,QAAQ,EAGR,kBAAkB,EAClB,YAAY,EAKZ,SAAS,EACV,MAAM,SAAS,CAAC;AAijBjB;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAgBzE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C;AAkID;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAkDA;AAyDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAkB/D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAK/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAGtD;AAMD;;;;;GAKG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,OAAO,EAChB,kBAAkB,CAAC,EAAE,MAAM,GAAG,YAAY,GACzC,OAAO,CAAC,QAAQ,CAAC,CAgGnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0OxE;AAED;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkGhE;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8CjF;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmClF;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAQxE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAWrE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ7E;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,kBAAkB,CAAC,CAiD7B;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LoginOptions } from './types';
|
|
2
|
+
export declare function sanitizeExtraAuthorizationParameters(params: LoginOptions['extraAuthParams'] | undefined, options?: Pick<LoginOptions, 'extraAuthParamNames' | 'extraAuthParamPrefixes'>): Record<string, string>;
|
|
3
|
+
export declare function normalizePublicAuthorizationStateContext(context: LoginOptions['publicStateContext']): Record<string, string> | null;
|
|
4
|
+
export declare function buildAuthorizationState(baseState: string, publicStateContext: LoginOptions['publicStateContext']): string;
|
|
5
|
+
//# sourceMappingURL=authorization-parameters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-parameters.d.ts","sourceRoot":"","sources":["../../src/auth/authorization-parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgC5C,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,GAAG,SAAS,EACnD,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,qBAAqB,GAAG,wBAAwB,CAAM,GACjF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmCxB;AAED,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,YAAY,CAAC,oBAAoB,CAAC,GAC1C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CA2B/B;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,YAAY,CAAC,oBAAoB,CAAC,GACrD,MAAM,CAOR"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* Client-side auth types live here.
|
|
5
5
|
* For server-side auth primitives, use `@eminuckan/spine/auth/server`.
|
|
6
6
|
*/
|
|
7
|
-
export type { UserInfo, AuthConfig, SessionData, OAuthState, LoginOptions, AuthError, ApplicationType, } from './types';
|
|
7
|
+
export type { UserInfo, AuthSessionSummary, AuthConfig, SessionData, OAuthState, LoginOptions, AuthError, ApplicationType, BackChannelLogoutResult, FrontChannelLogoutResult, OidcClientAuthMethod, } from './types';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,SAAS,EACT,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,QAAQ,EACR,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
|
|
@@ -5,12 +5,29 @@
|
|
|
5
5
|
* Provides secure session management with automatic expiration,
|
|
6
6
|
* without depending on a framework-specific session implementation.
|
|
7
7
|
*/
|
|
8
|
-
import type { SessionData, OAuthState } from './types';
|
|
8
|
+
import type { AuthSessionSummary, SessionData, OAuthState } from './types';
|
|
9
9
|
export declare const AUTH_ERROR_COOKIE_PREFIX: string;
|
|
10
10
|
export declare function createAuthSession(request: Request, sessionData: Partial<SessionData>): Promise<Headers>;
|
|
11
11
|
export declare function getAuthSession(request: Request): Promise<SessionData>;
|
|
12
12
|
export declare function updateAuthSession(request: Request, updates: Partial<SessionData>): Promise<Headers>;
|
|
13
13
|
export declare function destroyAuthSession(request: Request): Promise<Headers>;
|
|
14
|
+
export declare function getCurrentAuthSessionId(request: Request): Promise<string | null>;
|
|
15
|
+
export declare function getAuthSessionById(sessionId: string): Promise<SessionData | null>;
|
|
16
|
+
export declare function listAuthSessionDataForUser(userId: string): Promise<Array<{
|
|
17
|
+
sessionId: string;
|
|
18
|
+
data: SessionData;
|
|
19
|
+
}>>;
|
|
20
|
+
export declare function listAuthSessionsForUser(userId: string, currentSessionId?: string | null): Promise<AuthSessionSummary[]>;
|
|
21
|
+
export declare function listCurrentUserAuthSessions(request: Request): Promise<AuthSessionSummary[]>;
|
|
22
|
+
export declare function destroyAuthSessionById(sessionId: string): Promise<boolean>;
|
|
23
|
+
export declare function destroyAuthSessionsForUser(userId: string): Promise<number>;
|
|
24
|
+
export declare function destroyAuthSessionsBySid(sid: string): Promise<number>;
|
|
25
|
+
export declare function destroyAuthSessionsBySessionState(sessionState: string): Promise<number>;
|
|
26
|
+
export declare function destroyAuthSessionsByIdentitySession(params: {
|
|
27
|
+
sid?: string;
|
|
28
|
+
sessionState?: string;
|
|
29
|
+
userId?: string;
|
|
30
|
+
}): Promise<number>;
|
|
14
31
|
export declare function requireAuthSession(request: Request): Promise<SessionData>;
|
|
15
32
|
export declare function isSessionValid(request: Request): Promise<boolean>;
|
|
16
33
|
export declare function createOAuthState(state: OAuthState): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis-session-storage.server.d.ts","sourceRoot":"","sources":["../../src/auth/redis-session-storage.server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"redis-session-storage.server.d.ts","sourceRoot":"","sources":["../../src/auth/redis-session-storage.server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAsD3E,eAAO,MAAM,wBAAwB,QAAgE,CAAC;AA+ctG,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,GAChC,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA4B3E;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3E;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEtF;AAED,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAGvF;AAED,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,CAG1D;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,GAC/B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAM/B;AAED,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAOjG;AAED,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhF;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWhF;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW3E;AAED,wBAAsB,iCAAiC,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7F;AAED,wBAAsB,oCAAoC,CAAC,MAAM,EAAE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,MAAM,CAAC,CAclB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAQ/E;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBvE;AAMD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CASzE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAe/E;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrE;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAejE;AAMD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM1D"}
|
|
@@ -13,6 +13,8 @@ export declare function shouldRefreshToken(request: Request): Promise<boolean>;
|
|
|
13
13
|
*/
|
|
14
14
|
export interface DefaultRouteIdentityContext {
|
|
15
15
|
hasAnyMembership: boolean;
|
|
16
|
+
hasEntitlement?: boolean;
|
|
17
|
+
/** @deprecated Use hasEntitlement or app-specific fields instead. */
|
|
16
18
|
hasSubscription: boolean;
|
|
17
19
|
isOnboarded: boolean;
|
|
18
20
|
}
|
|
@@ -30,7 +32,9 @@ export interface TenantChecker {
|
|
|
30
32
|
} | null>;
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
35
|
+
* Legacy subscription checker configuration
|
|
36
|
+
*
|
|
37
|
+
* @deprecated Put entitlement policy in resolveRoute or app-level route loaders.
|
|
34
38
|
*/
|
|
35
39
|
export interface SubscriptionChecker {
|
|
36
40
|
checkTenantSubscriptionStatus: (request: Request, tenantId: string) => Promise<boolean>;
|
|
@@ -77,7 +81,7 @@ export interface RouteProtectionConfig<TIdentityContext = DefaultRouteIdentityCo
|
|
|
77
81
|
createAutomaticLogoutRequest?: (context: AutomaticLogoutRequestContext) => Promise<Request> | Request;
|
|
78
82
|
}
|
|
79
83
|
/**
|
|
80
|
-
* Configure route protection with identity
|
|
84
|
+
* Configure route protection with identity, tenant, and app policy checkers
|
|
81
85
|
*/
|
|
82
86
|
export declare function configureRouteProtection<TIdentityContext = DefaultRouteIdentityContext>(config: RouteProtectionConfig<TIdentityContext>): void;
|
|
83
87
|
/**
|
|
@@ -97,11 +101,23 @@ export declare const publicRoute: <T>(request: Request, loaderFn: (user?: UserIn
|
|
|
97
101
|
*/
|
|
98
102
|
export declare const authRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
|
|
99
103
|
/**
|
|
100
|
-
*
|
|
104
|
+
* Generic policy-protected route. Apps define policy in configureRouteProtection.
|
|
105
|
+
*/
|
|
106
|
+
export declare const policyRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
|
|
107
|
+
/**
|
|
108
|
+
* Alias for auth-protected routes.
|
|
109
|
+
*/
|
|
110
|
+
export declare const protectedRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
|
|
111
|
+
/**
|
|
112
|
+
* Setup policy route
|
|
113
|
+
*
|
|
114
|
+
* @deprecated Use policyRoute with configureRouteProtection instead.
|
|
101
115
|
*/
|
|
102
116
|
export declare const onboardingRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
|
|
103
117
|
/**
|
|
104
|
-
*
|
|
118
|
+
* Entitlement policy route
|
|
119
|
+
*
|
|
120
|
+
* @deprecated Use policyRoute with configureRouteProtection instead.
|
|
105
121
|
*/
|
|
106
122
|
export declare const subscriptionRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
|
|
107
123
|
//# sourceMappingURL=route-protection.server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-protection.server.d.ts","sourceRoot":"","sources":["../../src/auth/route-protection.server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"route-protection.server.d.ts","sourceRoot":"","sources":["../../src/auth/route-protection.server.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/server.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ export * from './auth.server';
|
|
|
8
8
|
export * from './redis-session-storage.server';
|
|
9
9
|
export * from './route-protection.server';
|
|
10
10
|
export * from './token-refresh.server';
|
|
11
|
-
export type { ApplicationType, AuthClaimMapping, AuthConfig, AuthError, LoginOptions, OAuthState, ProtectedLoaderFn, ProtectionLevel, SessionData, SessionFlashData, UserInfo, } from './types';
|
|
11
|
+
export type { ApplicationType, AuthSessionSummary, AuthClaimMapping, AuthConfig, AuthError, BackChannelLogoutResult, FrontChannelLogoutResult, LoginOptions, OAuthState, OidcClientAuthMethod, ProtectedLoaderFn, ProtectionLevel, PublicAuthorizationStateContext, SessionData, SessionFlashData, UserInfo, } from './types';
|
|
12
12
|
export type { TokenRefreshResult as AuthTokenRefreshResult, } from './types';
|
|
13
13
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/auth/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,kBAAkB,IAAI,sBAAsB,GAC7C,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/auth/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,uBAAuB,EACvB,wBAAwB,EACxB,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,+BAA+B,EAC/B,WAAW,EACX,gBAAgB,EAChB,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,kBAAkB,IAAI,sBAAsB,GAC7C,MAAM,SAAS,CAAC"}
|
package/dist/auth/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../logging-
|
|
2
|
-
import { AUTH_ERROR_COOKIE_PREFIX, cleanupExpiredOAuthStates, closeRedisConnection, createAuthSession, createOAuthState, deleteOAuthState, destroyAuthSession, getAuthSession, getOAuthState, isSessionValid, requireAuthSession, updateAuthSession } from "../redis-session-storage.server-
|
|
3
|
-
import { clearAuthErrorHeaders, clearAuthServerCache, configureAuthClaimMapping, extractUserInfo, getAccessToken, getAuthError, getUser, handleCallback, hasAuthError, login, logout, refreshTokens, requireAuth, resetAuthClaimMapping } from "../auth.server-
|
|
4
|
-
import { attemptTokenRefresh, authRoute, configureRouteProtection, isTokenExpiredResponse, onboardingRoute, protectRoute, publicRoute, resetRouteProtectionConfig, shouldAttemptTokenRefresh, shouldRefreshToken, subscriptionRoute } from "../server-
|
|
1
|
+
import "../logging-DviiAkLx.js";
|
|
2
|
+
import { AUTH_ERROR_COOKIE_PREFIX, cleanupExpiredOAuthStates, closeRedisConnection, createAuthSession, createOAuthState, deleteOAuthState, destroyAuthSession, destroyAuthSessionById, destroyAuthSessionsByIdentitySession, destroyAuthSessionsBySessionState, destroyAuthSessionsBySid, destroyAuthSessionsForUser, getAuthSession, getAuthSessionById, getCurrentAuthSessionId, getOAuthState, isSessionValid, listAuthSessionDataForUser, listAuthSessionsForUser, listCurrentUserAuthSessions, requireAuthSession, updateAuthSession } from "../redis-session-storage.server-v2VcpFsQ.js";
|
|
3
|
+
import { clearAuthErrorHeaders, clearAuthServerCache, configureAuthClaimMapping, extractUserInfo, getAccessToken, getAuthError, getUser, handleBackChannelLogout, handleCallback, handleFrontChannelLogout, hasAuthError, login, logout, refreshTokens, requireAuth, resetAuthClaimMapping } from "../auth.server-D5oiz9aF.js";
|
|
4
|
+
import { attemptTokenRefresh, authRoute, configureRouteProtection, isTokenExpiredResponse, onboardingRoute, policyRoute, protectRoute, protectedRoute, publicRoute, resetRouteProtectionConfig, shouldAttemptTokenRefresh, shouldRefreshToken, subscriptionRoute } from "../server-B6PCxc-T.js";
|
|
5
5
|
|
|
6
|
-
export { AUTH_ERROR_COOKIE_PREFIX, attemptTokenRefresh, authRoute, cleanupExpiredOAuthStates, clearAuthErrorHeaders, clearAuthServerCache, closeRedisConnection, configureAuthClaimMapping, configureRouteProtection, createAuthSession, createOAuthState, deleteOAuthState, destroyAuthSession, extractUserInfo, getAccessToken, getAuthError, getAuthSession, getOAuthState, getUser, handleCallback, hasAuthError, isSessionValid, isTokenExpiredResponse, login, logout, onboardingRoute, protectRoute, publicRoute, refreshTokens, requireAuth, requireAuthSession, resetAuthClaimMapping, resetRouteProtectionConfig, shouldAttemptTokenRefresh, shouldRefreshToken, subscriptionRoute, updateAuthSession };
|
|
6
|
+
export { AUTH_ERROR_COOKIE_PREFIX, attemptTokenRefresh, authRoute, cleanupExpiredOAuthStates, clearAuthErrorHeaders, clearAuthServerCache, closeRedisConnection, configureAuthClaimMapping, configureRouteProtection, createAuthSession, createOAuthState, deleteOAuthState, destroyAuthSession, destroyAuthSessionById, destroyAuthSessionsByIdentitySession, destroyAuthSessionsBySessionState, destroyAuthSessionsBySid, destroyAuthSessionsForUser, extractUserInfo, getAccessToken, getAuthError, getAuthSession, getAuthSessionById, getCurrentAuthSessionId, getOAuthState, getUser, handleBackChannelLogout, handleCallback, handleFrontChannelLogout, hasAuthError, isSessionValid, isTokenExpiredResponse, listAuthSessionDataForUser, listAuthSessionsForUser, listCurrentUserAuthSessions, login, logout, onboardingRoute, policyRoute, protectRoute, protectedRoute, publicRoute, refreshTokens, requireAuth, requireAuthSession, resetAuthClaimMapping, resetRouteProtectionConfig, shouldAttemptTokenRefresh, shouldRefreshToken, subscriptionRoute, updateAuthSession };
|