@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.
- package/dist/cache/CacheManager.d.ts.map +1 -0
- package/dist/cache/CacheManager.js +131 -0
- package/dist/cache/CacheManager.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/ir/index.d.ts +11 -0
- package/dist/ir/index.d.ts.map +1 -0
- package/dist/ir/index.js +9 -0
- package/dist/ir/index.js.map +1 -0
- package/dist/ir/normalize.d.ts +10 -0
- package/dist/ir/normalize.d.ts.map +1 -0
- package/dist/ir/normalize.js +207 -0
- package/dist/ir/normalize.js.map +1 -0
- package/dist/ir/persistence.d.ts +26 -0
- package/dist/ir/persistence.d.ts.map +1 -0
- package/dist/ir/persistence.js +21 -0
- package/dist/ir/persistence.js.map +1 -0
- package/dist/ir/sync.d.ts +12 -0
- package/dist/ir/sync.d.ts.map +1 -0
- package/dist/ir/sync.js +36 -0
- package/dist/ir/sync.js.map +1 -0
- package/dist/ir/types.d.ts +143 -0
- package/dist/ir/types.d.ts.map +1 -0
- package/dist/ir/types.js +13 -0
- package/dist/ir/types.js.map +1 -0
- package/dist/ir/views/dnd5e.d.ts +40 -0
- package/dist/ir/views/dnd5e.d.ts.map +1 -0
- package/dist/ir/views/dnd5e.js +50 -0
- package/dist/ir/views/dnd5e.js.map +1 -0
- package/dist/render/character.d.ts +19 -0
- package/dist/render/character.d.ts.map +1 -0
- package/dist/render/character.js +156 -0
- package/dist/render/character.js.map +1 -0
- package/dist/render/h.d.ts +27 -0
- package/dist/render/h.d.ts.map +1 -0
- package/dist/render/h.js +64 -0
- package/dist/render/h.js.map +1 -0
- package/dist/render/index.d.ts +11 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +8 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/mount.d.ts +31 -0
- package/dist/render/mount.d.ts.map +1 -0
- package/dist/render/mount.js +63 -0
- package/dist/render/mount.js.map +1 -0
- package/dist/supabase/fields.d.ts.map +1 -0
- package/dist/supabase/fields.js +120 -0
- package/dist/supabase/fields.js.map +1 -0
- package/dist/types/character.d.ts.map +1 -0
- package/dist/types/character.js +5 -0
- package/dist/types/character.js.map +1 -0
- package/package.json +73 -0
- package/src/browser.js +51 -0
- package/src/cache/CacheManager.ts +174 -0
- package/src/common/browser-polyfill.js +319 -0
- package/src/common/debug.js +123 -0
- package/src/common/html-utils.js +134 -0
- package/src/common/theme-manager.js +265 -0
- package/src/index.ts +25 -0
- package/src/ir/__fixtures__/dnd5e-character.json +75962 -0
- package/src/ir/__fixtures__/non-dnd-character.json +14218 -0
- package/src/ir/index.ts +10 -0
- package/src/ir/normalize.ts +245 -0
- package/src/ir/persistence.ts +37 -0
- package/src/ir/sync.ts +49 -0
- package/src/ir/types.ts +161 -0
- package/src/ir/views/dnd5e.ts +94 -0
- package/src/lib/indexeddb-cache.js +320 -0
- package/src/modules/action-announcements.js +102 -0
- package/src/modules/action-display.js +1557 -0
- package/src/modules/action-executor.js +860 -0
- package/src/modules/action-filters.js +167 -0
- package/src/modules/action-options.js +117 -0
- package/src/modules/card-creator.js +142 -0
- package/src/modules/character-portrait.js +169 -0
- package/src/modules/character-trait-popups.js +959 -0
- package/src/modules/character-traits.js +814 -0
- package/src/modules/class-feature-edge-cases.js +1320 -0
- package/src/modules/color-utils.js +69 -0
- package/src/modules/combat-maneuver-edge-cases.js +660 -0
- package/src/modules/companions-manager.js +178 -0
- package/src/modules/concentration-tracker.js +178 -0
- package/src/modules/data-manager.js +514 -0
- package/src/modules/dice-roller.js +719 -0
- package/src/modules/effects-manager.js +743 -0
- package/src/modules/feature-modals.js +1264 -0
- package/src/modules/formula-resolver.js +444 -0
- package/src/modules/gm-mode.js +184 -0
- package/src/modules/health-modals.js +399 -0
- package/src/modules/hp-management.js +752 -0
- package/src/modules/inventory-manager.js +242 -0
- package/src/modules/macro-system.js +825 -0
- package/src/modules/notification-system.js +92 -0
- package/src/modules/racial-feature-edge-cases.js +746 -0
- package/src/modules/resource-manager.js +775 -0
- package/src/modules/sheet-builder.js +654 -0
- package/src/modules/spell-action-modals.js +583 -0
- package/src/modules/spell-cards.js +602 -0
- package/src/modules/spell-casting.js +723 -0
- package/src/modules/spell-display.js +314 -0
- package/src/modules/spell-edge-cases.js +509 -0
- package/src/modules/spell-macros.js +201 -0
- package/src/modules/spell-modals.js +1221 -0
- package/src/modules/spell-slots.js +224 -0
- package/src/modules/status-bar-bridge.js +101 -0
- package/src/modules/ui-utilities.js +284 -0
- package/src/modules/warlock-invocations.js +219 -0
- package/src/modules/window-management.js +211 -0
- package/src/render/character.ts +234 -0
- package/src/render/h.ts +74 -0
- package/src/render/index.ts +10 -0
- package/src/render/mount.ts +94 -0
- package/src/supabase/client.js +1383 -0
- package/src/supabase/config.js +60 -0
- package/src/supabase/fields.ts +129 -0
- 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 @@
|
|
|
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
|
+
}
|