@hexclave/shared 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/ai/unified-prompts/reminders.js +1 -1
  2. package/dist/apps/apps-config.d.ts +6 -0
  3. package/dist/apps/apps-config.js +6 -0
  4. package/dist/apps/apps-config.js.map +1 -1
  5. package/dist/config/schema.d.ts +170 -170
  6. package/dist/config-authoring.d.ts.map +1 -1
  7. package/dist/config-authoring.js.map +1 -1
  8. package/dist/config-authoring.test.js +1 -1
  9. package/dist/config-authoring.test.js.map +1 -1
  10. package/dist/config-rendering.d.ts +2 -2
  11. package/dist/config-rendering.js +16 -0
  12. package/dist/config-rendering.js.map +1 -1
  13. package/dist/esm/ai/unified-prompts/reminders.js +1 -1
  14. package/dist/esm/apps/apps-config.d.ts +6 -0
  15. package/dist/esm/apps/apps-config.js +6 -0
  16. package/dist/esm/apps/apps-config.js.map +1 -1
  17. package/dist/esm/config/schema.d.ts +170 -170
  18. package/dist/esm/config-authoring.d.ts.map +1 -1
  19. package/dist/esm/config-authoring.js.map +1 -1
  20. package/dist/esm/config-authoring.test.js +1 -1
  21. package/dist/esm/config-authoring.test.js.map +1 -1
  22. package/dist/esm/config-rendering.d.ts +2 -2
  23. package/dist/esm/config-rendering.js +16 -2
  24. package/dist/esm/config-rendering.js.map +1 -1
  25. package/dist/esm/hexclave-config-file.d.ts +24 -1
  26. package/dist/esm/hexclave-config-file.d.ts.map +1 -1
  27. package/dist/esm/hexclave-config-file.js +69 -2
  28. package/dist/esm/hexclave-config-file.js.map +1 -1
  29. package/dist/esm/interface/admin-interface.d.ts +19 -1
  30. package/dist/esm/interface/admin-interface.d.ts.map +1 -1
  31. package/dist/esm/interface/admin-interface.js +14 -0
  32. package/dist/esm/interface/admin-interface.js.map +1 -1
  33. package/dist/esm/interface/admin-metrics.d.ts +99 -5
  34. package/dist/esm/interface/admin-metrics.d.ts.map +1 -1
  35. package/dist/esm/interface/admin-metrics.js +61 -1
  36. package/dist/esm/interface/admin-metrics.js.map +1 -1
  37. package/dist/esm/interface/conversations.d.ts +35 -35
  38. package/dist/esm/interface/crud/current-user.d.ts +2 -2
  39. package/dist/esm/interface/crud/email-outbox.d.ts +66 -66
  40. package/dist/esm/interface/crud/invoices.d.ts +2 -2
  41. package/dist/esm/interface/crud/projects.d.ts +35 -35
  42. package/dist/esm/interface/crud/team-member-profiles.d.ts +10 -10
  43. package/dist/esm/interface/crud/users.d.ts +10 -10
  44. package/dist/esm/interface/webhooks.d.ts +2 -2
  45. package/dist/esm/utils/analytics-clickmap-overlay.d.ts +18 -0
  46. package/dist/esm/utils/analytics-clickmap-overlay.d.ts.map +1 -0
  47. package/dist/esm/utils/analytics-clickmap-overlay.js +19 -0
  48. package/dist/esm/utils/analytics-clickmap-overlay.js.map +1 -0
  49. package/dist/esm/utils/dev-tool.d.ts +31 -0
  50. package/dist/esm/utils/dev-tool.d.ts.map +1 -0
  51. package/dist/esm/utils/dev-tool.js +32 -0
  52. package/dist/esm/utils/dev-tool.js.map +1 -0
  53. package/dist/esm/utils/dom.d.ts +7 -1
  54. package/dist/esm/utils/dom.d.ts.map +1 -1
  55. package/dist/esm/utils/dom.js +20 -1
  56. package/dist/esm/utils/dom.js.map +1 -1
  57. package/dist/esm/utils/elements-chain.d.ts +38 -0
  58. package/dist/esm/utils/elements-chain.d.ts.map +1 -0
  59. package/dist/esm/utils/elements-chain.js +297 -0
  60. package/dist/esm/utils/elements-chain.js.map +1 -0
  61. package/dist/hexclave-config-file.d.ts +24 -1
  62. package/dist/hexclave-config-file.d.ts.map +1 -1
  63. package/dist/hexclave-config-file.js +71 -1
  64. package/dist/hexclave-config-file.js.map +1 -1
  65. package/dist/interface/admin-interface.d.ts +19 -1
  66. package/dist/interface/admin-interface.d.ts.map +1 -1
  67. package/dist/interface/admin-interface.js +14 -0
  68. package/dist/interface/admin-interface.js.map +1 -1
  69. package/dist/interface/admin-metrics.d.ts +99 -5
  70. package/dist/interface/admin-metrics.d.ts.map +1 -1
  71. package/dist/interface/admin-metrics.js +65 -0
  72. package/dist/interface/admin-metrics.js.map +1 -1
  73. package/dist/interface/conversations.d.ts +35 -35
  74. package/dist/interface/crud/current-user.d.ts +2 -2
  75. package/dist/interface/crud/email-outbox.d.ts +66 -66
  76. package/dist/interface/crud/invoices.d.ts +2 -2
  77. package/dist/interface/crud/projects.d.ts +35 -35
  78. package/dist/interface/crud/team-member-profiles.d.ts +10 -10
  79. package/dist/interface/crud/users.d.ts +10 -10
  80. package/dist/interface/webhooks.d.ts +2 -2
  81. package/dist/utils/analytics-clickmap-overlay.d.ts +18 -0
  82. package/dist/utils/analytics-clickmap-overlay.d.ts.map +1 -0
  83. package/dist/utils/analytics-clickmap-overlay.js +23 -0
  84. package/dist/utils/analytics-clickmap-overlay.js.map +1 -0
  85. package/dist/utils/dev-tool.d.ts +31 -0
  86. package/dist/utils/dev-tool.d.ts.map +1 -0
  87. package/dist/utils/dev-tool.js +37 -0
  88. package/dist/utils/dev-tool.js.map +1 -0
  89. package/dist/utils/dom.d.ts +7 -1
  90. package/dist/utils/dom.d.ts.map +1 -1
  91. package/dist/utils/dom.js +20 -0
  92. package/dist/utils/dom.js.map +1 -1
  93. package/dist/utils/elements-chain.d.ts +38 -0
  94. package/dist/utils/elements-chain.d.ts.map +1 -0
  95. package/dist/utils/elements-chain.js +304 -0
  96. package/dist/utils/elements-chain.js.map +1 -0
  97. package/package.json +1 -1
  98. package/src/apps/apps-config.ts +6 -0
  99. package/src/config-authoring.test.ts +1 -1
  100. package/src/config-authoring.ts +6 -6
  101. package/src/config-rendering.ts +24 -2
  102. package/src/hexclave-config-file.ts +90 -1
  103. package/src/interface/admin-interface.ts +43 -1
  104. package/src/interface/admin-metrics.ts +92 -4
  105. package/src/utils/analytics-clickmap-overlay.tsx +15 -0
  106. package/src/utils/dev-tool.tsx +30 -0
  107. package/src/utils/dom.tsx +42 -0
  108. package/src/utils/elements-chain.tsx +349 -0
