@hexclave/shared 1.0.2 → 1.0.5
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/dist/ai/unified-prompts/reminders.js +4 -3
- package/dist/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts +3 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +217 -30
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.d.ts.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.js +1 -0
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +18 -6
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +23 -8
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js.map +1 -1
- package/dist/config/schema.d.ts +63 -63
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +5 -5
- package/dist/config/schema.js.map +1 -1
- package/dist/config-authoring.d.ts +4 -4
- package/dist/config-authoring.d.ts.map +1 -1
- package/dist/config-authoring.js +2 -2
- package/dist/config-authoring.js.map +1 -1
- package/dist/config-rendering.d.ts +4 -4
- package/dist/config-rendering.d.ts.map +1 -1
- package/dist/config-rendering.js +19 -18
- package/dist/config-rendering.js.map +1 -1
- package/dist/esm/ai/unified-prompts/reminders.js +4 -3
- package/dist/esm/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts +3 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +216 -31
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.d.ts.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.js +1 -0
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +18 -6
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +23 -8
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js.map +1 -1
- package/dist/esm/config/schema.d.ts +63 -63
- package/dist/esm/config/schema.d.ts.map +1 -1
- package/dist/esm/config/schema.js +5 -5
- package/dist/esm/config/schema.js.map +1 -1
- package/dist/esm/config-authoring.d.ts +4 -4
- package/dist/esm/config-authoring.d.ts.map +1 -1
- package/dist/esm/config-authoring.js +2 -2
- package/dist/esm/config-authoring.js.map +1 -1
- package/dist/esm/config-rendering.d.ts +4 -4
- package/dist/esm/config-rendering.d.ts.map +1 -1
- package/dist/esm/config-rendering.js +15 -14
- package/dist/esm/config-rendering.js.map +1 -1
- package/dist/esm/helpers/vault/client-side.d.ts.map +1 -1
- package/dist/esm/helpers/vault/client-side.js.map +1 -1
- package/dist/esm/helpers/vault/server-side.d.ts.map +1 -1
- package/dist/esm/helpers/vault/server-side.js.map +1 -1
- package/dist/esm/hexclave-config-file.d.ts +15 -0
- package/dist/esm/hexclave-config-file.d.ts.map +1 -0
- package/dist/esm/{stack-config-file.js → hexclave-config-file.js} +7 -7
- package/dist/esm/hexclave-config-file.js.map +1 -0
- package/dist/esm/hooks/use-async-callback.js +1 -1
- package/dist/esm/hooks/use-async-external-store.js +1 -1
- package/dist/esm/hooks/use-strict-memo.js +1 -1
- package/dist/esm/interface/admin-metrics.d.ts +8 -8
- package/dist/esm/interface/admin-metrics.js.map +1 -1
- package/dist/esm/interface/client-interface.js +2 -2
- package/dist/esm/interface/client-interface.js.map +1 -1
- package/dist/esm/interface/conversations.d.ts +32 -32
- package/dist/esm/interface/crud/current-user.d.ts +9 -9
- package/dist/esm/interface/crud/email-outbox.d.ts +200 -200
- package/dist/esm/interface/crud/products.d.ts +13 -13
- package/dist/esm/interface/crud/products.d.ts.map +1 -1
- package/dist/esm/interface/crud/project-api-keys.d.ts +4 -4
- package/dist/esm/interface/crud/project-permissions.js +5 -5
- package/dist/esm/interface/crud/project-permissions.js.map +1 -1
- package/dist/esm/interface/crud/projects.d.ts +36 -36
- package/dist/esm/interface/crud/team-member-profiles.d.ts +18 -18
- package/dist/esm/interface/crud/team-permissions.js +5 -5
- package/dist/esm/interface/crud/team-permissions.js.map +1 -1
- package/dist/esm/interface/crud/transactions.d.ts +6 -6
- package/dist/esm/interface/crud/transactions.d.ts.map +1 -1
- package/dist/esm/interface/crud/users.d.ts +12 -12
- package/dist/esm/interface/page-component-versions.js +107 -107
- package/dist/esm/interface/page-component-versions.js.map +1 -1
- package/dist/esm/interface/webhooks.d.ts +2 -2
- package/dist/esm/known-errors.d.ts +2 -2
- package/dist/esm/known-errors.js +4 -4
- package/dist/esm/known-errors.js.map +1 -1
- package/dist/esm/schema-fields.d.ts +17 -7
- package/dist/esm/schema-fields.d.ts.map +1 -1
- package/dist/esm/schema-fields.js +26 -16
- package/dist/esm/schema-fields.js.map +1 -1
- package/dist/esm/sessions.d.ts +7 -7
- package/dist/esm/utils/crypto.d.ts.map +1 -1
- package/dist/esm/utils/crypto.js.map +1 -1
- package/dist/esm/utils/currency-constants.d.ts +6 -0
- package/dist/esm/utils/currency-constants.d.ts.map +1 -1
- package/dist/esm/utils/currency-constants.js.map +1 -1
- package/dist/esm/utils/dev-env-state-path.d.ts +3 -3
- package/dist/esm/utils/dev-env-state-path.d.ts.map +1 -1
- package/dist/esm/utils/dev-env-state-path.js +4 -4
- package/dist/esm/utils/dev-env-state-path.js.map +1 -1
- package/dist/esm/utils/errors.js +2 -2
- package/dist/esm/utils/errors.js.map +1 -1
- package/dist/esm/utils/esbuild.d.ts.map +1 -1
- package/dist/esm/utils/esbuild.js +0 -1
- package/dist/esm/utils/esbuild.js.map +1 -1
- package/dist/esm/utils/featurebase.d.ts +3 -3
- package/dist/esm/utils/featurebase.d.ts.map +1 -1
- package/dist/esm/utils/featurebase.js +15 -15
- package/dist/esm/utils/featurebase.js.map +1 -1
- package/dist/esm/utils/fs.js +6 -6
- package/dist/esm/utils/fs.js.map +1 -1
- package/dist/esm/utils/globals.d.ts.map +1 -1
- package/dist/esm/utils/globals.js +10 -10
- package/dist/esm/utils/globals.js.map +1 -1
- package/dist/esm/utils/jwt.d.ts.map +1 -1
- package/dist/esm/utils/jwt.js +3 -3
- package/dist/esm/utils/jwt.js.map +1 -1
- package/dist/esm/utils/redirect-urls.d.ts +3 -3
- package/dist/esm/utils/redirect-urls.d.ts.map +1 -1
- package/dist/esm/utils/redirect-urls.js +5 -5
- package/dist/esm/utils/redirect-urls.js.map +1 -1
- package/dist/esm/utils/urls.js.map +1 -1
- package/dist/helpers/vault/client-side.d.ts.map +1 -1
- package/dist/helpers/vault/client-side.js.map +1 -1
- package/dist/helpers/vault/server-side.d.ts.map +1 -1
- package/dist/helpers/vault/server-side.js.map +1 -1
- package/dist/hexclave-config-file.d.ts +15 -0
- package/dist/hexclave-config-file.d.ts.map +1 -0
- package/dist/{stack-config-file.js → hexclave-config-file.js} +8 -8
- package/dist/hexclave-config-file.js.map +1 -0
- package/dist/hooks/use-async-callback.js +1 -1
- package/dist/hooks/use-async-external-store.js +1 -1
- package/dist/hooks/use-strict-memo.js +1 -1
- package/dist/interface/admin-metrics.d.ts +8 -8
- package/dist/interface/admin-metrics.js.map +1 -1
- package/dist/interface/client-interface.js +2 -2
- package/dist/interface/client-interface.js.map +1 -1
- package/dist/interface/conversations.d.ts +32 -32
- package/dist/interface/crud/current-user.d.ts +9 -9
- package/dist/interface/crud/email-outbox.d.ts +200 -200
- package/dist/interface/crud/products.d.ts +13 -13
- package/dist/interface/crud/products.d.ts.map +1 -1
- package/dist/interface/crud/project-api-keys.d.ts +4 -4
- package/dist/interface/crud/project-permissions.js +5 -5
- package/dist/interface/crud/project-permissions.js.map +1 -1
- package/dist/interface/crud/projects.d.ts +36 -36
- package/dist/interface/crud/team-member-profiles.d.ts +18 -18
- package/dist/interface/crud/team-permissions.js +5 -5
- package/dist/interface/crud/team-permissions.js.map +1 -1
- package/dist/interface/crud/transactions.d.ts +6 -6
- package/dist/interface/crud/transactions.d.ts.map +1 -1
- package/dist/interface/crud/users.d.ts +12 -12
- package/dist/interface/page-component-versions.js +107 -107
- package/dist/interface/page-component-versions.js.map +1 -1
- package/dist/interface/webhooks.d.ts +2 -2
- package/dist/known-errors.d.ts +2 -2
- package/dist/known-errors.js +4 -4
- package/dist/known-errors.js.map +1 -1
- package/dist/schema-fields.d.ts +17 -7
- package/dist/schema-fields.d.ts.map +1 -1
- package/dist/schema-fields.js +26 -16
- package/dist/schema-fields.js.map +1 -1
- package/dist/sessions.d.ts +7 -7
- package/dist/utils/crypto.d.ts.map +1 -1
- package/dist/utils/crypto.js.map +1 -1
- package/dist/utils/currency-constants.d.ts +6 -0
- package/dist/utils/currency-constants.d.ts.map +1 -1
- package/dist/utils/currency-constants.js.map +1 -1
- package/dist/utils/dev-env-state-path.d.ts +3 -3
- package/dist/utils/dev-env-state-path.d.ts.map +1 -1
- package/dist/utils/dev-env-state-path.js +5 -5
- package/dist/utils/dev-env-state-path.js.map +1 -1
- package/dist/utils/errors.js +2 -2
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/esbuild.d.ts.map +1 -1
- package/dist/utils/esbuild.js +0 -1
- package/dist/utils/esbuild.js.map +1 -1
- package/dist/utils/featurebase.d.ts +3 -3
- package/dist/utils/featurebase.d.ts.map +1 -1
- package/dist/utils/featurebase.js +15 -15
- package/dist/utils/featurebase.js.map +1 -1
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/globals.d.ts.map +1 -1
- package/dist/utils/globals.js +10 -10
- package/dist/utils/globals.js.map +1 -1
- package/dist/utils/jwt.d.ts.map +1 -1
- package/dist/utils/jwt.js +3 -3
- package/dist/utils/jwt.js.map +1 -1
- package/dist/utils/redirect-urls.d.ts +3 -3
- package/dist/utils/redirect-urls.d.ts.map +1 -1
- package/dist/utils/redirect-urls.js +5 -5
- package/dist/utils/redirect-urls.js.map +1 -1
- package/dist/utils/urls.js.map +1 -1
- package/package.json +2 -1
- package/src/ai/image-limits.ts +62 -0
- package/src/ai/llms/llms.ts +36 -0
- package/src/ai/unified-prompts/reminders.ts +27 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.ts +1047 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/brain.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/cli-help.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/config-docs.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/custom-components-instructions.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/dashboard-instructions.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/docs-index.ts +80 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.ts +322 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/sdk-interface-source.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt.ts +72 -0
- package/src/apps/apps-config.ts +177 -0
- package/src/apps/apps-ui.tsx +112 -0
- package/src/config/README.md +154 -0
- package/src/config/db-sync-mappings.ts +2293 -0
- package/src/config/format.ts +388 -0
- package/src/config/migrate-catalogs-to-product-lines.ts +475 -0
- package/src/config/schema-fuzzer.test.ts +377 -0
- package/src/config/schema.ts +1507 -0
- package/src/config-authoring.test.ts +52 -0
- package/src/config-authoring.ts +37 -0
- package/src/config-rendering.ts +142 -0
- package/src/crud.tsx +275 -0
- package/src/global.d.ts +1 -0
- package/src/helpers/emails.ts +250 -0
- package/src/helpers/init-prompt.ts +39 -0
- package/src/helpers/password.ts +16 -0
- package/src/helpers/production-mode.ts +58 -0
- package/src/helpers/support-sla.test.ts +124 -0
- package/src/helpers/support-sla.ts +93 -0
- package/src/helpers/vault/client-side.ts +92 -0
- package/src/helpers/vault/server-side.ts +153 -0
- package/src/hexclave-config-file.ts +120 -0
- package/src/hooks/use-async-callback.tsx +43 -0
- package/src/hooks/use-async-external-store.tsx +24 -0
- package/src/hooks/use-hash.tsx +14 -0
- package/src/hooks/use-hover.tsx +88 -0
- package/src/hooks/use-strict-memo.tsx +157 -0
- package/src/index.ts +17 -0
- package/src/interface/admin-interface.ts +1043 -0
- package/src/interface/admin-metrics.ts +214 -0
- package/src/interface/client-interface.test.ts +765 -0
- package/src/interface/client-interface.ts +2586 -0
- package/src/interface/conversations.ts +109 -0
- package/src/interface/crud/analytics.ts +11 -0
- package/src/interface/crud/connected-accounts.ts +52 -0
- package/src/interface/crud/contact-channels.ts +74 -0
- package/src/interface/crud/current-user.ts +72 -0
- package/src/interface/crud/email-outbox.ts +263 -0
- package/src/interface/crud/email-templates.ts +50 -0
- package/src/interface/crud/emails.ts +22 -0
- package/src/interface/crud/internal-api-keys.ts +69 -0
- package/src/interface/crud/invoices.ts +36 -0
- package/src/interface/crud/items.ts +24 -0
- package/src/interface/crud/notification-preferences.ts +33 -0
- package/src/interface/crud/oauth-providers.ts +91 -0
- package/src/interface/crud/products.ts +42 -0
- package/src/interface/crud/project-api-keys.ts +100 -0
- package/src/interface/crud/project-permissions.ts +118 -0
- package/src/interface/crud/projects.ts +229 -0
- package/src/interface/crud/session-replays.ts +85 -0
- package/src/interface/crud/sessions.ts +66 -0
- package/src/interface/crud/sign-up-rules.ts +12 -0
- package/src/interface/crud/svix-token.ts +20 -0
- package/src/interface/crud/team-invitation-details.ts +22 -0
- package/src/interface/crud/team-invitation.ts +35 -0
- package/src/interface/crud/team-member-profiles.ts +61 -0
- package/src/interface/crud/team-memberships.ts +56 -0
- package/src/interface/crud/team-permissions.ts +119 -0
- package/src/interface/crud/teams.ts +142 -0
- package/src/interface/crud/transactions.ts +131 -0
- package/src/interface/crud/users.ts +185 -0
- package/src/interface/handler-urls.ts +74 -0
- package/src/interface/page-component-versions.ts +1702 -0
- package/src/interface/server-interface.ts +1146 -0
- package/src/interface/webhooks.ts +28 -0
- package/src/known-errors.tsx +2031 -0
- package/src/local-emulator.ts +5 -0
- package/src/payments/payment-methods.ts +167 -0
- package/src/payments/stripe-limits.ts +18 -0
- package/src/plans.ts +107 -0
- package/src/schema-fields.ts +944 -0
- package/src/sessions.ts +310 -0
- package/src/utils/api-keys.tsx +122 -0
- package/src/utils/arrays.tsx +248 -0
- package/src/utils/auth-methods.ts +8 -0
- package/src/utils/base64.tsx +24 -0
- package/src/utils/booleans.tsx +34 -0
- package/src/utils/browser-compat.tsx +17 -0
- package/src/utils/bytes.tsx +280 -0
- package/src/utils/caches.tsx +280 -0
- package/src/utils/cel-fields.ts +92 -0
- package/src/utils/cloud-hosts.tsx +92 -0
- package/src/utils/compile-time.tsx +11 -0
- package/src/utils/country-codes.ts +39 -0
- package/src/utils/crypto.tsx +174 -0
- package/src/utils/currencies.tsx +53 -0
- package/src/utils/currency-constants.tsx +51 -0
- package/src/utils/dates.tsx +246 -0
- package/src/utils/dev-env-state-path.ts +14 -0
- package/src/utils/dom.tsx +7 -0
- package/src/utils/env.tsx +117 -0
- package/src/utils/errors.tsx +284 -0
- package/src/utils/esbuild.tsx +235 -0
- package/src/utils/featurebase.tsx +247 -0
- package/src/utils/fs.tsx +33 -0
- package/src/utils/functions.tsx +22 -0
- package/src/utils/geo.tsx +16 -0
- package/src/utils/globals.tsx +48 -0
- package/src/utils/hashes.tsx +52 -0
- package/src/utils/html.tsx +60 -0
- package/src/utils/http.tsx +91 -0
- package/src/utils/ips.tsx +47 -0
- package/src/utils/json.tsx +200 -0
- package/src/utils/jsx-editable-transpiler.test.ts +156 -0
- package/src/utils/jsx-editable-transpiler.tsx +401 -0
- package/src/utils/jwt.tsx +170 -0
- package/src/utils/locks.tsx +71 -0
- package/src/utils/maps.tsx +407 -0
- package/src/utils/math.tsx +18 -0
- package/src/utils/monkey-patch.tsx +29 -0
- package/src/utils/node-http.tsx +47 -0
- package/src/utils/numbers.tsx +82 -0
- package/src/utils/oauth.tsx +9 -0
- package/src/utils/objects.tsx +581 -0
- package/src/utils/paginated-lists.test.ts +1039 -0
- package/src/utils/paginated-lists.tsx +479 -0
- package/src/utils/passkey.tsx +1 -0
- package/src/utils/promises.tsx +540 -0
- package/src/utils/proxies.tsx +212 -0
- package/src/utils/react.tsx +308 -0
- package/src/utils/redirect-urls.tsx +299 -0
- package/src/utils/regex.tsx +10 -0
- package/src/utils/results.tsx +411 -0
- package/src/utils/sentry.tsx +20 -0
- package/src/utils/stores.tsx +238 -0
- package/src/utils/strings.nicify.test.ts +253 -0
- package/src/utils/strings.tsx +723 -0
- package/src/utils/telemetry.tsx +37 -0
- package/src/utils/turnstile-browser.ts +106 -0
- package/src/utils/turnstile-flow.test.ts +101 -0
- package/src/utils/turnstile-flow.ts +266 -0
- package/src/utils/turnstile.ts +34 -0
- package/src/utils/typed-arrays.tsx +17 -0
- package/src/utils/types.tsx +208 -0
- package/src/utils/unicode.tsx +24 -0
- package/src/utils/urls.tsx +411 -0
- package/src/utils/uuids.tsx +47 -0
- package/dist/esm/stack-config-file.d.ts +0 -15
- package/dist/esm/stack-config-file.d.ts.map +0 -1
- package/dist/esm/stack-config-file.js.map +0 -1
- package/dist/stack-config-file.d.ts +0 -15
- package/dist/stack-config-file.d.ts.map +0 -1
- package/dist/stack-config-file.js.map +0 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { generateRandomValues } from "./crypto";
|
|
2
|
+
|
|
3
|
+
export function generateUuid() {
|
|
4
|
+
// crypto.randomUuid is not supported in all browsers, so this is a polyfill
|
|
5
|
+
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
|
|
6
|
+
(+c ^ generateRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
import.meta.vitest?.test("generateUuid", ({ expect }) => {
|
|
10
|
+
// Test that the function returns a valid UUID
|
|
11
|
+
const uuid = generateUuid();
|
|
12
|
+
expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
|
13
|
+
|
|
14
|
+
// Test that multiple calls generate different UUIDs
|
|
15
|
+
const uuid2 = generateUuid();
|
|
16
|
+
expect(uuid).not.toBe(uuid2);
|
|
17
|
+
|
|
18
|
+
// Test that the UUID is version 4 (random)
|
|
19
|
+
expect(uuid.charAt(14)).toBe('4');
|
|
20
|
+
|
|
21
|
+
// Test that the UUID has the correct variant (8, 9, a, or b in position 19)
|
|
22
|
+
expect('89ab').toContain(uuid.charAt(19));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export function isUuid(str: string) {
|
|
26
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(str);
|
|
27
|
+
}
|
|
28
|
+
import.meta.vitest?.test("isUuid", ({ expect }) => {
|
|
29
|
+
// Test with valid UUIDs
|
|
30
|
+
expect(isUuid("123e4567-e89b-42d3-a456-426614174000")).toBe(true);
|
|
31
|
+
expect(isUuid("123e4567-e89b-42d3-8456-426614174000")).toBe(true);
|
|
32
|
+
expect(isUuid("123e4567-e89b-42d3-9456-426614174000")).toBe(true);
|
|
33
|
+
expect(isUuid("123e4567-e89b-42d3-a456-426614174000")).toBe(true);
|
|
34
|
+
expect(isUuid("123e4567-e89b-42d3-b456-426614174000")).toBe(true);
|
|
35
|
+
|
|
36
|
+
// Test with invalid UUIDs
|
|
37
|
+
expect(isUuid("")).toBe(false);
|
|
38
|
+
expect(isUuid("not-a-uuid")).toBe(false);
|
|
39
|
+
expect(isUuid("123e4567-e89b-12d3-a456-426614174000")).toBe(false); // Wrong version (not 4)
|
|
40
|
+
expect(isUuid("123e4567-e89b-42d3-c456-426614174000")).toBe(false); // Wrong variant (not 8, 9, a, or b)
|
|
41
|
+
expect(isUuid("123e4567-e89b-42d3-a456-42661417400")).toBe(false); // Too short
|
|
42
|
+
expect(isUuid("123e4567-e89b-42d3-a456-4266141740000")).toBe(false); // Too long
|
|
43
|
+
expect(isUuid("123e4567-e89b-42d3-a456_426614174000")).toBe(false); // Wrong format (underscore instead of dash)
|
|
44
|
+
|
|
45
|
+
// Test with uppercase letters (should fail as UUID should be lowercase)
|
|
46
|
+
expect(isUuid("123E4567-E89B-42D3-A456-426614174000")).toBe(false);
|
|
47
|
+
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/stack-config-file.d.ts
|
|
2
|
-
declare const showOnboardingStackConfigValue = "show-onboarding";
|
|
3
|
-
/**
|
|
4
|
-
* Renders a config object into the source text of a `stack.config.ts` file.
|
|
5
|
-
*
|
|
6
|
-
* Browser-safe: kept here (next to `parseStackConfigFileContent`) instead of in
|
|
7
|
-
* `config-rendering.ts` so dashboard client code can render config files
|
|
8
|
-
* without pulling in `fs` / `path`.
|
|
9
|
-
*/
|
|
10
|
-
declare function renderConfigFileContent(config: unknown, importPackage?: string): string;
|
|
11
|
-
type ParsedStackConfig = Record<string, unknown> | typeof showOnboardingStackConfigValue;
|
|
12
|
-
declare function parseStackConfigFileContent(content: string, filePath: string): ParsedStackConfig;
|
|
13
|
-
//#endregion
|
|
14
|
-
export { parseStackConfigFileContent, renderConfigFileContent, showOnboardingStackConfigValue };
|
|
15
|
-
//# sourceMappingURL=stack-config-file.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stack-config-file.d.ts","names":[],"sources":["../../src/stack-config-file.ts"],"mappings":";cAIa,8BAAA;AAAb;;;;;AAWA;;AAXA,iBAWgB,uBAAA,CAAwB,MAAA,WAAiB,aAAA;AAAA,KAmBpD,iBAAA,GAAoB,MAAA,2BAAiC,8BAAA;AAAA,iBA8D1C,2BAAA,CAA4B,OAAA,UAAiB,QAAA,WAAmB,iBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stack-config-file.js","names":[],"sources":["../../src/stack-config-file.ts"],"sourcesContent":["import * as parser from \"@babel/parser\";\nimport * as t from \"@babel/types\";\nimport { isValidConfig, normalize } from \"./config/format\";\n\nexport const showOnboardingStackConfigValue = \"show-onboarding\";\n\nconst DEFAULT_CONFIG_IMPORT_PACKAGE = \"@hexclave/js\";\n\n/**\n * Renders a config object into the source text of a `stack.config.ts` file.\n *\n * Browser-safe: kept here (next to `parseStackConfigFileContent`) instead of in\n * `config-rendering.ts` so dashboard client code can render config files\n * without pulling in `fs` / `path`.\n */\nexport function renderConfigFileContent(config: unknown, importPackage?: string): string {\n if (!isValidConfig(config)) {\n throw new Error(\"Invalid config: expected a plain object.\");\n }\n\n const droppedKeys: string[] = [];\n const normalizedConfig = normalize(config, {\n onDotIntoNonObject: \"ignore\",\n onDotIntoNull: \"empty-object\",\n droppedKeys,\n });\n if (droppedKeys.length > 0) {\n throw new Error(`Config has conflicting keys that would be dropped during normalization: ${droppedKeys.map(k => JSON.stringify(k)).join(\", \")}`);\n }\n const pkg = importPackage ?? DEFAULT_CONFIG_IMPORT_PACKAGE;\n const importLine = `import type { StackConfig } from \"${pkg}\";`;\n return `${importLine}\\n\\nexport const config: StackConfig = ${JSON.stringify(normalizedConfig, null, 2)};\\n`;\n}\n\ntype ParsedStackConfig = Record<string, unknown> | typeof showOnboardingStackConfigValue;\n\nfunction unwrapStaticConfigExpression(expression: t.Expression): t.Expression {\n if (\n t.isTSAsExpression(expression)\n || t.isTSSatisfiesExpression(expression)\n || t.isTSTypeAssertion(expression)\n || t.isTSNonNullExpression(expression)\n ) {\n return unwrapStaticConfigExpression(expression.expression);\n }\n return expression;\n}\n\nfunction evaluateStaticConfigExpression(expression: t.Expression): unknown {\n const unwrapped = unwrapStaticConfigExpression(expression);\n if (t.isStringLiteral(unwrapped)) return unwrapped.value;\n if (t.isBooleanLiteral(unwrapped)) return unwrapped.value;\n if (t.isNumericLiteral(unwrapped)) return unwrapped.value;\n if (t.isNullLiteral(unwrapped)) return null;\n if (t.isIdentifier(unwrapped) && unwrapped.name === \"undefined\") return undefined;\n if (t.isUnaryExpression(unwrapped) && unwrapped.operator === \"-\" && t.isNumericLiteral(unwrapped.argument)) {\n return -unwrapped.argument.value;\n }\n if (t.isArrayExpression(unwrapped)) {\n return unwrapped.elements.map((element) => {\n if (element == null || t.isSpreadElement(element)) {\n throw new Error(\"Config arrays cannot contain holes or spreads.\");\n }\n return evaluateStaticConfigExpression(element);\n });\n }\n if (t.isObjectExpression(unwrapped)) {\n const result: Record<string, unknown> = {};\n for (const property of unwrapped.properties) {\n if (t.isSpreadElement(property)) {\n throw new Error(\"Config objects cannot contain spreads.\");\n }\n if (property.computed) {\n throw new Error(\"Config object keys cannot be computed.\");\n }\n const key = t.isIdentifier(property.key)\n ? property.key.name\n : t.isStringLiteral(property.key) || t.isNumericLiteral(property.key)\n ? String(property.key.value)\n : null;\n if (key == null) {\n throw new Error(\"Unsupported config object key.\");\n }\n if (t.isObjectMethod(property)) {\n throw new Error(\"Config objects cannot contain methods.\");\n }\n if (!t.isExpression(property.value)) {\n throw new Error(\"Unsupported config object value.\");\n }\n result[key] = evaluateStaticConfigExpression(property.value);\n }\n return result;\n }\n throw new Error(`Unsupported config expression: ${unwrapped.type}`);\n}\n\nexport function parseStackConfigFileContent(content: string, filePath: string): ParsedStackConfig {\n if (content.trim() === \"\") return {};\n const ast = parser.parse(content, {\n sourceType: \"module\",\n plugins: [\"typescript\"],\n });\n\n for (const statement of ast.program.body) {\n if (!t.isExportNamedDeclaration(statement) || !t.isVariableDeclaration(statement.declaration)) {\n continue;\n }\n for (const declaration of statement.declaration.declarations) {\n if (!t.isIdentifier(declaration.id) || declaration.id.name !== \"config\") {\n continue;\n }\n if (declaration.init == null || !t.isExpression(declaration.init)) {\n throw new Error(`Config export in ${filePath} must have an initializer.`);\n }\n return evaluateStaticConfigExpression(declaration.init) as ParsedStackConfig;\n }\n }\n\n throw new Error(`Invalid config in ${filePath}. The file must export a plain \\`config\\` object or \"show-onboarding\".`);\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/stack-config-file.d.ts
|
|
2
|
-
declare const showOnboardingStackConfigValue = "show-onboarding";
|
|
3
|
-
/**
|
|
4
|
-
* Renders a config object into the source text of a `stack.config.ts` file.
|
|
5
|
-
*
|
|
6
|
-
* Browser-safe: kept here (next to `parseStackConfigFileContent`) instead of in
|
|
7
|
-
* `config-rendering.ts` so dashboard client code can render config files
|
|
8
|
-
* without pulling in `fs` / `path`.
|
|
9
|
-
*/
|
|
10
|
-
declare function renderConfigFileContent(config: unknown, importPackage?: string): string;
|
|
11
|
-
type ParsedStackConfig = Record<string, unknown> | typeof showOnboardingStackConfigValue;
|
|
12
|
-
declare function parseStackConfigFileContent(content: string, filePath: string): ParsedStackConfig;
|
|
13
|
-
//#endregion
|
|
14
|
-
export { parseStackConfigFileContent, renderConfigFileContent, showOnboardingStackConfigValue };
|
|
15
|
-
//# sourceMappingURL=stack-config-file.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stack-config-file.d.ts","names":[],"sources":["../src/stack-config-file.ts"],"mappings":";cAIa,8BAAA;AAAb;;;;;AAWA;;AAXA,iBAWgB,uBAAA,CAAwB,MAAA,WAAiB,aAAA;AAAA,KAmBpD,iBAAA,GAAoB,MAAA,2BAAiC,8BAAA;AAAA,iBA8D1C,2BAAA,CAA4B,OAAA,UAAiB,QAAA,WAAmB,iBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stack-config-file.js","names":["t","parser"],"sources":["../src/stack-config-file.ts"],"sourcesContent":["import * as parser from \"@babel/parser\";\nimport * as t from \"@babel/types\";\nimport { isValidConfig, normalize } from \"./config/format\";\n\nexport const showOnboardingStackConfigValue = \"show-onboarding\";\n\nconst DEFAULT_CONFIG_IMPORT_PACKAGE = \"@hexclave/js\";\n\n/**\n * Renders a config object into the source text of a `stack.config.ts` file.\n *\n * Browser-safe: kept here (next to `parseStackConfigFileContent`) instead of in\n * `config-rendering.ts` so dashboard client code can render config files\n * without pulling in `fs` / `path`.\n */\nexport function renderConfigFileContent(config: unknown, importPackage?: string): string {\n if (!isValidConfig(config)) {\n throw new Error(\"Invalid config: expected a plain object.\");\n }\n\n const droppedKeys: string[] = [];\n const normalizedConfig = normalize(config, {\n onDotIntoNonObject: \"ignore\",\n onDotIntoNull: \"empty-object\",\n droppedKeys,\n });\n if (droppedKeys.length > 0) {\n throw new Error(`Config has conflicting keys that would be dropped during normalization: ${droppedKeys.map(k => JSON.stringify(k)).join(\", \")}`);\n }\n const pkg = importPackage ?? DEFAULT_CONFIG_IMPORT_PACKAGE;\n const importLine = `import type { StackConfig } from \"${pkg}\";`;\n return `${importLine}\\n\\nexport const config: StackConfig = ${JSON.stringify(normalizedConfig, null, 2)};\\n`;\n}\n\ntype ParsedStackConfig = Record<string, unknown> | typeof showOnboardingStackConfigValue;\n\nfunction unwrapStaticConfigExpression(expression: t.Expression): t.Expression {\n if (\n t.isTSAsExpression(expression)\n || t.isTSSatisfiesExpression(expression)\n || t.isTSTypeAssertion(expression)\n || t.isTSNonNullExpression(expression)\n ) {\n return unwrapStaticConfigExpression(expression.expression);\n }\n return expression;\n}\n\nfunction evaluateStaticConfigExpression(expression: t.Expression): unknown {\n const unwrapped = unwrapStaticConfigExpression(expression);\n if (t.isStringLiteral(unwrapped)) return unwrapped.value;\n if (t.isBooleanLiteral(unwrapped)) return unwrapped.value;\n if (t.isNumericLiteral(unwrapped)) return unwrapped.value;\n if (t.isNullLiteral(unwrapped)) return null;\n if (t.isIdentifier(unwrapped) && unwrapped.name === \"undefined\") return undefined;\n if (t.isUnaryExpression(unwrapped) && unwrapped.operator === \"-\" && t.isNumericLiteral(unwrapped.argument)) {\n return -unwrapped.argument.value;\n }\n if (t.isArrayExpression(unwrapped)) {\n return unwrapped.elements.map((element) => {\n if (element == null || t.isSpreadElement(element)) {\n throw new Error(\"Config arrays cannot contain holes or spreads.\");\n }\n return evaluateStaticConfigExpression(element);\n });\n }\n if (t.isObjectExpression(unwrapped)) {\n const result: Record<string, unknown> = {};\n for (const property of unwrapped.properties) {\n if (t.isSpreadElement(property)) {\n throw new Error(\"Config objects cannot contain spreads.\");\n }\n if (property.computed) {\n throw new Error(\"Config object keys cannot be computed.\");\n }\n const key = t.isIdentifier(property.key)\n ? property.key.name\n : t.isStringLiteral(property.key) || t.isNumericLiteral(property.key)\n ? String(property.key.value)\n : null;\n if (key == null) {\n throw new Error(\"Unsupported config object key.\");\n }\n if (t.isObjectMethod(property)) {\n throw new Error(\"Config objects cannot contain methods.\");\n }\n if (!t.isExpression(property.value)) {\n throw new Error(\"Unsupported config object value.\");\n }\n result[key] = evaluateStaticConfigExpression(property.value);\n }\n return result;\n }\n throw new Error(`Unsupported config expression: ${unwrapped.type}`);\n}\n\nexport function parseStackConfigFileContent(content: string, filePath: string): ParsedStackConfig {\n if (content.trim() === \"\") return {};\n const ast = parser.parse(content, {\n sourceType: \"module\",\n plugins: [\"typescript\"],\n });\n\n for (const statement of ast.program.body) {\n if (!t.isExportNamedDeclaration(statement) || !t.isVariableDeclaration(statement.declaration)) {\n continue;\n }\n for (const declaration of statement.declaration.declarations) {\n if (!t.isIdentifier(declaration.id) || declaration.id.name !== \"config\") {\n continue;\n }\n if (declaration.init == null || !t.isExpression(declaration.init)) {\n throw new Error(`Config export in ${filePath} must have an initializer.`);\n }\n return evaluateStaticConfigExpression(declaration.init) as ParsedStackConfig;\n }\n }\n\n throw new Error(`Invalid config in ${filePath}. The file must export a plain \\`config\\` object or \"show-onboarding\".`);\n}\n"],"mappings":"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"}
|