juxscript 1.0.61 → 1.0.63

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 (141) hide show
  1. package/bin/cli.js +161 -293
  2. package/docs/v2comps/HEADLESS.md +83 -0
  3. package/docs/v2comps/ISOMORPHISM.md +10 -0
  4. package/juxconfig.example.js +63 -58
  5. package/lib/componentsv2/base/BaseEngine.js +258 -0
  6. package/lib/componentsv2/base/BaseEngine.js.map +1 -0
  7. package/lib/componentsv2/base/BaseEngine.ts +303 -0
  8. package/lib/componentsv2/base/BaseSkin.js +108 -0
  9. package/lib/componentsv2/base/BaseSkin.js.map +1 -0
  10. package/lib/componentsv2/base/BaseSkin.ts +137 -0
  11. package/lib/componentsv2/base/GlobalBus.js +56 -0
  12. package/lib/componentsv2/base/GlobalBus.js.map +1 -0
  13. package/lib/componentsv2/base/GlobalBus.ts +60 -0
  14. package/lib/componentsv2/base/State.js +68 -0
  15. package/lib/componentsv2/base/State.js.map +1 -0
  16. package/lib/componentsv2/base/State.ts +62 -0
  17. package/lib/componentsv2/grid/component.js +41 -0
  18. package/lib/componentsv2/grid/component.js.map +1 -0
  19. package/lib/componentsv2/grid/component.ts +67 -0
  20. package/lib/componentsv2/grid/engine.js +73 -0
  21. package/lib/componentsv2/grid/engine.js.map +1 -0
  22. package/lib/componentsv2/grid/engine.ts +110 -0
  23. package/lib/componentsv2/grid/skin.js +95 -0
  24. package/lib/componentsv2/grid/skin.js.map +1 -0
  25. package/lib/componentsv2/grid/skin.ts +105 -0
  26. package/lib/componentsv2/grid/structure.css +58 -0
  27. package/lib/componentsv2/index.js +218 -0
  28. package/lib/componentsv2/index.js.map +1 -0
  29. package/lib/componentsv2/index.ts +253 -0
  30. package/lib/componentsv2/input/component.js +21 -0
  31. package/lib/componentsv2/input/component.js.map +1 -0
  32. package/lib/componentsv2/input/component.ts +28 -0
  33. package/lib/componentsv2/input/engine.js +50 -0
  34. package/lib/componentsv2/input/engine.js.map +1 -0
  35. package/lib/componentsv2/input/engine.ts +76 -0
  36. package/lib/componentsv2/input/skin.js +91 -0
  37. package/lib/componentsv2/input/skin.js.map +1 -0
  38. package/lib/componentsv2/input/skin.ts +91 -0
  39. package/lib/componentsv2/input/structure.css +47 -0
  40. package/lib/componentsv2/list/component.js +83 -0
  41. package/lib/componentsv2/list/component.js.map +1 -0
  42. package/lib/componentsv2/list/component.ts +97 -0
  43. package/lib/componentsv2/list/engine.js +261 -0
  44. package/lib/componentsv2/list/engine.js.map +1 -0
  45. package/lib/componentsv2/list/engine.ts +345 -0
  46. package/lib/componentsv2/list/skin.js +343 -0
  47. package/lib/componentsv2/list/skin.js.map +1 -0
  48. package/lib/componentsv2/list/skin.ts +367 -0
  49. package/lib/componentsv2/list/structure.css +359 -0
  50. package/lib/componentsv2/plugins/ClientSQLitePlugin.js +130 -0
  51. package/lib/componentsv2/plugins/ClientSQLitePlugin.js.map +1 -0
  52. package/lib/componentsv2/plugins/ClientSQLitePlugin.ts +154 -0
  53. package/lib/componentsv2/plugins/IndexedDBPlugin.js +75 -0
  54. package/lib/componentsv2/plugins/IndexedDBPlugin.js.map +1 -0
  55. package/lib/componentsv2/plugins/IndexedDBPlugin.ts +96 -0
  56. package/lib/componentsv2/plugins/LocalStoragePlugin.js +65 -0
  57. package/lib/componentsv2/plugins/LocalStoragePlugin.js.map +1 -0
  58. package/lib/componentsv2/plugins/LocalStoragePlugin.ts +86 -0
  59. package/lib/componentsv2/plugins/ServerSQLitePlugin.js +70 -0
  60. package/lib/componentsv2/plugins/ServerSQLitePlugin.js.map +1 -0
  61. package/lib/componentsv2/plugins/ServerSQLitePlugin.ts +99 -0
  62. package/lib/componentsv2/stubs/ComponentComposition.ts.stub +32 -0
  63. package/lib/componentsv2/stubs/ComponentEngine.ts.stub +36 -0
  64. package/lib/componentsv2/stubs/ComponentSkin.ts.stub +34 -0
  65. package/lib/componentsv2/stubs/ComponentStructure.css.stub +13 -0
  66. package/lib/componentsv2/tools/CreateSkin.js +62 -0
  67. package/lib/componentsv2/tools/DocSpam.js +134 -0
  68. package/lib/componentsv2/tools/FluencyAudit.js +141 -0
  69. package/lib/componentsv2/tools/OptionsAudit.js +177 -0
  70. package/lib/componentsv2/tools/Scaffold.js +140 -0
  71. package/lib/utils/fetch.js +428 -0
  72. package/lib/utils/fetch.js.map +1 -0
  73. package/machinery/build.js +2 -1
  74. package/machinery/compiler.js +200 -37
  75. package/machinery/config.js +93 -6
  76. package/machinery/diagnose.js +72 -0
  77. package/machinery/jux-module-pattern.md +118 -0
  78. package/machinery/server.js +23 -7
  79. package/machinery/verifier.js +143 -0
  80. package/machinery/watcher.js +53 -64
  81. package/package.json +11 -2
  82. package/lib/components/alert.ts +0 -200
  83. package/lib/components/app.ts +0 -258
  84. package/lib/components/badge.ts +0 -101
  85. package/lib/components/base/BaseComponent.ts +0 -417
  86. package/lib/components/base/FormInput.ts +0 -227
  87. package/lib/components/button.ts +0 -178
  88. package/lib/components/card.ts +0 -173
  89. package/lib/components/chart.ts +0 -231
  90. package/lib/components/checkbox.ts +0 -242
  91. package/lib/components/code.ts +0 -123
  92. package/lib/components/container.ts +0 -140
  93. package/lib/components/data.ts +0 -135
  94. package/lib/components/datepicker.ts +0 -234
  95. package/lib/components/dialog.ts +0 -172
  96. package/lib/components/divider.ts +0 -100
  97. package/lib/components/dropdown.ts +0 -186
  98. package/lib/components/element.ts +0 -267
  99. package/lib/components/error-handler.ts +0 -285
  100. package/lib/components/fileupload.ts +0 -309
  101. package/lib/components/grid.ts +0 -291
  102. package/lib/components/guard.ts +0 -92
  103. package/lib/components/heading.ts +0 -96
  104. package/lib/components/helpers.ts +0 -41
  105. package/lib/components/hero.ts +0 -224
  106. package/lib/components/icon.ts +0 -160
  107. package/lib/components/icons.ts +0 -175
  108. package/lib/components/include.ts +0 -440
  109. package/lib/components/input.ts +0 -457
  110. package/lib/components/list.ts +0 -419
  111. package/lib/components/loading.ts +0 -100
  112. package/lib/components/menu.ts +0 -260
  113. package/lib/components/modal.ts +0 -239
  114. package/lib/components/nav.ts +0 -257
  115. package/lib/components/paragraph.ts +0 -97
  116. package/lib/components/progress.ts +0 -139
  117. package/lib/components/radio.ts +0 -278
  118. package/lib/components/req.ts +0 -302
  119. package/lib/components/script.ts +0 -43
  120. package/lib/components/select.ts +0 -252
  121. package/lib/components/sidebar.ts +0 -167
  122. package/lib/components/style.ts +0 -43
  123. package/lib/components/switch.ts +0 -246
  124. package/lib/components/table.ts +0 -1249
  125. package/lib/components/tabs.ts +0 -250
  126. package/lib/components/theme-toggle.ts +0 -300
  127. package/lib/components/token-calculator.ts +0 -313
  128. package/lib/components/tooltip.ts +0 -144
  129. package/lib/components/view.ts +0 -190
  130. package/lib/components/write.ts +0 -272
  131. package/lib/jux.ts +0 -365
  132. package/lib/layouts/default.css +0 -260
  133. package/lib/layouts/figma.css +0 -334
  134. package/lib/reactivity/state.ts +0 -78
  135. package/machinery/bundleAssets.js +0 -0
  136. package/machinery/bundleJux.js +0 -0
  137. package/machinery/bundleVendors.js +0 -0
  138. package/presets/default/all.jux +0 -343
  139. package/presets/default/index.jux +0 -90
  140. package/presets/default/layout.css +0 -1612
  141. package/presets/default/layout.jux +0 -55
