@open-mercato/shared 0.4.2-canary-c02407ff85
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/build.mjs +101 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +7 -0
- package/dist/lib/api/crud.js +47 -0
- package/dist/lib/api/crud.js.map +7 -0
- package/dist/lib/api/scoped.js +140 -0
- package/dist/lib/api/scoped.js.map +7 -0
- package/dist/lib/auth/jwt.js +34 -0
- package/dist/lib/auth/jwt.js.map +7 -0
- package/dist/lib/auth/server.js +157 -0
- package/dist/lib/auth/server.js.map +7 -0
- package/dist/lib/boolean.js +22 -0
- package/dist/lib/boolean.js.map +7 -0
- package/dist/lib/bootstrap/appResolver.js +43 -0
- package/dist/lib/bootstrap/appResolver.js.map +7 -0
- package/dist/lib/bootstrap/dynamicLoader.js +108 -0
- package/dist/lib/bootstrap/dynamicLoader.js.map +7 -0
- package/dist/lib/bootstrap/factory.js +59 -0
- package/dist/lib/bootstrap/factory.js.map +7 -0
- package/dist/lib/bootstrap/index.js +11 -0
- package/dist/lib/bootstrap/index.js.map +7 -0
- package/dist/lib/bootstrap/types.js +1 -0
- package/dist/lib/bootstrap/types.js.map +7 -0
- package/dist/lib/cache/segments.js +36 -0
- package/dist/lib/cache/segments.js.map +7 -0
- package/dist/lib/cli/progress.js +46 -0
- package/dist/lib/cli/progress.js.map +7 -0
- package/dist/lib/commands/command-bus.js +285 -0
- package/dist/lib/commands/command-bus.js.map +7 -0
- package/dist/lib/commands/customFieldSnapshots.js +66 -0
- package/dist/lib/commands/customFieldSnapshots.js.map +7 -0
- package/dist/lib/commands/helpers.js +98 -0
- package/dist/lib/commands/helpers.js.map +7 -0
- package/dist/lib/commands/index.js +8 -0
- package/dist/lib/commands/index.js.map +7 -0
- package/dist/lib/commands/operationMetadata.js +32 -0
- package/dist/lib/commands/operationMetadata.js.map +7 -0
- package/dist/lib/commands/registry.js +43 -0
- package/dist/lib/commands/registry.js.map +7 -0
- package/dist/lib/commands/scope.js +44 -0
- package/dist/lib/commands/scope.js.map +7 -0
- package/dist/lib/commands/types.js +8 -0
- package/dist/lib/commands/types.js.map +7 -0
- package/dist/lib/crud/cache-stats.js +98 -0
- package/dist/lib/crud/cache-stats.js.map +7 -0
- package/dist/lib/crud/cache.js +175 -0
- package/dist/lib/crud/cache.js.map +7 -0
- package/dist/lib/crud/custom-fields-client.js +52 -0
- package/dist/lib/crud/custom-fields-client.js.map +7 -0
- package/dist/lib/crud/custom-fields.js +467 -0
- package/dist/lib/crud/custom-fields.js.map +7 -0
- package/dist/lib/crud/errors.js +24 -0
- package/dist/lib/crud/errors.js.map +7 -0
- package/dist/lib/crud/exporters.js +154 -0
- package/dist/lib/crud/exporters.js.map +7 -0
- package/dist/lib/crud/factory.js +1311 -0
- package/dist/lib/crud/factory.js.map +7 -0
- package/dist/lib/crud/types.js +1 -0
- package/dist/lib/crud/types.js.map +7 -0
- package/dist/lib/custom-fields/normalize.js +36 -0
- package/dist/lib/custom-fields/normalize.js.map +7 -0
- package/dist/lib/data/engine.js +396 -0
- package/dist/lib/data/engine.js.map +7 -0
- package/dist/lib/db/escapeLikePattern.js +5 -0
- package/dist/lib/db/escapeLikePattern.js.map +7 -0
- package/dist/lib/db/mikro.js +82 -0
- package/dist/lib/db/mikro.js.map +7 -0
- package/dist/lib/di/container.js +94 -0
- package/dist/lib/di/container.js.map +7 -0
- package/dist/lib/email/send.js +12 -0
- package/dist/lib/email/send.js.map +7 -0
- package/dist/lib/encryption/aes.js +58 -0
- package/dist/lib/encryption/aes.js.map +7 -0
- package/dist/lib/encryption/customFieldValues.js +49 -0
- package/dist/lib/encryption/customFieldValues.js.map +7 -0
- package/dist/lib/encryption/entityFields.js +26 -0
- package/dist/lib/encryption/entityFields.js.map +7 -0
- package/dist/lib/encryption/entityIds.js +80 -0
- package/dist/lib/encryption/entityIds.js.map +7 -0
- package/dist/lib/encryption/find.js +45 -0
- package/dist/lib/encryption/find.js.map +7 -0
- package/dist/lib/encryption/indexDoc.js +69 -0
- package/dist/lib/encryption/indexDoc.js.map +7 -0
- package/dist/lib/encryption/kms.js +282 -0
- package/dist/lib/encryption/kms.js.map +7 -0
- package/dist/lib/encryption/subscriber.js +330 -0
- package/dist/lib/encryption/subscriber.js.map +7 -0
- package/dist/lib/encryption/tenantDataEncryptionService.js +252 -0
- package/dist/lib/encryption/tenantDataEncryptionService.js.map +7 -0
- package/dist/lib/encryption/toggles.js +18 -0
- package/dist/lib/encryption/toggles.js.map +7 -0
- package/dist/lib/entities/naming.js +9 -0
- package/dist/lib/entities/naming.js.map +7 -0
- package/dist/lib/entities/system-entities.js +43 -0
- package/dist/lib/entities/system-entities.js.map +7 -0
- package/dist/lib/frontend/organizationEvents.js +41 -0
- package/dist/lib/frontend/organizationEvents.js.map +7 -0
- package/dist/lib/frontend/useOrganizationScope.js +32 -0
- package/dist/lib/frontend/useOrganizationScope.js.map +7 -0
- package/dist/lib/hotkeys/index.js +128 -0
- package/dist/lib/hotkeys/index.js.map +7 -0
- package/dist/lib/i18n/app-dictionaries.js +17 -0
- package/dist/lib/i18n/app-dictionaries.js.map +7 -0
- package/dist/lib/i18n/config.js +7 -0
- package/dist/lib/i18n/config.js.map +7 -0
- package/dist/lib/i18n/context.js +50 -0
- package/dist/lib/i18n/context.js.map +7 -0
- package/dist/lib/i18n/server.js +68 -0
- package/dist/lib/i18n/server.js.map +7 -0
- package/dist/lib/i18n/translate.js +45 -0
- package/dist/lib/i18n/translate.js.map +7 -0
- package/dist/lib/indexers/error-log.js +82 -0
- package/dist/lib/indexers/error-log.js.map +7 -0
- package/dist/lib/indexers/status-log.js +80 -0
- package/dist/lib/indexers/status-log.js.map +7 -0
- package/dist/lib/lib/auth/jwt.js +34 -0
- package/dist/lib/lib/auth/jwt.js.map +7 -0
- package/dist/lib/lib/auth/server.js +77 -0
- package/dist/lib/lib/auth/server.js.map +7 -0
- package/dist/lib/lib/email/send.js +12 -0
- package/dist/lib/lib/email/send.js.map +7 -0
- package/dist/lib/lib/i18n/config.js +7 -0
- package/dist/lib/lib/i18n/config.js.map +7 -0
- package/dist/lib/lib/i18n/context.js +31 -0
- package/dist/lib/lib/i18n/context.js.map +7 -0
- package/dist/lib/lib/utils.js +9 -0
- package/dist/lib/lib/utils.js.map +7 -0
- package/dist/lib/location/countries.js +68 -0
- package/dist/lib/location/countries.js.map +7 -0
- package/dist/lib/modules/index.js +6 -0
- package/dist/lib/modules/index.js.map +7 -0
- package/dist/lib/modules/registry.js +18 -0
- package/dist/lib/modules/registry.js.map +7 -0
- package/dist/lib/openapi/crud.js +137 -0
- package/dist/lib/openapi/crud.js.map +7 -0
- package/dist/lib/openapi/generator.js +1131 -0
- package/dist/lib/openapi/generator.js.map +7 -0
- package/dist/lib/openapi/index.js +10 -0
- package/dist/lib/openapi/index.js.map +7 -0
- package/dist/lib/openapi/sanitize.js +110 -0
- package/dist/lib/openapi/sanitize.js.map +7 -0
- package/dist/lib/openapi/types.js +1 -0
- package/dist/lib/openapi/types.js.map +7 -0
- package/dist/lib/profiler/index.js +258 -0
- package/dist/lib/profiler/index.js.map +7 -0
- package/dist/lib/query/engine.js +729 -0
- package/dist/lib/query/engine.js.map +7 -0
- package/dist/lib/query/join-utils.js +195 -0
- package/dist/lib/query/join-utils.js.map +7 -0
- package/dist/lib/query/types.js +9 -0
- package/dist/lib/query/types.js.map +7 -0
- package/dist/lib/search/config.js +32 -0
- package/dist/lib/search/config.js.map +7 -0
- package/dist/lib/search/tokenize.js +34 -0
- package/dist/lib/search/tokenize.js.map +7 -0
- package/dist/lib/slugify.js +24 -0
- package/dist/lib/slugify.js.map +7 -0
- package/dist/lib/testing/bootstrap.js +51 -0
- package/dist/lib/testing/bootstrap.js.map +7 -0
- package/dist/lib/testing/index.js +17 -0
- package/dist/lib/testing/index.js.map +7 -0
- package/dist/lib/testing/renderWithProviders.js +15 -0
- package/dist/lib/testing/renderWithProviders.js.map +7 -0
- package/dist/lib/url.js +12 -0
- package/dist/lib/url.js.map +7 -0
- package/dist/lib/utils.js +13 -0
- package/dist/lib/utils.js.map +7 -0
- package/dist/lib/version.js +7 -0
- package/dist/lib/version.js.map +7 -0
- package/dist/modules/dashboard/widgets.js +1 -0
- package/dist/modules/dashboard/widgets.js.map +7 -0
- package/dist/modules/dsl.js +30 -0
- package/dist/modules/dsl.js.map +7 -0
- package/dist/modules/entities/kinds.js +22 -0
- package/dist/modules/entities/kinds.js.map +7 -0
- package/dist/modules/entities/options.js +26 -0
- package/dist/modules/entities/options.js.map +7 -0
- package/dist/modules/entities/validation.js +102 -0
- package/dist/modules/entities/validation.js.map +7 -0
- package/dist/modules/entities/validators.js +88 -0
- package/dist/modules/entities/validators.js.map +7 -0
- package/dist/modules/entities.js +1 -0
- package/dist/modules/entities.js.map +7 -0
- package/dist/modules/navigation/sidebarPreferences.js +50 -0
- package/dist/modules/navigation/sidebarPreferences.js.map +7 -0
- package/dist/modules/perspectives/types.js +1 -0
- package/dist/modules/perspectives/types.js.map +7 -0
- package/dist/modules/registry.js +96 -0
- package/dist/modules/registry.js.map +7 -0
- package/dist/modules/search.js +15 -0
- package/dist/modules/search.js.map +7 -0
- package/dist/modules/vector.js +1 -0
- package/dist/modules/vector.js.map +7 -0
- package/dist/modules/widgets/injection-loader.js +180 -0
- package/dist/modules/widgets/injection-loader.js.map +7 -0
- package/dist/modules/widgets/injection.js +1 -0
- package/dist/modules/widgets/injection.js.map +7 -0
- package/dist/security/features.js +23 -0
- package/dist/security/features.js.map +7 -0
- package/dist/types/pg.d.js +1 -0
- package/dist/types/pg.d.js.map +7 -0
- package/dist/types/react-email.d.js +1 -0
- package/dist/types/react-email.d.js.map +7 -0
- package/dist/types/resend.d.js +1 -0
- package/dist/types/resend.d.js.map +7 -0
- package/jest.config.cjs +22 -0
- package/package.json +88 -0
- package/src/index.ts +0 -0
- package/src/lib/api/__tests__/scoped.test.ts +38 -0
- package/src/lib/api/crud.ts +59 -0
- package/src/lib/api/scoped.ts +239 -0
- package/src/lib/auth/jwt.ts +39 -0
- package/src/lib/auth/server.ts +199 -0
- package/src/lib/boolean.ts +17 -0
- package/src/lib/bootstrap/appResolver.ts +85 -0
- package/src/lib/bootstrap/dynamicLoader.ts +177 -0
- package/src/lib/bootstrap/factory.ts +108 -0
- package/src/lib/bootstrap/index.ts +23 -0
- package/src/lib/bootstrap/types.ts +31 -0
- package/src/lib/cache/segments.ts +56 -0
- package/src/lib/cli/progress.ts +55 -0
- package/src/lib/commands/__tests__/command-bus.test.ts +84 -0
- package/src/lib/commands/__tests__/helpers.test.ts +42 -0
- package/src/lib/commands/command-bus.ts +349 -0
- package/src/lib/commands/customFieldSnapshots.ts +86 -0
- package/src/lib/commands/helpers.ts +143 -0
- package/src/lib/commands/index.ts +4 -0
- package/src/lib/commands/operationMetadata.ts +40 -0
- package/src/lib/commands/registry.ts +46 -0
- package/src/lib/commands/scope.ts +59 -0
- package/src/lib/commands/types.ts +63 -0
- package/src/lib/crud/__tests__/crud-factory.test.ts +333 -0
- package/src/lib/crud/__tests__/custom-fields.test.ts +150 -0
- package/src/lib/crud/cache-stats.ts +127 -0
- package/src/lib/crud/cache.ts +205 -0
- package/src/lib/crud/custom-fields-client.ts +54 -0
- package/src/lib/crud/custom-fields.ts +607 -0
- package/src/lib/crud/errors.ts +23 -0
- package/src/lib/crud/exporters.ts +188 -0
- package/src/lib/crud/factory.ts +1622 -0
- package/src/lib/crud/types.ts +29 -0
- package/src/lib/custom-fields/normalize.ts +45 -0
- package/src/lib/data/engine.ts +562 -0
- package/src/lib/db/escapeLikePattern.ts +2 -0
- package/src/lib/db/mikro.ts +100 -0
- package/src/lib/di/container.ts +105 -0
- package/src/lib/email/send.ts +18 -0
- package/src/lib/encryption/__tests__/customFieldValues.test.ts +63 -0
- package/src/lib/encryption/__tests__/indexDoc.test.ts +115 -0
- package/src/lib/encryption/aes.ts +64 -0
- package/src/lib/encryption/customFieldValues.ts +67 -0
- package/src/lib/encryption/entityFields.ts +39 -0
- package/src/lib/encryption/entityIds.ts +107 -0
- package/src/lib/encryption/find.ts +81 -0
- package/src/lib/encryption/indexDoc.ts +104 -0
- package/src/lib/encryption/kms.ts +337 -0
- package/src/lib/encryption/subscriber.ts +416 -0
- package/src/lib/encryption/tenantDataEncryptionService.ts +313 -0
- package/src/lib/encryption/toggles.ts +15 -0
- package/src/lib/entities/naming.ts +6 -0
- package/src/lib/entities/system-entities.ts +43 -0
- package/src/lib/frontend/organizationEvents.ts +55 -0
- package/src/lib/frontend/useOrganizationScope.ts +30 -0
- package/src/lib/hotkeys/index.ts +168 -0
- package/src/lib/i18n/app-dictionaries.ts +18 -0
- package/src/lib/i18n/config.ts +4 -0
- package/src/lib/i18n/context.tsx +66 -0
- package/src/lib/i18n/server.ts +74 -0
- package/src/lib/i18n/translate.ts +54 -0
- package/src/lib/indexers/error-log.ts +106 -0
- package/src/lib/indexers/status-log.ts +119 -0
- package/src/lib/lib/auth/jwt.ts +39 -0
- package/src/lib/lib/auth/server.ts +94 -0
- package/src/lib/lib/email/send.ts +18 -0
- package/src/lib/lib/i18n/config.ts +4 -0
- package/src/lib/lib/i18n/context.tsx +38 -0
- package/src/lib/lib/utils.ts +6 -0
- package/src/lib/location/countries.ts +97 -0
- package/src/lib/modules/index.ts +1 -0
- package/src/lib/modules/registry.ts +18 -0
- package/src/lib/openapi/crud.ts +218 -0
- package/src/lib/openapi/generator.ts +1311 -0
- package/src/lib/openapi/index.ts +4 -0
- package/src/lib/openapi/sanitize.ts +137 -0
- package/src/lib/openapi/types.ts +79 -0
- package/src/lib/profiler/index.ts +371 -0
- package/src/lib/query/__tests__/engine.test.ts +274 -0
- package/src/lib/query/engine.ts +837 -0
- package/src/lib/query/join-utils.ts +238 -0
- package/src/lib/query/types.ts +121 -0
- package/src/lib/search/config.ts +49 -0
- package/src/lib/search/tokenize.ts +45 -0
- package/src/lib/slugify.ts +28 -0
- package/src/lib/testing/bootstrap.ts +124 -0
- package/src/lib/testing/index.ts +15 -0
- package/src/lib/testing/renderWithProviders.tsx +31 -0
- package/src/lib/url.ts +12 -0
- package/src/lib/utils.ts +17 -0
- package/src/lib/version.ts +5 -0
- package/src/modules/__tests__/dsl.test.ts +35 -0
- package/src/modules/__tests__/registry.test.ts +300 -0
- package/src/modules/dashboard/widgets.ts +57 -0
- package/src/modules/dsl.ts +32 -0
- package/src/modules/entities/__tests__/validation.test.ts +52 -0
- package/src/modules/entities/kinds.ts +20 -0
- package/src/modules/entities/options.ts +36 -0
- package/src/modules/entities/validation.ts +118 -0
- package/src/modules/entities/validators.ts +93 -0
- package/src/modules/entities.ts +102 -0
- package/src/modules/navigation/sidebarPreferences.ts +62 -0
- package/src/modules/perspectives/types.ts +40 -0
- package/src/modules/registry.ts +249 -0
- package/src/modules/search.ts +325 -0
- package/src/modules/vector.ts +122 -0
- package/src/modules/widgets/__tests__/injection.test.ts +48 -0
- package/src/modules/widgets/injection-loader.ts +235 -0
- package/src/modules/widgets/injection.ts +120 -0
- package/src/security/features.ts +22 -0
- package/src/types/pg.d.ts +2 -0
- package/src/types/react-email.d.ts +2 -0
- package/src/types/resend.d.ts +2 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +9 -0
- package/watch.mjs +6 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { cookies } from "next/headers";
|
|
2
|
+
import { verifyJwt } from "./jwt.js";
|
|
3
|
+
async function resolveApiKeyAuth(secret) {
|
|
4
|
+
if (!secret) return null;
|
|
5
|
+
try {
|
|
6
|
+
const { createRequestContainer } = await import("@open-mercato/shared/lib/di/container");
|
|
7
|
+
const container = await createRequestContainer();
|
|
8
|
+
const em = container.resolve("em");
|
|
9
|
+
const { findApiKeyBySecret } = await import("@open-mercato/core/modules/api_keys/services/apiKeyService");
|
|
10
|
+
const { Role } = await import("@open-mercato/core/modules/auth/data/entities");
|
|
11
|
+
const record = await findApiKeyBySecret(em, secret);
|
|
12
|
+
if (!record) return null;
|
|
13
|
+
const roleIds = Array.isArray(record.rolesJson) ? record.rolesJson : [];
|
|
14
|
+
const roles = roleIds.length ? await em.find(Role, { id: { $in: roleIds } }) : [];
|
|
15
|
+
const roleNames = roles.map((role) => role.name).filter((name) => typeof name === "string" && name.length > 0);
|
|
16
|
+
try {
|
|
17
|
+
record.lastUsedAt = /* @__PURE__ */ new Date();
|
|
18
|
+
await em.persistAndFlush(record);
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
sub: `api_key:${record.id}`,
|
|
23
|
+
tenantId: record.tenantId ?? null,
|
|
24
|
+
orgId: record.organizationId ?? null,
|
|
25
|
+
roles: roleNames,
|
|
26
|
+
isApiKey: true,
|
|
27
|
+
keyId: record.id,
|
|
28
|
+
keyName: record.name
|
|
29
|
+
};
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function extractApiKey(req) {
|
|
35
|
+
const header = (req.headers.get("x-api-key") || "").trim();
|
|
36
|
+
if (header) return header;
|
|
37
|
+
const authHeader = (req.headers.get("authorization") || "").trim();
|
|
38
|
+
if (authHeader.toLowerCase().startsWith("apikey ")) {
|
|
39
|
+
return authHeader.slice(7).trim();
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
async function getAuthFromCookies() {
|
|
44
|
+
const token = (await cookies()).get("auth_token")?.value;
|
|
45
|
+
if (!token) return null;
|
|
46
|
+
try {
|
|
47
|
+
const payload = verifyJwt(token);
|
|
48
|
+
return payload;
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function getAuthFromRequest(req) {
|
|
54
|
+
const authHeader = (req.headers.get("authorization") || "").trim();
|
|
55
|
+
let token;
|
|
56
|
+
if (authHeader.toLowerCase().startsWith("bearer ")) token = authHeader.slice(7).trim();
|
|
57
|
+
if (!token) {
|
|
58
|
+
const cookie = req.headers.get("cookie") || "";
|
|
59
|
+
const match = cookie.match(/(?:^|;\s*)auth_token=([^;]+)/);
|
|
60
|
+
if (match) token = decodeURIComponent(match[1]);
|
|
61
|
+
}
|
|
62
|
+
if (token) {
|
|
63
|
+
try {
|
|
64
|
+
const payload = verifyJwt(token);
|
|
65
|
+
if (payload) return payload;
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const apiKey = extractApiKey(req);
|
|
70
|
+
if (!apiKey) return null;
|
|
71
|
+
return resolveApiKeyAuth(apiKey);
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
getAuthFromCookies,
|
|
75
|
+
getAuthFromRequest
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/lib/auth/server.ts"],
|
|
4
|
+
"sourcesContent": ["import { cookies } from 'next/headers'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { verifyJwt } from './jwt'\n\nexport type AuthContext = {\n sub: string\n tenantId: string | null\n orgId: string | null\n email?: string\n roles?: string[]\n isApiKey?: boolean\n keyId?: string\n keyName?: string\n [k: string]: any\n} | null\n\nasync function resolveApiKeyAuth(secret: string): Promise<AuthContext> {\n if (!secret) return null\n try {\n const { createRequestContainer } = await import('@open-mercato/shared/lib/di/container')\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n const { findApiKeyBySecret } = await import('@open-mercato/core/modules/api_keys/services/apiKeyService')\n const { Role } = await import('@open-mercato/core/modules/auth/data/entities')\n\n const record = await findApiKeyBySecret(em, secret)\n if (!record) return null\n\n const roleIds = Array.isArray(record.rolesJson) ? record.rolesJson : []\n const roles = roleIds.length\n ? await em.find(Role, { id: { $in: roleIds as any } } as any)\n : []\n const roleNames = roles.map((role) => role.name).filter((name): name is string => typeof name === 'string' && name.length > 0)\n\n try {\n record.lastUsedAt = new Date()\n await em.persistAndFlush(record)\n } catch {}\n\n return {\n sub: `api_key:${record.id}`,\n tenantId: record.tenantId ?? null,\n orgId: record.organizationId ?? null,\n roles: roleNames,\n isApiKey: true,\n keyId: record.id,\n keyName: record.name,\n }\n } catch {\n return null\n }\n}\n\nfunction extractApiKey(req: Request): string | null {\n const header = (req.headers.get('x-api-key') || '').trim()\n if (header) return header\n const authHeader = (req.headers.get('authorization') || '').trim()\n if (authHeader.toLowerCase().startsWith('apikey ')) {\n return authHeader.slice(7).trim()\n }\n return null\n}\n\nexport async function getAuthFromCookies(): Promise<AuthContext> {\n const token = (await cookies()).get('auth_token')?.value\n if (!token) return null\n try {\n const payload = verifyJwt(token)\n return payload\n } catch {\n return null\n }\n}\n\nexport async function getAuthFromRequest(req: Request): Promise<AuthContext> {\n const authHeader = (req.headers.get('authorization') || '').trim()\n let token: string | undefined\n if (authHeader.toLowerCase().startsWith('bearer ')) token = authHeader.slice(7).trim()\n if (!token) {\n const cookie = req.headers.get('cookie') || ''\n const match = cookie.match(/(?:^|;\\s*)auth_token=([^;]+)/)\n if (match) token = decodeURIComponent(match[1])\n }\n if (token) {\n try {\n const payload = verifyJwt(token)\n if (payload) return payload\n } catch {}\n }\n\n const apiKey = extractApiKey(req)\n if (!apiKey) return null\n return resolveApiKeyAuth(apiKey)\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,eAAe;AAExB,SAAS,iBAAiB;AAc1B,eAAe,kBAAkB,QAAsC;AACrE,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AACF,UAAM,EAAE,uBAAuB,IAAI,MAAM,OAAO,uCAAuC;AACvF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,4DAA4D;AACxG,UAAM,EAAE,KAAK,IAAI,MAAM,OAAO,+CAA+C;AAE7E,UAAM,SAAS,MAAM,mBAAmB,IAAI,MAAM;AAClD,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,UAAU,MAAM,QAAQ,OAAO,SAAS,IAAI,OAAO,YAAY,CAAC;AACtE,UAAM,QAAQ,QAAQ,SAClB,MAAM,GAAG,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,QAAe,EAAE,CAAQ,IAC1D,CAAC;AACL,UAAM,YAAY,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS,CAAC;AAE7H,QAAI;AACF,aAAO,aAAa,oBAAI,KAAK;AAC7B,YAAM,GAAG,gBAAgB,MAAM;AAAA,IACjC,QAAQ;AAAA,IAAC;AAET,WAAO;AAAA,MACL,KAAK,WAAW,OAAO,EAAE;AAAA,MACzB,UAAU,OAAO,YAAY;AAAA,MAC7B,OAAO,OAAO,kBAAkB;AAAA,MAChC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,KAA6B;AAClD,QAAM,UAAU,IAAI,QAAQ,IAAI,WAAW,KAAK,IAAI,KAAK;AACzD,MAAI,OAAQ,QAAO;AACnB,QAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,KAAK,IAAI,KAAK;AACjE,MAAI,WAAW,YAAY,EAAE,WAAW,SAAS,GAAG;AAClD,WAAO,WAAW,MAAM,CAAC,EAAE,KAAK;AAAA,EAClC;AACA,SAAO;AACT;AAEA,eAAsB,qBAA2C;AAC/D,QAAM,SAAS,MAAM,QAAQ,GAAG,IAAI,YAAY,GAAG;AACnD,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,UAAM,UAAU,UAAU,KAAK;AAC/B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,mBAAmB,KAAoC;AAC3E,QAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,KAAK,IAAI,KAAK;AACjE,MAAI;AACJ,MAAI,WAAW,YAAY,EAAE,WAAW,SAAS,EAAG,SAAQ,WAAW,MAAM,CAAC,EAAE,KAAK;AACrF,MAAI,CAAC,OAAO;AACV,UAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ,KAAK;AAC5C,UAAM,QAAQ,OAAO,MAAM,8BAA8B;AACzD,QAAI,MAAO,SAAQ,mBAAmB,MAAM,CAAC,CAAC;AAAA,EAChD;AACA,MAAI,OAAO;AACT,QAAI;AACF,YAAM,UAAU,UAAU,KAAK;AAC/B,UAAI,QAAS,QAAO;AAAA,IACtB,QAAQ;AAAA,IAAC;AAAA,EACX;AAEA,QAAM,SAAS,cAAc,GAAG;AAChC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,kBAAkB,MAAM;AACjC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Resend } from "resend";
|
|
2
|
+
async function sendEmail({ to, subject, react, from }) {
|
|
3
|
+
const apiKey = process.env.RESEND_API_KEY;
|
|
4
|
+
if (!apiKey) throw new Error("RESEND_API_KEY is not set");
|
|
5
|
+
const resend = new Resend(apiKey);
|
|
6
|
+
const fromAddr = from || process.env.EMAIL_FROM || "no-reply@localhost";
|
|
7
|
+
await resend.emails.send({ to, subject, from: fromAddr, react });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
sendEmail
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=send.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/lib/email/send.ts"],
|
|
4
|
+
"sourcesContent": ["import { Resend } from 'resend'\nimport React from 'react'\n\nexport type SendEmailOptions = {\n to: string\n subject: string\n react: React.ReactElement\n from?: string\n}\n\nexport async function sendEmail({ to, subject, react, from }: SendEmailOptions) {\n const apiKey = process.env.RESEND_API_KEY\n if (!apiKey) throw new Error('RESEND_API_KEY is not set')\n const resend = new Resend(apiKey)\n const fromAddr = from || process.env.EMAIL_FROM || 'no-reply@localhost'\n await resend.emails.send({ to, subject, from: fromAddr, react })\n}\n\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,cAAc;AAUvB,eAAsB,UAAU,EAAE,IAAI,SAAS,OAAO,KAAK,GAAqB;AAC9E,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AACxD,QAAM,SAAS,IAAI,OAAO,MAAM;AAChC,QAAM,WAAW,QAAQ,QAAQ,IAAI,cAAc;AACnD,QAAM,OAAO,OAAO,KAAK,EAAE,IAAI,SAAS,MAAM,UAAU,MAAM,CAAC;AACjE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/lib/i18n/config.ts"],
|
|
4
|
+
"sourcesContent": ["export type Locale = 'en' | 'pl' | 'es' | 'de'\n\nexport const locales: Locale[] = ['en', 'pl', 'es', 'de']\nexport const defaultLocale: Locale = 'en'\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,UAAoB,CAAC,MAAM,MAAM,MAAM,IAAI;AACjD,MAAM,gBAAwB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useMemo } from "react";
|
|
4
|
+
const I18nContext = createContext(null);
|
|
5
|
+
function format(template, params) {
|
|
6
|
+
if (!params) return template;
|
|
7
|
+
return template.replace(/\{(\w+)\}/g, (_, k) => String(params[k] ?? `{${k}}`));
|
|
8
|
+
}
|
|
9
|
+
function I18nProvider({ children, locale, dict }) {
|
|
10
|
+
const value = useMemo(() => ({
|
|
11
|
+
locale,
|
|
12
|
+
t: (key, params) => format(dict[key] ?? key, params)
|
|
13
|
+
}), [locale, dict]);
|
|
14
|
+
return /* @__PURE__ */ jsx(I18nContext.Provider, { value, children });
|
|
15
|
+
}
|
|
16
|
+
function useT() {
|
|
17
|
+
const ctx = useContext(I18nContext);
|
|
18
|
+
if (!ctx) throw new Error("useT must be used within I18nProvider");
|
|
19
|
+
return ctx.t;
|
|
20
|
+
}
|
|
21
|
+
function useLocale() {
|
|
22
|
+
const ctx = useContext(I18nContext);
|
|
23
|
+
if (!ctx) throw new Error("useLocale must be used within I18nProvider");
|
|
24
|
+
return ctx.locale;
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
I18nProvider,
|
|
28
|
+
useLocale,
|
|
29
|
+
useT
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/lib/i18n/context.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport React, { createContext, useContext, useMemo } from 'react'\nimport type { Locale } from './config'\n\nexport type Dict = Record<string, string>\n\nexport type I18nContextValue = {\n locale: Locale\n t: (key: string, params?: Record<string, string | number>) => string\n}\n\nconst I18nContext = createContext<I18nContextValue | null>(null)\n\nfunction format(template: string, params?: Record<string, string | number>) {\n if (!params) return template\n return template.replace(/\\{(\\w+)\\}/g, (_, k) => String(params[k] ?? `{${k}}`))\n}\n\nexport function I18nProvider({ children, locale, dict }: { children: React.ReactNode; locale: Locale; dict: Dict }) {\n const value = useMemo<I18nContextValue>(() => ({\n locale,\n t: (key, params) => format(dict[key] ?? key, params),\n }), [locale, dict])\n return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>\n}\n\nexport function useT() {\n const ctx = useContext(I18nContext)\n if (!ctx) throw new Error('useT must be used within I18nProvider')\n return ctx.t\n}\n\nexport function useLocale() {\n const ctx = useContext(I18nContext)\n if (!ctx) throw new Error('useLocale must be used within I18nProvider')\n return ctx.locale\n}\n\n"],
|
|
5
|
+
"mappings": ";AAuBS;AAtBT,SAAgB,eAAe,YAAY,eAAe;AAU1D,MAAM,cAAc,cAAuC,IAAI;AAE/D,SAAS,OAAO,UAAkB,QAA0C;AAC1E,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,SAAS,QAAQ,cAAc,CAAC,GAAG,MAAM,OAAO,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC;AAC/E;AAEO,SAAS,aAAa,EAAE,UAAU,QAAQ,KAAK,GAA8D;AAClH,QAAM,QAAQ,QAA0B,OAAO;AAAA,IAC7C;AAAA,IACA,GAAG,CAAC,KAAK,WAAW,OAAO,KAAK,GAAG,KAAK,KAAK,MAAM;AAAA,EACrD,IAAI,CAAC,QAAQ,IAAI,CAAC;AAClB,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAEO,SAAS,OAAO;AACrB,QAAM,MAAM,WAAW,WAAW;AAClC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,uCAAuC;AACjE,SAAO,IAAI;AACb;AAEO,SAAS,YAAY;AAC1B,QAAM,MAAM,WAAW,WAAW;AAClC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4CAA4C;AACtE,SAAO,IAAI;AACb;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/lib/utils.ts"],
|
|
4
|
+
"sourcesContent": ["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import registry from "language-subtag-registry/data/json/registry.json";
|
|
2
|
+
function isIsoAlpha2(entry) {
|
|
3
|
+
if (entry.Type !== "region") return false;
|
|
4
|
+
if (!entry.Subtag || !/^[A-Z]{2}$/.test(entry.Subtag)) return false;
|
|
5
|
+
if (entry.Deprecated) return false;
|
|
6
|
+
if (!entry.Description || !entry.Description.length) return false;
|
|
7
|
+
if (entry.Description[0] === "Private use") return false;
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
const RAW_COUNTRIES = registry.filter(isIsoAlpha2).map((entry) => ({
|
|
11
|
+
code: entry.Subtag,
|
|
12
|
+
name: entry.Description.join(", ")
|
|
13
|
+
}));
|
|
14
|
+
const ISO_COUNTRIES = [...RAW_COUNTRIES].sort(
|
|
15
|
+
(a, b) => a.name.localeCompare(b.name, "en", { sensitivity: "base" })
|
|
16
|
+
);
|
|
17
|
+
const COUNTRY_PRIORITY = ["PL", "DE", "ES", "FR", "IT", "US", "GB", "CA"];
|
|
18
|
+
const displayNameCache = /* @__PURE__ */ new Map();
|
|
19
|
+
function getDisplayNames(locale) {
|
|
20
|
+
if (typeof Intl === "undefined" || typeof Intl.DisplayNames === "undefined") return null;
|
|
21
|
+
const key = locale || "en";
|
|
22
|
+
let instance = displayNameCache.get(key);
|
|
23
|
+
if (!instance) {
|
|
24
|
+
try {
|
|
25
|
+
instance = new Intl.DisplayNames([key], { type: "region" });
|
|
26
|
+
displayNameCache.set(key, instance);
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return instance;
|
|
32
|
+
}
|
|
33
|
+
function resolveCountryName(code, options = {}) {
|
|
34
|
+
const normalized = code.toUpperCase();
|
|
35
|
+
const fallback = ISO_COUNTRIES.find((entry) => entry.code === normalized)?.name ?? normalized;
|
|
36
|
+
const displayNames = getDisplayNames(options.locale ?? "en");
|
|
37
|
+
if (!displayNames) return fallback;
|
|
38
|
+
try {
|
|
39
|
+
const label = displayNames.of(normalized);
|
|
40
|
+
return typeof label === "string" ? label : fallback;
|
|
41
|
+
} catch {
|
|
42
|
+
return fallback;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function buildCountryOptions(options = {}) {
|
|
46
|
+
const { locale, transformLabel } = options;
|
|
47
|
+
const priority = (options.priority ?? COUNTRY_PRIORITY).map((code) => code.toUpperCase());
|
|
48
|
+
const prioritySet = new Set(priority);
|
|
49
|
+
const labelFor = (code) => {
|
|
50
|
+
const base = resolveCountryName(code, { locale });
|
|
51
|
+
return transformLabel ? transformLabel(code, base) : base;
|
|
52
|
+
};
|
|
53
|
+
const byCode = new Map(ISO_COUNTRIES.map((entry) => [entry.code, entry]));
|
|
54
|
+
const prioritized = priority.map((code) => {
|
|
55
|
+
const base = byCode.get(code);
|
|
56
|
+
if (!base) return null;
|
|
57
|
+
return { code, label: labelFor(code) };
|
|
58
|
+
}).filter((entry) => !!entry).sort((a, b) => a.label.localeCompare(b.label, locale ?? "en", { sensitivity: "base" }));
|
|
59
|
+
const remaining = ISO_COUNTRIES.filter((entry) => !prioritySet.has(entry.code)).map((entry) => ({ code: entry.code, label: labelFor(entry.code) })).sort((a, b) => a.label.localeCompare(b.label, locale ?? "en", { sensitivity: "base" }));
|
|
60
|
+
return [...prioritized, ...remaining];
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
COUNTRY_PRIORITY,
|
|
64
|
+
ISO_COUNTRIES,
|
|
65
|
+
buildCountryOptions,
|
|
66
|
+
resolveCountryName
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=countries.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/location/countries.ts"],
|
|
4
|
+
"sourcesContent": ["import registry from 'language-subtag-registry/data/json/registry.json'\n\ntype RegistryEntry = {\n Type: string\n Subtag?: string\n Description?: string[]\n Deprecated?: string\n}\n\nexport type IsoCountry = {\n code: string\n name: string\n}\n\nfunction isIsoAlpha2(entry: RegistryEntry): entry is RegistryEntry & { Subtag: string; Description: string[] } {\n if (entry.Type !== 'region') return false\n if (!entry.Subtag || !/^[A-Z]{2}$/.test(entry.Subtag)) return false\n if (entry.Deprecated) return false\n if (!entry.Description || !entry.Description.length) return false\n if (entry.Description[0] === 'Private use') return false\n return true\n}\n\nconst RAW_COUNTRIES: IsoCountry[] = (registry as RegistryEntry[])\n .filter(isIsoAlpha2)\n .map((entry) => ({\n code: entry.Subtag,\n name: entry.Description.join(', '),\n }))\n\nexport const ISO_COUNTRIES: IsoCountry[] = [...RAW_COUNTRIES].sort((a, b) =>\n a.name.localeCompare(b.name, 'en', { sensitivity: 'base' })\n)\n\nexport const COUNTRY_PRIORITY: string[] = ['PL', 'DE', 'ES', 'FR', 'IT', 'US', 'GB', 'CA']\n\nconst displayNameCache = new Map<string, Intl.DisplayNames>()\n\nfunction getDisplayNames(locale: string): Intl.DisplayNames | null {\n if (typeof Intl === 'undefined' || typeof Intl.DisplayNames === 'undefined') return null\n const key = locale || 'en'\n let instance = displayNameCache.get(key)\n if (!instance) {\n try {\n instance = new Intl.DisplayNames([key], { type: 'region' })\n displayNameCache.set(key, instance)\n } catch {\n return null\n }\n }\n return instance\n}\n\nexport function resolveCountryName(code: string, options: { locale?: string } = {}): string {\n const normalized = code.toUpperCase()\n const fallback = ISO_COUNTRIES.find((entry) => entry.code === normalized)?.name ?? normalized\n const displayNames = getDisplayNames(options.locale ?? 'en')\n if (!displayNames) return fallback\n try {\n const label = displayNames.of(normalized as any)\n return typeof label === 'string' ? label : fallback\n } catch {\n return fallback\n }\n}\n\nexport function buildCountryOptions(options: {\n locale?: string\n priority?: string[]\n transformLabel?: (code: string, defaultLabel: string) => string\n} = {}): Array<{ code: string; label: string }> {\n const { locale, transformLabel } = options\n const priority = (options.priority ?? COUNTRY_PRIORITY).map((code) => code.toUpperCase())\n const prioritySet = new Set(priority)\n const labelFor = (code: string) => {\n const base = resolveCountryName(code, { locale })\n return transformLabel ? transformLabel(code, base) : base\n }\n\n const byCode = new Map(ISO_COUNTRIES.map((entry) => [entry.code, entry]))\n\n const prioritized = priority\n .map((code) => {\n const base = byCode.get(code)\n if (!base) return null\n return { code, label: labelFor(code) }\n })\n .filter((entry): entry is { code: string; label: string } => !!entry)\n .sort((a, b) => a.label.localeCompare(b.label, locale ?? 'en', { sensitivity: 'base' }))\n\n const remaining = ISO_COUNTRIES\n .filter((entry) => !prioritySet.has(entry.code))\n .map((entry) => ({ code: entry.code, label: labelFor(entry.code) }))\n .sort((a, b) => a.label.localeCompare(b.label, locale ?? 'en', { sensitivity: 'base' }))\n\n return [...prioritized, ...remaining]\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
let _modules = null;
|
|
2
|
+
function registerModules(modules) {
|
|
3
|
+
if (_modules !== null && process.env.NODE_ENV === "development") {
|
|
4
|
+
console.debug("[Bootstrap] Modules re-registered (this may occur during HMR)");
|
|
5
|
+
}
|
|
6
|
+
_modules = modules;
|
|
7
|
+
}
|
|
8
|
+
function getModules() {
|
|
9
|
+
if (!_modules) {
|
|
10
|
+
throw new Error("[Bootstrap] Modules not registered. Call registerModules() at bootstrap.");
|
|
11
|
+
}
|
|
12
|
+
return _modules;
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
getModules,
|
|
16
|
+
registerModules
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/modules/registry.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Module } from '@open-mercato/shared/modules/registry'\n\n// Registration pattern for publishable packages\nlet _modules: Module[] | null = null\n\nexport function registerModules(modules: Module[]) {\n if (_modules !== null && process.env.NODE_ENV === 'development') {\n console.debug('[Bootstrap] Modules re-registered (this may occur during HMR)')\n }\n _modules = modules\n}\n\nexport function getModules(): Module[] {\n if (!_modules) {\n throw new Error('[Bootstrap] Modules not registered. Call registerModules() at bootstrap.')\n }\n return _modules\n}\n"],
|
|
5
|
+
"mappings": "AAGA,IAAI,WAA4B;AAEzB,SAAS,gBAAgB,SAAmB;AACjD,MAAI,aAAa,QAAQ,QAAQ,IAAI,aAAa,eAAe;AAC/D,YAAQ,MAAM,+DAA+D;AAAA,EAC/E;AACA,aAAW;AACb;AAEO,SAAS,aAAuB;AACrC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,0EAA0E;AAAA,EAC5F;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const defaultCreateResponseSchema = z.object({ id: z.string().uuid().nullable() });
|
|
3
|
+
const defaultOkResponseSchema = z.object({ ok: z.literal(true) });
|
|
4
|
+
function createPagedListResponseSchema(itemSchema, options = {}) {
|
|
5
|
+
const paginationMetaOptional = options.paginationMetaOptional ?? false;
|
|
6
|
+
return z.object({
|
|
7
|
+
items: z.array(itemSchema),
|
|
8
|
+
total: z.number(),
|
|
9
|
+
page: paginationMetaOptional ? z.number().optional() : z.number(),
|
|
10
|
+
pageSize: paginationMetaOptional ? z.number().optional() : z.number(),
|
|
11
|
+
totalPages: z.number()
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function resolveDefault(factory, ctx, fallback) {
|
|
15
|
+
if (typeof factory === "function") return factory(ctx);
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
function createCrudOpenApiFactory(config) {
|
|
19
|
+
return function createCrudOpenApi(options) {
|
|
20
|
+
const {
|
|
21
|
+
resourceName,
|
|
22
|
+
pluralName,
|
|
23
|
+
tag,
|
|
24
|
+
description,
|
|
25
|
+
querySchema,
|
|
26
|
+
listResponseSchema,
|
|
27
|
+
create,
|
|
28
|
+
update,
|
|
29
|
+
del
|
|
30
|
+
} = options;
|
|
31
|
+
const plural = pluralName ?? `${resourceName}s`;
|
|
32
|
+
const resourceLower = resourceName.toLowerCase();
|
|
33
|
+
const pluralLower = plural.toLowerCase();
|
|
34
|
+
const context = {
|
|
35
|
+
resourceName,
|
|
36
|
+
resourceLower,
|
|
37
|
+
pluralName: plural,
|
|
38
|
+
pluralLower
|
|
39
|
+
};
|
|
40
|
+
const fallbackCreateResponseSchema = config.defaultCreateResponseSchema ?? defaultCreateResponseSchema;
|
|
41
|
+
const fallbackOkResponseSchema = config.defaultOkResponseSchema ?? defaultOkResponseSchema;
|
|
42
|
+
const methods = {};
|
|
43
|
+
methods.GET = {
|
|
44
|
+
summary: `List ${pluralLower}`,
|
|
45
|
+
description: description ?? resolveDefault(config.makeListDescription, context, `Returns a paginated collection of ${pluralLower}.`),
|
|
46
|
+
query: querySchema,
|
|
47
|
+
responses: [
|
|
48
|
+
{
|
|
49
|
+
status: 200,
|
|
50
|
+
description: `Paginated ${pluralLower}`,
|
|
51
|
+
schema: listResponseSchema
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
};
|
|
55
|
+
if (create) {
|
|
56
|
+
const createDescription = create.description ?? resolveDefault(config.makeCreateDescription, context, `Creates a new ${resourceLower}.`);
|
|
57
|
+
const createBodyDescription = resolveDefault(
|
|
58
|
+
config.makeCreateRequestBodyDescription,
|
|
59
|
+
context,
|
|
60
|
+
create.description ?? `Payload describing the ${resourceLower} to create.`
|
|
61
|
+
);
|
|
62
|
+
methods.POST = {
|
|
63
|
+
summary: `Create ${resourceLower}`,
|
|
64
|
+
description: createDescription,
|
|
65
|
+
requestBody: {
|
|
66
|
+
schema: create.schema,
|
|
67
|
+
description: createBodyDescription
|
|
68
|
+
},
|
|
69
|
+
responses: [
|
|
70
|
+
{
|
|
71
|
+
status: create.status ?? 201,
|
|
72
|
+
description: `${resourceName} created`,
|
|
73
|
+
schema: create.responseSchema ?? fallbackCreateResponseSchema
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (update) {
|
|
79
|
+
const updateDescription = update.description ?? resolveDefault(config.makeUpdateDescription, context, `Updates an existing ${resourceLower} by id.`);
|
|
80
|
+
const updateBodyDescription = resolveDefault(
|
|
81
|
+
config.makeUpdateRequestBodyDescription,
|
|
82
|
+
context,
|
|
83
|
+
update.description ?? `Fields to update on the ${resourceLower}.`
|
|
84
|
+
);
|
|
85
|
+
methods.PUT = {
|
|
86
|
+
summary: `Update ${resourceLower}`,
|
|
87
|
+
description: updateDescription,
|
|
88
|
+
requestBody: {
|
|
89
|
+
schema: update.schema,
|
|
90
|
+
description: updateBodyDescription
|
|
91
|
+
},
|
|
92
|
+
responses: [
|
|
93
|
+
{
|
|
94
|
+
status: 200,
|
|
95
|
+
description: `${resourceName} updated`,
|
|
96
|
+
schema: update.responseSchema ?? fallbackOkResponseSchema
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (del) {
|
|
102
|
+
const deleteDescription = del.description ?? resolveDefault(config.makeDeleteDescription, context, `Deletes a ${resourceLower} identified by id.`);
|
|
103
|
+
const deleteBodyDescription = resolveDefault(
|
|
104
|
+
config.makeDeleteRequestBodyDescription,
|
|
105
|
+
context,
|
|
106
|
+
del.description ?? "Identifier payload."
|
|
107
|
+
);
|
|
108
|
+
methods.DELETE = {
|
|
109
|
+
summary: `Delete ${resourceLower}`,
|
|
110
|
+
description: deleteDescription,
|
|
111
|
+
requestBody: del.schema ? {
|
|
112
|
+
schema: del.schema,
|
|
113
|
+
description: deleteBodyDescription
|
|
114
|
+
} : void 0,
|
|
115
|
+
responses: [
|
|
116
|
+
{
|
|
117
|
+
status: 200,
|
|
118
|
+
description: `${resourceName} deleted`,
|
|
119
|
+
schema: del.responseSchema ?? fallbackOkResponseSchema
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
tag: tag ?? config.defaultTag,
|
|
126
|
+
summary: `${resourceName} management`,
|
|
127
|
+
methods
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
createCrudOpenApiFactory,
|
|
133
|
+
createPagedListResponseSchema,
|
|
134
|
+
defaultCreateResponseSchema,
|
|
135
|
+
defaultOkResponseSchema
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=crud.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/openapi/crud.ts"],
|
|
4
|
+
"sourcesContent": ["import { z, type ZodTypeAny } from 'zod'\nimport type { OpenApiRouteDoc } from './types'\n\nexport const defaultCreateResponseSchema = z.object({ id: z.string().uuid().nullable() })\nexport const defaultOkResponseSchema = z.object({ ok: z.literal(true) })\n\nexport type PagedListResponseOptions = {\n paginationMetaOptional?: boolean\n}\n\nexport function createPagedListResponseSchema(itemSchema: ZodTypeAny, options: PagedListResponseOptions = {}) {\n const paginationMetaOptional = options.paginationMetaOptional ?? false\n\n return z.object({\n items: z.array(itemSchema),\n total: z.number(),\n page: paginationMetaOptional ? z.number().optional() : z.number(),\n pageSize: paginationMetaOptional ? z.number().optional() : z.number(),\n totalPages: z.number(),\n })\n}\n\ntype CrudMethodConfig = {\n schema: ZodTypeAny\n description?: string\n responseSchema?: ZodTypeAny\n}\n\ntype CrudCreateConfig = CrudMethodConfig & {\n status?: number\n}\n\ntype CrudDeleteConfig = {\n schema?: ZodTypeAny\n description?: string\n responseSchema?: ZodTypeAny\n}\n\nexport type CrudOpenApiOptions = {\n tag?: string\n resourceName: string\n pluralName?: string\n description?: string\n querySchema?: ZodTypeAny\n listResponseSchema: ZodTypeAny\n create?: CrudCreateConfig\n update?: CrudMethodConfig\n del?: CrudDeleteConfig\n}\n\nexport type CrudTextContext = {\n resourceName: string\n resourceLower: string\n pluralName: string\n pluralLower: string\n}\n\nexport type CrudOpenApiFactoryConfig = {\n defaultTag: string\n defaultCreateResponseSchema?: ZodTypeAny\n defaultOkResponseSchema?: ZodTypeAny\n makeListDescription?: (ctx: CrudTextContext) => string\n makeCreateDescription?: (ctx: CrudTextContext) => string\n makeCreateRequestBodyDescription?: (ctx: CrudTextContext) => string\n makeUpdateDescription?: (ctx: CrudTextContext) => string\n makeUpdateRequestBodyDescription?: (ctx: CrudTextContext) => string\n makeDeleteDescription?: (ctx: CrudTextContext) => string\n makeDeleteRequestBodyDescription?: (ctx: CrudTextContext) => string\n}\n\nfunction resolveDefault(\n factory: ((ctx: CrudTextContext) => string) | undefined,\n ctx: CrudTextContext,\n fallback: string,\n) {\n if (typeof factory === 'function') return factory(ctx)\n return fallback\n}\n\nexport function createCrudOpenApiFactory(config: CrudOpenApiFactoryConfig) {\n return function createCrudOpenApi(options: CrudOpenApiOptions): OpenApiRouteDoc {\n const {\n resourceName,\n pluralName,\n tag,\n description,\n querySchema,\n listResponseSchema,\n create,\n update,\n del,\n } = options\n\n const plural = pluralName ?? `${resourceName}s`\n const resourceLower = resourceName.toLowerCase()\n const pluralLower = plural.toLowerCase()\n const context: CrudTextContext = {\n resourceName,\n resourceLower,\n pluralName: plural,\n pluralLower,\n }\n\n const fallbackCreateResponseSchema = config.defaultCreateResponseSchema ?? defaultCreateResponseSchema\n const fallbackOkResponseSchema = config.defaultOkResponseSchema ?? defaultOkResponseSchema\n\n const methods: NonNullable<OpenApiRouteDoc['methods']> = {}\n\n methods.GET = {\n summary: `List ${pluralLower}`,\n description:\n description ?? resolveDefault(config.makeListDescription, context, `Returns a paginated collection of ${pluralLower}.`),\n query: querySchema,\n responses: [\n {\n status: 200,\n description: `Paginated ${pluralLower}`,\n schema: listResponseSchema,\n },\n ],\n }\n\n if (create) {\n const createDescription =\n create.description ??\n resolveDefault(config.makeCreateDescription, context, `Creates a new ${resourceLower}.`)\n\n const createBodyDescription =\n resolveDefault(\n config.makeCreateRequestBodyDescription,\n context,\n create.description ?? `Payload describing the ${resourceLower} to create.`,\n )\n\n methods.POST = {\n summary: `Create ${resourceLower}`,\n description: createDescription,\n requestBody: {\n schema: create.schema,\n description: createBodyDescription,\n },\n responses: [\n {\n status: create.status ?? 201,\n description: `${resourceName} created`,\n schema: create.responseSchema ?? fallbackCreateResponseSchema,\n },\n ],\n }\n }\n\n if (update) {\n const updateDescription =\n update.description ??\n resolveDefault(config.makeUpdateDescription, context, `Updates an existing ${resourceLower} by id.`)\n\n const updateBodyDescription =\n resolveDefault(\n config.makeUpdateRequestBodyDescription,\n context,\n update.description ?? `Fields to update on the ${resourceLower}.`,\n )\n\n methods.PUT = {\n summary: `Update ${resourceLower}`,\n description: updateDescription,\n requestBody: {\n schema: update.schema,\n description: updateBodyDescription,\n },\n responses: [\n {\n status: 200,\n description: `${resourceName} updated`,\n schema: update.responseSchema ?? fallbackOkResponseSchema,\n },\n ],\n }\n }\n\n if (del) {\n const deleteDescription =\n del.description ??\n resolveDefault(config.makeDeleteDescription, context, `Deletes a ${resourceLower} identified by id.`)\n\n const deleteBodyDescription =\n resolveDefault(\n config.makeDeleteRequestBodyDescription,\n context,\n del.description ?? 'Identifier payload.',\n )\n\n methods.DELETE = {\n summary: `Delete ${resourceLower}`,\n description: deleteDescription,\n requestBody: del.schema\n ? {\n schema: del.schema,\n description: deleteBodyDescription,\n }\n : undefined,\n responses: [\n {\n status: 200,\n description: `${resourceName} deleted`,\n schema: del.responseSchema ?? fallbackOkResponseSchema,\n },\n ],\n }\n }\n\n return {\n tag: tag ?? config.defaultTag,\n summary: `${resourceName} management`,\n methods,\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|