@htlkg/core 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -0
- package/dist/amplify-astro-adapter/index.d.ts +109 -0
- package/dist/amplify-astro-adapter/index.js +295 -0
- package/dist/amplify-astro-adapter/index.js.map +1 -0
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +305 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/index.d.ts +220 -0
- package/dist/index.js +426 -1
- package/dist/index.js.map +1 -1
- package/dist/logger-BTW3fOeM.d.ts +45 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +55 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +56 -33
- package/src/amplify-astro-adapter/amplify-astro-adapter.md +167 -0
- package/src/amplify-astro-adapter/createCookieStorageAdapterFromAstroContext.test.ts +296 -0
- package/src/amplify-astro-adapter/createCookieStorageAdapterFromAstroContext.ts +97 -0
- package/src/amplify-astro-adapter/createRunWithAmplifyServerContext.ts +84 -0
- package/src/amplify-astro-adapter/errors.test.ts +115 -0
- package/src/amplify-astro-adapter/errors.ts +105 -0
- package/src/amplify-astro-adapter/globalSettings.test.ts +78 -0
- package/src/amplify-astro-adapter/globalSettings.ts +16 -0
- package/src/amplify-astro-adapter/index.ts +14 -0
- package/src/amplify-astro-adapter/types.ts +55 -0
- package/src/auth/auth.md +178 -0
- package/src/auth/index.test.ts +180 -0
- package/src/auth/index.ts +294 -0
- package/src/constants/constants.md +132 -0
- package/src/constants/index.test.ts +116 -0
- package/src/constants/index.ts +98 -0
- package/src/core-exports.property.test.ts +186 -0
- package/src/errors/errors.md +177 -0
- package/src/errors/index.test.ts +153 -0
- package/src/errors/index.ts +134 -0
- package/src/index.ts +65 -0
- package/src/routes/index.ts +225 -0
- package/src/routes/routes.md +189 -0
- package/src/types/index.ts +94 -0
- package/src/types/types.md +144 -0
- package/src/utils/index.test.ts +257 -0
- package/src/utils/index.ts +112 -0
- package/src/utils/logger.ts +88 -0
- package/src/utils/utils.md +199 -0
- package/src/workspace.property.test.ts +235 -0
package/dist/auth/index.js
CHANGED
|
@@ -1,11 +1,315 @@
|
|
|
1
1
|
// src/auth/index.ts
|
|
2
|
+
import { Amplify } from "aws-amplify";
|
|
2
3
|
import { fetchAuthSession } from "aws-amplify/auth";
|
|
4
|
+
import {
|
|
5
|
+
fetchAuthSession as fetchServerAuthSession,
|
|
6
|
+
getCurrentUser as getServerCurrentUser
|
|
7
|
+
} from "aws-amplify/auth/server";
|
|
8
|
+
|
|
9
|
+
// src/amplify-astro-adapter/createRunWithAmplifyServerContext.ts
|
|
10
|
+
import { sharedInMemoryStorage } from "aws-amplify/utils";
|
|
11
|
+
import {
|
|
12
|
+
createAWSCredentialsAndIdentityIdProvider,
|
|
13
|
+
createKeyValueStorageFromCookieStorageAdapter,
|
|
14
|
+
createUserPoolsTokenProvider,
|
|
15
|
+
runWithAmplifyServerContext as coreRunWithContext
|
|
16
|
+
} from "aws-amplify/adapter-core";
|
|
17
|
+
|
|
18
|
+
// src/amplify-astro-adapter/globalSettings.ts
|
|
19
|
+
var globalSettings = /* @__PURE__ */ (() => {
|
|
20
|
+
let runtimeOptions = {};
|
|
21
|
+
let serverSideAuthEnabled = true;
|
|
22
|
+
let sslOrigin = false;
|
|
23
|
+
return {
|
|
24
|
+
setRuntimeOptions(opts) {
|
|
25
|
+
runtimeOptions = opts ?? {};
|
|
26
|
+
},
|
|
27
|
+
getRuntimeOptions() {
|
|
28
|
+
return runtimeOptions;
|
|
29
|
+
},
|
|
30
|
+
enableServerSideAuth() {
|
|
31
|
+
serverSideAuthEnabled = true;
|
|
32
|
+
},
|
|
33
|
+
isServerSideAuthEnabled() {
|
|
34
|
+
return serverSideAuthEnabled;
|
|
35
|
+
},
|
|
36
|
+
setIsSSLOrigin(v) {
|
|
37
|
+
sslOrigin = v;
|
|
38
|
+
},
|
|
39
|
+
isSSLOrigin() {
|
|
40
|
+
return sslOrigin;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
|
|
45
|
+
// src/utils/logger.ts
|
|
46
|
+
var isDebugEnabled = () => {
|
|
47
|
+
if (typeof process !== "undefined" && process.env) {
|
|
48
|
+
return process.env.DEBUG === "true" || process.env.HTLKG_DEBUG === "true" || process.env.DEBUG === "*";
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
if (typeof import.meta !== "undefined" && import.meta.env) {
|
|
52
|
+
return import.meta.env.DEBUG === "true" || // @ts-ignore
|
|
53
|
+
import.meta.env.HTLKG_DEBUG === "true" || // @ts-ignore
|
|
54
|
+
import.meta.env.DEV === true;
|
|
55
|
+
}
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
};
|
|
60
|
+
var formatMessage = (namespace, message) => {
|
|
61
|
+
return `[${namespace}] ${message}`;
|
|
62
|
+
};
|
|
63
|
+
var logger = {
|
|
64
|
+
/**
|
|
65
|
+
* Debug log - only shown when DEBUG=true
|
|
66
|
+
*/
|
|
67
|
+
debug(namespace, message, ...args) {
|
|
68
|
+
if (isDebugEnabled()) {
|
|
69
|
+
console.log(formatMessage(namespace, message), ...args);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Info log - always shown
|
|
74
|
+
*/
|
|
75
|
+
info(namespace, message, ...args) {
|
|
76
|
+
console.info(formatMessage(namespace, message), ...args);
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Warning log - always shown
|
|
80
|
+
*/
|
|
81
|
+
warn(namespace, message, ...args) {
|
|
82
|
+
console.warn(formatMessage(namespace, message), ...args);
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* Error log - always shown
|
|
86
|
+
*/
|
|
87
|
+
error(namespace, message, ...args) {
|
|
88
|
+
console.error(formatMessage(namespace, message), ...args);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
var createLogger = (namespace) => ({
|
|
92
|
+
debug: (message, ...args) => logger.debug(namespace, message, ...args),
|
|
93
|
+
info: (message, ...args) => logger.info(namespace, message, ...args),
|
|
94
|
+
warn: (message, ...args) => logger.warn(namespace, message, ...args),
|
|
95
|
+
error: (message, ...args) => logger.error(namespace, message, ...args)
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// src/amplify-astro-adapter/createCookieStorageAdapterFromAstroContext.ts
|
|
99
|
+
var log = createLogger("cookie-storage-adapter");
|
|
100
|
+
function ensureEncodedForJSCookie(name) {
|
|
101
|
+
return encodeURIComponent(name).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent);
|
|
102
|
+
}
|
|
103
|
+
function parseCookieHeader(cookieHeader) {
|
|
104
|
+
const out = {};
|
|
105
|
+
if (!cookieHeader) return out;
|
|
106
|
+
for (const part of cookieHeader.split(";")) {
|
|
107
|
+
const [rawName, ...rest] = part.trim().split("=");
|
|
108
|
+
const name = decodeURIComponent(rawName || "");
|
|
109
|
+
const value = decodeURIComponent(rest.join("=") || "");
|
|
110
|
+
if (name) out[name] = value;
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
function mapSameSite(s) {
|
|
115
|
+
if (s === true) return "strict";
|
|
116
|
+
if (s === false) return "lax";
|
|
117
|
+
if (s === "lax" || s === "strict" || s === "none") return s;
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
async function createCookieStorageAdapterFromAstroContext(astroServerContext) {
|
|
121
|
+
if (astroServerContext === null) {
|
|
122
|
+
log.debug("Context is null, returning no-op adapter");
|
|
123
|
+
return {
|
|
124
|
+
get: () => void 0,
|
|
125
|
+
getAll: () => [],
|
|
126
|
+
set: () => {
|
|
127
|
+
},
|
|
128
|
+
delete: () => {
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const { cookies, request } = astroServerContext;
|
|
133
|
+
const cookieHeader = request?.headers?.get("cookie");
|
|
134
|
+
const headerCookies = parseCookieHeader(cookieHeader ?? null);
|
|
135
|
+
const cookieNames = Object.keys(headerCookies);
|
|
136
|
+
const cognitoCookies = cookieNames.filter((name) => name.includes("CognitoIdentityServiceProvider"));
|
|
137
|
+
log.debug("Available cookies:", cookieNames.length);
|
|
138
|
+
log.debug("Cognito cookies found:", cognitoCookies.length);
|
|
139
|
+
if (cognitoCookies.length > 0) {
|
|
140
|
+
log.debug("Cognito cookie names:", cognitoCookies);
|
|
141
|
+
}
|
|
142
|
+
const adapter = {
|
|
143
|
+
get(name) {
|
|
144
|
+
const encodedName = ensureEncodedForJSCookie(name);
|
|
145
|
+
const v = cookies?.get(encodedName)?.value ?? headerCookies[encodedName] ?? headerCookies[name];
|
|
146
|
+
if (name.includes("accessToken") || name.includes("idToken") || name.includes("refreshToken") || name.includes("LastAuthUser")) {
|
|
147
|
+
log.debug(`get('${name}'): ${v ? "FOUND" : "NOT FOUND"}`);
|
|
148
|
+
}
|
|
149
|
+
return v ? { name, value: v } : void 0;
|
|
150
|
+
},
|
|
151
|
+
getAll() {
|
|
152
|
+
const fromAPI = typeof cookies?.getAll === "function" ? cookies.getAll().map((c) => ({ name: c.name, value: c.value })) : Object.entries(headerCookies).map(([name, value]) => ({ name, value }));
|
|
153
|
+
return fromAPI;
|
|
154
|
+
},
|
|
155
|
+
set(name, value, options) {
|
|
156
|
+
try {
|
|
157
|
+
cookies.set(name, value, {
|
|
158
|
+
...options ?? {},
|
|
159
|
+
sameSite: mapSameSite(options?.sameSite)
|
|
160
|
+
});
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
delete(name) {
|
|
165
|
+
try {
|
|
166
|
+
cookies.delete(name);
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
return adapter;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/amplify-astro-adapter/createRunWithAmplifyServerContext.ts
|
|
175
|
+
var log2 = createLogger("amplify-server-context");
|
|
176
|
+
var createRunWithAmplifyServerContext = ({
|
|
177
|
+
config: resourcesConfig,
|
|
178
|
+
globalSettings: globalSettings2 = globalSettings
|
|
179
|
+
}) => {
|
|
180
|
+
const isServerSideAuthEnabled = globalSettings2.isServerSideAuthEnabled();
|
|
181
|
+
const isSSLOrigin = globalSettings2.isSSLOrigin();
|
|
182
|
+
const setCookieOptions = globalSettings2.getRuntimeOptions().cookies ?? {};
|
|
183
|
+
log2.debug("Settings:", {
|
|
184
|
+
isServerSideAuthEnabled,
|
|
185
|
+
isSSLOrigin,
|
|
186
|
+
hasCookieOptions: Object.keys(setCookieOptions).length > 0
|
|
187
|
+
});
|
|
188
|
+
const mergedSetCookieOptions = {
|
|
189
|
+
...isServerSideAuthEnabled && { httpOnly: true, sameSite: "lax" },
|
|
190
|
+
...setCookieOptions,
|
|
191
|
+
...isServerSideAuthEnabled && { secure: isSSLOrigin },
|
|
192
|
+
path: "/"
|
|
193
|
+
};
|
|
194
|
+
const runWithContext = async ({
|
|
195
|
+
astroServerContext,
|
|
196
|
+
operation
|
|
197
|
+
}) => {
|
|
198
|
+
if (resourcesConfig.Auth) {
|
|
199
|
+
const cookieAdapter = await createCookieStorageAdapterFromAstroContext(astroServerContext);
|
|
200
|
+
const keyValueStorage = astroServerContext === null ? sharedInMemoryStorage : createKeyValueStorageFromCookieStorageAdapter(
|
|
201
|
+
cookieAdapter,
|
|
202
|
+
void 0,
|
|
203
|
+
mergedSetCookieOptions
|
|
204
|
+
);
|
|
205
|
+
const credentialsProvider = createAWSCredentialsAndIdentityIdProvider(
|
|
206
|
+
resourcesConfig.Auth,
|
|
207
|
+
keyValueStorage
|
|
208
|
+
);
|
|
209
|
+
const tokenProvider = createUserPoolsTokenProvider(
|
|
210
|
+
resourcesConfig.Auth,
|
|
211
|
+
keyValueStorage
|
|
212
|
+
);
|
|
213
|
+
return coreRunWithContext(
|
|
214
|
+
resourcesConfig,
|
|
215
|
+
{ Auth: { credentialsProvider, tokenProvider } },
|
|
216
|
+
operation
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
return coreRunWithContext(resourcesConfig, {}, operation);
|
|
220
|
+
};
|
|
221
|
+
return runWithContext;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// src/auth/index.ts
|
|
3
225
|
function parseIds(ids) {
|
|
4
226
|
if (!ids) return [];
|
|
5
227
|
return ids.split(",").map((id) => Number.parseInt(id.trim(), 10)).filter((id) => !Number.isNaN(id));
|
|
6
228
|
}
|
|
229
|
+
var amplifyConfigured = false;
|
|
230
|
+
function ensureAmplifyConfigured() {
|
|
231
|
+
if (amplifyConfigured) return;
|
|
232
|
+
try {
|
|
233
|
+
const config = Amplify.getConfig();
|
|
234
|
+
if (!config.Auth) {
|
|
235
|
+
throw new Error("Amplify Auth not configured");
|
|
236
|
+
}
|
|
237
|
+
amplifyConfigured = true;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
240
|
+
console.error(`[Auth] Amplify not configured: ${errorMsg}`);
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
7
244
|
async function getUser(context) {
|
|
8
|
-
|
|
245
|
+
try {
|
|
246
|
+
ensureAmplifyConfigured();
|
|
247
|
+
const amplifyConfig = Amplify.getConfig();
|
|
248
|
+
const runWithAmplifyServerContext = createRunWithAmplifyServerContext({
|
|
249
|
+
config: amplifyConfig,
|
|
250
|
+
globalSettings
|
|
251
|
+
});
|
|
252
|
+
const astroServerContext = {
|
|
253
|
+
cookies: context.cookies,
|
|
254
|
+
request: context.request
|
|
255
|
+
};
|
|
256
|
+
const user = await runWithAmplifyServerContext({
|
|
257
|
+
astroServerContext,
|
|
258
|
+
operation: async (contextSpec) => {
|
|
259
|
+
try {
|
|
260
|
+
const currentUser = await getServerCurrentUser(contextSpec);
|
|
261
|
+
const session = await fetchServerAuthSession(contextSpec);
|
|
262
|
+
if (!session.tokens?.accessToken) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
const accessPayload = session.tokens.accessToken.payload;
|
|
266
|
+
const idPayload = session.tokens.idToken?.payload;
|
|
267
|
+
const email = idPayload?.email || accessPayload.email || "";
|
|
268
|
+
const brandIds = parseIds(
|
|
269
|
+
accessPayload["custom:brand_ids"]
|
|
270
|
+
);
|
|
271
|
+
const accountIds = parseIds(
|
|
272
|
+
accessPayload["custom:account_ids"]
|
|
273
|
+
);
|
|
274
|
+
const groups = accessPayload["cognito:groups"] || [];
|
|
275
|
+
const isAdmin = groups.includes("admin") || groups.includes("ADMINS") || groups.includes("SUPER_ADMINS");
|
|
276
|
+
const isSuperAdmin = groups.includes("SUPER_ADMINS");
|
|
277
|
+
return {
|
|
278
|
+
username: currentUser.username,
|
|
279
|
+
email,
|
|
280
|
+
brandIds,
|
|
281
|
+
accountIds,
|
|
282
|
+
isAdmin,
|
|
283
|
+
isSuperAdmin,
|
|
284
|
+
roles: groups
|
|
285
|
+
};
|
|
286
|
+
} catch (error) {
|
|
287
|
+
if (error instanceof Error && error.name !== "UserUnAuthenticatedException") {
|
|
288
|
+
console.error(
|
|
289
|
+
"[Auth] Error in server context:",
|
|
290
|
+
error.name,
|
|
291
|
+
"-",
|
|
292
|
+
error.message.replace(/token[=:]\s*[^\s,}]+/gi, "token=***")
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
return user;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
if (error instanceof Error) {
|
|
302
|
+
console.error(
|
|
303
|
+
"[Auth] Server-side auth error:",
|
|
304
|
+
error.name,
|
|
305
|
+
"-",
|
|
306
|
+
error.message.replace(/token[=:]\s*[^\s,}]+/gi, "token=***")
|
|
307
|
+
);
|
|
308
|
+
} else {
|
|
309
|
+
console.error("[Auth] Server-side auth error: Unknown error");
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
9
313
|
}
|
|
10
314
|
async function getClientUser() {
|
|
11
315
|
try {
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["/**\n * @htlkg/core/auth\n * Core authentication functions and utilities\n */\n\nimport type { APIContext } from \"astro\";\nimport { Amplify } from \"aws-amplify\";\nimport { fetchAuthSession } from \"aws-amplify/auth\";\nimport {\n\tfetchAuthSession as fetchServerAuthSession,\n\tgetCurrentUser as getServerCurrentUser,\n} from \"aws-amplify/auth/server\";\n\n// Re-export types\nexport type { APIContext } from \"astro\";\n\n/**\n * User interface representing an authenticated user\n */\nexport interface User {\n\tusername: string;\n\temail: string;\n\tbrandIds: number[];\n\taccountIds: number[];\n\tisAdmin: boolean;\n\tisSuperAdmin: boolean;\n\troles: string[];\n}\n\n/**\n * Parse comma-separated IDs from Cognito custom attributes\n */\nfunction parseIds(ids: string | undefined): number[] {\n\tif (!ids) return [];\n\treturn ids\n\t\t.split(\",\")\n\t\t.map((id) => Number.parseInt(id.trim(), 10))\n\t\t.filter((id) => !Number.isNaN(id));\n}\n\n/**\n * Get current authenticated user (server-side)\n * This is a simplified version that will be enhanced with Amplify server context\n */\nexport async function getUser(context: APIContext): Promise<User | null> {\n\t// This is a placeholder - the full implementation will be in the integration layer\n\t// that has access to the Amplify server context utilities\n\treturn null;\n}\n\n/**\n * Get current authenticated user (client-side)\n */\nexport async function getClientUser(): Promise<User | null> {\n\ttry {\n\t\tconst session = await fetchAuthSession();\n\n\t\tif (!session.tokens?.accessToken) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst accessPayload = session.tokens.accessToken.payload;\n\t\tconst idPayload = session.tokens.idToken?.payload;\n\n\t\tconst email =\n\t\t\t(idPayload?.email as string) || (accessPayload.email as string) || \"\";\n\t\tconst brandIds = parseIds(accessPayload[\"custom:brand_ids\"] as string);\n\t\tconst accountIds = parseIds(accessPayload[\"custom:account_ids\"] as string);\n\n\t\tconst groups = (accessPayload[\"cognito:groups\"] as string[]) || [];\n\t\tconst isAdmin =\n\t\t\tgroups.includes(\"admin\") ||\n\t\t\tgroups.includes(\"ADMINS\") ||\n\t\t\tgroups.includes(\"SUPER_ADMINS\");\n\t\tconst isSuperAdmin = groups.includes(\"SUPER_ADMINS\");\n\n\t\treturn {\n\t\t\tusername: (accessPayload.username as string) || \"\",\n\t\t\temail,\n\t\t\tbrandIds,\n\t\t\taccountIds,\n\t\t\tisAdmin,\n\t\t\tisSuperAdmin,\n\t\t\troles: groups,\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tconsole.error(\n\t\t\t\t\"[Auth] Client auth error:\",\n\t\t\t\terror.name,\n\t\t\t\t\"-\",\n\t\t\t\terror.message.replace(/token[=:]\\s*[^\\s,}]+/gi, \"token=***\"),\n\t\t\t);\n\t\t}\n\t\treturn null;\n\t}\n}\n\n/**\n * Check if user has access to a specific brand\n */\nexport function hasAccessToBrand(\n\tuser: User | null,\n\tbrandId: number,\n): boolean {\n\tif (!user) return false;\n\tif (user.isAdmin) return true;\n\treturn user.brandIds.includes(brandId);\n}\n\n/**\n * Check if user has access to a specific account\n */\nexport function hasAccessToAccount(\n\tuser: User | null,\n\taccountId: number,\n): boolean {\n\tif (!user) return false;\n\tif (user.isAdmin) return true;\n\treturn user.accountIds.includes(accountId);\n}\n\n/**\n * Check if user is an admin\n */\nexport function isAdminUser(user: User | null): boolean {\n\treturn user?.isAdmin || false;\n}\n\n/**\n * Check if user is a super admin\n */\nexport function isSuperAdminUser(user: User | null): boolean {\n\treturn user?.isSuperAdmin || false;\n}\n\n/**\n * Placeholder for requireAuth - will be implemented in @htlkg/integrations\n * This is here for type exports and documentation\n */\nexport async function requireAuth(\n\tcontext: APIContext,\n\tloginUrl?: string,\n): Promise<{ success: boolean; user?: User; redirectTo?: string }> {\n\tthrow new Error(\n\t\t\"requireAuth should be imported from @htlkg/astro/middleware\",\n\t);\n}\n\n/**\n * Placeholder for requireAdminAccess - will be implemented in @htlkg/integrations\n */\nexport async function requireAdminAccess(\n\tcontext: APIContext,\n\tloginUrl?: string,\n): Promise<{ success: boolean; user?: User; redirectTo?: string }> {\n\tthrow new Error(\n\t\t\"requireAdminAccess should be imported from @htlkg/astro/middleware\",\n\t);\n}\n\n/**\n * Placeholder for requireBrandAccess - will be implemented in @htlkg/integrations\n */\nexport async function requireBrandAccess(\n\tcontext: APIContext,\n\tbrandId: number,\n\tloginUrl?: string,\n): Promise<{ success: boolean; user?: User; redirectTo?: string }> {\n\tthrow new Error(\n\t\t\"requireBrandAccess should be imported from @htlkg/astro/middleware\",\n\t);\n}\n"],"mappings":";AAOA,SAAS,wBAAwB;AAyBjC,SAAS,SAAS,KAAmC;AACpD,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,SAAO,IACL,MAAM,GAAG,EACT,IAAI,CAAC,OAAO,OAAO,SAAS,GAAG,KAAK,GAAG,EAAE,CAAC,EAC1C,OAAO,CAAC,OAAO,CAAC,OAAO,MAAM,EAAE,CAAC;AACnC;AAMA,eAAsB,QAAQ,SAA2C;AAGxE,SAAO;AACR;AAKA,eAAsB,gBAAsC;AAC3D,MAAI;AACH,UAAM,UAAU,MAAM,iBAAiB;AAEvC,QAAI,CAAC,QAAQ,QAAQ,aAAa;AACjC,aAAO;AAAA,IACR;AAEA,UAAM,gBAAgB,QAAQ,OAAO,YAAY;AACjD,UAAM,YAAY,QAAQ,OAAO,SAAS;AAE1C,UAAM,QACJ,WAAW,SAAqB,cAAc,SAAoB;AACpE,UAAM,WAAW,SAAS,cAAc,kBAAkB,CAAW;AACrE,UAAM,aAAa,SAAS,cAAc,oBAAoB,CAAW;AAEzE,UAAM,SAAU,cAAc,gBAAgB,KAAkB,CAAC;AACjE,UAAM,UACL,OAAO,SAAS,OAAO,KACvB,OAAO,SAAS,QAAQ,KACxB,OAAO,SAAS,cAAc;AAC/B,UAAM,eAAe,OAAO,SAAS,cAAc;AAEnD,WAAO;AAAA,MACN,UAAW,cAAc,YAAuB;AAAA,MAChD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACR;AAAA,EACD,SAAS,OAAO;AACf,QAAI,iBAAiB,OAAO;AAC3B,cAAQ;AAAA,QACP;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA,MAAM,QAAQ,QAAQ,0BAA0B,WAAW;AAAA,MAC5D;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAKO,SAAS,iBACf,MACA,SACU;AACV,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,QAAS,QAAO;AACzB,SAAO,KAAK,SAAS,SAAS,OAAO;AACtC;AAKO,SAAS,mBACf,MACA,WACU;AACV,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,QAAS,QAAO;AACzB,SAAO,KAAK,WAAW,SAAS,SAAS;AAC1C;AAKO,SAAS,YAAY,MAA4B;AACvD,SAAO,MAAM,WAAW;AACzB;AAKO,SAAS,iBAAiB,MAA4B;AAC5D,SAAO,MAAM,gBAAgB;AAC9B;AAMA,eAAsB,YACrB,SACA,UACkE;AAClE,QAAM,IAAI;AAAA,IACT;AAAA,EACD;AACD;AAKA,eAAsB,mBACrB,SACA,UACkE;AAClE,QAAM,IAAI;AAAA,IACT;AAAA,EACD;AACD;AAKA,eAAsB,mBACrB,SACA,SACA,UACkE;AAClE,QAAM,IAAI;AAAA,IACT;AAAA,EACD;AACD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/auth/index.ts","../../src/amplify-astro-adapter/createRunWithAmplifyServerContext.ts","../../src/amplify-astro-adapter/globalSettings.ts","../../src/utils/logger.ts","../../src/amplify-astro-adapter/createCookieStorageAdapterFromAstroContext.ts"],"sourcesContent":["/**\n * @htlkg/core/auth\n * Core authentication functions and utilities\n */\n\nimport type { APIContext } from \"astro\";\nimport { Amplify } from \"aws-amplify\";\nimport { fetchAuthSession } from \"aws-amplify/auth\";\nimport {\n\tfetchAuthSession as fetchServerAuthSession,\n\tgetCurrentUser as getServerCurrentUser,\n} from \"aws-amplify/auth/server\";\nimport { createRunWithAmplifyServerContext, globalSettings } from \"../amplify-astro-adapter\";\n\n// Re-export types\nexport type { APIContext } from \"astro\";\n\n/**\n * User interface representing an authenticated user\n */\nexport interface User {\n\tusername: string;\n\temail: string;\n\tbrandIds: number[];\n\taccountIds: number[];\n\tisAdmin: boolean;\n\tisSuperAdmin: boolean;\n\troles: string[];\n}\n\n/**\n * Parse comma-separated IDs from Cognito custom attributes\n */\nfunction parseIds(ids: string | undefined): number[] {\n\tif (!ids) return [];\n\treturn ids\n\t\t.split(\",\")\n\t\t.map((id) => Number.parseInt(id.trim(), 10))\n\t\t.filter((id) => !Number.isNaN(id));\n}\n\n// Track if Amplify has been configured\nlet amplifyConfigured = false;\n\n/**\n * Configure Amplify on first use (server-side)\n * This must be called before any auth operations\n */\nfunction ensureAmplifyConfigured(): void {\n\tif (amplifyConfigured) return;\n\n\ttry {\n\t\t// Amplify should already be configured by the middleware\n\t\t// This is just a safety check\n\t\tconst config = Amplify.getConfig();\n\t\tif (!config.Auth) {\n\t\t\tthrow new Error(\"Amplify Auth not configured\");\n\t\t}\n\t\tamplifyConfigured = true;\n\t} catch (error) {\n\t\tconst errorMsg = error instanceof Error ? error.message : \"Unknown error\";\n\t\tconsole.error(`[Auth] Amplify not configured: ${errorMsg}`);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Get current authenticated user (server-side)\n * Reads Amplify auth cookies from the request and validates the session\n */\nexport async function getUser(context: APIContext): Promise<User | null> {\n\ttry {\n\t\tensureAmplifyConfigured();\n\t\t\n\t\t// Get the current Amplify configuration\n\t\tconst amplifyConfig = Amplify.getConfig();\n\n\t\t// Create the server context runner - pass globalSettings explicitly\n\t\t// to ensure the same instance is used across all modules\n\t\tconst runWithAmplifyServerContext = createRunWithAmplifyServerContext({\n\t\t\tconfig: amplifyConfig,\n\t\t\tglobalSettings,\n\t\t});\n\n\t\t// Create Astro server context\n\t\tconst astroServerContext = {\n\t\t\tcookies: context.cookies,\n\t\t\trequest: context.request,\n\t\t};\n\n\t\t// Run in Amplify server context\n\t\tconst user = await runWithAmplifyServerContext({\n\t\t\tastroServerContext,\n\t\t\toperation: async (contextSpec) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst currentUser = await getServerCurrentUser(contextSpec as any);\n\t\t\t\t\tconst session = await fetchServerAuthSession(contextSpec as any);\n\n\t\t\t\t\tif (!session.tokens?.accessToken) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst accessPayload = session.tokens.accessToken.payload;\n\t\t\t\t\tconst idPayload = session.tokens.idToken?.payload;\n\n\t\t\t\t\t// Parse user attributes - email is typically in ID token, not access token\n\t\t\t\t\tconst email =\n\t\t\t\t\t\t(idPayload?.email as string) ||\n\t\t\t\t\t\t(accessPayload.email as string) ||\n\t\t\t\t\t\t\"\";\n\t\t\t\t\tconst brandIds = parseIds(\n\t\t\t\t\t\taccessPayload[\"custom:brand_ids\"] as string,\n\t\t\t\t\t);\n\t\t\t\t\tconst accountIds = parseIds(\n\t\t\t\t\t\taccessPayload[\"custom:account_ids\"] as string,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Check admin status\n\t\t\t\t\tconst groups = (accessPayload[\"cognito:groups\"] as string[]) || [];\n\t\t\t\t\tconst isAdmin =\n\t\t\t\t\t\tgroups.includes(\"admin\") ||\n\t\t\t\t\t\tgroups.includes(\"ADMINS\") ||\n\t\t\t\t\t\tgroups.includes(\"SUPER_ADMINS\");\n\t\t\t\t\tconst isSuperAdmin = groups.includes(\"SUPER_ADMINS\");\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tusername: currentUser.username,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\tbrandIds,\n\t\t\t\t\t\taccountIds,\n\t\t\t\t\t\tisAdmin,\n\t\t\t\t\t\tisSuperAdmin,\n\t\t\t\t\t\troles: groups,\n\t\t\t\t\t};\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// UserUnAuthenticatedException is expected when user is not logged in\n\t\t\t\t\t// Only log other errors without sensitive data\n\t\t\t\t\tif (\n\t\t\t\t\t\terror instanceof Error &&\n\t\t\t\t\t\terror.name !== \"UserUnAuthenticatedException\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Log error name and message without stack trace or sensitive data\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\"[Auth] Error in server context:\",\n\t\t\t\t\t\t\terror.name,\n\t\t\t\t\t\t\t\"-\",\n\t\t\t\t\t\t\terror.message.replace(/token[=:]\\s*[^\\s,}]+/gi, \"token=***\"),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\treturn user;\n\t} catch (error) {\n\t\t// Log error without exposing sensitive information\n\t\tif (error instanceof Error) {\n\t\t\tconsole.error(\n\t\t\t\t\"[Auth] Server-side auth error:\",\n\t\t\t\terror.name,\n\t\t\t\t\"-\",\n\t\t\t\terror.message.replace(/token[=:]\\s*[^\\s,}]+/gi, \"token=***\"),\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.error(\"[Auth] Server-side auth error: Unknown error\");\n\t\t}\n\t\treturn null;\n\t}\n}\n\n/**\n * Get current authenticated user (client-side)\n */\nexport async function getClientUser(): Promise<User | null> {\n\ttry {\n\t\tconst session = await fetchAuthSession();\n\n\t\tif (!session.tokens?.accessToken) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst accessPayload = session.tokens.accessToken.payload;\n\t\tconst idPayload = session.tokens.idToken?.payload;\n\n\t\tconst email =\n\t\t\t(idPayload?.email as string) || (accessPayload.email as string) || \"\";\n\t\tconst brandIds = parseIds(accessPayload[\"custom:brand_ids\"] as string);\n\t\tconst accountIds = parseIds(accessPayload[\"custom:account_ids\"] as string);\n\n\t\tconst groups = (accessPayload[\"cognito:groups\"] as string[]) || [];\n\t\tconst isAdmin =\n\t\t\tgroups.includes(\"admin\") ||\n\t\t\tgroups.includes(\"ADMINS\") ||\n\t\t\tgroups.includes(\"SUPER_ADMINS\");\n\t\tconst isSuperAdmin = groups.includes(\"SUPER_ADMINS\");\n\n\t\treturn {\n\t\t\tusername: (accessPayload.username as string) || \"\",\n\t\t\temail,\n\t\t\tbrandIds,\n\t\t\taccountIds,\n\t\t\tisAdmin,\n\t\t\tisSuperAdmin,\n\t\t\troles: groups,\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tconsole.error(\n\t\t\t\t\"[Auth] Client auth error:\",\n\t\t\t\terror.name,\n\t\t\t\t\"-\",\n\t\t\t\terror.message.replace(/token[=:]\\s*[^\\s,}]+/gi, \"token=***\"),\n\t\t\t);\n\t\t}\n\t\treturn null;\n\t}\n}\n\n/**\n * Check if user has access to a specific brand\n */\nexport function hasAccessToBrand(\n\tuser: User | null,\n\tbrandId: number,\n): boolean {\n\tif (!user) return false;\n\tif (user.isAdmin) return true;\n\treturn user.brandIds.includes(brandId);\n}\n\n/**\n * Check if user has access to a specific account\n */\nexport function hasAccessToAccount(\n\tuser: User | null,\n\taccountId: number,\n): boolean {\n\tif (!user) return false;\n\tif (user.isAdmin) return true;\n\treturn user.accountIds.includes(accountId);\n}\n\n/**\n * Check if user is an admin\n */\nexport function isAdminUser(user: User | null): boolean {\n\treturn user?.isAdmin || false;\n}\n\n/**\n * Check if user is a super admin\n */\nexport function isSuperAdminUser(user: User | null): boolean {\n\treturn user?.isSuperAdmin || false;\n}\n\n/**\n * Placeholder for requireAuth - will be implemented in @htlkg/integrations\n * This is here for type exports and documentation\n */\nexport async function requireAuth(\n\tcontext: APIContext,\n\tloginUrl?: string,\n): Promise<{ success: boolean; user?: User; redirectTo?: string }> {\n\tthrow new Error(\n\t\t\"requireAuth should be imported from @htlkg/astro/middleware\",\n\t);\n}\n\n/**\n * Placeholder for requireAdminAccess - will be implemented in @htlkg/integrations\n */\nexport async function requireAdminAccess(\n\tcontext: APIContext,\n\tloginUrl?: string,\n): Promise<{ success: boolean; user?: User; redirectTo?: string }> {\n\tthrow new Error(\n\t\t\"requireAdminAccess should be imported from @htlkg/astro/middleware\",\n\t);\n}\n\n/**\n * Placeholder for requireBrandAccess - will be implemented in @htlkg/integrations\n */\nexport async function requireBrandAccess(\n\tcontext: APIContext,\n\tbrandId: number,\n\tloginUrl?: string,\n): Promise<{ success: boolean; user?: User; redirectTo?: string }> {\n\tthrow new Error(\n\t\t\"requireBrandAccess should be imported from @htlkg/astro/middleware\",\n\t);\n}\n","import type { ResourcesConfig } from 'aws-amplify';\nimport { sharedInMemoryStorage } from 'aws-amplify/utils';\nimport {\n createAWSCredentialsAndIdentityIdProvider,\n createKeyValueStorageFromCookieStorageAdapter,\n createUserPoolsTokenProvider,\n runWithAmplifyServerContext as coreRunWithContext,\n} from 'aws-amplify/adapter-core';\n\nimport type { AstroServer } from './types';\nimport { globalSettings as defaultGlobalSettings } from './globalSettings';\nimport { createCookieStorageAdapterFromAstroContext } from './createCookieStorageAdapterFromAstroContext';\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('amplify-server-context');\n\n/**\n * Creates a function that runs operations within the Amplify server context.\n *\n * IMPORTANT: Pass globalSettings explicitly to avoid module singleton issues\n * when using linked packages or different bundling contexts.\n */\nexport const createRunWithAmplifyServerContext = ({\n config: resourcesConfig,\n globalSettings = defaultGlobalSettings,\n}: {\n config: ResourcesConfig;\n globalSettings?: AstroServer.GlobalSettings;\n}): AstroServer.RunOperationWithContext => {\n const isServerSideAuthEnabled = globalSettings.isServerSideAuthEnabled();\n const isSSLOrigin = globalSettings.isSSLOrigin();\n const setCookieOptions = globalSettings.getRuntimeOptions().cookies ?? {};\n\n log.debug('Settings:', {\n isServerSideAuthEnabled,\n isSSLOrigin,\n hasCookieOptions: Object.keys(setCookieOptions).length > 0,\n });\n \n const mergedSetCookieOptions = {\n ...(isServerSideAuthEnabled && { httpOnly: true, sameSite: 'lax' as const }),\n ...setCookieOptions,\n ...(isServerSideAuthEnabled && { secure: isSSLOrigin }),\n path: '/',\n };\n\n const runWithContext: AstroServer.RunOperationWithContext = async ({\n astroServerContext,\n operation,\n }) => {\n if (resourcesConfig.Auth) {\n const cookieAdapter = await createCookieStorageAdapterFromAstroContext(astroServerContext);\n \n const keyValueStorage =\n astroServerContext === null\n ? sharedInMemoryStorage\n : createKeyValueStorageFromCookieStorageAdapter(\n cookieAdapter,\n undefined,\n mergedSetCookieOptions\n );\n\n const credentialsProvider = createAWSCredentialsAndIdentityIdProvider(\n resourcesConfig.Auth,\n keyValueStorage\n );\n \n const tokenProvider = createUserPoolsTokenProvider(\n resourcesConfig.Auth,\n keyValueStorage\n );\n\n return coreRunWithContext(\n resourcesConfig,\n { Auth: { credentialsProvider, tokenProvider } },\n operation\n );\n }\n\n return coreRunWithContext(resourcesConfig, {}, operation);\n };\n\n return runWithContext;\n};\n","import type { AstroServer } from './types';\n\nexport const globalSettings: AstroServer.GlobalSettings = (() => {\n let runtimeOptions: AstroServer.RuntimeOptions = {};\n let serverSideAuthEnabled = true;\n let sslOrigin = false;\n\n return {\n setRuntimeOptions(opts) { runtimeOptions = opts ?? {}; },\n getRuntimeOptions() { return runtimeOptions; },\n enableServerSideAuth() { serverSideAuthEnabled = true; },\n isServerSideAuthEnabled() { return serverSideAuthEnabled; },\n setIsSSLOrigin(v: boolean) { sslOrigin = v; },\n isSSLOrigin() { return sslOrigin; },\n };\n})();\n","/**\n * Simple debug logger utility\n * \n * Debug logs are only shown when DEBUG=true or HTLKG_DEBUG=true is set in environment.\n * Info logs are always shown.\n * \n * @example\n * ```typescript\n * import { logger } from '@htlkg/core/utils/logger';\n * \n * logger.debug('server-client', 'Detailed debug info', { data });\n * logger.info('server-client', 'Important info message');\n * logger.warn('server-client', 'Warning message');\n * logger.error('server-client', 'Error occurred', error);\n * ```\n */\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst isDebugEnabled = (): boolean => {\n // Check Node.js environment variables\n if (typeof process !== 'undefined' && process.env) {\n return process.env.DEBUG === 'true' || \n process.env.HTLKG_DEBUG === 'true' ||\n process.env.DEBUG === '*';\n }\n // Browser/Vite environment - check for DEV mode\n try {\n // @ts-ignore - import.meta.env is Vite-specific\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n // @ts-ignore\n return import.meta.env.DEBUG === 'true' || \n // @ts-ignore\n import.meta.env.HTLKG_DEBUG === 'true' ||\n // @ts-ignore\n import.meta.env.DEV === true;\n }\n } catch {\n // Ignore errors accessing import.meta\n }\n return false;\n};\n\nconst formatMessage = (namespace: string, message: string): string => {\n return `[${namespace}] ${message}`;\n};\n\nexport const logger = {\n /**\n * Debug log - only shown when DEBUG=true\n */\n debug(namespace: string, message: string, ...args: unknown[]): void {\n if (isDebugEnabled()) {\n console.log(formatMessage(namespace, message), ...args);\n }\n },\n\n /**\n * Info log - always shown\n */\n info(namespace: string, message: string, ...args: unknown[]): void {\n console.info(formatMessage(namespace, message), ...args);\n },\n\n /**\n * Warning log - always shown\n */\n warn(namespace: string, message: string, ...args: unknown[]): void {\n console.warn(formatMessage(namespace, message), ...args);\n },\n\n /**\n * Error log - always shown\n */\n error(namespace: string, message: string, ...args: unknown[]): void {\n console.error(formatMessage(namespace, message), ...args);\n },\n};\n\n/**\n * Create a namespaced logger for a specific module\n */\nexport const createLogger = (namespace: string) => ({\n debug: (message: string, ...args: unknown[]) => logger.debug(namespace, message, ...args),\n info: (message: string, ...args: unknown[]) => logger.info(namespace, message, ...args),\n warn: (message: string, ...args: unknown[]) => logger.warn(namespace, message, ...args),\n error: (message: string, ...args: unknown[]) => logger.error(namespace, message, ...args),\n});\n","import type { CookieStorage } from 'aws-amplify/adapter-core';\nimport type { AstroServer } from './types';\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('cookie-storage-adapter');\n\n// Ensures the cookie names are encoded in order to look up the cookie store\n// that is manipulated by js-cookie on the client side.\n// Details of the js-cookie encoding behavior see:\n// https://github.com/js-cookie/js-cookie#encoding\n// The implementation is borrowed from js-cookie without escaping `[()]` as\n// we are not using those chars in the auth keys.\nfunction ensureEncodedForJSCookie(name: string): string {\n return encodeURIComponent(name).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent);\n}\n\nfunction parseCookieHeader(cookieHeader: string | null) {\n const out: Record<string, string> = {};\n if (!cookieHeader) return out;\n for (const part of cookieHeader.split(';')) {\n const [rawName, ...rest] = part.trim().split('=');\n const name = decodeURIComponent(rawName || '');\n const value = decodeURIComponent(rest.join('=') || '');\n if (name) out[name] = value;\n }\n return out;\n}\n\nfunction mapSameSite(\n s: CookieStorage.SetCookieOptions['sameSite']\n): 'lax' | 'strict' | 'none' | undefined {\n if (s === true) return 'strict';\n if (s === false) return 'lax';\n if (s === 'lax' || s === 'strict' || s === 'none') return s;\n return undefined;\n}\n\nexport async function createCookieStorageAdapterFromAstroContext(\n astroServerContext: AstroServer.ServerContext\n): Promise<CookieStorage.Adapter> {\n if (astroServerContext === null) {\n log.debug('Context is null, returning no-op adapter');\n return {\n get: () => undefined,\n getAll: () => [],\n set: () => {},\n delete: () => {},\n };\n }\n\n const { cookies, request } = astroServerContext;\n const cookieHeader = request?.headers?.get('cookie');\n const headerCookies = parseCookieHeader(cookieHeader ?? null);\n\n // Debug: Log available cookies (names only for security)\n const cookieNames = Object.keys(headerCookies);\n const cognitoCookies = cookieNames.filter(name => name.includes('CognitoIdentityServiceProvider'));\n log.debug('Available cookies:', cookieNames.length);\n log.debug('Cognito cookies found:', cognitoCookies.length);\n if (cognitoCookies.length > 0) {\n log.debug('Cognito cookie names:', cognitoCookies);\n }\n\n const adapter: CookieStorage.Adapter = {\n get(name) {\n const encodedName = ensureEncodedForJSCookie(name);\n const v = cookies?.get(encodedName)?.value ?? headerCookies[encodedName] ?? headerCookies[name];\n // Debug: Log token lookups (only for auth-related cookies)\n if (name.includes('accessToken') || name.includes('idToken') || name.includes('refreshToken') || name.includes('LastAuthUser')) {\n log.debug(`get('${name}'): ${v ? 'FOUND' : 'NOT FOUND'}`);\n }\n return v ? { name, value: v } : undefined;\n },\n getAll() {\n const fromAPI =\n (typeof (cookies as any)?.getAll === 'function'\n ? (cookies as any).getAll().map((c: any) => ({ name: c.name, value: c.value }))\n : Object.entries(headerCookies).map(([name, value]) => ({ name, value })));\n return fromAPI;\n },\n set(name, value, options) {\n try {\n (cookies as any).set(name, value, {\n ...(options ?? {}),\n sameSite: mapSameSite(options?.sameSite),\n });\n } catch {}\n },\n delete(name: string) {\n try {\n (cookies as any).delete(name);\n } catch {}\n },\n };\n\n return adapter;\n}\n"],"mappings":"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","names":["log","globalSettings"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,3 +4,223 @@ export { debounce, formatDate, groupBy, throttle, truncateText } from './utils/i
|
|
|
4
4
|
export { PERMISSIONS, PRODUCTS, ROUTES, USER_ROLES } from './constants/index.js';
|
|
5
5
|
export { AppError, AuthError, NotFoundError, ValidationError } from './errors/index.js';
|
|
6
6
|
export { APIContext } from 'astro';
|
|
7
|
+
import './logger-BTW3fOeM.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Type-Safe Routes
|
|
11
|
+
*
|
|
12
|
+
* Centralized route definitions with type safety and parameter interpolation.
|
|
13
|
+
* Eliminates string literals scattered across the codebase.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Route parameters type
|
|
17
|
+
*/
|
|
18
|
+
type RouteParams = Record<string, string | number>;
|
|
19
|
+
/**
|
|
20
|
+
* Route function interface - can be called with params or used as path
|
|
21
|
+
*/
|
|
22
|
+
interface Route<TParams extends RouteParams = RouteParams> {
|
|
23
|
+
/** Base path of the route */
|
|
24
|
+
readonly path: string;
|
|
25
|
+
/** Generate URL with interpolated parameters */
|
|
26
|
+
(params?: TParams): string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a route with optional parameters
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const userRoute = createRoute<{ id: string }>('/users/:id');
|
|
34
|
+
* userRoute({ id: '123' }); // "/users/123"
|
|
35
|
+
* userRoute.path; // "/users/:id"
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function createRoute<TParams extends RouteParams = Record<string, never>>(path: string): Route<TParams>;
|
|
39
|
+
/**
|
|
40
|
+
* Admin routes
|
|
41
|
+
*/
|
|
42
|
+
declare const adminRoutes: {
|
|
43
|
+
/** Dashboard */
|
|
44
|
+
readonly dashboard: Route<Record<string, never>>;
|
|
45
|
+
/** Accounts list */
|
|
46
|
+
readonly accounts: Route<Record<string, never>>;
|
|
47
|
+
/** Account detail */
|
|
48
|
+
readonly account: Route<{
|
|
49
|
+
id: string | number;
|
|
50
|
+
}>;
|
|
51
|
+
/** Account brands */
|
|
52
|
+
readonly accountBrands: Route<{
|
|
53
|
+
id: string | number;
|
|
54
|
+
}>;
|
|
55
|
+
/** Brands list */
|
|
56
|
+
readonly brands: Route<Record<string, never>>;
|
|
57
|
+
/** Brand detail */
|
|
58
|
+
readonly brand: Route<{
|
|
59
|
+
id: string | number;
|
|
60
|
+
}>;
|
|
61
|
+
/** Brand settings */
|
|
62
|
+
readonly brandSettings: Route<{
|
|
63
|
+
id: string | number;
|
|
64
|
+
}>;
|
|
65
|
+
/** Users list */
|
|
66
|
+
readonly users: Route<Record<string, never>>;
|
|
67
|
+
/** User detail */
|
|
68
|
+
readonly user: Route<{
|
|
69
|
+
id: string;
|
|
70
|
+
}>;
|
|
71
|
+
/** Current user profile */
|
|
72
|
+
readonly profile: Route<Record<string, never>>;
|
|
73
|
+
/** Analytics */
|
|
74
|
+
readonly analytics: Route<Record<string, never>>;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Portal routes (customer-facing)
|
|
78
|
+
*/
|
|
79
|
+
declare const portalRoutes: {
|
|
80
|
+
/** Portal home */
|
|
81
|
+
readonly home: Route<Record<string, never>>;
|
|
82
|
+
/** Brand portal */
|
|
83
|
+
readonly brand: Route<{
|
|
84
|
+
brandId: string | number;
|
|
85
|
+
}>;
|
|
86
|
+
/** Brand settings */
|
|
87
|
+
readonly brandSettings: Route<{
|
|
88
|
+
brandId: string | number;
|
|
89
|
+
}>;
|
|
90
|
+
/** Brand dashboard */
|
|
91
|
+
readonly brandDashboard: Route<{
|
|
92
|
+
brandId: string | number;
|
|
93
|
+
}>;
|
|
94
|
+
/** Brand analytics */
|
|
95
|
+
readonly brandAnalytics: Route<{
|
|
96
|
+
brandId: string | number;
|
|
97
|
+
}>;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Auth routes
|
|
101
|
+
*/
|
|
102
|
+
declare const authRoutes: {
|
|
103
|
+
/** Login page */
|
|
104
|
+
readonly login: Route<Record<string, never>>;
|
|
105
|
+
/** Logout endpoint */
|
|
106
|
+
readonly logout: Route<Record<string, never>>;
|
|
107
|
+
/** Confirm sign in */
|
|
108
|
+
readonly confirmSignIn: Route<Record<string, never>>;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* API routes
|
|
112
|
+
*/
|
|
113
|
+
declare const apiRoutes: {
|
|
114
|
+
/** Auth endpoints */
|
|
115
|
+
readonly auth: {
|
|
116
|
+
readonly logout: Route<Record<string, never>>;
|
|
117
|
+
readonly confirmSignIn: Route<Record<string, never>>;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* All routes combined
|
|
122
|
+
*/
|
|
123
|
+
declare const routes: {
|
|
124
|
+
readonly admin: {
|
|
125
|
+
/** Dashboard */
|
|
126
|
+
readonly dashboard: Route<Record<string, never>>;
|
|
127
|
+
/** Accounts list */
|
|
128
|
+
readonly accounts: Route<Record<string, never>>;
|
|
129
|
+
/** Account detail */
|
|
130
|
+
readonly account: Route<{
|
|
131
|
+
id: string | number;
|
|
132
|
+
}>;
|
|
133
|
+
/** Account brands */
|
|
134
|
+
readonly accountBrands: Route<{
|
|
135
|
+
id: string | number;
|
|
136
|
+
}>;
|
|
137
|
+
/** Brands list */
|
|
138
|
+
readonly brands: Route<Record<string, never>>;
|
|
139
|
+
/** Brand detail */
|
|
140
|
+
readonly brand: Route<{
|
|
141
|
+
id: string | number;
|
|
142
|
+
}>;
|
|
143
|
+
/** Brand settings */
|
|
144
|
+
readonly brandSettings: Route<{
|
|
145
|
+
id: string | number;
|
|
146
|
+
}>;
|
|
147
|
+
/** Users list */
|
|
148
|
+
readonly users: Route<Record<string, never>>;
|
|
149
|
+
/** User detail */
|
|
150
|
+
readonly user: Route<{
|
|
151
|
+
id: string;
|
|
152
|
+
}>;
|
|
153
|
+
/** Current user profile */
|
|
154
|
+
readonly profile: Route<Record<string, never>>;
|
|
155
|
+
/** Analytics */
|
|
156
|
+
readonly analytics: Route<Record<string, never>>;
|
|
157
|
+
};
|
|
158
|
+
readonly portal: {
|
|
159
|
+
/** Portal home */
|
|
160
|
+
readonly home: Route<Record<string, never>>;
|
|
161
|
+
/** Brand portal */
|
|
162
|
+
readonly brand: Route<{
|
|
163
|
+
brandId: string | number;
|
|
164
|
+
}>;
|
|
165
|
+
/** Brand settings */
|
|
166
|
+
readonly brandSettings: Route<{
|
|
167
|
+
brandId: string | number;
|
|
168
|
+
}>;
|
|
169
|
+
/** Brand dashboard */
|
|
170
|
+
readonly brandDashboard: Route<{
|
|
171
|
+
brandId: string | number;
|
|
172
|
+
}>;
|
|
173
|
+
/** Brand analytics */
|
|
174
|
+
readonly brandAnalytics: Route<{
|
|
175
|
+
brandId: string | number;
|
|
176
|
+
}>;
|
|
177
|
+
};
|
|
178
|
+
readonly auth: {
|
|
179
|
+
/** Login page */
|
|
180
|
+
readonly login: Route<Record<string, never>>;
|
|
181
|
+
/** Logout endpoint */
|
|
182
|
+
readonly logout: Route<Record<string, never>>;
|
|
183
|
+
/** Confirm sign in */
|
|
184
|
+
readonly confirmSignIn: Route<Record<string, never>>;
|
|
185
|
+
};
|
|
186
|
+
readonly api: {
|
|
187
|
+
/** Auth endpoints */
|
|
188
|
+
readonly auth: {
|
|
189
|
+
readonly logout: Route<Record<string, never>>;
|
|
190
|
+
readonly confirmSignIn: Route<Record<string, never>>;
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* Type for all routes
|
|
196
|
+
*/
|
|
197
|
+
type Routes = typeof routes;
|
|
198
|
+
/**
|
|
199
|
+
* Helper to check if a path matches a route pattern
|
|
200
|
+
*/
|
|
201
|
+
declare function matchesRoute(path: string, route: Route): boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Extract parameters from a path given a route pattern
|
|
204
|
+
*/
|
|
205
|
+
declare function extractRouteParams<TParams extends RouteParams>(path: string, route: Route<TParams>): TParams | null;
|
|
206
|
+
/**
|
|
207
|
+
* Navigate to a route (client-side helper)
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* navigateTo(routes.admin.account({ id: '123' }));
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
declare function navigateTo(url: string): void;
|
|
215
|
+
/**
|
|
216
|
+
* Build a URL with query parameters
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const url = buildUrl(routes.admin.users(), { page: 2, status: 'active' });
|
|
221
|
+
* // "/admin/users?page=2&status=active"
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function buildUrl(path: string, params?: Record<string, string | number | boolean | null | undefined>): string;
|
|
225
|
+
|
|
226
|
+
export { type Route, type RouteParams, type Routes, adminRoutes, apiRoutes, authRoutes, buildUrl, createRoute, extractRouteParams, matchesRoute, navigateTo, portalRoutes, routes };
|