@@ -0,0 +1,75 @@
1
+ /**
2
+ * IndexedDB Plugin
3
+ * Asynchronous persistence for larger datasets.
4
+ */
5
+ export const IndexedDBPlugin = (config) => ({
6
+ name: 'indexed-db-persist',
7
+ version: '1.0.0',
8
+ targetEnv: 'client',
9
+ install: (engine) => {
10
+ // @ts-ignore
11
+ const initialState = engine.state[config.bindTo];
12
+ if (initialState !== undefined && !Array.isArray(initialState)) {
13
+ console.error(`[IndexedDBPlugin] 🛑 Configuration Error: bindTo='${config.bindTo}' is not an Array. This plugin is designed for List/Collection data.`);
14
+ return;
15
+ }
16
+ let db = null;
17
+ const request = indexedDB.open(config.dbName, 1);
18
+ // 1. Schema Setup
19
+ request.onupgradeneeded = (e) => {
20
+ const d = e.target.result;
21
+ if (!d.objectStoreNames.contains(config.storeName)) {
22
+ d.createObjectStore(config.storeName);
23
+ }
24
+ };
25
+ // 2. IO Operations
26
+ const save = (data) => {
27
+ if (!db)
28
+ return;
29
+ const tx = db.transaction([config.storeName], 'readwrite');
30
+ const store = tx.objectStore(config.storeName);
31
+ store.put(data, 'state_snapshot'); // Storing entire bound state as one blob for simplicity
32
+ };
33
+ const load = () => {
34
+ if (!db)
35
+ return;
36
+ // @ts-ignore
37
+ if (typeof engine.loading === 'function')
38
+ engine.loading(true);
39
+ const tx = db.transaction([config.storeName], 'readonly');
40
+ const store = tx.objectStore(config.storeName);
41
+ const req = store.get('state_snapshot');
42
+ req.onsuccess = () => {
43
+ if (req.result) {
44
+ // @ts-ignore
45
+ engine.updateState({ [config.bindTo]: req.result });
46
+ // @ts-ignore
47
+ if (engine.emit)
48
+ engine.emit('plugin:hydrated', { source: 'IndexedDB' });
49
+ }
50
+ // @ts-ignore
51
+ if (typeof engine.loading === 'function')
52
+ engine.loading(false);
53
+ };
54
+ req.onerror = () => {
55
+ // @ts-ignore
56
+ if (typeof engine.loading === 'function')
57
+ engine.loading(false);
58
+ };
59
+ };
60
+ // 3. Initialization
61
+ request.onsuccess = (e) => {
62
+ db = e.target.result;
63
+ if (config.autoLoad) {
64
+ load();
65
+ }
66
+ // Auto-save subscription (debounced slightly in real world, direct here)
67
+ engine.subscribe((state) => {
68
+ if (db)
69
+ save(state[config.bindTo]);
70
+ });
71
+ };
72
+ request.onerror = (e) => console.error('[IndexedDBPlugin] Open Error', e);
73
+ }
74
+ });
75
+ //# sourceMappingURL=IndexedDBPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexedDBPlugin.js","sourceRoot":"","sources":["IndexedDBPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { JuxServiceContract, BaseEngine } from '../base/BaseEngine.js';
2
+
3
+ export interface IndexedDBConfig {
4
+ dbName: string;
5
+ storeName: string;
6
+
7
+ /**
8
+ * State Binding: The property key on the Engine's state to persist.
9
+ * e.g., 'items'
10
+ */
11
+ bindTo: string;
12
+
13
+ /** If true, loads data immediately on install */
14
+ autoLoad?: boolean;
15
+ }
16
+
17
+ /**
18
+ * IndexedDB Plugin
19
+ * Asynchronous persistence for larger datasets.
20
+ */
21
+ export const IndexedDBPlugin = (config: IndexedDBConfig): JuxServiceContract<BaseEngine<any>> => ({
22
+ name: 'indexed-db-persist',
23
+ version: '1.0.0',
24
+ targetEnv: 'client',
25
+
26
+ install: (engine) => {
27
+
28
+ // @ts-ignore
29
+ const initialState = engine.state[config.bindTo];
30
+ if (initialState !== undefined && !Array.isArray(initialState)) {
31
+ console.error(`[IndexedDBPlugin] 🛑 Configuration Error: bindTo='${config.bindTo}' is not an Array. This plugin is designed for List/Collection data.`);
32
+ return;
33
+ }
34
+
35
+ let db: IDBDatabase | null = null;
36
+ const request = indexedDB.open(config.dbName, 1);
37
+
38
+ // 1. Schema Setup
39
+ request.onupgradeneeded = (e: any) => {
40
+ const d = e.target.result;
41
+ if (!d.objectStoreNames.contains(config.storeName)) {
42
+ d.createObjectStore(config.storeName);
43
+ }
44
+ };
45
+
46
+ // 2. IO Operations
47
+ const save = (data: any) => {
48
+ if (!db) return;
49
+ const tx = db.transaction([config.storeName], 'readwrite');
50
+ const store = tx.objectStore(config.storeName);
51
+ store.put(data, 'state_snapshot'); // Storing entire bound state as one blob for simplicity
52
+ };
53
+
54
+ const load = () => {
55
+ if (!db) return;
56
+ // @ts-ignore
57
+ if (typeof engine.loading === 'function') engine.loading(true);
58
+
59
+ const tx = db.transaction([config.storeName], 'readonly');
60
+ const store = tx.objectStore(config.storeName);
61
+ const req = store.get('state_snapshot');
62
+
63
+ req.onsuccess = () => {
64
+ if (req.result) {
65
+ // @ts-ignore
66
+ engine.updateState({ [config.bindTo]: req.result });
67
+ // @ts-ignore
68
+ if (engine.emit) engine.emit('plugin:hydrated', { source: 'IndexedDB' });
69
+ }
70
+ // @ts-ignore
71
+ if (typeof engine.loading === 'function') engine.loading(false);
72
+ };
73
+
74
+ req.onerror = () => {
75
+ // @ts-ignore
76
+ if (typeof engine.loading === 'function') engine.loading(false);
77
+ };
78
+ };
79
+
80
+ // 3. Initialization
81
+ request.onsuccess = (e: any) => {
82
+ db = e.target.result;
83
+
84
+ if (config.autoLoad) {
85
+ load();
86
+ }
87
+
88
+ // Auto-save subscription (debounced slightly in real world, direct here)
89
+ engine.subscribe((state) => {
90
+ if (db) save(state[config.bindTo]);
91
+ });
92
+ };
93
+
94
+ request.onerror = (e) => console.error('[IndexedDBPlugin] Open Error', e);
95
+ }
96
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * LocalStorage Plugin
3
+ * Persists a slice of Engine State to Browser LocalStorage.
4
+ */
5
+ export const LocalStoragePlugin = (config) => ({
6
+ name: 'local-storage-persist',
7
+ version: '1.0.0',
8
+ targetEnv: 'client',
9
+ install: (engine) => {
10
+ // @ts-ignore
11
+ const initialState = engine.state[config.bindTo];
12
+ if (initialState !== undefined && !Array.isArray(initialState)) {
13
+ console.error(`[LocalStoragePlugin] 🛑 Configuration Error: bindTo='${config.bindTo}' is not an Array. This plugin is designed for List/Collection data.`);
14
+ return;
15
+ }
16
+ const storageKey = `jux:${config.key}`;
17
+ // 1. Hydrate (Load from Storage)
18
+ const load = () => {
19
+ try {
20
+ const raw = localStorage.getItem(storageKey);
21
+ if (raw) {
22
+ const data = JSON.parse(raw);
23
+ // @ts-ignore - Generic update
24
+ engine.updateState({ [config.bindTo]: data });
25
+ // @ts-ignore
26
+ if (engine.emit)
27
+ engine.emit('plugin:hydrated', { source: 'localStorage', count: Array.isArray(data) ? data.length : 1 });
28
+ }
29
+ }
30
+ catch (e) {
31
+ console.error('[LocalStoragePlugin] Load Failed', e);
32
+ }
33
+ };
34
+ // 2. Persist (Save to Storage)
35
+ const save = (state) => {
36
+ try {
37
+ const value = state[config.bindTo];
38
+ localStorage.setItem(storageKey, JSON.stringify(value));
39
+ }
40
+ catch (e) {
41
+ console.error('[LocalStoragePlugin] Save Failed', e);
42
+ }
43
+ };
44
+ // Logic
45
+ if (config.clearOnInstall) {
46
+ localStorage.removeItem(storageKey);
47
+ }
48
+ else {
49
+ load();
50
+ }
51
+ if (config.autoSave !== false) {
52
+ engine.subscribe((state) => save(state));
53
+ }
54
+ // Expose manual triggers
55
+ engine.on('storage:save', () => save(engine.state));
56
+ engine.on('storage:load', load);
57
+ engine.on('storage:clear', () => {
58
+ localStorage.removeItem(storageKey);
59
+ // @ts-ignore
60
+ if (engine.emit)
61
+ engine.emit('plugin:cleared', { source: 'localStorage' });
62
+ });
63
+ }
64
+ });
65
+ //# sourceMappingURL=LocalStoragePlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalStoragePlugin.js","sourceRoot":"","sources":["LocalStoragePlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import { JuxServiceContract, BaseEngine } from '../base/BaseEngine.js';
2
+
3
+ export interface LocalStorageConfig {
4
+ /** Unique key for storage (e.g. 'my-app-list-v1') */
5
+ key: string;
6
+
7
+ /**
8
+ * State Binding: The property key on the Engine's state to persist.
9
+ * e.g., 'items' for a ListEngine.
10
+ */
11
+ bindTo: string;
12
+
13
+ /** If true, clears storage on install (fresh start) */
14
+ clearOnInstall?: boolean;
15
+
16
+ /** If true, automatically saves to storage when state changes */
17
+ autoSave?: boolean;
18
+ }
19
+
20
+ /**
21
+ * LocalStorage Plugin
22
+ * Persists a slice of Engine State to Browser LocalStorage.
23
+ */
24
+ export const LocalStoragePlugin = (config: LocalStorageConfig): JuxServiceContract<BaseEngine<any>> => ({
25
+ name: 'local-storage-persist',
26
+ version: '1.0.0',
27
+ targetEnv: 'client',
28
+
29
+ install: (engine) => {
30
+
31
+ // @ts-ignore
32
+ const initialState = engine.state[config.bindTo];
33
+ if (initialState !== undefined && !Array.isArray(initialState)) {
34
+ console.error(`[LocalStoragePlugin] 🛑 Configuration Error: bindTo='${config.bindTo}' is not an Array. This plugin is designed for List/Collection data.`);
35
+ return;
36
+ }
37
+
38
+ const storageKey = `jux:${config.key}`;
39
+
40
+ // 1. Hydrate (Load from Storage)
41
+ const load = () => {
42
+ try {
43
+ const raw = localStorage.getItem(storageKey);
44
+ if (raw) {
45
+ const data = JSON.parse(raw);
46
+ // @ts-ignore - Generic update
47
+ engine.updateState({ [config.bindTo]: data });
48
+ // @ts-ignore
49
+ if (engine.emit) engine.emit('plugin:hydrated', { source: 'localStorage', count: Array.isArray(data) ? data.length : 1 });
50
+ }
51
+ } catch (e) {
52
+ console.error('[LocalStoragePlugin] Load Failed', e);
53
+ }
54
+ };
55
+
56
+ // 2. Persist (Save to Storage)
57
+ const save = (state: any) => {
58
+ try {
59
+ const value = state[config.bindTo];
60
+ localStorage.setItem(storageKey, JSON.stringify(value));
61
+ } catch (e) {
62
+ console.error('[LocalStoragePlugin] Save Failed', e);
63
+ }
64
+ };
65
+
66
+ // Logic
67
+ if (config.clearOnInstall) {
68
+ localStorage.removeItem(storageKey);
69
+ } else {
70
+ load();
71
+ }
72
+
73
+ if (config.autoSave !== false) {
74
+ engine.subscribe((state) => save(state));
75
+ }
76
+
77
+ // Expose manual triggers
78
+ engine.on('storage:save', () => save(engine.state));
79
+ engine.on('storage:load', load);
80
+ engine.on('storage:clear', () => {
81
+ localStorage.removeItem(storageKey);
82
+ // @ts-ignore
83
+ if (engine.emit) engine.emit('plugin:cleared', { source: 'localStorage' });
84
+ });
85
+ }
86
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Server-Side SQLite Plugin
3
+ * Decoupled Service that injects SQL capabilities and binds data to ANY Engine state.
4
+ */
5
+ export const ServerSQLitePlugin = (config) => ({
6
+ name: 'server-sqlite-driver',
7
+ version: '2.0.0',
8
+ targetEnv: 'server',
9
+ install: (engine) => {
10
+ // 1. Expose SQL Capability (Mixin)
11
+ // Adds a .query() method to the engine instance
12
+ Object.assign(engine, {
13
+ query: (sql, params = []) => {
14
+ if (!config.database || typeof config.database.prepare !== 'function') {
15
+ throw new Error('Invalid Database Driver provided to ServerSQLitePlugin.');
16
+ }
17
+ const stmt = config.database.prepare(sql);
18
+ const rows = stmt.all(params);
19
+ // Emit audit event for queries
20
+ // @ts-ignore - access protected emit
21
+ if (typeof engine.emit === 'function')
22
+ engine.emit('sql:query', { sql, rows: rows.length });
23
+ return rows;
24
+ }
25
+ });
26
+ // 2. Hydration Logic
27
+ const hydrate = () => {
28
+ if (!config.query)
29
+ return;
30
+ try {
31
+ // Use the newly injected capability
32
+ // @ts-ignore
33
+ const rows = engine.query(config.query);
34
+ if (config.bindTo) {
35
+ const data = config.mapRow ? rows.map(config.mapRow) : rows;
36
+ // Generic State Update (Decoupled from ListEngine)
37
+ // @ts-ignore - access protected updateState
38
+ if (typeof engine.updateState === 'function') {
39
+ // @ts-ignore
40
+ engine.updateState({ [config.bindTo]: data });
41
+ }
42
+ // Optional: Update loading state if the engine supports it
43
+ // @ts-ignore
44
+ if (typeof engine.loading === 'function')
45
+ engine.loading(false);
46
+ // Emit data event for loose coupling
47
+ // @ts-ignore
48
+ if (typeof engine.emit === 'function')
49
+ engine.emit('plugin:data', { source: 'sqlite', count: data.length });
50
+ }
51
+ }
52
+ catch (err) {
53
+ console.error('[ServerSQLitePlugin] Hydration Error:', err.message);
54
+ // @ts-ignore
55
+ if (typeof engine.loading === 'function')
56
+ engine.loading(false);
57
+ }
58
+ };
59
+ // 3. Auto-Start
60
+ if (config.autoLoad) {
61
+ // @ts-ignore
62
+ if (typeof engine.loading === 'function')
63
+ engine.loading(true);
64
+ hydrate();
65
+ }
66
+ // 4. Listen for Reload Signal
67
+ engine.on('db:reload', hydrate);
68
+ }
69
+ });
70
+ //# sourceMappingURL=ServerSQLitePlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ServerSQLitePlugin.js","sourceRoot":"","sources":["ServerSQLitePlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import { JuxServiceContract, BaseEngine } from '../base/BaseEngine.js';
2
+
3
+ export interface ServerSQLiteConfig {
4
+ /** The Database Driver Instance (e.g. better-sqlite3) */
5
+ database: any;
6
+
7
+ /** Optional: SQL Query to fetch data automatically */
8
+ query?: string;
9
+
10
+ /**
11
+ * State Binding: The property key on the Engine's state to populate.
12
+ * e.g., 'items' for a ListEngine, or 'rows' for a GridEngine.
13
+ */
14
+ bindTo?: string;
15
+
16
+ /**
17
+ * Transformation Strategy:
18
+ * Converts a raw DB row into the shape expected by the Engine's state.
19
+ */
20
+ mapRow?: (row: any) => any;
21
+
22
+ /** If true, runs the query immediately on install */
23
+ autoLoad?: boolean;
24
+ }
25
+
26
+ /**
27
+ * Server-Side SQLite Plugin
28
+ * Decoupled Service that injects SQL capabilities and binds data to ANY Engine state.
29
+ */
30
+ export const ServerSQLitePlugin = (config: ServerSQLiteConfig): JuxServiceContract<BaseEngine<any>> => ({
31
+ name: 'server-sqlite-driver',
32
+ version: '2.0.0',
33
+ targetEnv: 'server',
34
+
35
+ install: (engine) => {
36
+ // 1. Expose SQL Capability (Mixin)
37
+ // Adds a .query() method to the engine instance
38
+ Object.assign(engine, {
39
+ query: (sql: string, params: any[] = []) => {
40
+ if (!config.database || typeof config.database.prepare !== 'function') {
41
+ throw new Error('Invalid Database Driver provided to ServerSQLitePlugin.');
42
+ }
43
+ const stmt = config.database.prepare(sql);
44
+ const rows = stmt.all(params);
45
+
46
+ // Emit audit event for queries
47
+ // @ts-ignore - access protected emit
48
+ if (typeof engine.emit === 'function') engine.emit('sql:query', { sql, rows: rows.length });
49
+
50
+ return rows;
51
+ }
52
+ });
53
+
54
+ // 2. Hydration Logic
55
+ const hydrate = () => {
56
+ if (!config.query) return;
57
+
58
+ try {
59
+ // Use the newly injected capability
60
+ // @ts-ignore
61
+ const rows = engine.query(config.query);
62
+
63
+ if (config.bindTo) {
64
+ const data = config.mapRow ? rows.map(config.mapRow) : rows;
65
+
66
+ // Generic State Update (Decoupled from ListEngine)
67
+ // @ts-ignore - access protected updateState
68
+ if (typeof engine.updateState === 'function') {
69
+ // @ts-ignore
70
+ engine.updateState({ [config.bindTo]: data });
71
+ }
72
+
73
+ // Optional: Update loading state if the engine supports it
74
+ // @ts-ignore
75
+ if (typeof engine.loading === 'function') engine.loading(false);
76
+
77
+ // Emit data event for loose coupling
78
+ // @ts-ignore
79
+ if (typeof engine.emit === 'function') engine.emit('plugin:data', { source: 'sqlite', count: data.length });
80
+ }
81
+
82
+ } catch (err: any) {
83
+ console.error('[ServerSQLitePlugin] Hydration Error:', err.message);
84
+ // @ts-ignore
85
+ if (typeof engine.loading === 'function') engine.loading(false);
86
+ }
87
+ };
88
+
89
+ // 3. Auto-Start
90
+ if (config.autoLoad) {
91
+ // @ts-ignore
92
+ if (typeof engine.loading === 'function') engine.loading(true);
93
+ hydrate();
94
+ }
95
+
96
+ // 4. Listen for Reload Signal
97
+ engine.on('db:reload', hydrate);
98
+ }
99
+ });
@@ -0,0 +1,32 @@
1
+ import { [% ComponentName %]Engine, [% ComponentName %]Options } from './engine.js';
2
+ import { [% ComponentName %]Skin } from './skin.js';
3
+
4
+ export type [% ComponentName %]Component = [% ComponentName %]Engine & {
5
+ render: (targetId: string | HTMLElement) => [% ComponentName %]Component;
6
+ injectCSS: (id: string, cssContent: string) => void;
7
+ };
8
+
9
+ export function [% ComponentName %](id: string, options: [% ComponentName %]Options = {}): [% ComponentName %]Component {
10
+ const engine = new [% ComponentName %]Engine(id, options);
11
+
12
+ if (typeof window !== 'undefined') {
13
+ // @ts-ignore
14
+ window.juxEngines = window.juxEngines || {};
15
+ // @ts-ignore
16
+ window.juxEngines[id] = engine;
17
+ }
18
+
19
+ const skin = new [% ComponentName %]Skin(engine);
20
+
21
+ // @ts-ignore
22
+ engine.render = (targetId: string | HTMLElement) => {
23
+ const target = typeof targetId === 'string' ? document.getElementById(targetId) : targetId;
24
+ if (target) skin.renderSkin(target);
25
+ return engine as [% ComponentName %]Component;
26
+ };
27
+
28
+ // @ts-ignore
29
+ engine.injectCSS = (id, css) => skin.injectCSS(id, css);
30
+
31
+ return engine as [% ComponentName %]Component;
32
+ }
@@ -0,0 +1,36 @@
1
+ import { BaseEngine, BaseState } from '../base/BaseEngine.js';
2
+
3
+ export interface [% ComponentName %]State extends BaseState {
4
+ // TODO: Define your state properties
5
+ text: string;
6
+ }
7
+
8
+ export interface [% ComponentName %]Options {
9
+ // TODO: Define configuration options
10
+ text?: string;
11
+ }
12
+
13
+ export class [% ComponentName %]Engine extends BaseEngine<[% ComponentName %]State, [% ComponentName %]Options> {
14
+ constructor(id: string, options: [% ComponentName %]Options = {}) {
15
+ super(id, options);
16
+ }
17
+
18
+ protected prepareState(id: string, options: [% ComponentName %]Options): [% ComponentName %]State {
19
+ return {
20
+ id,
21
+ classes: ['jux-[% component-name %]'],
22
+ visible: true,
23
+ disabled: false,
24
+ loading: false,
25
+ attributes: {},
26
+ text: options.text || 'Hello World'
27
+ };
28
+ }
29
+
30
+ // Example Mutator
31
+ setText(value: string): this {
32
+ this.updateState({ text: value });
33
+ this.emit('textChange', { value });
34
+ return this;
35
+ }
36
+ }
@@ -0,0 +1,34 @@
1
+ import { BaseSkin } from '../base/BaseSkin.js';
2
+ import { [% ComponentName %]Engine, [% ComponentName %]State } from './engine.js';
3
+
4
+ export class [% ComponentName %]Skin extends BaseSkin<[% ComponentName %]State, [% ComponentName %]Engine> {
5
+ constructor(engine: [% ComponentName %]Engine) {
6
+ super(engine);
7
+ }
8
+
9
+ /**
10
+ * Define the structural CSS for this component.
11
+ */
12
+ protected get structureCss(): string {
13
+ return new URL('./structure.css', import.meta.url).href;
14
+ }
15
+
16
+ protected bindEvents(root: HTMLElement): void {
17
+ // TODO: Bind DOM events to Engine methods
18
+ root.addEventListener('click', () => {
19
+ console.log('[% ComponentName %] clicked');
20
+ });
21
+ }
22
+
23
+ protected updateSkin(state: [% ComponentName %]State): void {
24
+ if (!this.root) return;
25
+ this.applySkinAttributes(this.root, state);
26
+
27
+ // TODO: Render state to DOM
28
+ this.root.textContent = state.text;
29
+ }
30
+
31
+ protected createRoot(): HTMLElement {
32
+ return document.createElement('div');
33
+ }
34
+ }
@@ -0,0 +1,13 @@
1
+ .jux-[% component-name %] {
2
+ display: block;
3
+ padding: var(--space-md);
4
+ border: 1px solid var(--color-border);
5
+ border-radius: var(--radius-sm);
6
+ background-color: var(--color-surface-base);
7
+ color: var(--color-text-primary);
8
+ transition: all var(--transition-fast);
9
+ }
10
+
11
+ .jux-[% component-name %]:hover {
12
+ background-color: var(--color-surface-hover);
13
+ }