@carmaclouds/core 2.3.1

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 (118) hide show
  1. package/dist/cache/CacheManager.d.ts.map +1 -0
  2. package/dist/cache/CacheManager.js +131 -0
  3. package/dist/cache/CacheManager.js.map +1 -0
  4. package/dist/index.d.ts +18 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +22 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/ir/index.d.ts +11 -0
  9. package/dist/ir/index.d.ts.map +1 -0
  10. package/dist/ir/index.js +9 -0
  11. package/dist/ir/index.js.map +1 -0
  12. package/dist/ir/normalize.d.ts +10 -0
  13. package/dist/ir/normalize.d.ts.map +1 -0
  14. package/dist/ir/normalize.js +207 -0
  15. package/dist/ir/normalize.js.map +1 -0
  16. package/dist/ir/persistence.d.ts +26 -0
  17. package/dist/ir/persistence.d.ts.map +1 -0
  18. package/dist/ir/persistence.js +21 -0
  19. package/dist/ir/persistence.js.map +1 -0
  20. package/dist/ir/sync.d.ts +12 -0
  21. package/dist/ir/sync.d.ts.map +1 -0
  22. package/dist/ir/sync.js +36 -0
  23. package/dist/ir/sync.js.map +1 -0
  24. package/dist/ir/types.d.ts +143 -0
  25. package/dist/ir/types.d.ts.map +1 -0
  26. package/dist/ir/types.js +13 -0
  27. package/dist/ir/types.js.map +1 -0
  28. package/dist/ir/views/dnd5e.d.ts +40 -0
  29. package/dist/ir/views/dnd5e.d.ts.map +1 -0
  30. package/dist/ir/views/dnd5e.js +50 -0
  31. package/dist/ir/views/dnd5e.js.map +1 -0
  32. package/dist/render/character.d.ts +19 -0
  33. package/dist/render/character.d.ts.map +1 -0
  34. package/dist/render/character.js +156 -0
  35. package/dist/render/character.js.map +1 -0
  36. package/dist/render/h.d.ts +27 -0
  37. package/dist/render/h.d.ts.map +1 -0
  38. package/dist/render/h.js +64 -0
  39. package/dist/render/h.js.map +1 -0
  40. package/dist/render/index.d.ts +11 -0
  41. package/dist/render/index.d.ts.map +1 -0
  42. package/dist/render/index.js +8 -0
  43. package/dist/render/index.js.map +1 -0
  44. package/dist/render/mount.d.ts +31 -0
  45. package/dist/render/mount.d.ts.map +1 -0
  46. package/dist/render/mount.js +63 -0
  47. package/dist/render/mount.js.map +1 -0
  48. package/dist/supabase/fields.d.ts.map +1 -0
  49. package/dist/supabase/fields.js +120 -0
  50. package/dist/supabase/fields.js.map +1 -0
  51. package/dist/types/character.d.ts.map +1 -0
  52. package/dist/types/character.js +5 -0
  53. package/dist/types/character.js.map +1 -0
  54. package/package.json +73 -0
  55. package/src/browser.js +51 -0
  56. package/src/cache/CacheManager.ts +174 -0
  57. package/src/common/browser-polyfill.js +319 -0
  58. package/src/common/debug.js +123 -0
  59. package/src/common/html-utils.js +134 -0
  60. package/src/common/theme-manager.js +265 -0
  61. package/src/index.ts +25 -0
  62. package/src/ir/__fixtures__/dnd5e-character.json +75962 -0
  63. package/src/ir/__fixtures__/non-dnd-character.json +14218 -0
  64. package/src/ir/index.ts +10 -0
  65. package/src/ir/normalize.ts +245 -0
  66. package/src/ir/persistence.ts +37 -0
  67. package/src/ir/sync.ts +49 -0
  68. package/src/ir/types.ts +161 -0
  69. package/src/ir/views/dnd5e.ts +94 -0
  70. package/src/lib/indexeddb-cache.js +320 -0
  71. package/src/modules/action-announcements.js +102 -0
  72. package/src/modules/action-display.js +1557 -0
  73. package/src/modules/action-executor.js +860 -0
  74. package/src/modules/action-filters.js +167 -0
  75. package/src/modules/action-options.js +117 -0
  76. package/src/modules/card-creator.js +142 -0
  77. package/src/modules/character-portrait.js +169 -0
  78. package/src/modules/character-trait-popups.js +959 -0
  79. package/src/modules/character-traits.js +814 -0
  80. package/src/modules/class-feature-edge-cases.js +1320 -0
  81. package/src/modules/color-utils.js +69 -0
  82. package/src/modules/combat-maneuver-edge-cases.js +660 -0
  83. package/src/modules/companions-manager.js +178 -0
  84. package/src/modules/concentration-tracker.js +178 -0
  85. package/src/modules/data-manager.js +514 -0
  86. package/src/modules/dice-roller.js +719 -0
  87. package/src/modules/effects-manager.js +743 -0
  88. package/src/modules/feature-modals.js +1264 -0
  89. package/src/modules/formula-resolver.js +444 -0
  90. package/src/modules/gm-mode.js +184 -0
  91. package/src/modules/health-modals.js +399 -0
  92. package/src/modules/hp-management.js +752 -0
  93. package/src/modules/inventory-manager.js +242 -0
  94. package/src/modules/macro-system.js +825 -0
  95. package/src/modules/notification-system.js +92 -0
  96. package/src/modules/racial-feature-edge-cases.js +746 -0
  97. package/src/modules/resource-manager.js +775 -0
  98. package/src/modules/sheet-builder.js +654 -0
  99. package/src/modules/spell-action-modals.js +583 -0
  100. package/src/modules/spell-cards.js +602 -0
  101. package/src/modules/spell-casting.js +723 -0
  102. package/src/modules/spell-display.js +314 -0
  103. package/src/modules/spell-edge-cases.js +509 -0
  104. package/src/modules/spell-macros.js +201 -0
  105. package/src/modules/spell-modals.js +1221 -0
  106. package/src/modules/spell-slots.js +224 -0
  107. package/src/modules/status-bar-bridge.js +101 -0
  108. package/src/modules/ui-utilities.js +284 -0
  109. package/src/modules/warlock-invocations.js +219 -0
  110. package/src/modules/window-management.js +211 -0
  111. package/src/render/character.ts +234 -0
  112. package/src/render/h.ts +74 -0
  113. package/src/render/index.ts +10 -0
  114. package/src/render/mount.ts +94 -0
  115. package/src/supabase/client.js +1383 -0
  116. package/src/supabase/config.js +60 -0
  117. package/src/supabase/fields.ts +129 -0
  118. package/src/types/character.ts +85 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/render/mount.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAGpE,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,yEAAyE;AACzE,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAQ7B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,EAChB,IAAI,GAAE,UAAe,GACpB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmB7B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAC1C,MAAM,EAAE,QAAQ,EAChB,IAAI,GAAE,UAAe,EACrB,KAAK,SAAsB,GAC1B;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CAqB5C"}
