lumix-js 0.1.0
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/README.md +156 -0
- package/bin/lumix.js +63 -0
- package/dist/bind.d.ts +13 -0
- package/dist/bind.js +103 -0
- package/dist/cli/build.d.ts +1 -0
- package/dist/cli/build.js +69 -0
- package/dist/cli/dev.d.ts +1 -0
- package/dist/cli/dev.js +69 -0
- package/dist/cli/init.d.ts +5 -0
- package/dist/cli/init.js +199 -0
- package/dist/cli/loader.d.ts +9 -0
- package/dist/cli/loader.js +34 -0
- package/dist/cli/preview.d.ts +1 -0
- package/dist/cli/preview.js +39 -0
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.js +4 -0
- package/dist/config.d.ts +42 -0
- package/dist/config.js +21 -0
- package/dist/control.d.ts +17 -0
- package/dist/control.js +47 -0
- package/dist/dom.d.ts +8 -0
- package/dist/dom.js +136 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/lifecycle.d.ts +16 -0
- package/dist/lifecycle.js +45 -0
- package/dist/signals.d.ts +21 -0
- package/dist/signals.js +144 -0
- package/dist/store.d.ts +37 -0
- package/dist/store.js +147 -0
- package/package.json +47 -0
- package/templates/blank/lumix.config.mjs +10 -0
- package/templates/blank/main.js +5 -0
- package/templates/blank/package.json +15 -0
- package/templates/blank/src/App.lumix +28 -0
- package/templates/blank-ts/lumix-env.d.ts +4 -0
- package/templates/blank-ts/lumix.config.mts +10 -0
- package/templates/blank-ts/main.ts +5 -0
- package/templates/blank-ts/package.json +17 -0
- package/templates/blank-ts/src/App.lumix +28 -0
- package/templates/blank-ts/tsconfig.json +16 -0
package/dist/store.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { signal, batch } from "./signals.js";
|
|
2
|
+
// ─── store() ───────────────────────────────────────────────
|
|
3
|
+
export function store(initialState) {
|
|
4
|
+
const initial = structuredClone(initialState);
|
|
5
|
+
const signals = new Map();
|
|
6
|
+
const listeners = new Set();
|
|
7
|
+
function getSignal(key) {
|
|
8
|
+
const k = key;
|
|
9
|
+
if (!signals.has(k)) {
|
|
10
|
+
signals.set(k, signal(initial[key]));
|
|
11
|
+
}
|
|
12
|
+
return signals.get(k);
|
|
13
|
+
}
|
|
14
|
+
function get(key) {
|
|
15
|
+
return getSignal(key)();
|
|
16
|
+
}
|
|
17
|
+
function set(key, value) {
|
|
18
|
+
getSignal(key)(value);
|
|
19
|
+
notifyListeners(key);
|
|
20
|
+
}
|
|
21
|
+
function update(partial) {
|
|
22
|
+
batch(() => {
|
|
23
|
+
for (const [key, value] of Object.entries(partial)) {
|
|
24
|
+
getSignal(key)(value);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
for (const key of Object.keys(partial)) {
|
|
28
|
+
notifyListeners(key);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function reset() {
|
|
32
|
+
batch(() => {
|
|
33
|
+
for (const [key, value] of Object.entries(initial)) {
|
|
34
|
+
getSignal(key)(structuredClone(value));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
notifyListeners();
|
|
38
|
+
}
|
|
39
|
+
function snapshot() {
|
|
40
|
+
const snap = {};
|
|
41
|
+
// Include all keys from initial state
|
|
42
|
+
for (const key of Object.keys(initial)) {
|
|
43
|
+
const sig = signals.get(key);
|
|
44
|
+
snap[key] = sig ? sig._peek() : initial[key];
|
|
45
|
+
}
|
|
46
|
+
return Object.freeze(snap);
|
|
47
|
+
}
|
|
48
|
+
function subscribe(fn) {
|
|
49
|
+
listeners.add(fn);
|
|
50
|
+
return () => listeners.delete(fn);
|
|
51
|
+
}
|
|
52
|
+
function notifyListeners(key) {
|
|
53
|
+
const state = snapshot();
|
|
54
|
+
for (const fn of listeners) {
|
|
55
|
+
fn(state, key);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Reactive proxy
|
|
59
|
+
const stateProxy = new Proxy({}, {
|
|
60
|
+
get(_target, prop) {
|
|
61
|
+
return get(prop);
|
|
62
|
+
},
|
|
63
|
+
set(_target, prop, value) {
|
|
64
|
+
set(prop, value);
|
|
65
|
+
return true;
|
|
66
|
+
},
|
|
67
|
+
ownKeys() {
|
|
68
|
+
return Object.keys(initial);
|
|
69
|
+
},
|
|
70
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
71
|
+
if (prop in initial) {
|
|
72
|
+
return { configurable: true, enumerable: true, writable: true };
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
},
|
|
76
|
+
has(_target, prop) {
|
|
77
|
+
return prop in initial;
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
get,
|
|
82
|
+
set,
|
|
83
|
+
update,
|
|
84
|
+
reset,
|
|
85
|
+
snapshot,
|
|
86
|
+
subscribe,
|
|
87
|
+
signal: getSignal,
|
|
88
|
+
state: stateProxy,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// ─── persist() ─────────────────────────────────────────────
|
|
92
|
+
export function persist(st, options) {
|
|
93
|
+
const { key, storage = typeof localStorage !== "undefined" ? localStorage : null, serialize = JSON.stringify, deserialize = JSON.parse, include, exclude, } = options;
|
|
94
|
+
if (!storage)
|
|
95
|
+
return () => { };
|
|
96
|
+
// Hydrate from storage on init
|
|
97
|
+
try {
|
|
98
|
+
const stored = storage.getItem(key);
|
|
99
|
+
if (stored) {
|
|
100
|
+
const parsed = deserialize(stored);
|
|
101
|
+
if (parsed && typeof parsed === "object") {
|
|
102
|
+
st.update(parsed);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Ignore hydration errors — use initial state
|
|
108
|
+
}
|
|
109
|
+
// Persist on every change
|
|
110
|
+
const unsub = st.subscribe((state) => {
|
|
111
|
+
try {
|
|
112
|
+
let toSave = { ...state };
|
|
113
|
+
if (include) {
|
|
114
|
+
const filtered = {};
|
|
115
|
+
for (const k of include) {
|
|
116
|
+
if (k in toSave)
|
|
117
|
+
filtered[k] = toSave[k];
|
|
118
|
+
}
|
|
119
|
+
toSave = filtered;
|
|
120
|
+
}
|
|
121
|
+
if (exclude) {
|
|
122
|
+
for (const k of exclude) {
|
|
123
|
+
delete toSave[k];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
storage.setItem(key, serialize(toSave));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Ignore storage write errors
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return unsub;
|
|
133
|
+
}
|
|
134
|
+
// ─── derived() ────────────────────────────────────────────
|
|
135
|
+
export function derived(st, fn) {
|
|
136
|
+
const inner = signal(fn(st.snapshot()));
|
|
137
|
+
// Re-derive whenever any signal in the store changes
|
|
138
|
+
const keys = Object.keys(st.snapshot());
|
|
139
|
+
const unsubs = [];
|
|
140
|
+
for (const key of keys) {
|
|
141
|
+
const sig = st.signal(key);
|
|
142
|
+
unsubs.push(sig._subscribe(() => {
|
|
143
|
+
inner(fn(st.snapshot()));
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
return inner;
|
|
147
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lumix-js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The modular runtime for LuminJS",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
"bin/",
|
|
12
|
+
"templates/"
|
|
13
|
+
],
|
|
14
|
+
"bin": {
|
|
15
|
+
"lumix": "./bin/lumix.js"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"lumix-js",
|
|
23
|
+
"runtime",
|
|
24
|
+
"signals",
|
|
25
|
+
"framework",
|
|
26
|
+
"framework-cli"
|
|
27
|
+
],
|
|
28
|
+
"author": "ZMDev",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"happy-dom": "^20.6.1",
|
|
32
|
+
"typescript": "^5.0.0",
|
|
33
|
+
"@types/node": "^25.2.3",
|
|
34
|
+
"@types/prompts": "^2.4.9",
|
|
35
|
+
"@types/fs-extra": "^11.0.4"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@types/bun": "^1.3.9",
|
|
39
|
+
"vite": "^7.3.1",
|
|
40
|
+
"commander": "^12.0.0",
|
|
41
|
+
"prompts": "^2.4.2",
|
|
42
|
+
"picocolors": "^1.0.0",
|
|
43
|
+
"bundle-require": "^5.0.0",
|
|
44
|
+
"vite-plugin-lumix": "workspace:*",
|
|
45
|
+
"fs-extra": "^11.2.0"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-lumin-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "lumix dev",
|
|
8
|
+
"build": "lumix build",
|
|
9
|
+
"preview": "lumix preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"lumix-js": "latest"
|
|
13
|
+
},
|
|
14
|
+
"sideEffects": false
|
|
15
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { signal } from "lumix-js";
|
|
3
|
+
const message = signal("Hello LumixJS!");
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<div class="container">
|
|
7
|
+
<h1>{message()}</h1>
|
|
8
|
+
<p>Edit <code>src/App.lumix</code> to get started.</p>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<style>
|
|
12
|
+
.container {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
height: 100vh;
|
|
18
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
19
|
+
}
|
|
20
|
+
h1 {
|
|
21
|
+
color: #4f46e5;
|
|
22
|
+
}
|
|
23
|
+
code {
|
|
24
|
+
background: #f3f4f6;
|
|
25
|
+
padding: 0.2rem 0.4rem;
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-lumin-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "lumix dev",
|
|
8
|
+
"build": "lumix build",
|
|
9
|
+
"preview": "lumix preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"lumix-js": "latest"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"typescript": "^5.0.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { signal, type Signal } from "lumix-js";
|
|
3
|
+
const message: Signal<string> = signal("Hello LumixJS!");
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<div class="container">
|
|
7
|
+
<h1>{message()}</h1>
|
|
8
|
+
<p>Edit <code>src/App.lumix</code> to get started.</p>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<style>
|
|
12
|
+
.container {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
height: 100vh;
|
|
18
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
19
|
+
}
|
|
20
|
+
h1 {
|
|
21
|
+
color: #4f46e5;
|
|
22
|
+
}
|
|
23
|
+
code {
|
|
24
|
+
background: #f3f4f6;
|
|
25
|
+
padding: 0.2rem 0.4rem;
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"jsx": "preserve"
|
|
14
|
+
},
|
|
15
|
+
"include": ["main.ts", "src/**/*", "lumix-env.d.ts"]
|
|
16
|
+
}
|