@uniforge/portal 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/auth/index.d.cts +104 -0
  2. package/dist/auth/index.d.ts +104 -0
  3. package/dist/auth/index.js +194 -0
  4. package/dist/auth/index.js.map +1 -0
  5. package/dist/auth/index.mjs +160 -0
  6. package/dist/auth/index.mjs.map +1 -0
  7. package/dist/dashboard/index.d.cts +76 -0
  8. package/dist/dashboard/index.d.ts +76 -0
  9. package/dist/dashboard/index.js +158 -0
  10. package/dist/dashboard/index.js.map +1 -0
  11. package/dist/dashboard/index.mjs +129 -0
  12. package/dist/dashboard/index.mjs.map +1 -0
  13. package/dist/feature-flags/index.d.cts +75 -0
  14. package/dist/feature-flags/index.d.ts +75 -0
  15. package/dist/feature-flags/index.js +111 -0
  16. package/dist/feature-flags/index.js.map +1 -0
  17. package/dist/feature-flags/index.mjs +83 -0
  18. package/dist/feature-flags/index.mjs.map +1 -0
  19. package/dist/index.d.cts +15 -0
  20. package/dist/index.d.ts +15 -0
  21. package/dist/index.js +31 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/index.mjs +6 -0
  24. package/dist/index.mjs.map +1 -0
  25. package/dist/merchants/index.d.cts +100 -0
  26. package/dist/merchants/index.d.ts +100 -0
  27. package/dist/merchants/index.js +120 -0
  28. package/dist/merchants/index.js.map +1 -0
  29. package/dist/merchants/index.mjs +90 -0
  30. package/dist/merchants/index.mjs.map +1 -0
  31. package/dist/metrics/index.d.cts +83 -0
  32. package/dist/metrics/index.d.ts +83 -0
  33. package/dist/metrics/index.js +112 -0
  34. package/dist/metrics/index.js.map +1 -0
  35. package/dist/metrics/index.mjs +83 -0
  36. package/dist/metrics/index.mjs.map +1 -0
  37. package/dist/tickets/index.d.cts +96 -0
  38. package/dist/tickets/index.d.ts +96 -0
  39. package/dist/tickets/index.js +102 -0
  40. package/dist/tickets/index.js.map +1 -0
  41. package/dist/tickets/index.mjs +73 -0
  42. package/dist/tickets/index.mjs.map +1 -0
  43. package/dist/webhook-logs/index.d.cts +88 -0
  44. package/dist/webhook-logs/index.d.ts +88 -0
  45. package/dist/webhook-logs/index.js +111 -0
  46. package/dist/webhook-logs/index.js.map +1 -0
  47. package/dist/webhook-logs/index.mjs +82 -0
  48. package/dist/webhook-logs/index.mjs.map +1 -0
  49. package/package.json +70 -0
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Portal authentication and authorization types.
3
+ */
4
+ type PortalRole = 'owner' | 'admin' | 'developer' | 'viewer';
5
+ interface PortalUser {
6
+ id: string;
7
+ email: string;
8
+ name: string;
9
+ role: PortalRole;
10
+ avatarUrl?: string;
11
+ teamId?: string;
12
+ }
13
+ interface PortalTeam {
14
+ id: string;
15
+ name: string;
16
+ memberCount: number;
17
+ }
18
+ interface PortalContext {
19
+ user: PortalUser;
20
+ team: PortalTeam;
21
+ permissions: string[];
22
+ }
23
+ interface PortalSessionData {
24
+ userId: string;
25
+ email: string;
26
+ role: PortalRole;
27
+ teamId: string;
28
+ createdAt: number;
29
+ expiresAt: number;
30
+ }
31
+
32
+ /**
33
+ * Portal permission definitions and role-based access mappings.
34
+ */
35
+
36
+ declare const PORTAL_PERMISSIONS: {
37
+ readonly 'dashboard.view': "dashboard.view";
38
+ readonly 'merchants.view': "merchants.view";
39
+ readonly 'merchants.manage': "merchants.manage";
40
+ readonly 'settings.view': "settings.view";
41
+ readonly 'settings.manage': "settings.manage";
42
+ readonly 'team.view': "team.view";
43
+ readonly 'team.manage': "team.manage";
44
+ readonly 'billing.view': "billing.view";
45
+ readonly 'billing.manage': "billing.manage";
46
+ readonly 'webhooks.view': "webhooks.view";
47
+ readonly 'api.view': "api.view";
48
+ };
49
+ declare const ROLE_PERMISSIONS: Record<PortalRole, readonly string[]>;
50
+ declare function getPermissionsForRole(role: PortalRole): string[];
51
+ declare function hasPermission(role: PortalRole, permission: string): boolean;
52
+
53
+ /**
54
+ * Portal session store interface and in-memory implementation.
55
+ */
56
+
57
+ interface PortalSessionStore {
58
+ get(sessionId: string): Promise<PortalSessionData | null>;
59
+ set(sessionId: string, data: PortalSessionData, ttl?: number): Promise<void>;
60
+ delete(sessionId: string): Promise<void>;
61
+ exists(sessionId: string): Promise<boolean>;
62
+ }
63
+ declare class InMemoryPortalSessionStore implements PortalSessionStore {
64
+ private readonly store;
65
+ get(sessionId: string): Promise<PortalSessionData | null>;
66
+ set(sessionId: string, data: PortalSessionData, ttl?: number): Promise<void>;
67
+ delete(sessionId: string): Promise<void>;
68
+ exists(sessionId: string): Promise<boolean>;
69
+ }
70
+
71
+ /**
72
+ * Developer authentication service for portal access.
73
+ */
74
+
75
+ interface PortalAuthConfig {
76
+ validateApiKey: (apiKey: string) => Promise<PortalUser | null>;
77
+ sessionStore: PortalSessionStore;
78
+ getTeam: (teamId: string) => Promise<PortalTeam | null>;
79
+ getUser: (userId: string) => Promise<PortalUser | null>;
80
+ }
81
+ declare class DeveloperAuthService {
82
+ private readonly config;
83
+ constructor(config: PortalAuthConfig);
84
+ authenticate(token: string): Promise<PortalUser | null>;
85
+ validateApiKey(apiKey: string): Promise<PortalUser | null>;
86
+ getPortalContext(userId: string): Promise<PortalContext | null>;
87
+ }
88
+
89
+ /**
90
+ * Permission guard for portal access control.
91
+ */
92
+
93
+ declare class PermissionGuardError extends Error {
94
+ readonly requiredPermission: string;
95
+ constructor(permission: string);
96
+ }
97
+ declare class PermissionGuard {
98
+ requirePermission(context: PortalContext, permission: string): void;
99
+ requireAnyPermission(context: PortalContext, permissions: string[]): void;
100
+ requireAllPermissions(context: PortalContext, permissions: string[]): void;
101
+ canAccess(context: PortalContext, permission: string): boolean;
102
+ }
103
+
104
+ export { DeveloperAuthService, InMemoryPortalSessionStore, PORTAL_PERMISSIONS, PermissionGuard, PermissionGuardError, type PortalAuthConfig, type PortalContext, type PortalRole, type PortalSessionData, type PortalSessionStore, type PortalTeam, type PortalUser, ROLE_PERMISSIONS, getPermissionsForRole, hasPermission };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Portal authentication and authorization types.
3
+ */
4
+ type PortalRole = 'owner' | 'admin' | 'developer' | 'viewer';
5
+ interface PortalUser {
6
+ id: string;
7
+ email: string;
8
+ name: string;
9
+ role: PortalRole;
10
+ avatarUrl?: string;
11
+ teamId?: string;
12
+ }
13
+ interface PortalTeam {
14
+ id: string;
15
+ name: string;
16
+ memberCount: number;
17
+ }
18
+ interface PortalContext {
19
+ user: PortalUser;
20
+ team: PortalTeam;
21
+ permissions: string[];
22
+ }
23
+ interface PortalSessionData {
24
+ userId: string;
25
+ email: string;
26
+ role: PortalRole;
27
+ teamId: string;
28
+ createdAt: number;
29
+ expiresAt: number;
30
+ }
31
+
32
+ /**
33
+ * Portal permission definitions and role-based access mappings.
34
+ */
35
+
36
+ declare const PORTAL_PERMISSIONS: {
37
+ readonly 'dashboard.view': "dashboard.view";
38
+ readonly 'merchants.view': "merchants.view";
39
+ readonly 'merchants.manage': "merchants.manage";
40
+ readonly 'settings.view': "settings.view";
41
+ readonly 'settings.manage': "settings.manage";
42
+ readonly 'team.view': "team.view";
43
+ readonly 'team.manage': "team.manage";
44
+ readonly 'billing.view': "billing.view";
45
+ readonly 'billing.manage': "billing.manage";
46
+ readonly 'webhooks.view': "webhooks.view";
47
+ readonly 'api.view': "api.view";
48
+ };
49
+ declare const ROLE_PERMISSIONS: Record<PortalRole, readonly string[]>;
50
+ declare function getPermissionsForRole(role: PortalRole): string[];
51
+ declare function hasPermission(role: PortalRole, permission: string): boolean;
52
+
53
+ /**
54
+ * Portal session store interface and in-memory implementation.
55
+ */
56
+
57
+ interface PortalSessionStore {
58
+ get(sessionId: string): Promise<PortalSessionData | null>;
59
+ set(sessionId: string, data: PortalSessionData, ttl?: number): Promise<void>;
60
+ delete(sessionId: string): Promise<void>;
61
+ exists(sessionId: string): Promise<boolean>;
62
+ }
63
+ declare class InMemoryPortalSessionStore implements PortalSessionStore {
64
+ private readonly store;
65
+ get(sessionId: string): Promise<PortalSessionData | null>;
66
+ set(sessionId: string, data: PortalSessionData, ttl?: number): Promise<void>;
67
+ delete(sessionId: string): Promise<void>;
68
+ exists(sessionId: string): Promise<boolean>;
69
+ }
70
+
71
+ /**
72
+ * Developer authentication service for portal access.
73
+ */
74
+
75
+ interface PortalAuthConfig {
76
+ validateApiKey: (apiKey: string) => Promise<PortalUser | null>;
77
+ sessionStore: PortalSessionStore;
78
+ getTeam: (teamId: string) => Promise<PortalTeam | null>;
79
+ getUser: (userId: string) => Promise<PortalUser | null>;
80
+ }
81
+ declare class DeveloperAuthService {
82
+ private readonly config;
83
+ constructor(config: PortalAuthConfig);
84
+ authenticate(token: string): Promise<PortalUser | null>;
85
+ validateApiKey(apiKey: string): Promise<PortalUser | null>;
86
+ getPortalContext(userId: string): Promise<PortalContext | null>;
87
+ }
88
+
89
+ /**
90
+ * Permission guard for portal access control.
91
+ */
92
+
93
+ declare class PermissionGuardError extends Error {
94
+ readonly requiredPermission: string;
95
+ constructor(permission: string);
96
+ }
97
+ declare class PermissionGuard {
98
+ requirePermission(context: PortalContext, permission: string): void;
99
+ requireAnyPermission(context: PortalContext, permissions: string[]): void;
100
+ requireAllPermissions(context: PortalContext, permissions: string[]): void;
101
+ canAccess(context: PortalContext, permission: string): boolean;
102
+ }
103
+
104
+ export { DeveloperAuthService, InMemoryPortalSessionStore, PORTAL_PERMISSIONS, PermissionGuard, PermissionGuardError, type PortalAuthConfig, type PortalContext, type PortalRole, type PortalSessionData, type PortalSessionStore, type PortalTeam, type PortalUser, ROLE_PERMISSIONS, getPermissionsForRole, hasPermission };
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/auth/index.ts
21
+ var auth_exports = {};
22
+ __export(auth_exports, {
23
+ DeveloperAuthService: () => DeveloperAuthService,
24
+ InMemoryPortalSessionStore: () => InMemoryPortalSessionStore,
25
+ PORTAL_PERMISSIONS: () => PORTAL_PERMISSIONS,
26
+ PermissionGuard: () => PermissionGuard,
27
+ PermissionGuardError: () => PermissionGuardError,
28
+ ROLE_PERMISSIONS: () => ROLE_PERMISSIONS,
29
+ getPermissionsForRole: () => getPermissionsForRole,
30
+ hasPermission: () => hasPermission
31
+ });
32
+ module.exports = __toCommonJS(auth_exports);
33
+
34
+ // src/auth/permissions.ts
35
+ var PORTAL_PERMISSIONS = {
36
+ "dashboard.view": "dashboard.view",
37
+ "merchants.view": "merchants.view",
38
+ "merchants.manage": "merchants.manage",
39
+ "settings.view": "settings.view",
40
+ "settings.manage": "settings.manage",
41
+ "team.view": "team.view",
42
+ "team.manage": "team.manage",
43
+ "billing.view": "billing.view",
44
+ "billing.manage": "billing.manage",
45
+ "webhooks.view": "webhooks.view",
46
+ "api.view": "api.view"
47
+ };
48
+ var ALL_PERMISSIONS = Object.values(PORTAL_PERMISSIONS);
49
+ var ADMIN_PERMISSIONS = ALL_PERMISSIONS.filter(
50
+ (p) => p !== PORTAL_PERMISSIONS["team.manage"]
51
+ );
52
+ var DEVELOPER_PERMISSIONS = [
53
+ PORTAL_PERMISSIONS["dashboard.view"],
54
+ PORTAL_PERMISSIONS["merchants.view"],
55
+ PORTAL_PERMISSIONS["merchants.manage"],
56
+ PORTAL_PERMISSIONS["settings.view"],
57
+ PORTAL_PERMISSIONS["webhooks.view"],
58
+ PORTAL_PERMISSIONS["api.view"]
59
+ ];
60
+ var VIEWER_PERMISSIONS = [
61
+ PORTAL_PERMISSIONS["dashboard.view"],
62
+ PORTAL_PERMISSIONS["merchants.view"],
63
+ PORTAL_PERMISSIONS["settings.view"],
64
+ PORTAL_PERMISSIONS["billing.view"],
65
+ PORTAL_PERMISSIONS["webhooks.view"],
66
+ PORTAL_PERMISSIONS["api.view"]
67
+ ];
68
+ var ROLE_PERMISSIONS = {
69
+ owner: ALL_PERMISSIONS,
70
+ admin: ADMIN_PERMISSIONS,
71
+ developer: DEVELOPER_PERMISSIONS,
72
+ viewer: VIEWER_PERMISSIONS
73
+ };
74
+ function getPermissionsForRole(role) {
75
+ return [...ROLE_PERMISSIONS[role]];
76
+ }
77
+ function hasPermission(role, permission) {
78
+ return ROLE_PERMISSIONS[role].includes(permission);
79
+ }
80
+
81
+ // src/auth/session-store.ts
82
+ var InMemoryPortalSessionStore = class {
83
+ store = /* @__PURE__ */ new Map();
84
+ async get(sessionId) {
85
+ const entry = this.store.get(sessionId);
86
+ if (!entry) {
87
+ return null;
88
+ }
89
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
90
+ this.store.delete(sessionId);
91
+ return null;
92
+ }
93
+ return entry.data;
94
+ }
95
+ async set(sessionId, data, ttl) {
96
+ const expiresAt = ttl !== void 0 && ttl > 0 ? Date.now() + ttl * 1e3 : null;
97
+ this.store.set(sessionId, { data, expiresAt });
98
+ }
99
+ async delete(sessionId) {
100
+ this.store.delete(sessionId);
101
+ }
102
+ async exists(sessionId) {
103
+ const entry = this.store.get(sessionId);
104
+ if (!entry) {
105
+ return false;
106
+ }
107
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
108
+ this.store.delete(sessionId);
109
+ return false;
110
+ }
111
+ return true;
112
+ }
113
+ };
114
+
115
+ // src/auth/developer-auth-service.ts
116
+ var DeveloperAuthService = class {
117
+ config;
118
+ constructor(config) {
119
+ this.config = config;
120
+ }
121
+ async authenticate(token) {
122
+ if (!token) {
123
+ return null;
124
+ }
125
+ return this.config.validateApiKey(token);
126
+ }
127
+ async validateApiKey(apiKey) {
128
+ if (!apiKey) {
129
+ return null;
130
+ }
131
+ return this.config.validateApiKey(apiKey);
132
+ }
133
+ async getPortalContext(userId) {
134
+ const user = await this.config.getUser(userId);
135
+ if (!user) {
136
+ return null;
137
+ }
138
+ const teamId = user.teamId;
139
+ if (teamId === void 0) {
140
+ return null;
141
+ }
142
+ const team = await this.config.getTeam(teamId);
143
+ if (!team) {
144
+ return null;
145
+ }
146
+ const permissions = getPermissionsForRole(user.role);
147
+ return { user, team, permissions };
148
+ }
149
+ };
150
+
151
+ // src/auth/permission-guard.ts
152
+ var PermissionGuardError = class extends Error {
153
+ requiredPermission;
154
+ constructor(permission) {
155
+ super(`Missing required permission: ${permission}`);
156
+ this.name = "PermissionGuardError";
157
+ this.requiredPermission = permission;
158
+ }
159
+ };
160
+ var PermissionGuard = class {
161
+ requirePermission(context, permission) {
162
+ if (!context.permissions.includes(permission)) {
163
+ throw new PermissionGuardError(permission);
164
+ }
165
+ }
166
+ requireAnyPermission(context, permissions) {
167
+ const hasAny = permissions.some((p) => context.permissions.includes(p));
168
+ if (!hasAny) {
169
+ throw new PermissionGuardError(permissions.join(" | "));
170
+ }
171
+ }
172
+ requireAllPermissions(context, permissions) {
173
+ for (const p of permissions) {
174
+ if (!context.permissions.includes(p)) {
175
+ throw new PermissionGuardError(p);
176
+ }
177
+ }
178
+ }
179
+ canAccess(context, permission) {
180
+ return context.permissions.includes(permission);
181
+ }
182
+ };
183
+ // Annotate the CommonJS export names for ESM import in node:
184
+ 0 && (module.exports = {
185
+ DeveloperAuthService,
186
+ InMemoryPortalSessionStore,
187
+ PORTAL_PERMISSIONS,
188
+ PermissionGuard,
189
+ PermissionGuardError,
190
+ ROLE_PERMISSIONS,
191
+ getPermissionsForRole,
192
+ hasPermission
193
+ });
194
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/index.ts","../../src/auth/permissions.ts","../../src/auth/session-store.ts","../../src/auth/developer-auth-service.ts","../../src/auth/permission-guard.ts"],"sourcesContent":["export type {\n PortalRole,\n PortalUser,\n PortalTeam,\n PortalContext,\n PortalSessionData,\n} from './types.js';\n\nexport {\n PORTAL_PERMISSIONS,\n ROLE_PERMISSIONS,\n hasPermission,\n getPermissionsForRole,\n} from './permissions.js';\n\nexport type { PortalSessionStore } from './session-store.js';\nexport { InMemoryPortalSessionStore } from './session-store.js';\n\nexport type { PortalAuthConfig } from './developer-auth-service.js';\nexport { DeveloperAuthService } from './developer-auth-service.js';\n\nexport { PermissionGuard, PermissionGuardError } from './permission-guard.js';\n","/**\n * Portal permission definitions and role-based access mappings.\n */\n\nimport type { PortalRole } from './types.js';\n\nexport const PORTAL_PERMISSIONS = {\n 'dashboard.view': 'dashboard.view',\n 'merchants.view': 'merchants.view',\n 'merchants.manage': 'merchants.manage',\n 'settings.view': 'settings.view',\n 'settings.manage': 'settings.manage',\n 'team.view': 'team.view',\n 'team.manage': 'team.manage',\n 'billing.view': 'billing.view',\n 'billing.manage': 'billing.manage',\n 'webhooks.view': 'webhooks.view',\n 'api.view': 'api.view',\n} as const satisfies Record<string, string>;\n\nconst ALL_PERMISSIONS = Object.values(PORTAL_PERMISSIONS);\n\nconst ADMIN_PERMISSIONS = ALL_PERMISSIONS.filter(\n (p) => p !== PORTAL_PERMISSIONS['team.manage']\n);\n\nconst DEVELOPER_PERMISSIONS: string[] = [\n PORTAL_PERMISSIONS['dashboard.view'],\n PORTAL_PERMISSIONS['merchants.view'],\n PORTAL_PERMISSIONS['merchants.manage'],\n PORTAL_PERMISSIONS['settings.view'],\n PORTAL_PERMISSIONS['webhooks.view'],\n PORTAL_PERMISSIONS['api.view'],\n];\n\nconst VIEWER_PERMISSIONS: string[] = [\n PORTAL_PERMISSIONS['dashboard.view'],\n PORTAL_PERMISSIONS['merchants.view'],\n PORTAL_PERMISSIONS['settings.view'],\n PORTAL_PERMISSIONS['billing.view'],\n PORTAL_PERMISSIONS['webhooks.view'],\n PORTAL_PERMISSIONS['api.view'],\n];\n\nexport const ROLE_PERMISSIONS: Record<PortalRole, readonly string[]> = {\n owner: ALL_PERMISSIONS,\n admin: ADMIN_PERMISSIONS,\n developer: DEVELOPER_PERMISSIONS,\n viewer: VIEWER_PERMISSIONS,\n};\n\nexport function getPermissionsForRole(role: PortalRole): string[] {\n return [...ROLE_PERMISSIONS[role]];\n}\n\nexport function hasPermission(role: PortalRole, permission: string): boolean {\n return ROLE_PERMISSIONS[role].includes(permission);\n}\n","/**\n * Portal session store interface and in-memory implementation.\n */\n\nimport type { PortalSessionData } from './types.js';\n\nexport interface PortalSessionStore {\n get(sessionId: string): Promise<PortalSessionData | null>;\n set(sessionId: string, data: PortalSessionData, ttl?: number): Promise<void>;\n delete(sessionId: string): Promise<void>;\n exists(sessionId: string): Promise<boolean>;\n}\n\ninterface StoredEntry {\n data: PortalSessionData;\n expiresAt: number | null;\n}\n\nexport class InMemoryPortalSessionStore implements PortalSessionStore {\n private readonly store = new Map<string, StoredEntry>();\n\n async get(sessionId: string): Promise<PortalSessionData | null> {\n const entry = this.store.get(sessionId);\n if (!entry) {\n return null;\n }\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return null;\n }\n return entry.data;\n }\n\n async set(\n sessionId: string,\n data: PortalSessionData,\n ttl?: number\n ): Promise<void> {\n const expiresAt =\n ttl !== undefined && ttl > 0 ? Date.now() + ttl * 1000 : null;\n this.store.set(sessionId, { data, expiresAt });\n }\n\n async delete(sessionId: string): Promise<void> {\n this.store.delete(sessionId);\n }\n\n async exists(sessionId: string): Promise<boolean> {\n const entry = this.store.get(sessionId);\n if (!entry) {\n return false;\n }\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return false;\n }\n return true;\n }\n}\n","/**\n * Developer authentication service for portal access.\n */\n\nimport type {\n PortalContext,\n PortalTeam,\n PortalUser,\n} from './types.js';\nimport { getPermissionsForRole } from './permissions.js';\nimport type { PortalSessionStore } from './session-store.js';\n\nexport interface PortalAuthConfig {\n validateApiKey: (apiKey: string) => Promise<PortalUser | null>;\n sessionStore: PortalSessionStore;\n getTeam: (teamId: string) => Promise<PortalTeam | null>;\n getUser: (userId: string) => Promise<PortalUser | null>;\n}\n\nexport class DeveloperAuthService {\n private readonly config: PortalAuthConfig;\n\n constructor(config: PortalAuthConfig) {\n this.config = config;\n }\n\n async authenticate(token: string): Promise<PortalUser | null> {\n if (!token) {\n return null;\n }\n return this.config.validateApiKey(token);\n }\n\n async validateApiKey(apiKey: string): Promise<PortalUser | null> {\n if (!apiKey) {\n return null;\n }\n return this.config.validateApiKey(apiKey);\n }\n\n async getPortalContext(userId: string): Promise<PortalContext | null> {\n const user = await this.config.getUser(userId);\n if (!user) {\n return null;\n }\n\n const teamId = user.teamId;\n if (teamId === undefined) {\n return null;\n }\n\n const team = await this.config.getTeam(teamId);\n if (!team) {\n return null;\n }\n\n const permissions = getPermissionsForRole(user.role);\n\n return { user, team, permissions };\n }\n}\n","/**\n * Permission guard for portal access control.\n */\n\nimport type { PortalContext } from './types.js';\n\nexport class PermissionGuardError extends Error {\n public readonly requiredPermission: string;\n\n constructor(permission: string) {\n super(`Missing required permission: ${permission}`);\n this.name = 'PermissionGuardError';\n this.requiredPermission = permission;\n }\n}\n\nexport class PermissionGuard {\n requirePermission(context: PortalContext, permission: string): void {\n if (!context.permissions.includes(permission)) {\n throw new PermissionGuardError(permission);\n }\n }\n\n requireAnyPermission(\n context: PortalContext,\n permissions: string[]\n ): void {\n const hasAny = permissions.some((p) => context.permissions.includes(p));\n if (!hasAny) {\n throw new PermissionGuardError(permissions.join(' | '));\n }\n }\n\n requireAllPermissions(\n context: PortalContext,\n permissions: string[]\n ): void {\n for (const p of permissions) {\n if (!context.permissions.includes(p)) {\n throw new PermissionGuardError(p);\n }\n }\n }\n\n canAccess(context: PortalContext, permission: string): boolean {\n return context.permissions.includes(permission);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,160 @@
1
+ // src/auth/permissions.ts
2
+ var PORTAL_PERMISSIONS = {
3
+ "dashboard.view": "dashboard.view",
4
+ "merchants.view": "merchants.view",
5
+ "merchants.manage": "merchants.manage",
6
+ "settings.view": "settings.view",
7
+ "settings.manage": "settings.manage",
8
+ "team.view": "team.view",
9
+ "team.manage": "team.manage",
10
+ "billing.view": "billing.view",
11
+ "billing.manage": "billing.manage",
12
+ "webhooks.view": "webhooks.view",
13
+ "api.view": "api.view"
14
+ };
15
+ var ALL_PERMISSIONS = Object.values(PORTAL_PERMISSIONS);
16
+ var ADMIN_PERMISSIONS = ALL_PERMISSIONS.filter(
17
+ (p) => p !== PORTAL_PERMISSIONS["team.manage"]
18
+ );
19
+ var DEVELOPER_PERMISSIONS = [
20
+ PORTAL_PERMISSIONS["dashboard.view"],
21
+ PORTAL_PERMISSIONS["merchants.view"],
22
+ PORTAL_PERMISSIONS["merchants.manage"],
23
+ PORTAL_PERMISSIONS["settings.view"],
24
+ PORTAL_PERMISSIONS["webhooks.view"],
25
+ PORTAL_PERMISSIONS["api.view"]
26
+ ];
27
+ var VIEWER_PERMISSIONS = [
28
+ PORTAL_PERMISSIONS["dashboard.view"],
29
+ PORTAL_PERMISSIONS["merchants.view"],
30
+ PORTAL_PERMISSIONS["settings.view"],
31
+ PORTAL_PERMISSIONS["billing.view"],
32
+ PORTAL_PERMISSIONS["webhooks.view"],
33
+ PORTAL_PERMISSIONS["api.view"]
34
+ ];
35
+ var ROLE_PERMISSIONS = {
36
+ owner: ALL_PERMISSIONS,
37
+ admin: ADMIN_PERMISSIONS,
38
+ developer: DEVELOPER_PERMISSIONS,
39
+ viewer: VIEWER_PERMISSIONS
40
+ };
41
+ function getPermissionsForRole(role) {
42
+ return [...ROLE_PERMISSIONS[role]];
43
+ }
44
+ function hasPermission(role, permission) {
45
+ return ROLE_PERMISSIONS[role].includes(permission);
46
+ }
47
+
48
+ // src/auth/session-store.ts
49
+ var InMemoryPortalSessionStore = class {
50
+ store = /* @__PURE__ */ new Map();
51
+ async get(sessionId) {
52
+ const entry = this.store.get(sessionId);
53
+ if (!entry) {
54
+ return null;
55
+ }
56
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
57
+ this.store.delete(sessionId);
58
+ return null;
59
+ }
60
+ return entry.data;
61
+ }
62
+ async set(sessionId, data, ttl) {
63
+ const expiresAt = ttl !== void 0 && ttl > 0 ? Date.now() + ttl * 1e3 : null;
64
+ this.store.set(sessionId, { data, expiresAt });
65
+ }
66
+ async delete(sessionId) {
67
+ this.store.delete(sessionId);
68
+ }
69
+ async exists(sessionId) {
70
+ const entry = this.store.get(sessionId);
71
+ if (!entry) {
72
+ return false;
73
+ }
74
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
75
+ this.store.delete(sessionId);
76
+ return false;
77
+ }
78
+ return true;
79
+ }
80
+ };
81
+
82
+ // src/auth/developer-auth-service.ts
83
+ var DeveloperAuthService = class {
84
+ config;
85
+ constructor(config) {
86
+ this.config = config;
87
+ }
88
+ async authenticate(token) {
89
+ if (!token) {
90
+ return null;
91
+ }
92
+ return this.config.validateApiKey(token);
93
+ }
94
+ async validateApiKey(apiKey) {
95
+ if (!apiKey) {
96
+ return null;
97
+ }
98
+ return this.config.validateApiKey(apiKey);
99
+ }
100
+ async getPortalContext(userId) {
101
+ const user = await this.config.getUser(userId);
102
+ if (!user) {
103
+ return null;
104
+ }
105
+ const teamId = user.teamId;
106
+ if (teamId === void 0) {
107
+ return null;
108
+ }
109
+ const team = await this.config.getTeam(teamId);
110
+ if (!team) {
111
+ return null;
112
+ }
113
+ const permissions = getPermissionsForRole(user.role);
114
+ return { user, team, permissions };
115
+ }
116
+ };
117
+
118
+ // src/auth/permission-guard.ts
119
+ var PermissionGuardError = class extends Error {
120
+ requiredPermission;
121
+ constructor(permission) {
122
+ super(`Missing required permission: ${permission}`);
123
+ this.name = "PermissionGuardError";
124
+ this.requiredPermission = permission;
125
+ }
126
+ };
127
+ var PermissionGuard = class {
128
+ requirePermission(context, permission) {
129
+ if (!context.permissions.includes(permission)) {
130
+ throw new PermissionGuardError(permission);
131
+ }
132
+ }
133
+ requireAnyPermission(context, permissions) {
134
+ const hasAny = permissions.some((p) => context.permissions.includes(p));
135
+ if (!hasAny) {
136
+ throw new PermissionGuardError(permissions.join(" | "));
137
+ }
138
+ }
139
+ requireAllPermissions(context, permissions) {
140
+ for (const p of permissions) {
141
+ if (!context.permissions.includes(p)) {
142
+ throw new PermissionGuardError(p);
143
+ }
144
+ }
145
+ }
146
+ canAccess(context, permission) {
147
+ return context.permissions.includes(permission);
148
+ }
149
+ };
150
+ export {
151
+ DeveloperAuthService,
152
+ InMemoryPortalSessionStore,
153
+ PORTAL_PERMISSIONS,
154
+ PermissionGuard,
155
+ PermissionGuardError,
156
+ ROLE_PERMISSIONS,
157
+ getPermissionsForRole,
158
+ hasPermission
159
+ };
160
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/permissions.ts","../../src/auth/session-store.ts","../../src/auth/developer-auth-service.ts","../../src/auth/permission-guard.ts"],"sourcesContent":["/**\n * Portal permission definitions and role-based access mappings.\n */\n\nimport type { PortalRole } from './types.js';\n\nexport const PORTAL_PERMISSIONS = {\n 'dashboard.view': 'dashboard.view',\n 'merchants.view': 'merchants.view',\n 'merchants.manage': 'merchants.manage',\n 'settings.view': 'settings.view',\n 'settings.manage': 'settings.manage',\n 'team.view': 'team.view',\n 'team.manage': 'team.manage',\n 'billing.view': 'billing.view',\n 'billing.manage': 'billing.manage',\n 'webhooks.view': 'webhooks.view',\n 'api.view': 'api.view',\n} as const satisfies Record<string, string>;\n\nconst ALL_PERMISSIONS = Object.values(PORTAL_PERMISSIONS);\n\nconst ADMIN_PERMISSIONS = ALL_PERMISSIONS.filter(\n (p) => p !== PORTAL_PERMISSIONS['team.manage']\n);\n\nconst DEVELOPER_PERMISSIONS: string[] = [\n PORTAL_PERMISSIONS['dashboard.view'],\n PORTAL_PERMISSIONS['merchants.view'],\n PORTAL_PERMISSIONS['merchants.manage'],\n PORTAL_PERMISSIONS['settings.view'],\n PORTAL_PERMISSIONS['webhooks.view'],\n PORTAL_PERMISSIONS['api.view'],\n];\n\nconst VIEWER_PERMISSIONS: string[] = [\n PORTAL_PERMISSIONS['dashboard.view'],\n PORTAL_PERMISSIONS['merchants.view'],\n PORTAL_PERMISSIONS['settings.view'],\n PORTAL_PERMISSIONS['billing.view'],\n PORTAL_PERMISSIONS['webhooks.view'],\n PORTAL_PERMISSIONS['api.view'],\n];\n\nexport const ROLE_PERMISSIONS: Record<PortalRole, readonly string[]> = {\n owner: ALL_PERMISSIONS,\n admin: ADMIN_PERMISSIONS,\n developer: DEVELOPER_PERMISSIONS,\n viewer: VIEWER_PERMISSIONS,\n};\n\nexport function getPermissionsForRole(role: PortalRole): string[] {\n return [...ROLE_PERMISSIONS[role]];\n}\n\nexport function hasPermission(role: PortalRole, permission: string): boolean {\n return ROLE_PERMISSIONS[role].includes(permission);\n}\n","/**\n * Portal session store interface and in-memory implementation.\n */\n\nimport type { PortalSessionData } from './types.js';\n\nexport interface PortalSessionStore {\n get(sessionId: string): Promise<PortalSessionData | null>;\n set(sessionId: string, data: PortalSessionData, ttl?: number): Promise<void>;\n delete(sessionId: string): Promise<void>;\n exists(sessionId: string): Promise<boolean>;\n}\n\ninterface StoredEntry {\n data: PortalSessionData;\n expiresAt: number | null;\n}\n\nexport class InMemoryPortalSessionStore implements PortalSessionStore {\n private readonly store = new Map<string, StoredEntry>();\n\n async get(sessionId: string): Promise<PortalSessionData | null> {\n const entry = this.store.get(sessionId);\n if (!entry) {\n return null;\n }\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return null;\n }\n return entry.data;\n }\n\n async set(\n sessionId: string,\n data: PortalSessionData,\n ttl?: number\n ): Promise<void> {\n const expiresAt =\n ttl !== undefined && ttl > 0 ? Date.now() + ttl * 1000 : null;\n this.store.set(sessionId, { data, expiresAt });\n }\n\n async delete(sessionId: string): Promise<void> {\n this.store.delete(sessionId);\n }\n\n async exists(sessionId: string): Promise<boolean> {\n const entry = this.store.get(sessionId);\n if (!entry) {\n return false;\n }\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return false;\n }\n return true;\n }\n}\n","/**\n * Developer authentication service for portal access.\n */\n\nimport type {\n PortalContext,\n PortalTeam,\n PortalUser,\n} from './types.js';\nimport { getPermissionsForRole } from './permissions.js';\nimport type { PortalSessionStore } from './session-store.js';\n\nexport interface PortalAuthConfig {\n validateApiKey: (apiKey: string) => Promise<PortalUser | null>;\n sessionStore: PortalSessionStore;\n getTeam: (teamId: string) => Promise<PortalTeam | null>;\n getUser: (userId: string) => Promise<PortalUser | null>;\n}\n\nexport class DeveloperAuthService {\n private readonly config: PortalAuthConfig;\n\n constructor(config: PortalAuthConfig) {\n this.config = config;\n }\n\n async authenticate(token: string): Promise<PortalUser | null> {\n if (!token) {\n return null;\n }\n return this.config.validateApiKey(token);\n }\n\n async validateApiKey(apiKey: string): Promise<PortalUser | null> {\n if (!apiKey) {\n return null;\n }\n return this.config.validateApiKey(apiKey);\n }\n\n async getPortalContext(userId: string): Promise<PortalContext | null> {\n const user = await this.config.getUser(userId);\n if (!user) {\n return null;\n }\n\n const teamId = user.teamId;\n if (teamId === undefined) {\n return null;\n }\n\n const team = await this.config.getTeam(teamId);\n if (!team) {\n return null;\n }\n\n const permissions = getPermissionsForRole(user.role);\n\n return { user, team, permissions };\n }\n}\n","/**\n * Permission guard for portal access control.\n */\n\nimport type { PortalContext } from './types.js';\n\nexport class PermissionGuardError extends Error {\n public readonly requiredPermission: string;\n\n constructor(permission: string) {\n super(`Missing required permission: ${permission}`);\n this.name = 'PermissionGuardError';\n this.requiredPermission = permission;\n }\n}\n\nexport class PermissionGuard {\n requirePermission(context: PortalContext, permission: string): void {\n if (!context.permissions.includes(permission)) {\n throw new PermissionGuardError(permission);\n }\n }\n\n requireAnyPermission(\n context: PortalContext,\n permissions: string[]\n ): void {\n const hasAny = permissions.some((p) => context.permissions.includes(p));\n if (!hasAny) {\n throw new PermissionGuardError(permissions.join(' | '));\n }\n }\n\n requireAllPermissions(\n context: PortalContext,\n permissions: string[]\n ): void {\n for (const p of permissions) {\n if (!context.permissions.includes(p)) {\n throw new PermissionGuardError(p);\n }\n }\n }\n\n canAccess(context: PortalContext, permission: string): boolean {\n return context.permissions.includes(permission);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,76 @@
1
+ interface DashboardMetrics {
2
+ totalInstalls: number;
3
+ activeMerchants: number;
4
+ monthlyRevenue: string;
5
+ churnRate: number;
6
+ }
7
+ interface DashboardActivity {
8
+ id: string;
9
+ title: string;
10
+ description?: string;
11
+ timestamp: Date;
12
+ type: 'install' | 'uninstall' | 'upgrade' | 'downgrade' | 'payment' | 'error';
13
+ shopDomain?: string;
14
+ }
15
+ type DashboardTimeRange = 'day' | 'week' | 'month' | 'quarter' | 'year';
16
+ interface MetricsSnapshot {
17
+ metrics: DashboardMetrics;
18
+ timestamp: Date;
19
+ timeRange: DashboardTimeRange;
20
+ }
21
+ interface DashboardConfig {
22
+ metricsDataSource: MetricsDataSource;
23
+ activityDataSource: ActivityDataSource;
24
+ defaultTimeRange?: DashboardTimeRange;
25
+ defaultActivityLimit?: number;
26
+ }
27
+ interface MetricsDataSource {
28
+ countShops(filter?: string): Promise<number>;
29
+ countActiveShops(): Promise<number>;
30
+ sumRevenue(since: Date): Promise<number>;
31
+ countChurned(since: Date): Promise<number>;
32
+ getInstallTimeline(range: DashboardTimeRange): Promise<{
33
+ date: string;
34
+ count: number;
35
+ }[]>;
36
+ }
37
+ interface ActivityDataSource {
38
+ getRecentActivities(limit: number): Promise<DashboardActivity[]>;
39
+ getActivitiesByShop(shopDomain: string, limit: number): Promise<DashboardActivity[]>;
40
+ getActivitiesByType(type: string, limit: number): Promise<DashboardActivity[]>;
41
+ }
42
+
43
+ declare class MetricsService {
44
+ private readonly dataSource;
45
+ constructor(dataSource: MetricsDataSource);
46
+ getMetrics(range?: DashboardTimeRange): Promise<DashboardMetrics>;
47
+ getMetricsSnapshot(range?: DashboardTimeRange): Promise<MetricsSnapshot>;
48
+ calculateChurnRate(totalShops: number, churnedShops: number): number;
49
+ formatRevenue(amount: number, currency?: string): string;
50
+ private getStartDate;
51
+ }
52
+
53
+ declare class ActivityService {
54
+ private readonly dataSource;
55
+ constructor(dataSource: ActivityDataSource);
56
+ getRecentActivity(limit?: number): Promise<DashboardActivity[]>;
57
+ getActivityByShop(shopDomain: string, limit?: number): Promise<DashboardActivity[]>;
58
+ getActivityFeed(options?: {
59
+ limit?: number;
60
+ types?: string[];
61
+ shopDomain?: string;
62
+ }): Promise<DashboardActivity[]>;
63
+ }
64
+
65
+ interface DashboardData {
66
+ metrics: DashboardMetrics;
67
+ recentActivity: DashboardActivity[];
68
+ }
69
+ declare class DashboardService {
70
+ private readonly metricsService;
71
+ private readonly activityService;
72
+ constructor(metricsDataSource: MetricsDataSource, activityDataSource: ActivityDataSource);
73
+ getDashboardData(range?: DashboardTimeRange): Promise<DashboardData>;
74
+ }
75
+
76
+ export { type ActivityDataSource, ActivityService, type DashboardActivity, type DashboardConfig, type DashboardData, type DashboardMetrics, DashboardService, type DashboardTimeRange, type MetricsDataSource, MetricsService, type MetricsSnapshot };