@@ -1 +1 @@
1
- {"version":3,"file":"config-authoring.d.ts","names":[],"sources":["../../src/config-authoring.ts"],"mappings":";;;KAEK,iBAAA,GAAoB,8BAAA;AAAA,cACZ,iCAAA;AAHyD;AAAA,KAK1D,WAAA,GAAc,iBAAA,UAA2B,iCAAA;AAAA,KAGzC,cAAA,GAAiB,iBAAA,UAA2B,iCAAA;AAAA,KAEnD,iBAAA,qBACH,QAAA,8BACI,MAAA,4CACgB,MAAA,GAAS,CAAA,eAAgB,QAAA,GAAW,iBAAA,CAAkB,MAAA,CAAO,CAAA,GAAI,QAAA,CAAS,CAAA,eACxF,MAAA,GACF,QAAA,kBACE,MAAA,kBACE,OAAA,OAAc,MAAA,QAAc,QAAA,gCACZ,MAAA,GAAS,CAAA,eAAgB,QAAA,GAAW,iBAAA,CAAkB,MAAA,CAAO,CAAA,GAAI,QAAA,CAAS,CAAA,uBAE1F,MAAA,GACF,MAAA;AAAA,KAEH,iBAAA,WAA4B,WAAA,IAC/B,CAAA,SAAU,iBAAA,GACN,CAAA,GAAI,iBAAA,CAAkB,CAAA,EAAG,iBAAA,IACzB,CAAA;;iBAGU,iBAAA,iBAAkC,WAAA,CAAA,CAAa,MAAA,EAAQ,iBAAA,CAAkB,CAAA,IAAK,CAAA;AAAA,iBAK9E,oBAAA,iBAAqC,cAAA,CAAA,CAAgB,MAAA,EAAQ,iBAAA,CAAkB,CAAA,IAAK,CAAA"}
1
+ {"version":3,"file":"config-authoring.d.ts","names":[],"sources":["../../src/config-authoring.ts"],"mappings":";;;KAEK,iBAAA,GAAoB,8BAAA;AAAA,cACZ,iCAAA;AAHyD;AAAA,KAK1D,WAAA,GAAc,iBAAA,UAA2B,iCAAA;AAAA,KAGzC,cAAA,GAAiB,iBAAA,UAA2B,iCAAA;AAAA,KAEnD,iBAAA,qBACH,QAAA,8BACM,MAAA,4CACc,MAAA,GAAS,CAAA,eAAgB,QAAA,GAAW,iBAAA,CAAkB,MAAA,CAAO,CAAA,GAAI,QAAA,CAAS,CAAA,eACtF,MAAA,GACJ,QAAA,kBACI,MAAA,kBACA,OAAA,OAAc,MAAA,QAAc,QAAA,gCACZ,MAAA,GAAS,CAAA,eAAgB,QAAA,GAAW,iBAAA,CAAkB,MAAA,CAAO,CAAA,GAAI,QAAA,CAAS,CAAA,uBAExF,MAAA,GACF,MAAA;AAAA,KAEL,iBAAA,WAA4B,WAAA,IAC/B,CAAA,SAAU,iBAAA,GACN,CAAA,GAAI,iBAAA,CAAkB,CAAA,EAAG,iBAAA,IACzB,CAAA;;iBAGU,iBAAA,iBAAkC,WAAA,CAAA,CAAa,MAAA,EAAQ,iBAAA,CAAkB,CAAA,IAAK,CAAA;AAAA,iBAK9E,oBAAA,iBAAqC,cAAA,CAAA,CAAgB,MAAA,EAAQ,iBAAA,CAAkB,CAAA,IAAK,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"config-authoring.js","names":[],"sources":["../../src/config-authoring.ts"],"sourcesContent":["import type { BranchConfigNormalizedOverride } from \"./config/schema\";\n\ntype StackConfigObject = BranchConfigNormalizedOverride;\nexport const showOnboardingHexclaveConfigValue = \"show-onboarding\";\n/** @deprecated Use `HexclaveConfig` from the `@hexclave/*` package instead — same symbol, new brand name. See https://docs.hexclave.com/migration. */\nexport type StackConfig = StackConfigObject | typeof showOnboardingHexclaveConfigValue;\n\n// Hexclave alias — same shape, declared separately so it doesn't inherit the deprecation tag.\nexport type HexclaveConfig = StackConfigObject | typeof showOnboardingHexclaveConfigValue;\n\ntype StrictConfigShape<Actual, Expected> =\n Expected extends readonly unknown[]\n ? Actual extends readonly unknown[]\n ? { [K in keyof Actual]: K extends keyof Expected ? StrictConfigShape<Actual[K], Expected[K]> : never }\n : Actual\n : Expected extends object\n ? Actual extends object\n ? Exclude<keyof Actual, keyof Expected> extends never\n ? { [K in keyof Actual]: K extends keyof Expected ? StrictConfigShape<Actual[K], Expected[K]> : never }\n : never\n : Actual\n : Actual;\n\ntype StrictStackConfig<T extends StackConfig> =\n T extends StackConfigObject\n ? T & StrictConfigShape<T, StackConfigObject>\n : T;\n\n/** @deprecated Use `defineHexclaveConfig` from the `@hexclave/*` package instead — same symbol, new brand name. See https://docs.hexclave.com/migration. */\nexport function defineStackConfig<const T extends StackConfig>(config: StrictStackConfig<T>): T {\n return config;\n}\n\n// Hexclave alias — separate function so it does not inherit the deprecation tag.\nexport function defineHexclaveConfig<const T extends HexclaveConfig>(config: StrictStackConfig<T>): T {\n return config;\n}\n"],"mappings":";AAGA,MAAa,oCAAoC;;AA0BjD,SAAgB,kBAA+C,QAAiC;AAC9F,QAAO;;AAIT,SAAgB,qBAAqD,QAAiC;AACpG,QAAO"}
1
+ {"version":3,"file":"config-authoring.js","names":[],"sources":["../../src/config-authoring.ts"],"sourcesContent":["import type { BranchConfigNormalizedOverride } from \"./config/schema\";\n\ntype StackConfigObject = BranchConfigNormalizedOverride;\nexport const showOnboardingHexclaveConfigValue = \"show-onboarding\";\n/** @deprecated Use `HexclaveConfig` from the `@hexclave/*` package instead — same symbol, new brand name. See https://docs.hexclave.com/migration. */\nexport type StackConfig = StackConfigObject | typeof showOnboardingHexclaveConfigValue;\n\n// Hexclave alias — same shape, declared separately so it doesn't inherit the deprecation tag.\nexport type HexclaveConfig = StackConfigObject | typeof showOnboardingHexclaveConfigValue;\n\ntype StrictConfigShape<Actual, Expected> =\n Expected extends readonly unknown[]\n ? Actual extends readonly unknown[]\n ? { [K in keyof Actual]: K extends keyof Expected ? StrictConfigShape<Actual[K], Expected[K]> : never }\n : Actual\n : Expected extends object\n ? Actual extends object\n ? Exclude<keyof Actual, keyof Expected> extends never\n ? { [K in keyof Actual]: K extends keyof Expected ? StrictConfigShape<Actual[K], Expected[K]> : never }\n : never\n : Actual\n : Actual;\n\ntype StrictStackConfig<T extends StackConfig> =\n T extends StackConfigObject\n ? T & StrictConfigShape<T, StackConfigObject>\n : T;\n\n/** @deprecated Use `defineHexclaveConfig` from the `@hexclave/*` package instead — same symbol, new brand name. See https://docs.hexclave.com/migration. */\nexport function defineStackConfig<const T extends StackConfig>(config: StrictStackConfig<T>): T {\n return config;\n}\n\n// Hexclave alias — separate function so it does not inherit the deprecation tag.\nexport function defineHexclaveConfig<const T extends HexclaveConfig>(config: StrictStackConfig<T>): T {\n return config;\n}\n"],"mappings":";AAGA,MAAa,oCAAoC;;AA0BjD,SAAgB,kBAA+C,QAAiC;AAC9F,QAAO;;AAIT,SAAgB,qBAAqD,QAAiC;AACpG,QAAO"}
@@ -1,6 +1,6 @@
1
1
  import { expect, it } from "vitest";