@@ -0,0 +1,63 @@
1
+ import { renderCharacterSheet } from './character';
2
+ import { h } from './h';
3
+ /** GET the stored IR for a character, or null if there isn't one yet. */
4
+ export async function fetchCharacterIR(charId, target) {
5
+ const res = await fetch(`${target.url}/rest/v1/clouds_character_ir?dicecloud_character_id=eq.${encodeURIComponent(charId)}&select=ir`, { headers: { apikey: target.anonKey, Authorization: `Bearer ${target.anonKey}` } });
6
+ if (!res.ok)
7
+ return null;
8
+ const rows = await res.json().catch(() => []);
9
+ return rows?.[0]?.ir ?? null;
10
+ }
11
+ /**
12
+ * Fetch + render into `container`. Returns the IR (or null). On no-IR / error it
13
+ * renders a small message rather than throwing, so callers can fire-and-forget.
14
+ */
15
+ export async function mountCharacterIR(container, charId, target, opts = {}) {
16
+ try {
17
+ const ir = await fetchCharacterIR(charId, target);
18
+ if (!ir) {
19
+ container.replaceChildren(h('div', {
20
+ class: 'cc-empty', style: 'padding: 10px; font-size: 12px; opacity: 0.7;',
21
+ text: 'No IR stored yet - re-sync this character from DiceCloud.',
22
+ }));
23
+ return null;
24
+ }
25
+ container.replaceChildren(renderCharacterSheet(ir, opts));
26
+ return ir;
27
+ }
28
+ catch (e) {
29
+ container.replaceChildren(h('div', {
30
+ class: 'cc-empty', style: 'padding: 10px; font-size: 12px; opacity: 0.7;',
31
+ text: 'Failed to load IR view.',
32
+ }));
33
+ return null;
34
+ }
35
+ }
36
+ /**
37
+ * Append a "โš—๏ธ IR view (beta)" toggle + collapsible panel to `host`. The IR is
38
+ * lazily fetched and rendered the first time the panel opens, using `getCharId()`
39
+ * (read live, so it picks up whichever character is currently active).
40
+ *
41
+ * This is the whole per-adapter integration: one call.
42
+ */
43
+ export function mountIRToggle(host, getCharId, target, opts = {}, label = 'โš—๏ธ IR view (beta)') {
44
+ const btn = h('button', { class: 'cc-ir-toggle', text: label });
45
+ const panel = h('div', { class: 'cc-ir-panel', style: 'display:none; margin-top:8px;' });
46
+ let loaded = false;
47
+ btn.addEventListener('click', async () => {
48
+ const open = panel.style.display === 'none';
49
+ panel.style.display = open ? 'block' : 'none';
50
+ if (open && !loaded) {
51
+ const id = getCharId();
52
+ if (!id) {
53
+ panel.replaceChildren(h('div', { class: 'cc-empty', text: 'No character loaded yet.' }));
54
+ return;
55
+ }
56
+ loaded = true;
57
+ await mountCharacterIR(panel, id, target, opts);
58
+ }
59
+ });
60
+ host.append(btn, panel);
61
+ return { panel, reload: () => { loaded = false; } };
62
+ }
63
+ //# sourceMappingURL=mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../../src/render/mount.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/supabase/fields.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,mBAAmB,QAUrB,CAAC;AAGZ,eAAO,MAAM,cAAc,QA2BhB,CAAC;AAGZ,eAAO,MAAM,gBAAgB,QAgBlB,CAAC;AAGZ,eAAO,MAAM,gBAAgB,QAWlB,CAAC;AAGZ,eAAO,MAAM,mBAAmB,QAUrB,CAAC;AAGZ,eAAO,MAAM,cAAc,QAUhB,CAAC;AAGZ,eAAO,MAAM,cAAc,QAQhB,CAAC;AAEZ,eAAO,MAAM,UAAU;;;;;;;;CAQb,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,UAAU,CAAC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Optimized Supabase Field Selections
3
+ * Reduces egress costs by fetching only needed fields
4
+ */
5
+ // Essential character fields for most operations
6
+ export const CHARACTER_ESSENTIAL = [
7
+ 'dicecloud_character_id',
8
+ 'character_name',
9
+ 'class',
10
+ 'level',
11
+ 'race',
12
+ 'alignment',
13
+ 'discord_user_id',
14
+ 'user_id_dicecloud',
15
+ 'is_active'
16
+ ].join(',');
17
+ // Full character data for detailed views
18
+ export const CHARACTER_FULL = [
19
+ 'dicecloud_character_id',
20
+ 'character_name',
21
+ 'class',
22
+ 'level',
23
+ 'race',
24
+ 'alignment',
25
+ 'hit_points',
26
+ 'hit_dice',
27
+ 'temporary_hp',
28
+ 'death_saves',
29
+ 'armor_class',
30
+ 'speed',
31
+ 'initiative',
32
+ 'proficiency_bonus',
33
+ 'attributes',
34
+ 'attribute_mods',
35
+ 'saves',
36
+ 'skills',
37
+ 'spell_slots',
38
+ 'resources',
39
+ 'conditions',
40
+ 'discord_user_id',
41
+ 'user_id_dicecloud',
42
+ 'owlbear_player_id',
43
+ 'is_active',
44
+ 'updated_at'
45
+ ].join(',');
46
+ // Combat-focused fields
47
+ export const CHARACTER_COMBAT = [
48
+ 'dicecloud_character_id',
49
+ 'character_name',
50
+ 'class',
51
+ 'level',
52
+ 'hit_points',
53
+ 'temporary_hp',
54
+ 'armor_class',
55
+ 'speed',
56
+ 'initiative',
57
+ 'proficiency_bonus',
58
+ 'attributes',
59
+ 'attribute_mods',
60
+ 'saves',
61
+ 'conditions',
62
+ 'discord_user_id'
63
+ ].join(',');
64
+ // Spell-focused fields
65
+ export const CHARACTER_SPELLS = [
66
+ 'dicecloud_character_id',
67
+ 'character_name',
68
+ 'class',
69
+ 'level',
70
+ 'spell_slots',
71
+ 'proficiency_bonus',
72
+ 'attributes',
73
+ 'attribute_mods',
74
+ 'raw_dicecloud_data',
75
+ 'discord_user_id'
76
+ ].join(',');
77
+ // Resource management fields
78
+ export const CHARACTER_RESOURCES = [
79
+ 'dicecloud_character_id',
80
+ 'character_name',
81
+ 'class',
82
+ 'level',
83
+ 'hit_points',
84
+ 'hit_dice',
85
+ 'spell_slots',
86
+ 'resources',
87
+ 'discord_user_id'
88
+ ].join(',');
89
+ // Minimal fields for character list
90
+ export const CHARACTER_LIST = [
91
+ 'dicecloud_character_id',
92
+ 'character_name',
93
+ 'class',
94
+ 'level',
95
+ 'race',
96
+ 'hit_points',
97
+ 'armor_class',
98
+ 'is_active',
99
+ 'discord_user_id'
100
+ ].join(',');
101
+ // Pairing fields
102
+ export const PAIRING_FIELDS = [
103
+ 'id',
104
+ 'pairing_code',
105
+ 'discord_user_id',
106
+ 'dicecloud_user_id',
107
+ 'status',
108
+ 'created_at',
109
+ 'expires_at'
110
+ ].join(',');
111
+ export const FIELD_SETS = {
112
+ essential: CHARACTER_ESSENTIAL,
113
+ full: CHARACTER_FULL,
114
+ combat: CHARACTER_COMBAT,
115
+ spells: CHARACTER_SPELLS,
116
+ resources: CHARACTER_RESOURCES,
117
+ list: CHARACTER_LIST,
118
+ pairing: PAIRING_FIELDS
119
+ };
120
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/supabase/fields.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,iDAAiD;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,wBAAwB;IACxB,gBAAgB;IAChB,OAAO;IACP,OAAO;IACP,MAAM;IACN,WAAW;IACX,iBAAiB;IACjB,mBAAmB;IACnB,WAAW;CACZ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,yCAAyC;AACzC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,wBAAwB;IACxB,gBAAgB;IAChB,OAAO;IACP,OAAO;IACP,MAAM;IACN,WAAW;IACX,YAAY;IACZ,UAAU;IACV,cAAc;IACd,aAAa;IACb,aAAa;IACb,OAAO;IACP,YAAY;IACZ,mBAAmB;IACnB,YAAY;IACZ,gBAAgB;IAChB,OAAO;IACP,QAAQ;IACR,aAAa;IACb,WAAW;IACX,YAAY;IACZ,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;IACnB,WAAW;IACX,YAAY;CACb,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,wBAAwB;AACxB,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,wBAAwB;IACxB,gBAAgB;IAChB,OAAO;IACP,OAAO;IACP,YAAY;IACZ,cAAc;IACd,aAAa;IACb,OAAO;IACP,YAAY;IACZ,mBAAmB;IACnB,YAAY;IACZ,gBAAgB;IAChB,OAAO;IACP,YAAY;IACZ,iBAAiB;CAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,uBAAuB;AACvB,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,wBAAwB;IACxB,gBAAgB;IAChB,OAAO;IACP,OAAO;IACP,aAAa;IACb,mBAAmB;IACnB,YAAY;IACZ,gBAAgB;IAChB,oBAAoB;IACpB,iBAAiB;CAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,6BAA6B;AAC7B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,wBAAwB;IACxB,gBAAgB;IAChB,OAAO;IACP,OAAO;IACP,YAAY;IACZ,UAAU;IACV,aAAa;IACb,WAAW;IACX,iBAAiB;CAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,oCAAoC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,wBAAwB;IACxB,gBAAgB;IAChB,OAAO;IACP,OAAO;IACP,MAAM;IACN,YAAY;IACZ,aAAa;IACb,WAAW;IACX,iBAAiB;CAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,iBAAiB;AACjB,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI;IACJ,cAAc;IACd,iBAAiB;IACjB,mBAAmB;IACnB,QAAQ;IACR,YAAY;IACZ,YAAY;CACb,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,mBAAmB;IAC9B,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,gBAAgB;IACxB,MAAM,EAAE,gBAAgB;IACxB,SAAS,EAAE,mBAAmB;IAC9B,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,cAAc;CACf,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character.d.ts","sourceRoot":"","sources":["../../src/types/character.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared Character Types for CarmaClouds
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=character.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character.js","sourceRoot":"","sources":["../../src/types/character.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@carmaclouds/core",
3
+ "version": "2.3.1",
4
+ "description": "Core utilities and types shared across CarmaClouds packages",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ },
12
+ "./cache": {
13
+ "import": "./dist/cache/index.js",
14
+ "types": "./dist/cache/index.d.ts"
15
+ },
16
+ "./supabase": {
17
+ "import": "./dist/supabase/index.js",
18
+ "types": "./dist/supabase/index.d.ts"
19
+ },
20
+ "./supabase/config.js": "./src/supabase/config.js",
21
+ "./types": {
22
+ "import": "./dist/types/index.js",
23
+ "types": "./dist/types/index.d.ts"
24
+ },
25
+ "./common/*": "./src/common/*",
26
+ "./modules/*": "./src/modules/*",
27
+ "./browser.js": "./src/browser.js",
28
+ "./ir": {
29
+ "import": "./dist/ir/index.js",
30
+ "types": "./dist/ir/index.d.ts"
31
+ },
32
+ "./render": {
33
+ "import": "./dist/render/index.js",
34
+ "types": "./dist/render/index.d.ts"
35
+ },
36
+ "./src/*": "./src/*"
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "src"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/CarmaNayeli/carmaclouds.git",
48
+ "directory": "packages/core"
49
+ },
50
+ "sideEffects": false,
51
+ "scripts": {
52
+ "build": "tsc",
53
+ "dev": "tsc --watch",
54
+ "clean": "rm -rf dist",
55
+ "prepublishOnly": "npm run build",
56
+ "test": "echo \"No tests yet\"",
57
+ "lint": "eslint src --ext .ts"
58
+ },
59
+ "keywords": [
60
+ "carmaclouds",
61
+ "dicecloud",
62
+ "vtt",
63
+ "character-sheet"
64
+ ],
65
+ "license": "MIT",
66
+ "devDependencies": {
67
+ "linkedom": "^0.18.12",
68
+ "typescript": "^5.0.0"
69
+ },
70
+ "dependencies": {
71
+ "@supabase/supabase-js": "^2.0.0"
72
+ }
73
+ }
package/src/browser.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Browser Extension Bundle
3
+ * Imports all modules needed by browser extensions
4
+ */
5
+
6
+ // Common utilities
7
+ import './common/debug.js';
8
+ import './common/browser-polyfill.js';
9
+ import './common/html-utils.js';
10
+ import './common/theme-manager.js';
11
+
12
+ // Supabase client and config (make config globally available)
13
+ import { SUPABASE_URL, SUPABASE_ANON_KEY, TABLES, PROJECT_CONFIGS, getProjectConfig } from './supabase/config.js';
14
+ import './supabase/client.js';
15
+
16
+ // Export Supabase config globally for legacy code
17
+ // TODO: Fix race condition - code sometimes checks for Supabase config before this executes,
18
+ // causing brief "Supabase not configured" flash before it connects successfully
19
+ if (typeof window !== 'undefined') {
20
+ window.SUPABASE_URL = SUPABASE_URL;
21
+ window.SUPABASE_ANON_KEY = SUPABASE_ANON_KEY;
22
+ window.SUPABASE_TABLES = TABLES;
23
+ window.SUPABASE_PROJECT_CONFIGS = PROJECT_CONFIGS;
24
+ window.getProjectConfig = getProjectConfig;
25
+ }
26
+
27
+ // Libraries
28
+ import './lib/indexeddb-cache.js';
29
+
30
+ // Edge case modules
31
+ import './modules/spell-edge-cases.js';
32
+ import './modules/class-feature-edge-cases.js';
33
+ import './modules/racial-feature-edge-cases.js';
34
+ import './modules/combat-maneuver-edge-cases.js';
35
+
36
+ // Action system
37
+ import './modules/action-executor.js';
38
+ import './modules/action-announcements.js';
39
+ import './modules/action-display.js';
40
+ import './modules/action-filters.js';
41
+ import './modules/action-options.js';
42
+
43
+ // Other modules
44
+ import './modules/card-creator.js';
45
+ import './modules/character-trait-popups.js';
46
+ import './modules/character-traits.js';
47
+ import './modules/color-utils.js';
48
+ import './modules/companions-manager.js';
49
+ import './modules/concentration-tracker.js';
50
+ import './modules/data-manager.js';
51
+ import './modules/dice-roller.js';
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Generic Cache Manager for CarmaClouds
3
+ * Reduces database egress costs with configurable TTL caching
4
+ */
5
+
6
+ import type { CacheStats } from '../types/character';
7
+
8
+ export interface CacheEntry<T> {
9
+ data: T;
10
+ timestamp: number;
11
+ }
12
+
13
+ export interface CacheManagerOptions {
14
+ /** Cache expiry time in milliseconds */
15
+ expiryMs?: number;
16
+ /** Cleanup interval in milliseconds */
17
+ cleanupIntervalMs?: number;
18
+ /** Enable debug logging */
19
+ debug?: boolean;
20
+ }
21
+
22
+ export class CacheManager<T = any> {
23
+ private cache: Map<string, CacheEntry<T>>;
24
+ private expiryMs: number;
25
+ private cleanupInterval?: NodeJS.Timeout;
26
+ private stats: {
27
+ hits: number;
28
+ misses: number;
29
+ stores: number;
30
+ invalidations: number;
31
+ };
32
+ private debug: boolean;
33
+
34
+ constructor(options: CacheManagerOptions = {}) {
35
+ this.cache = new Map();
36
+ this.expiryMs = options.expiryMs || 15 * 60 * 1000; // Default 15 minutes
37
+ this.debug = options.debug || false;
38
+ this.stats = {
39
+ hits: 0,
40
+ misses: 0,
41
+ stores: 0,
42
+ invalidations: 0
43
+ };
44
+
45
+ // Auto-cleanup expired entries
46
+ const cleanupInterval = options.cleanupIntervalMs || 5 * 60 * 1000;
47
+ this.cleanupInterval = setInterval(() => this.cleanupExpired(), cleanupInterval);
48
+ }
49
+
50
+ /**
51
+ * Get value from cache
52
+ */
53
+ get(key: string): T | null {
54
+ const entry = this.cache.get(key);
55
+
56
+ if (!entry) {
57
+ this.stats.misses++;
58
+ return null;
59
+ }
60
+
61
+ // Check if expired
62
+ const now = Date.now();
63
+ if (now - entry.timestamp >= this.expiryMs) {
64
+ this.cache.delete(key);
65
+ this.stats.misses++;
66
+ if (this.debug) {
67
+ console.log(`โฐ [Cache] Expired: ${key}`);
68
+ }
69
+ return null;
70
+ }
71
+
72
+ this.stats.hits++;
73
+ if (this.debug) {
74
+ const age = Math.floor((now - entry.timestamp) / 1000);
75
+ console.log(`โœ… [Cache] Hit: ${key} (age: ${age}s)`);
76
+ }
77
+ return entry.data;
78
+ }
79
+
80
+ /**
81
+ * Store value in cache
82
+ */
83
+ set(key: string, data: T): void {
84
+ this.cache.set(key, {
85
+ data,
86
+ timestamp: Date.now()
87
+ });
88
+ this.stats.stores++;
89
+
90
+ if (this.debug) {
91
+ console.log(`๐Ÿ“ฆ [Cache] Stored: ${key}`);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Check if key exists and is valid
97
+ */
98
+ has(key: string): boolean {
99
+ return this.get(key) !== null;
100
+ }
101
+
102
+ /**
103
+ * Delete specific cache entry
104
+ */
105
+ delete(key: string): boolean {
106
+ const deleted = this.cache.delete(key);
107
+ if (deleted) {
108
+ this.stats.invalidations++;
109
+ if (this.debug) {
110
+ console.log(`๐Ÿ—‘๏ธ [Cache] Invalidated: ${key}`);
111
+ }
112
+ }
113
+ return deleted;
114
+ }
115
+
116
+ /**
117
+ * Clear all cache
118
+ */
119
+ clear(): void {
120
+ const size = this.cache.size;
121
+ this.cache.clear();
122
+ if (this.debug) {
123
+ console.log(`๐Ÿ—‘๏ธ [Cache] Cleared ${size} entries`);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Get cache statistics
129
+ */
130
+ getStats(): CacheStats {
131
+ const hitRate = this.stats.hits + this.stats.misses > 0
132
+ ? ((this.stats.hits / (this.stats.hits + this.stats.misses)) * 100).toFixed(2)
133
+ : '0';
134
+
135
+ return {
136
+ size: this.cache.size,
137
+ hits: this.stats.hits,
138
+ misses: this.stats.misses,
139
+ stores: this.stats.stores,
140
+ invalidations: this.stats.invalidations,
141
+ hitRate: `${hitRate}%`,
142
+ expiryMinutes: this.expiryMs / 60000
143
+ };
144
+ }
145
+
146
+ /**
147
+ * Cleanup expired cache entries
148
+ */
149
+ private cleanupExpired(): void {
150
+ const now = Date.now();
151
+ let cleaned = 0;
152
+
153
+ for (const [key, entry] of this.cache.entries()) {
154
+ if (now - entry.timestamp >= this.expiryMs) {
155
+ this.cache.delete(key);
156
+ cleaned++;
157
+ }
158
+ }
159
+
160
+ if (cleaned > 0 && this.debug) {
161
+ console.log(`๐Ÿงน [Cache] Cleaned up ${cleaned} expired entries`);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Destroy cache manager (cleanup interval)
167
+ */
168
+ destroy(): void {
169
+ if (this.cleanupInterval) {
170
+ clearInterval(this.cleanupInterval);
171
+ }
172
+ this.clear();
173
+ }
174
+ }