2
- import { typeAssertExtends } from "./utils/types.js";
3
2
  import { defineStackConfig } from "./config-authoring.js";
3
+ import { typeAssertExtends } from "./utils/types.js";
4
4
 
5
5
  //#region src/config-authoring.test.ts
6
6
  const validConfig = defineStackConfig({ payments: { items: { todos: {
@@ -1 +1 @@
1
- {"version":3,"file":"config-authoring.test.js","names":[],"sources":["../../src/config-authoring.test.ts"],"sourcesContent":["import { expect, it } from \"vitest\";\nimport { typeAssertExtends } from \"./utils/types\";\nimport { defineStackConfig, type StackConfig } from \"./config-authoring\";\n\nconst validConfig = defineStackConfig({\n payments: {\n items: {\n todos: {\n displayName: \"Todo Slots\",\n customerType: \"user\",\n },\n },\n },\n});\nconst showOnboardingConfig = defineStackConfig(\"show-onboarding\");\n\ntypeAssertExtends<typeof validConfig, StackConfig>()();\ntypeAssertExtends<typeof showOnboardingConfig, StackConfig>()();\n\nit(\"returns its input unchanged\", () => {\n expect(defineStackConfig(validConfig)).toBe(validConfig);\n expect(defineStackConfig(showOnboardingConfig)).toBe(showOnboardingConfig);\n});\n\ndefineStackConfig({\n // @ts-expect-error Top-level dot notation should not be accepted in typed config files.\n \"payments.items\": {\n todos: {\n displayName: \"Todo Slots\",\n customerType: \"user\",\n },\n },\n});\n\ndefineStackConfig({\n payments: {\n // @ts-expect-error Unknown keys should not be accepted in typed config files.\n missingField: true,\n },\n});\n\ndefineStackConfig({\n payments: {\n items: {\n todos: {\n displayName: \"Todo Slots\",\n // @ts-expect-error Invalid enum values should fail type-checking.\n customerType: \"workspace\",\n },\n },\n },\n});\n"],"mappings":";;;;;AAIA,MAAM,cAAc,kBAAkB,EACpC,UAAU,EACR,OAAO,EACL,OAAO;CACL,aAAa;CACb,cAAc;CACf,EACF,EACF,EACF,CAAC;AACF,MAAM,uBAAuB,kBAAkB,kBAAkB;AAEjE,mBAAoD,EAAE;AACtD,mBAA6D,EAAE;AAE/D,GAAG,qCAAqC;AACtC,QAAO,kBAAkB,YAAY,CAAC,CAAC,KAAK,YAAY;AACxD,QAAO,kBAAkB,qBAAqB,CAAC,CAAC,KAAK,qBAAqB;EAC1E;AAEF,kBAAkB,EAEhB,kBAAkB,EAChB,OAAO;CACL,aAAa;CACb,cAAc;CACf,EACF,EACF,CAAC;AAEF,kBAAkB,EAChB,UAAU,EAER,cAAc,MACf,EACF,CAAC;AAEF,kBAAkB,EAChB,UAAU,EACR,OAAO,EACL,OAAO;CACL,aAAa;CAEb,cAAc;CACf,EACF,EACF,EACF,CAAC"}
1
+ {"version":3,"file":"config-authoring.test.js","names":[],"sources":["../../src/config-authoring.test.ts"],"sourcesContent":["import { expect, it } from \"vitest\";\nimport { defineStackConfig, type StackConfig } from \"./config-authoring\";\nimport { typeAssertExtends } from \"./utils/types\";\n\nconst validConfig = defineStackConfig({\n payments: {\n items: {\n todos: {\n displayName: \"Todo Slots\",\n customerType: \"user\",\n },\n },\n },\n});\nconst showOnboardingConfig = defineStackConfig(\"show-onboarding\");\n\ntypeAssertExtends<typeof validConfig, StackConfig>()();\ntypeAssertExtends<typeof showOnboardingConfig, StackConfig>()();\n\nit(\"returns its input unchanged\", () => {\n expect(defineStackConfig(validConfig)).toBe(validConfig);\n expect(defineStackConfig(showOnboardingConfig)).toBe(showOnboardingConfig);\n});\n\ndefineStackConfig({\n // @ts-expect-error Top-level dot notation should not be accepted in typed config files.\n \"payments.items\": {\n todos: {\n displayName: \"Todo Slots\",\n customerType: \"user\",\n },\n },\n});\n\ndefineStackConfig({\n payments: {\n // @ts-expect-error Unknown keys should not be accepted in typed config files.\n missingField: true,\n },\n});\n\ndefineStackConfig({\n payments: {\n items: {\n todos: {\n displayName: \"Todo Slots\",\n // @ts-expect-error Invalid enum values should fail type-checking.\n customerType: \"workspace\",\n },\n },\n },\n});\n"],"mappings":";;;;;AAIA,MAAM,cAAc,kBAAkB,EACpC,UAAU,EACR,OAAO,EACL,OAAO;CACL,aAAa;CACb,cAAc;CACf,EACF,EACF,EACF,CAAC;AACF,MAAM,uBAAuB,kBAAkB,kBAAkB;AAEjE,mBAAoD,EAAE;AACtD,mBAA6D,EAAE;AAE/D,GAAG,qCAAqC;AACtC,QAAO,kBAAkB,YAAY,CAAC,CAAC,KAAK,YAAY;AACxD,QAAO,kBAAkB,qBAAqB,CAAC,CAAC,KAAK,qBAAqB;EAC1E;AAEF,kBAAkB,EAEhB,kBAAkB,EAChB,OAAO;CACL,aAAa;CACb,cAAc;CACf,EACF,EACF,CAAC;AAEF,kBAAkB,EAChB,UAAU,EAER,cAAc,MACf,EACF,CAAC;AAEF,kBAAkB,EAChB,UAAU,EACR,OAAO,EACL,OAAO;CACL,aAAa;CAEb,cAAc;CACf,EACF,EACF,EACF,CAAC"}
@@ -1,4 +1,4 @@
1
- import { parseHexclaveConfigFileContent, renderConfigFileContent } from "./hexclave-config-file";
1
+ import { hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, tryParseHexclaveConfigFileContent } from "./hexclave-config-file";
2
2
 
3
3
  //#region src/config-rendering.d.ts
4
4
  /**
@@ -13,5 +13,5 @@ declare function detectConfigImportPackage(dependencies: string[]): string | und
13
13
  */
14
14
  declare function detectImportPackageFromDir(dir: string): string | undefined;
15
15
  //#endregion
16
- export { detectConfigImportPackage, detectImportPackageFromDir, parseHexclaveConfigFileContent, renderConfigFileContent };
16
+ export { detectConfigImportPackage, detectImportPackageFromDir, hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, tryParseHexclaveConfigFileContent };
17
17
  //# sourceMappingURL=config-rendering.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "fs";
2
2
  import path from "path";
3
- import { parseHexclaveConfigFileContent, renderConfigFileContent } from "./hexclave-config-file.js";
3
+ import { hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, tryParseHexclaveConfigFileContent } from "./hexclave-config-file.js";
4
4
 
5
5
  //#region src/config-rendering.ts
6
6
  /**
@@ -87,6 +87,20 @@ function detectImportPackageFromDir(dir) {
87
87
  (void 0)?.test("parseHexclaveConfigFileContent rejects dynamic config exports", ({ expect }) => {
88
88
  expect(() => parseHexclaveConfigFileContent("export const config = makeConfig();", "stack.config.ts")).toThrow(/Unsupported config expression/);
89
89
  });
90
+ (void 0)?.test("tryParseHexclaveConfigFileContent returns the config for static exports", ({ expect }) => {
91
+ expect(tryParseHexclaveConfigFileContent("export const config = { auth: { allowSignUp: true } };", "stack.config.ts")).toEqual({ auth: { allowSignUp: true } });
92
+ });
93
+ (void 0)?.test("tryParseHexclaveConfigFileContent returns null for non-static exports", ({ expect }) => {
94
+ expect(tryParseHexclaveConfigFileContent("export const config = makeConfig();", "stack.config.ts")).toBeNull();
95
+ expect(tryParseHexclaveConfigFileContent("import x from \"./x.txt\" with { type: \"text\" };\nexport const config = { a: x };", "stack.config.ts")).toBeNull();
96
+ expect(tryParseHexclaveConfigFileContent("export const config = {", "stack.config.ts")).toBeNull();
97
+ });
98
+ (void 0)?.test("hexclaveConfigFileExportsConfig detects a config export", ({ expect }) => {
99
+ expect(hexclaveConfigFileExportsConfig("export const config = { a: 1 };", "stack.config.ts")).toBe(true);
100
+ expect(hexclaveConfigFileExportsConfig("import x from \"./x.txt\" with { type: \"text\" };\nexport const config = { a: x };", "stack.config.ts")).toBe(true);
101
+ expect(hexclaveConfigFileExportsConfig("export const notConfig = { a: 1 };", "stack.config.ts")).toBe(false);
102
+ expect(hexclaveConfigFileExportsConfig("export const config = {", "stack.config.ts")).toBe(false);
103
+ });
90
104
  (void 0)?.test("renderConfigFileContent rejects conflicting dotted keys", ({ expect }) => {
91
105
  expect(() => renderConfigFileContent({
92
106
  "a.b": 1,
@@ -118,5 +132,5 @@ function detectImportPackageFromDir(dir) {
118
132
  });
119
133
 
120
134
  //#endregion
121
- export { detectConfigImportPackage, detectImportPackageFromDir, parseHexclaveConfigFileContent, renderConfigFileContent };
135
+ export { detectConfigImportPackage, detectImportPackageFromDir, hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, tryParseHexclaveConfigFileContent };
122
136
  //# sourceMappingURL=config-rendering.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-rendering.js","names":[],"sources":["../../src/config-rendering.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"fs\";\nimport path from \"path\";\nimport { parseHexclaveConfigFileContent, renderConfigFileContent } from \"./hexclave-config-file\";\nexport { parseHexclaveConfigFileContent, renderConfigFileContent };\n\n/**\n * Packages that export the `HexclaveConfig` type, in priority order.\n * The first match found in a project's dependencies wins. Hexclave-branded\n * packages come first (canonical); the legacy `@stackframe/*` names remain\n * so projects pinned to the last legacy release still render a config file\n * that compiles against their installed SDK.\n */\nconst CONFIG_IMPORT_PACKAGES = [\n \"@hexclave/next\",\n \"@hexclave/react\",\n \"@hexclave/tanstack-start\",\n \"@hexclave/js\",\n \"@hexclave/template\",\n \"@stackframe/stack\",\n \"@stackframe/react\",\n \"@stackframe/js\",\n \"@stackframe/template\",\n] as const;\n\n/**\n * Given a list of dependency names (from package.json), returns the SDK\n * package that should be used for the `HexclaveConfig` import, or `undefined`\n * if none of the known packages are installed.\n */\nexport function detectConfigImportPackage(dependencies: string[]): string | undefined {\n for (const pkg of CONFIG_IMPORT_PACKAGES) {\n if (dependencies.includes(pkg)) {\n return pkg;\n }\n }\n return undefined;\n}\n\n/**\n * Walks up from `dir` to find the nearest `package.json` and returns the\n * best SDK package to use for the `HexclaveConfig` type import.\n */\nexport function detectImportPackageFromDir(dir: string): string | undefined {\n let current = dir;\n while (true) {\n const pkgPath = path.join(current, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n const deps = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n return detectConfigImportPackage(deps);\n } catch {\n return undefined;\n }\n }\n const parent = path.dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return undefined;\n}\n\nimport.meta.vitest?.test(\"renderConfigFileContent normalizes config exports\", ({ expect }) => {\n expect(renderConfigFileContent({\n \"payments.items.todos.displayName\": \"Todo Slots\",\n \"payments.items.todos.customerType\": \"user\",\n })).toContain(`export const config: HexclaveConfig = {\n \"payments\": {\n \"items\": {\n \"todos\": {\n \"displayName\": \"Todo Slots\",\n \"customerType\": \"user\"\n }\n }\n }\n};`);\n});\n\nimport.meta.vitest?.test(\"parseHexclaveConfigFileContent parses static config exports\", ({ expect }) => {\n expect(parseHexclaveConfigFileContent(`\n import type { StackConfig } from \"@hexclave/js\";\n export const config: StackConfig = {\n auth: { allowSignUp: true },\n payments: { testMode: false },\n };\n `, \"stack.config.ts\")).toMatchInlineSnapshot(`\n {\n \"auth\": {\n \"allowSignUp\": true,\n },\n \"payments\": {\n \"testMode\": false,\n },\n }\n `);\n});\n\nimport.meta.vitest?.test(\"parseHexclaveConfigFileContent parses show-onboarding\", ({ expect }) => {\n expect(parseHexclaveConfigFileContent('export const config = \"show-onboarding\";', \"stack.config.ts\")).toBe(\"show-onboarding\");\n});\n\nimport.meta.vitest?.test(\"parseHexclaveConfigFileContent rejects dynamic config exports\", ({ expect }) => {\n expect(() => parseHexclaveConfigFileContent(\"export const config = makeConfig();\", \"stack.config.ts\")).toThrow(/Unsupported config expression/);\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent rejects conflicting dotted keys\", ({ expect }) => {\n expect(() => renderConfigFileContent({\n \"a.b\": 1,\n \"a.b.c\": 2,\n })).toThrowError(/conflicting keys.*\"a\\.b\\.c\"/);\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent rejects invalid config exports\", ({ expect }) => {\n expect(() => renderConfigFileContent(null)).toThrowErrorMatchingInlineSnapshot(\n `[Error: Invalid config: expected a plain object.]`,\n );\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent uses custom import package\", ({ expect }) => {\n const content = renderConfigFileContent({}, \"@hexclave/next\");\n expect(content).toContain('import type { HexclaveConfig } from \"@hexclave/next/config\";');\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent defaults to @hexclave/js\", ({ expect }) => {\n const content = renderConfigFileContent({});\n expect(content).toContain('import type { HexclaveConfig } from \"@hexclave/js/config\";');\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent keeps legacy @stackframe packages on their root entrypoint\", ({ expect }) => {\n // The lightweight `/config` subpath only exists on Hexclave-branded packages;\n // already-published @stackframe/* releases predate it.\n const content = renderConfigFileContent({}, \"@stackframe/next\");\n expect(content).toContain('import type { HexclaveConfig } from \"@stackframe/next\";');\n});\n\nimport.meta.vitest?.test(\"detectConfigImportPackage picks first matching package by priority\", ({ expect }) => {\n expect(detectConfigImportPackage([\"@hexclave/next\", \"@hexclave/js\"])).toBe(\"@hexclave/next\");\n expect(detectConfigImportPackage([\"@hexclave/react\", \"@hexclave/js\"])).toBe(\"@hexclave/react\");\n expect(detectConfigImportPackage([\"@hexclave/js\"])).toBe(\"@hexclave/js\");\n expect(detectConfigImportPackage([\"@hexclave/tanstack-start\"])).toBe(\"@hexclave/tanstack-start\");\n // Hexclave names take priority over legacy stackframe names when both appear.\n expect(detectConfigImportPackage([\"@stackframe/stack\", \"@hexclave/next\"])).toBe(\"@hexclave/next\");\n // Legacy fallback still works for projects pinned to the last @stackframe/* release.\n expect(detectConfigImportPackage([\"@stackframe/stack\"])).toBe(\"@stackframe/stack\");\n expect(detectConfigImportPackage([\"@stackframe/template\"])).toBe(\"@stackframe/template\");\n expect(detectConfigImportPackage([\"lodash\", \"express\"])).toBeUndefined();\n expect(detectConfigImportPackage([])).toBeUndefined();\n});\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,yBAAyB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;AAOD,SAAgB,0BAA0B,cAA4C;AACpF,MAAK,MAAM,OAAO,uBAChB,KAAI,aAAa,SAAS,IAAI,CAC5B,QAAO;;;;;;AAUb,SAAgB,2BAA2B,KAAiC;CAC1E,IAAI,UAAU;AACd,QAAO,MAAM;EACX,MAAM,UAAU,KAAK,KAAK,SAAS,eAAe;AAClD,MAAI,WAAW,QAAQ,CACrB,KAAI;GACF,MAAM,MAAM,KAAK,MAAM,aAAa,SAAS,QAAQ,CAAC;AAKtD,UAAO,0BAJM,CACX,GAAG,OAAO,KAAK,IAAI,gBAAgB,EAAE,CAAC,EACtC,GAAG,OAAO,KAAK,IAAI,mBAAmB,EAAE,CAAC,CAC1C,CACqC;UAChC;AACN;;EAGJ,MAAM,SAAS,KAAK,QAAQ,QAAQ;AACpC,MAAI,WAAW,QAAS;AACxB,YAAU;;;CAKd,SAAW,KAAC,sDAAwD,EAAA,aAAa;AAC/E,QAAO,wBAAwB;EAC7B,oCAAoC;EACpC,qCAAqC;EACtC,CAAC,CAAC,CAAC,UAAU;;;;;;;;;IASZ;EACF;CAEF,SAAW,KAAC,gEAAkE,EAAA,aAAa;AACzF,QAAO,+BAA+B;;;;;;KAMnC,kBAAkB,CAAC,CAAC,sBAAsB;;;;;;;;;IAS3C;EACF;CAEF,SAAW,KAAC,0DAAyD,EAAA,aAAgB;AACnF,QAAO,+BAA+B,8CAA4C,kBAAkB,CAAC,CAAC,KAAK,kBAAkB;EAC7H;CAEF,SAAW,KAAC,kEAAoE,EAAA,aAAa;AAC3F,cAAa,+BAA+B,uCAAuC,kBAAkB,CAAC,CAAC,QAAQ,gCAAgC;EAC/I;CAEF,SAAW,KAAC,4DAAgE,EAAC,aAAU;AACrF,cAAa,wBAAwB;EACnC,OAAO;EACP,SAAS;EACV,CAAC,CAAC,CAAC,aAAa,8BAA8B;EAC/C;CAEF,SAAW,KAAC,2DAA6D,EAAA,aAAa;AACpF,cAAa,wBAAwB,KAAK,CAAC,CAAC,mCAC1C,oDACD;EACD;CAEF,SAAW,KAAC,uDAAyD,EAAA,aAAa;AAEhF,QADgB,wBAAwB,EAAE,EAAE,iBAAiB,CAC9C,CAAC,UAAU,iEAA+D;EACzF;CAEF,SAAW,KAAC,qDAAmD,EAAQ,aAAS;AAE9E,QADgB,wBAAwB,EAAE,CAAC,CAC5B,CAAC,UAAU,+DAA6D;EACvF;CAEF,SAAW,KAAC,uFAAsF,EAAA,aAAgB;AAIhH,QADgB,wBAAwB,EAAE,EAAE,mBAAmB,CAChD,CAAC,UAAU,4DAA0D;EACpF;CAEF,SAAW,KAAC,uEAAwE,EAAA,aAAc;AAChG,QAAO,0BAA0B,CAAC,kBAAkB,eAAe,CAAC,CAAC,CAAC,KAAK,iBAAiB;AAC5F,QAAO,0BAA0B,CAAC,mBAAmB,eAAe,CAAC,CAAC,CAAC,KAAK,kBAAkB;AAC9F,QAAO,0BAA0B,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,eAAe;AACxE,QAAO,0BAA0B,CAAC,2BAA2B,CAAC,CAAC,CAAC,KAAK,2BAA2B;AAEhG,QAAO,0BAA0B,CAAC,qBAAqB,iBAAiB,CAAC,CAAC,CAAC,KAAK,iBAAiB;AAEjG,QAAO,0BAA0B,CAAC,oBAAoB,CAAC,CAAC,CAAC,KAAK,oBAAoB;AAClF,QAAO,0BAA0B,CAAC,uBAAuB,CAAC,CAAC,CAAC,KAAK,uBAAuB;AACxF,QAAO,0BAA0B,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC,eAAe;AACxE,QAAO,0BAA0B,EAAE,CAAC,CAAC,CAAC,eAAe;EACrD"}
1
+ {"version":3,"file":"config-rendering.js","names":[],"sources":["../../src/config-rendering.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"fs\";\nimport path from \"path\";\nimport { hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, tryParseHexclaveConfigFileContent } from \"./hexclave-config-file\";\nexport { hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, tryParseHexclaveConfigFileContent };\n\n/**\n * Packages that export the `HexclaveConfig` type, in priority order.\n * The first match found in a project's dependencies wins. Hexclave-branded\n * packages come first (canonical); the legacy `@stackframe/*` names remain\n * so projects pinned to the last legacy release still render a config file\n * that compiles against their installed SDK.\n */\nconst CONFIG_IMPORT_PACKAGES = [\n \"@hexclave/next\",\n \"@hexclave/react\",\n \"@hexclave/tanstack-start\",\n \"@hexclave/js\",\n \"@hexclave/template\",\n \"@stackframe/stack\",\n \"@stackframe/react\",\n \"@stackframe/js\",\n \"@stackframe/template\",\n] as const;\n\n/**\n * Given a list of dependency names (from package.json), returns the SDK\n * package that should be used for the `HexclaveConfig` import, or `undefined`\n * if none of the known packages are installed.\n */\nexport function detectConfigImportPackage(dependencies: string[]): string | undefined {\n for (const pkg of CONFIG_IMPORT_PACKAGES) {\n if (dependencies.includes(pkg)) {\n return pkg;\n }\n }\n return undefined;\n}\n\n/**\n * Walks up from `dir` to find the nearest `package.json` and returns the\n * best SDK package to use for the `HexclaveConfig` type import.\n */\nexport function detectImportPackageFromDir(dir: string): string | undefined {\n let current = dir;\n while (true) {\n const pkgPath = path.join(current, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n const deps = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n return detectConfigImportPackage(deps);\n } catch {\n return undefined;\n }\n }\n const parent = path.dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return undefined;\n}\n\nimport.meta.vitest?.test(\"renderConfigFileContent normalizes config exports\", ({ expect }) => {\n expect(renderConfigFileContent({\n \"payments.items.todos.displayName\": \"Todo Slots\",\n \"payments.items.todos.customerType\": \"user\",\n })).toContain(`export const config: HexclaveConfig = {\n \"payments\": {\n \"items\": {\n \"todos\": {\n \"displayName\": \"Todo Slots\",\n \"customerType\": \"user\"\n }\n }\n }\n};`);\n});\n\nimport.meta.vitest?.test(\"parseHexclaveConfigFileContent parses static config exports\", ({ expect }) => {\n expect(parseHexclaveConfigFileContent(`\n import type { StackConfig } from \"@hexclave/js\";\n export const config: StackConfig = {\n auth: { allowSignUp: true },\n payments: { testMode: false },\n };\n `, \"stack.config.ts\")).toMatchInlineSnapshot(`\n {\n \"auth\": {\n \"allowSignUp\": true,\n },\n \"payments\": {\n \"testMode\": false,\n },\n }\n `);\n});\n\nimport.meta.vitest?.test(\"parseHexclaveConfigFileContent parses show-onboarding\", ({ expect }) => {\n expect(parseHexclaveConfigFileContent('export const config = \"show-onboarding\";', \"stack.config.ts\")).toBe(\"show-onboarding\");\n});\n\nimport.meta.vitest?.test(\"parseHexclaveConfigFileContent rejects dynamic config exports\", ({ expect }) => {\n expect(() => parseHexclaveConfigFileContent(\"export const config = makeConfig();\", \"stack.config.ts\")).toThrow(/Unsupported config expression/);\n});\n\nimport.meta.vitest?.test(\"tryParseHexclaveConfigFileContent returns the config for static exports\", ({ expect }) => {\n expect(tryParseHexclaveConfigFileContent(\"export const config = { auth: { allowSignUp: true } };\", \"stack.config.ts\")).toEqual({\n auth: { allowSignUp: true },\n });\n});\n\nimport.meta.vitest?.test(\"tryParseHexclaveConfigFileContent returns null for non-static exports\", ({ expect }) => {\n // Wrapped in a helper call (e.g. defineStackConfig) -> not a plain literal.\n expect(tryParseHexclaveConfigFileContent(\"export const config = makeConfig();\", \"stack.config.ts\")).toBeNull();\n // References an imported value -> has structure to preserve.\n expect(tryParseHexclaveConfigFileContent('import x from \"./x.txt\" with { type: \"text\" };\\nexport const config = { a: x };', \"stack.config.ts\")).toBeNull();\n // Syntax error.\n expect(tryParseHexclaveConfigFileContent(\"export const config = {\", \"stack.config.ts\")).toBeNull();\n});\n\nimport.meta.vitest?.test(\"hexclaveConfigFileExportsConfig detects a config export\", ({ expect }) => {\n expect(hexclaveConfigFileExportsConfig(\"export const config = { a: 1 };\", \"stack.config.ts\")).toBe(true);\n expect(hexclaveConfigFileExportsConfig('import x from \"./x.txt\" with { type: \"text\" };\\nexport const config = { a: x };', \"stack.config.ts\")).toBe(true);\n expect(hexclaveConfigFileExportsConfig(\"export const notConfig = { a: 1 };\", \"stack.config.ts\")).toBe(false);\n expect(hexclaveConfigFileExportsConfig(\"export const config = {\", \"stack.config.ts\")).toBe(false);\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent rejects conflicting dotted keys\", ({ expect }) => {\n expect(() => renderConfigFileContent({\n \"a.b\": 1,\n \"a.b.c\": 2,\n })).toThrowError(/conflicting keys.*\"a\\.b\\.c\"/);\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent rejects invalid config exports\", ({ expect }) => {\n expect(() => renderConfigFileContent(null)).toThrowErrorMatchingInlineSnapshot(\n `[Error: Invalid config: expected a plain object.]`,\n );\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent uses custom import package\", ({ expect }) => {\n const content = renderConfigFileContent({}, \"@hexclave/next\");\n expect(content).toContain('import type { HexclaveConfig } from \"@hexclave/next/config\";');\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent defaults to @hexclave/js\", ({ expect }) => {\n const content = renderConfigFileContent({});\n expect(content).toContain('import type { HexclaveConfig } from \"@hexclave/js/config\";');\n});\n\nimport.meta.vitest?.test(\"renderConfigFileContent keeps legacy @stackframe packages on their root entrypoint\", ({ expect }) => {\n // The lightweight `/config` subpath only exists on Hexclave-branded packages;\n // already-published @stackframe/* releases predate it.\n const content = renderConfigFileContent({}, \"@stackframe/next\");\n expect(content).toContain('import type { HexclaveConfig } from \"@stackframe/next\";');\n});\n\nimport.meta.vitest?.test(\"detectConfigImportPackage picks first matching package by priority\", ({ expect }) => {\n expect(detectConfigImportPackage([\"@hexclave/next\", \"@hexclave/js\"])).toBe(\"@hexclave/next\");\n expect(detectConfigImportPackage([\"@hexclave/react\", \"@hexclave/js\"])).toBe(\"@hexclave/react\");\n expect(detectConfigImportPackage([\"@hexclave/js\"])).toBe(\"@hexclave/js\");\n expect(detectConfigImportPackage([\"@hexclave/tanstack-start\"])).toBe(\"@hexclave/tanstack-start\");\n // Hexclave names take priority over legacy stackframe names when both appear.\n expect(detectConfigImportPackage([\"@stackframe/stack\", \"@hexclave/next\"])).toBe(\"@hexclave/next\");\n // Legacy fallback still works for projects pinned to the last @stackframe/* release.\n expect(detectConfigImportPackage([\"@stackframe/stack\"])).toBe(\"@stackframe/stack\");\n expect(detectConfigImportPackage([\"@stackframe/template\"])).toBe(\"@stackframe/template\");\n expect(detectConfigImportPackage([\"lodash\", \"express\"])).toBeUndefined();\n expect(detectConfigImportPackage([])).toBeUndefined();\n});\n"],"mappings":"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"}
@@ -9,7 +9,30 @@ declare const showOnboardingHexclaveConfigValue = "show-onboarding";
9
9
  */
10
10
  declare function renderConfigFileContent(config: unknown, importPackage?: string): string;
11
11
  type ParsedStackConfig = Record<string, unknown> | typeof showOnboardingHexclaveConfigValue;
12
+ /**
13
+ * Like {@link parseHexclaveConfigFileContent}, but returns `null` instead of
14
+ * throwing when the file is not a plain static config (e.g. it wraps the config
15
+ * in a helper call, references imported values, or has a syntax error). Useful
16
+ * for deciding whether a config file can be safely regenerated deterministically
17
+ * or whether it has custom structure that must be preserved.
18
+ */
19
+ declare function tryParseHexclaveConfigFileContent(content: string, filePath: string): ParsedStackConfig | null;
20
+ /**
21
+ * Returns whether `content` parses as a module that exports a `config` binding.
22
+ * Used as a lightweight structural sanity check after editing config files whose
23
+ * values can't be evaluated by our loader (e.g. they import external text
24
+ * files), where a full semantic comparison isn't possible.
25
+ */
26
+ declare function hexclaveConfigFileExportsConfig(content: string, filePath: string): boolean;
27
+ /**
28
+ * Returns the relative import sources (those starting with `./` or `../`)
29
+ * declared in `content`. Used to discover the external files a config update may
30
+ * touch — e.g. `import x from "./welcome-email.tsx" with { type: "text" }` — so
31
+ * they can be snapshotted and rolled back if an in-place update fails. Returns
32
+ * an empty array if the file can't be parsed.
33
+ */
34
+ declare function getRelativeImportSpecifiers(content: string): string[];
12
35
  declare function parseHexclaveConfigFileContent(content: string, filePath: string): ParsedStackConfig;
13
36
  //#endregion
14
- export { parseHexclaveConfigFileContent, renderConfigFileContent, showOnboardingHexclaveConfigValue };
37
+ export { getRelativeImportSpecifiers, hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, showOnboardingHexclaveConfigValue, tryParseHexclaveConfigFileContent };
15
38
  //# sourceMappingURL=hexclave-config-file.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hexclave-config-file.d.ts","names":[],"sources":["../../src/hexclave-config-file.ts"],"mappings":";cAIa,iCAAA;AAAb;;;;;AAWA;;AAXA,iBAWgB,uBAAA,CAAwB,MAAA,WAAiB,aAAA;AAAA,KAyBpD,iBAAA,GAAoB,MAAA,2BAAiC,iCAAA;AAAA,iBA8D1C,8BAAA,CAA+B,OAAA,UAAiB,QAAA,WAAmB,iBAAA"}
1
+ {"version":3,"file":"hexclave-config-file.d.ts","names":[],"sources":["../../src/hexclave-config-file.ts"],"mappings":";cAIa,iCAAA;AAAb;;;;;AAWA;;AAXA,iBAWgB,uBAAA,CAAwB,MAAA,WAAiB,aAAA;AAAA,KAyBpD,iBAAA,GAAoB,MAAA,2BAAiC,iCAAA;;AAFzD;;;;;AAuED;iBAAgB,iCAAA,CAAkC,OAAA,UAAiB,QAAA,WAAmB,iBAAA;;;;;;;iBActE,+BAAA,CAAgC,OAAA,UAAiB,QAAA;AAAjE;;;;;AA8CA;;AA9CA,iBA8CgB,2BAAA,CAA4B,OAAA;AAAA,iBAsB5B,8BAAA,CAA+B,OAAA,UAAiB,QAAA,WAAmB,iBAAA"}
@@ -55,11 +55,78 @@ function evaluateStaticConfigExpression(expression) {
55
55
  }
56
56
  throw new Error(`Unsupported config expression: ${unwrapped.type}`);
57
57
  }
58
+ /**
59
+ * Like {@link parseHexclaveConfigFileContent}, but returns `null` instead of
60
+ * throwing when the file is not a plain static config (e.g. it wraps the config
61
+ * in a helper call, references imported values, or has a syntax error). Useful
62
+ * for deciding whether a config file can be safely regenerated deterministically
63
+ * or whether it has custom structure that must be preserved.
64
+ */
65
+ function tryParseHexclaveConfigFileContent(content, filePath) {
66
+ try {
67
+ return parseHexclaveConfigFileContent(content, filePath);
68
+ } catch {
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Returns whether `content` parses as a module that exports a `config` binding.
74
+ * Used as a lightweight structural sanity check after editing config files whose
75
+ * values can't be evaluated by our loader (e.g. they import external text
76
+ * files), where a full semantic comparison isn't possible.
77
+ */
78
+ function hexclaveConfigFileExportsConfig(content, filePath) {
79
+ let ast;
80
+ try {
81
+ ast = parser.parse(content, {
82
+ sourceType: "module",
83
+ sourceFilename: filePath,
84
+ plugins: ["typescript", "importAttributes"]
85
+ });
86
+ } catch {
87
+ return false;
88
+ }
89
+ for (const statement of ast.program.body) {
90
+ if (!t.isExportNamedDeclaration(statement)) continue;
91
+ if (statement.exportKind === "type") continue;
92
+ if (t.isVariableDeclaration(statement.declaration)) {
93
+ for (const declaration of statement.declaration.declarations) if (t.isIdentifier(declaration.id) && declaration.id.name === "config" && declaration.init != null) return true;
94
+ }
95
+ for (const specifier of statement.specifiers) if (t.isExportSpecifier(specifier) && specifier.exportKind !== "type") {
96
+ if ((t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value) === "config") return true;
97
+ }
98
+ }
99
+ return false;
100
+ }
101
+ /**
102
+ * Returns the relative import sources (those starting with `./` or `../`)
103
+ * declared in `content`. Used to discover the external files a config update may
104
+ * touch — e.g. `import x from "./welcome-email.tsx" with { type: "text" }` — so
105
+ * they can be snapshotted and rolled back if an in-place update fails. Returns
106
+ * an empty array if the file can't be parsed.
107
+ */
108
+ function getRelativeImportSpecifiers(content) {
109
+ let ast;
110
+ try {
111
+ ast = parser.parse(content, {
112
+ sourceType: "module",
113
+ plugins: ["typescript", "importAttributes"]
114
+ });
115
+ } catch {
116
+ return [];
117
+ }
118
+ const sources = [];
119
+ for (const statement of ast.program.body) if (t.isImportDeclaration(statement)) {
120
+ const source = statement.source.value;
121
+ if (source.startsWith("./") || source.startsWith("../")) sources.push(source);
122
+ }
123
+ return sources;
124
+ }
58
125
  function parseHexclaveConfigFileContent(content, filePath) {
59
126
  if (content.trim() === "") return {};
60
127
  const ast = parser.parse(content, {
61
128
  sourceType: "module",
62
- plugins: ["typescript"]
129
+ plugins: ["typescript", "importAttributes"]
63
130
  });
64
131
  for (const statement of ast.program.body) {
65
132
  if (!t.isExportNamedDeclaration(statement) || !t.isVariableDeclaration(statement.declaration)) continue;
@@ -73,5 +140,5 @@ function parseHexclaveConfigFileContent(content, filePath) {
73
140
  }
74
141
 
75
142
  //#endregion
76
- export { parseHexclaveConfigFileContent, renderConfigFileContent, showOnboardingHexclaveConfigValue };
143
+ export { getRelativeImportSpecifiers, hexclaveConfigFileExportsConfig, parseHexclaveConfigFileContent, renderConfigFileContent, showOnboardingHexclaveConfigValue, tryParseHexclaveConfigFileContent };
77
144
  //# sourceMappingURL=hexclave-config-file.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hexclave-config-file.js","names":[],"sources":["../../src/hexclave-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 showOnboardingHexclaveConfigValue = \"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 `parseHexclaveConfigFileContent`) 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 // Import the `HexclaveConfig` type from the package's lightweight `/config`\n // entrypoint, which is free of framework runtime code and therefore safe for\n // tooling (e.g. the local dashboard) to load in a plain Node context. Only the\n // Hexclave-branded packages expose this subpath; legacy `@stackframe/*`\n // releases predate it, so fall back to their package root.\n const importSpecifier = pkg.startsWith(\"@hexclave/\") ? `${pkg}/config` : pkg;\n const importLine = `import type { HexclaveConfig } from \"${importSpecifier}\";`;\n return `${importLine}\\n\\nexport const config: HexclaveConfig = ${JSON.stringify(normalizedConfig, null, 2)};\\n`;\n}\n\ntype ParsedStackConfig = Record<string, unknown> | typeof showOnboardingHexclaveConfigValue;\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 parseHexclaveConfigFileContent(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
+ {"version":3,"file":"hexclave-config-file.js","names":[],"sources":["../../src/hexclave-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 showOnboardingHexclaveConfigValue = \"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 `parseHexclaveConfigFileContent`) 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 // Import the `HexclaveConfig` type from the package's lightweight `/config`\n // entrypoint, which is free of framework runtime code and therefore safe for\n // tooling (e.g. the local dashboard) to load in a plain Node context. Only the\n // Hexclave-branded packages expose this subpath; legacy `@stackframe/*`\n // releases predate it, so fall back to their package root.\n const importSpecifier = pkg.startsWith(\"@hexclave/\") ? `${pkg}/config` : pkg;\n const importLine = `import type { HexclaveConfig } from \"${importSpecifier}\";`;\n return `${importLine}\\n\\nexport const config: HexclaveConfig = ${JSON.stringify(normalizedConfig, null, 2)};\\n`;\n}\n\ntype ParsedStackConfig = Record<string, unknown> | typeof showOnboardingHexclaveConfigValue;\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\n/**\n * Like {@link parseHexclaveConfigFileContent}, but returns `null` instead of\n * throwing when the file is not a plain static config (e.g. it wraps the config\n * in a helper call, references imported values, or has a syntax error). Useful\n * for deciding whether a config file can be safely regenerated deterministically\n * or whether it has custom structure that must be preserved.\n */\nexport function tryParseHexclaveConfigFileContent(content: string, filePath: string): ParsedStackConfig | null {\n try {\n return parseHexclaveConfigFileContent(content, filePath);\n } catch {\n return null;\n }\n}\n\n/**\n * Returns whether `content` parses as a module that exports a `config` binding.\n * Used as a lightweight structural sanity check after editing config files whose\n * values can't be evaluated by our loader (e.g. they import external text\n * files), where a full semantic comparison isn't possible.\n */\nexport function hexclaveConfigFileExportsConfig(content: string, filePath: string): boolean {\n let ast: parser.ParseResult<t.File>;\n try {\n ast = parser.parse(content, {\n sourceType: \"module\",\n sourceFilename: filePath,\n plugins: [\"typescript\", \"importAttributes\"],\n });\n } catch {\n return false;\n }\n for (const statement of ast.program.body) {\n if (!t.isExportNamedDeclaration(statement)) {\n continue;\n }\n // Ignore type-only exports (`export type { config }`): they don't produce a\n // runtime `config` value, so they must not satisfy the structural check.\n if (statement.exportKind === \"type\") {\n continue;\n }\n if (t.isVariableDeclaration(statement.declaration)) {\n for (const declaration of statement.declaration.declarations) {\n if (t.isIdentifier(declaration.id) && declaration.id.name === \"config\" && declaration.init != null) {\n return true;\n }\n }\n }\n for (const specifier of statement.specifiers) {\n if (t.isExportSpecifier(specifier) && specifier.exportKind !== \"type\") {\n const exportedName = t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value;\n if (exportedName === \"config\") {\n return true;\n }\n }\n }\n }\n return false;\n}\n\n/**\n * Returns the relative import sources (those starting with `./` or `../`)\n * declared in `content`. Used to discover the external files a config update may\n * touch — e.g. `import x from \"./welcome-email.tsx\" with { type: \"text\" }` — so\n * they can be snapshotted and rolled back if an in-place update fails. Returns\n * an empty array if the file can't be parsed.\n */\nexport function getRelativeImportSpecifiers(content: string): string[] {\n let ast: parser.ParseResult<t.File>;\n try {\n ast = parser.parse(content, {\n sourceType: \"module\",\n plugins: [\"typescript\", \"importAttributes\"],\n });\n } catch {\n return [];\n }\n const sources: string[] = [];\n for (const statement of ast.program.body) {\n if (t.isImportDeclaration(statement)) {\n const source = statement.source.value;\n if (source.startsWith(\"./\") || source.startsWith(\"../\")) {\n sources.push(source);\n }\n }\n }\n return sources;\n}\n\nexport function parseHexclaveConfigFileContent(content: string, filePath: string): ParsedStackConfig {\n if (content.trim() === \"\") return {};\n const ast = parser.parse(content, {\n sourceType: \"module\",\n plugins: [\"typescript\", \"importAttributes\"],\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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"}
@@ -4,7 +4,7 @@ import { KnownErrors } from "../known-errors";
4
4
  import { RestrictedReason, branchConfigSourceSchema } from "../schema-fields";
5
5
  import { AccessToken, InternalSession, RefreshToken } from "../sessions";
6
6
  import { MoneyAmount } from "../utils/currency-constants";
7
- import { MetricsResponse, MetricsUserCounts, UserActivityResponse } from "./admin-metrics";
7
+ import { AnalyticsClickmapDevice, AnalyticsClickmapKind, AnalyticsClickmapResponse, AnalyticsClickmapTokenResponse, MetricsResponse, MetricsUserCounts, UserActivityResponse } from "./admin-metrics";
8
8
  import { AnalyticsQueryOptions, AnalyticsQueryResponse } from "./crud/analytics";
9
9
  import { EmailOutboxCrud } from "./crud/email-outbox";
10
10
  import { InternalEmailsCrud } from "./crud/emails";
@@ -127,6 +127,24 @@ declare class HexclaveAdminInterface extends HexclaveServerInterface {
127
127
  until?: string;
128
128
  }): Promise<MetricsResponse>;
129
129
  getUserActivity(userId: string): Promise<UserActivityResponse>;
130
+ getAnalyticsClickmap(options: {
131
+ kind: AnalyticsClickmapKind;
132
+ member_user_ids?: string[];
133
+ route_path?: string;
134
+ route_regex?: string;
135
+ url_pattern?: string;
136
+ user_id?: string;
137
+ replay_id?: string;
138
+ device?: AnalyticsClickmapDevice;
139
+ viewport_width_min?: number;
140
+ viewport_width_max?: number;
141
+ sampling?: number;
142
+ since: string;
143
+ until: string;
144
+ }): Promise<AnalyticsClickmapResponse>;
145
+ createAnalyticsClickmapToken(options: {
146
+ origin: string;
147
+ }): Promise<AnalyticsClickmapTokenResponse>;
130
148
  getMetricsUserCounts(): Promise<MetricsUserCounts>;
131
149
  sendTestEmail(data: {
132
150
  recipient_email: string;
@@ -1 +1 @@
1
- {"version":3,"file":"admin-interface.d.ts","names":[],"sources":["../../../src/interface/admin-interface.ts"],"mappings":"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"}
1
+ {"version":3,"file":"admin-interface.d.ts","names":[],"sources":["../../../src/interface/admin-interface.ts"],"mappings":"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"}
@@ -182,6 +182,20 @@ var HexclaveAdminInterface = class extends HexclaveServerInterface {
182
182
  async getUserActivity(userId) {
183
183
  return await (await this.sendAdminRequest(urlString`/internal/user-activity?user_id=${userId}`, { method: "GET" }, null)).json();
184
184
  }
185
+ async getAnalyticsClickmap(options) {
186
+ return await (await this.sendAdminRequest("/internal/analytics/clickmap", {
187
+ method: "POST",
188
+ headers: { "content-type": "application/json" },
189
+ body: JSON.stringify(options)
190
+ }, null)).json();
191
+ }
192
+ async createAnalyticsClickmapToken(options) {
193
+ return await (await this.sendAdminRequest("/internal/analytics/clickmap-token", {
194
+ method: "POST",
195
+ headers: { "content-type": "application/json" },
196
+ body: JSON.stringify(options)
197
+ }, null)).json();
198
+ }
185
199
  async getMetricsUserCounts() {
186
200
  return await (await this.sendAdminRequest("/internal/metrics/user-counts", { method: "GET" }, null)).json();
187
201
  }