saloe 0.0.1 → 0.0.2
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 +8 -8
- package/dist/actions.cjs.js +0 -19
- package/dist/actions.es.js +0 -19
- package/dist/listener.cjs.js +179 -0
- package/dist/listener.es.js +179 -0
- package/package.json +6 -2
- package/src/listener.js +250 -0
- package/src/vite.js +2 -2
- package/vite.config.js +1 -0
- package/demos/cloudflare-worker-actions/.wrangler/state/v3/cache/miniflare-CacheObject/9f458c07675338a7426a7b81ac4fb1baf92d034efbcaaf4336379640ed744ded.sqlite +0 -0
- package/demos/cloudflare-worker-actions/package.json +0 -29
- package/demos/cloudflare-worker-actions/public/input.js +0 -5
- package/demos/cloudflare-worker-actions/public/load.js +0 -5
- package/demos/cloudflare-worker-actions/public/submit.js +0 -6
- package/demos/cloudflare-worker-actions/server.js +0 -93
- package/demos/cloudflare-worker-actions/vite.config.js +0 -25
- package/demos/cloudflare-worker-actions/wrangler.toml +0 -35
- package/demos/cloudflare-worker-server/package.json +0 -29
- package/demos/cloudflare-worker-server/server.js +0 -75
- package/demos/cloudflare-worker-server/vite.config.js +0 -25
- package/demos/cloudflare-worker-server/wrangler.toml +0 -32
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
#
|
|
1
|
+
# saloe
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`saloe` is a toolkit that makes building reactive web apps easy, with `0kb of initial JavaScript` and lightning-fast rendering.
|
|
4
4
|
|
|
5
|
-
It works seamlessly with Cloudflare Workers and Service Workers
|
|
5
|
+
It works seamlessly with `Cloudflare Workers` and `Service Workers`, and can also be used in Node or other server-side JavaScript environments.
|
|
6
6
|
|
|
7
|
-
**Note:** `
|
|
7
|
+
**Note:** `saloe` is still under development, and version 1.0 is not ready yet. Expect changes and improvements as we work towards the initial release.
|
|
8
8
|
|
|
9
9
|
## Packages
|
|
10
10
|
|
|
11
|
-
- [
|
|
11
|
+
- [`saloe/router`](./src/router.js) - Manage web requests using URLPattern for route matching.
|
|
12
12
|
|
|
13
|
-
- [
|
|
13
|
+
- [`saloe/html`](./src/html.js) - Stream HTML templates and render temporary templates while waiting for asynchronous functions to finish processing the final template.
|
|
14
14
|
|
|
15
|
-
- [
|
|
15
|
+
- [`saloe/actions`](./src/actions.js) - Add reactivity to HTML nodes with 0kb of initial JavaScript.
|
|
16
16
|
|
|
17
17
|
## Coming Soon
|
|
18
18
|
|
|
19
|
-
- [
|
|
19
|
+
- [`saloe/offline`](./src/offline.js) Manage browser cache resources to handle HTML template requests.
|
package/dist/actions.cjs.js
CHANGED
|
@@ -241,28 +241,9 @@ const LISTENER_SCRIPT = html.html(_a || (_a = __template([`
|
|
|
241
241
|
executeListeners({ e, srcElement, listeners })
|
|
242
242
|
addListener({ srcElement, event, listeners })
|
|
243
243
|
|
|
244
|
-
console.log('--- removeAttribute =', srcElement?.removeAttribute)
|
|
245
244
|
if (srcElement?.removeAttribute) srcElement.removeAttribute('on-' + event)
|
|
246
245
|
}
|
|
247
246
|
})
|
|
248
|
-
|
|
249
|
-
// ['mouseover', 'click', 'submit', 'input', 'blur', 'change']?.forEach((event) => {
|
|
250
|
-
// document.body['on' + event] = async (e) => {
|
|
251
|
-
// if (EVENTS_FIRE_DOCUMENT_BODY_LISTENERS.includes(event)) {
|
|
252
|
-
// await addScripts()
|
|
253
|
-
|
|
254
|
-
// fireLoadListener()
|
|
255
|
-
// fireInvalidListener()
|
|
256
|
-
// fireBlurListener()
|
|
257
|
-
// fireFocusListener()
|
|
258
|
-
|
|
259
|
-
// fireObserverListeners()
|
|
260
|
-
// }
|
|
261
|
-
|
|
262
|
-
// const srcElement = getSrcElement({ srcElement: e.srcElement, event })
|
|
263
|
-
// fetchListeners({ srcElement, event, e })
|
|
264
|
-
// }
|
|
265
|
-
// })
|
|
266
247
|
}
|
|
267
248
|
|
|
268
249
|
fireListeners()
|
package/dist/actions.es.js
CHANGED
|
@@ -239,28 +239,9 @@ const LISTENER_SCRIPT = html(_a || (_a = __template([`
|
|
|
239
239
|
executeListeners({ e, srcElement, listeners })
|
|
240
240
|
addListener({ srcElement, event, listeners })
|
|
241
241
|
|
|
242
|
-
console.log('--- removeAttribute =', srcElement?.removeAttribute)
|
|
243
242
|
if (srcElement?.removeAttribute) srcElement.removeAttribute('on-' + event)
|
|
244
243
|
}
|
|
245
244
|
})
|
|
246
|
-
|
|
247
|
-
// ['mouseover', 'click', 'submit', 'input', 'blur', 'change']?.forEach((event) => {
|
|
248
|
-
// document.body['on' + event] = async (e) => {
|
|
249
|
-
// if (EVENTS_FIRE_DOCUMENT_BODY_LISTENERS.includes(event)) {
|
|
250
|
-
// await addScripts()
|
|
251
|
-
|
|
252
|
-
// fireLoadListener()
|
|
253
|
-
// fireInvalidListener()
|
|
254
|
-
// fireBlurListener()
|
|
255
|
-
// fireFocusListener()
|
|
256
|
-
|
|
257
|
-
// fireObserverListeners()
|
|
258
|
-
// }
|
|
259
|
-
|
|
260
|
-
// const srcElement = getSrcElement({ srcElement: e.srcElement, event })
|
|
261
|
-
// fetchListeners({ srcElement, event, e })
|
|
262
|
-
// }
|
|
263
|
-
// })
|
|
264
245
|
}
|
|
265
246
|
|
|
266
247
|
fireListeners()
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const listener = () => {
|
|
4
|
+
const EVENTS_PREVENT_DEFAULT_MANDATORY = [
|
|
5
|
+
"submit"
|
|
6
|
+
];
|
|
7
|
+
const EVENTS_FIRE_DOCUMENT_BODY_LISTENERS = [
|
|
8
|
+
"mouseover",
|
|
9
|
+
"click"
|
|
10
|
+
];
|
|
11
|
+
const EVENTS = [
|
|
12
|
+
"submit",
|
|
13
|
+
"input",
|
|
14
|
+
"blur",
|
|
15
|
+
"change",
|
|
16
|
+
"focus",
|
|
17
|
+
"invalid"
|
|
18
|
+
];
|
|
19
|
+
const addListener = ({ srcElement, event, listeners }) => {
|
|
20
|
+
srcElement == null ? void 0 : srcElement.addEventListener(event, (e) => {
|
|
21
|
+
executeListeners({ e, srcElement, listeners });
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const executeListeners = ({ e, srcElement, listeners }) => {
|
|
25
|
+
listeners == null ? void 0 : listeners.forEach((listener2) => {
|
|
26
|
+
if (listener2) listener2({ e, srcElement });
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const getListenerFromScript = ({ script, event }) => {
|
|
30
|
+
var _a;
|
|
31
|
+
if (!script) return null;
|
|
32
|
+
if (script[event]) return script[event];
|
|
33
|
+
const prev = (_a = Object.keys(script)) == null ? void 0 : _a.find((key) => script[key][event]);
|
|
34
|
+
if (!prev) return null;
|
|
35
|
+
return script[prev][event];
|
|
36
|
+
};
|
|
37
|
+
const fetchListeners = async ({ srcElement, event, e }) => {
|
|
38
|
+
var _a;
|
|
39
|
+
if (!(srcElement == null ? void 0 : srcElement.getAttribute)) return;
|
|
40
|
+
const scriptNames = srcElement == null ? void 0 : srcElement.getAttribute("on-" + event);
|
|
41
|
+
if (!scriptNames) return;
|
|
42
|
+
if (scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(event)) e.preventDefault();
|
|
43
|
+
const scripts = await Promise.all(
|
|
44
|
+
(_a = scriptNames == null ? void 0 : scriptNames.split(",")) == null ? void 0 : _a.map((scriptName) => {
|
|
45
|
+
var _a2;
|
|
46
|
+
const scriptToImport = "/" + (scriptName == null ? void 0 : scriptName.trim()) + ".js";
|
|
47
|
+
return (_a2 = import(scriptToImport)) == null ? void 0 : _a2.catch((err) => {
|
|
48
|
+
});
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
const listeners = scripts == null ? void 0 : scripts.map((script) => getListenerFromScript({ script, event }));
|
|
52
|
+
return listeners;
|
|
53
|
+
};
|
|
54
|
+
const addScripts = () => {
|
|
55
|
+
const scriptsToLoad = [...document.querySelectorAll("script[data-script-to-load]")];
|
|
56
|
+
return Promise.all(
|
|
57
|
+
scriptsToLoad == null ? void 0 : scriptsToLoad.map((scriptToLoad) => {
|
|
58
|
+
var _a;
|
|
59
|
+
const id = scriptToLoad == null ? void 0 : scriptToLoad.getAttribute("data-script-to-load");
|
|
60
|
+
scriptToLoad.removeAttribute("data-script-to-load");
|
|
61
|
+
const attrs = (_a = scriptToLoad == null ? void 0 : scriptToLoad.getAttributeNames()) == null ? void 0 : _a.reduce((acc, attrName) => {
|
|
62
|
+
const attrValue = scriptToLoad.getAttribute(attrName);
|
|
63
|
+
if (attrValue !== "text/script-to-load") acc[attrName] = attrValue;
|
|
64
|
+
return acc;
|
|
65
|
+
}, {});
|
|
66
|
+
const content = scriptToLoad == null ? void 0 : scriptToLoad.textContent;
|
|
67
|
+
scriptToLoad == null ? void 0 : scriptToLoad.remove();
|
|
68
|
+
return loadScript({ id, attrs, content }).catch((err) => {
|
|
69
|
+
console.error(err);
|
|
70
|
+
});
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
const loadScript = ({ id, attrs, content }) => {
|
|
75
|
+
var _a;
|
|
76
|
+
const script = document == null ? void 0 : document.createElement("script");
|
|
77
|
+
(_a = Object.keys(attrs)) == null ? void 0 : _a.forEach((attrKey) => script == null ? void 0 : script.setAttribute(attrKey, attrs[attrKey]));
|
|
78
|
+
script.id = id;
|
|
79
|
+
if (content) script == null ? void 0 : script.insertAdjacentHTML("beforeend", content);
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
var _a2, _b;
|
|
82
|
+
if (!attrs.src) {
|
|
83
|
+
resolve();
|
|
84
|
+
(_a2 = document == null ? void 0 : document.body) == null ? void 0 : _a2.insertAdjacentElement("beforeend", script);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
script.onload = script.onreadystatechange = function() {
|
|
88
|
+
if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
|
|
89
|
+
resolve();
|
|
90
|
+
script.onload = script.onreadystatechange = null;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
script.onerror = () => {
|
|
94
|
+
console.error("script failed to load");
|
|
95
|
+
reject(new Error("Failed to load script with src " + script.src));
|
|
96
|
+
};
|
|
97
|
+
(_b = document == null ? void 0 : document.body) == null ? void 0 : _b.insertAdjacentElement("beforeend", script);
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const fireLoadListener = () => {
|
|
101
|
+
const event = "load";
|
|
102
|
+
const srcElements = document == null ? void 0 : document.querySelectorAll("[on-" + event + "]");
|
|
103
|
+
srcElements == null ? void 0 : srcElements.forEach(async (srcElement) => {
|
|
104
|
+
const listeners = await fetchListeners({ srcElement, event, e: null });
|
|
105
|
+
executeListeners({ e: null, srcElement, listeners });
|
|
106
|
+
srcElement == null ? void 0 : srcElement.removeAttribute("on-" + event);
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
const fireObserverListeners = () => {
|
|
110
|
+
var _a;
|
|
111
|
+
const srcElements = [...document.querySelectorAll("[on-observe]")];
|
|
112
|
+
const uniqueScriptNames = [...(_a = srcElements == null ? void 0 : srcElements.reduce((acc, srcElement) => {
|
|
113
|
+
const attribute = srcElement == null ? void 0 : srcElement.getAttribute("on-observe");
|
|
114
|
+
if (attribute === "undefined") return acc;
|
|
115
|
+
const scriptNames = attribute == null ? void 0 : attribute.split(",");
|
|
116
|
+
scriptNames == null ? void 0 : scriptNames.forEach((scriptName) => acc == null ? void 0 : acc.set(scriptName, 1));
|
|
117
|
+
return acc;
|
|
118
|
+
}, /* @__PURE__ */ new Map())) == null ? void 0 : _a.keys()];
|
|
119
|
+
uniqueScriptNames == null ? void 0 : uniqueScriptNames.forEach(async (scriptName) => {
|
|
120
|
+
var _a2;
|
|
121
|
+
const observedSrcElements = document.querySelectorAll('[on-observe*="' + scriptName + '"]');
|
|
122
|
+
const script = await ((_a2 = import("/" + (scriptName == null ? void 0 : scriptName.trim()) + ".js")) == null ? void 0 : _a2.catch((err) => {
|
|
123
|
+
}));
|
|
124
|
+
const listener2 = getListenerFromScript({ script, event: "observe" });
|
|
125
|
+
if (!listener2) return;
|
|
126
|
+
const observer = new IntersectionObserver((entries) => {
|
|
127
|
+
entries.forEach((entry) => listener2({ entry, observer }));
|
|
128
|
+
});
|
|
129
|
+
observedSrcElements == null ? void 0 : observedSrcElements.forEach((observerSrcElement) => {
|
|
130
|
+
var _a3, _b;
|
|
131
|
+
observer.observe(observerSrcElement);
|
|
132
|
+
const observerAttr = observerSrcElement == null ? void 0 : observerSrcElement.getAttribute("on-observe");
|
|
133
|
+
const updatedObserverAttr = (_b = (_a3 = observerAttr == null ? void 0 : observerAttr.replaceAll(scriptName + ", ", "")) == null ? void 0 : _a3.replaceAll(", " + scriptName, "")) == null ? void 0 : _b.replaceAll(scriptName, "");
|
|
134
|
+
if (updatedObserverAttr === "") observerSrcElement.removeAttribute("on-observe");
|
|
135
|
+
else observerSrcElement.setAttribute("on-observe", updatedObserverAttr);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
const getSrcElement = ({ srcElement, event }) => {
|
|
140
|
+
if (!(srcElement == null ? void 0 : srcElement.hasAttribute)) return srcElement;
|
|
141
|
+
const attribute = "on-" + event;
|
|
142
|
+
const hasScriptName = srcElement == null ? void 0 : srcElement.hasAttribute(attribute);
|
|
143
|
+
if (hasScriptName) return srcElement;
|
|
144
|
+
const query = ":is(a, button, li)[" + attribute + "]";
|
|
145
|
+
const closestButton = srcElement == null ? void 0 : srcElement.closest(query);
|
|
146
|
+
if (closestButton) return closestButton;
|
|
147
|
+
return srcElement;
|
|
148
|
+
};
|
|
149
|
+
const fireListeners = () => {
|
|
150
|
+
EVENTS_FIRE_DOCUMENT_BODY_LISTENERS == null ? void 0 : EVENTS_FIRE_DOCUMENT_BODY_LISTENERS.forEach((event) => {
|
|
151
|
+
document.body["on" + event] = async (e) => {
|
|
152
|
+
await addScripts();
|
|
153
|
+
fireLoadListener();
|
|
154
|
+
fireObserverListeners();
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
EVENTS == null ? void 0 : EVENTS.forEach((event) => {
|
|
158
|
+
document.body["on" + event] = async (e) => {
|
|
159
|
+
const srcElement = getSrcElement({ srcElement: e == null ? void 0 : e.srcElement, event });
|
|
160
|
+
const listeners = await fetchListeners({ srcElement, event, e });
|
|
161
|
+
executeListeners({ e, srcElement, listeners });
|
|
162
|
+
addListener({ srcElement, event, listeners });
|
|
163
|
+
if (srcElement == null ? void 0 : srcElement.removeAttribute) srcElement.removeAttribute("on-" + event);
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
fireListeners();
|
|
168
|
+
window.onload = () => {
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
var _a;
|
|
171
|
+
(_a = document == null ? void 0 : document.body) == null ? void 0 : _a.click();
|
|
172
|
+
}, 2500);
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
const getScriptListener = () => {
|
|
176
|
+
return `<script defer>(${listener.toString()})()<\/script>`;
|
|
177
|
+
};
|
|
178
|
+
exports.getScriptListener = getScriptListener;
|
|
179
|
+
exports.listener = listener;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
const listener = () => {
|
|
2
|
+
const EVENTS_PREVENT_DEFAULT_MANDATORY = [
|
|
3
|
+
"submit"
|
|
4
|
+
];
|
|
5
|
+
const EVENTS_FIRE_DOCUMENT_BODY_LISTENERS = [
|
|
6
|
+
"mouseover",
|
|
7
|
+
"click"
|
|
8
|
+
];
|
|
9
|
+
const EVENTS = [
|
|
10
|
+
"submit",
|
|
11
|
+
"input",
|
|
12
|
+
"blur",
|
|
13
|
+
"change",
|
|
14
|
+
"focus",
|
|
15
|
+
"invalid"
|
|
16
|
+
];
|
|
17
|
+
const addListener = ({ srcElement, event, listeners }) => {
|
|
18
|
+
srcElement == null ? void 0 : srcElement.addEventListener(event, (e) => {
|
|
19
|
+
executeListeners({ e, srcElement, listeners });
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const executeListeners = ({ e, srcElement, listeners }) => {
|
|
23
|
+
listeners == null ? void 0 : listeners.forEach((listener2) => {
|
|
24
|
+
if (listener2) listener2({ e, srcElement });
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const getListenerFromScript = ({ script, event }) => {
|
|
28
|
+
var _a;
|
|
29
|
+
if (!script) return null;
|
|
30
|
+
if (script[event]) return script[event];
|
|
31
|
+
const prev = (_a = Object.keys(script)) == null ? void 0 : _a.find((key) => script[key][event]);
|
|
32
|
+
if (!prev) return null;
|
|
33
|
+
return script[prev][event];
|
|
34
|
+
};
|
|
35
|
+
const fetchListeners = async ({ srcElement, event, e }) => {
|
|
36
|
+
var _a;
|
|
37
|
+
if (!(srcElement == null ? void 0 : srcElement.getAttribute)) return;
|
|
38
|
+
const scriptNames = srcElement == null ? void 0 : srcElement.getAttribute("on-" + event);
|
|
39
|
+
if (!scriptNames) return;
|
|
40
|
+
if (scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(event)) e.preventDefault();
|
|
41
|
+
const scripts = await Promise.all(
|
|
42
|
+
(_a = scriptNames == null ? void 0 : scriptNames.split(",")) == null ? void 0 : _a.map((scriptName) => {
|
|
43
|
+
var _a2;
|
|
44
|
+
const scriptToImport = "/" + (scriptName == null ? void 0 : scriptName.trim()) + ".js";
|
|
45
|
+
return (_a2 = import(scriptToImport)) == null ? void 0 : _a2.catch((err) => {
|
|
46
|
+
});
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
const listeners = scripts == null ? void 0 : scripts.map((script) => getListenerFromScript({ script, event }));
|
|
50
|
+
return listeners;
|
|
51
|
+
};
|
|
52
|
+
const addScripts = () => {
|
|
53
|
+
const scriptsToLoad = [...document.querySelectorAll("script[data-script-to-load]")];
|
|
54
|
+
return Promise.all(
|
|
55
|
+
scriptsToLoad == null ? void 0 : scriptsToLoad.map((scriptToLoad) => {
|
|
56
|
+
var _a;
|
|
57
|
+
const id = scriptToLoad == null ? void 0 : scriptToLoad.getAttribute("data-script-to-load");
|
|
58
|
+
scriptToLoad.removeAttribute("data-script-to-load");
|
|
59
|
+
const attrs = (_a = scriptToLoad == null ? void 0 : scriptToLoad.getAttributeNames()) == null ? void 0 : _a.reduce((acc, attrName) => {
|
|
60
|
+
const attrValue = scriptToLoad.getAttribute(attrName);
|
|
61
|
+
if (attrValue !== "text/script-to-load") acc[attrName] = attrValue;
|
|
62
|
+
return acc;
|
|
63
|
+
}, {});
|
|
64
|
+
const content = scriptToLoad == null ? void 0 : scriptToLoad.textContent;
|
|
65
|
+
scriptToLoad == null ? void 0 : scriptToLoad.remove();
|
|
66
|
+
return loadScript({ id, attrs, content }).catch((err) => {
|
|
67
|
+
console.error(err);
|
|
68
|
+
});
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
const loadScript = ({ id, attrs, content }) => {
|
|
73
|
+
var _a;
|
|
74
|
+
const script = document == null ? void 0 : document.createElement("script");
|
|
75
|
+
(_a = Object.keys(attrs)) == null ? void 0 : _a.forEach((attrKey) => script == null ? void 0 : script.setAttribute(attrKey, attrs[attrKey]));
|
|
76
|
+
script.id = id;
|
|
77
|
+
if (content) script == null ? void 0 : script.insertAdjacentHTML("beforeend", content);
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
var _a2, _b;
|
|
80
|
+
if (!attrs.src) {
|
|
81
|
+
resolve();
|
|
82
|
+
(_a2 = document == null ? void 0 : document.body) == null ? void 0 : _a2.insertAdjacentElement("beforeend", script);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
script.onload = script.onreadystatechange = function() {
|
|
86
|
+
if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
|
|
87
|
+
resolve();
|
|
88
|
+
script.onload = script.onreadystatechange = null;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
script.onerror = () => {
|
|
92
|
+
console.error("script failed to load");
|
|
93
|
+
reject(new Error("Failed to load script with src " + script.src));
|
|
94
|
+
};
|
|
95
|
+
(_b = document == null ? void 0 : document.body) == null ? void 0 : _b.insertAdjacentElement("beforeend", script);
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const fireLoadListener = () => {
|
|
99
|
+
const event = "load";
|
|
100
|
+
const srcElements = document == null ? void 0 : document.querySelectorAll("[on-" + event + "]");
|
|
101
|
+
srcElements == null ? void 0 : srcElements.forEach(async (srcElement) => {
|
|
102
|
+
const listeners = await fetchListeners({ srcElement, event, e: null });
|
|
103
|
+
executeListeners({ e: null, srcElement, listeners });
|
|
104
|
+
srcElement == null ? void 0 : srcElement.removeAttribute("on-" + event);
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
const fireObserverListeners = () => {
|
|
108
|
+
var _a;
|
|
109
|
+
const srcElements = [...document.querySelectorAll("[on-observe]")];
|
|
110
|
+
const uniqueScriptNames = [...(_a = srcElements == null ? void 0 : srcElements.reduce((acc, srcElement) => {
|
|
111
|
+
const attribute = srcElement == null ? void 0 : srcElement.getAttribute("on-observe");
|
|
112
|
+
if (attribute === "undefined") return acc;
|
|
113
|
+
const scriptNames = attribute == null ? void 0 : attribute.split(",");
|
|
114
|
+
scriptNames == null ? void 0 : scriptNames.forEach((scriptName) => acc == null ? void 0 : acc.set(scriptName, 1));
|
|
115
|
+
return acc;
|
|
116
|
+
}, /* @__PURE__ */ new Map())) == null ? void 0 : _a.keys()];
|
|
117
|
+
uniqueScriptNames == null ? void 0 : uniqueScriptNames.forEach(async (scriptName) => {
|
|
118
|
+
var _a2;
|
|
119
|
+
const observedSrcElements = document.querySelectorAll('[on-observe*="' + scriptName + '"]');
|
|
120
|
+
const script = await ((_a2 = import("/" + (scriptName == null ? void 0 : scriptName.trim()) + ".js")) == null ? void 0 : _a2.catch((err) => {
|
|
121
|
+
}));
|
|
122
|
+
const listener2 = getListenerFromScript({ script, event: "observe" });
|
|
123
|
+
if (!listener2) return;
|
|
124
|
+
const observer = new IntersectionObserver((entries) => {
|
|
125
|
+
entries.forEach((entry) => listener2({ entry, observer }));
|
|
126
|
+
});
|
|
127
|
+
observedSrcElements == null ? void 0 : observedSrcElements.forEach((observerSrcElement) => {
|
|
128
|
+
var _a3, _b;
|
|
129
|
+
observer.observe(observerSrcElement);
|
|
130
|
+
const observerAttr = observerSrcElement == null ? void 0 : observerSrcElement.getAttribute("on-observe");
|
|
131
|
+
const updatedObserverAttr = (_b = (_a3 = observerAttr == null ? void 0 : observerAttr.replaceAll(scriptName + ", ", "")) == null ? void 0 : _a3.replaceAll(", " + scriptName, "")) == null ? void 0 : _b.replaceAll(scriptName, "");
|
|
132
|
+
if (updatedObserverAttr === "") observerSrcElement.removeAttribute("on-observe");
|
|
133
|
+
else observerSrcElement.setAttribute("on-observe", updatedObserverAttr);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
const getSrcElement = ({ srcElement, event }) => {
|
|
138
|
+
if (!(srcElement == null ? void 0 : srcElement.hasAttribute)) return srcElement;
|
|
139
|
+
const attribute = "on-" + event;
|
|
140
|
+
const hasScriptName = srcElement == null ? void 0 : srcElement.hasAttribute(attribute);
|
|
141
|
+
if (hasScriptName) return srcElement;
|
|
142
|
+
const query = ":is(a, button, li)[" + attribute + "]";
|
|
143
|
+
const closestButton = srcElement == null ? void 0 : srcElement.closest(query);
|
|
144
|
+
if (closestButton) return closestButton;
|
|
145
|
+
return srcElement;
|
|
146
|
+
};
|
|
147
|
+
const fireListeners = () => {
|
|
148
|
+
EVENTS_FIRE_DOCUMENT_BODY_LISTENERS == null ? void 0 : EVENTS_FIRE_DOCUMENT_BODY_LISTENERS.forEach((event) => {
|
|
149
|
+
document.body["on" + event] = async (e) => {
|
|
150
|
+
await addScripts();
|
|
151
|
+
fireLoadListener();
|
|
152
|
+
fireObserverListeners();
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
EVENTS == null ? void 0 : EVENTS.forEach((event) => {
|
|
156
|
+
document.body["on" + event] = async (e) => {
|
|
157
|
+
const srcElement = getSrcElement({ srcElement: e == null ? void 0 : e.srcElement, event });
|
|
158
|
+
const listeners = await fetchListeners({ srcElement, event, e });
|
|
159
|
+
executeListeners({ e, srcElement, listeners });
|
|
160
|
+
addListener({ srcElement, event, listeners });
|
|
161
|
+
if (srcElement == null ? void 0 : srcElement.removeAttribute) srcElement.removeAttribute("on-" + event);
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
fireListeners();
|
|
166
|
+
window.onload = () => {
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
var _a;
|
|
169
|
+
(_a = document == null ? void 0 : document.body) == null ? void 0 : _a.click();
|
|
170
|
+
}, 2500);
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
const getScriptListener = () => {
|
|
174
|
+
return `<script defer>(${listener.toString()})()<\/script>`;
|
|
175
|
+
};
|
|
176
|
+
export {
|
|
177
|
+
getScriptListener,
|
|
178
|
+
listener
|
|
179
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "saloe",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Tools for making web development easy and efficient",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "vite build",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/jaimytacovega/
|
|
11
|
+
"url": "git+https://github.com/jaimytacovega/saloe.git"
|
|
12
12
|
},
|
|
13
13
|
"author": "Jaimy Taco",
|
|
14
14
|
"license": "ISC",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"import": "./dist/html.es.js",
|
|
34
34
|
"require": "./dist/html.cjs.js"
|
|
35
35
|
},
|
|
36
|
+
"./listener": {
|
|
37
|
+
"import": "./dist/listener.es.js",
|
|
38
|
+
"require": "./dist/listener.cjs.js"
|
|
39
|
+
},
|
|
36
40
|
"./router": {
|
|
37
41
|
"import": "./dist/router.es.js",
|
|
38
42
|
"require": "./dist/router.cjs.js"
|
package/src/listener.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
const listener = () => {
|
|
2
|
+
const EVENTS_PREVENT_DEFAULT_MANDATORY = [
|
|
3
|
+
'submit'
|
|
4
|
+
]
|
|
5
|
+
|
|
6
|
+
const EVENTS_FIRE_DOCUMENT_BODY_LISTENERS = [
|
|
7
|
+
'mouseover',
|
|
8
|
+
'click',
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const EVENTS = [
|
|
12
|
+
'submit',
|
|
13
|
+
'input',
|
|
14
|
+
'blur',
|
|
15
|
+
'change',
|
|
16
|
+
'focus',
|
|
17
|
+
'invalid',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
const addListener = ({ srcElement, event, listeners }) => {
|
|
21
|
+
srcElement?.addEventListener(event, (e) => {
|
|
22
|
+
executeListeners({ e, srcElement, listeners })
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const executeListeners = ({ e, srcElement, listeners }) => {
|
|
27
|
+
listeners?.forEach((listener) => {
|
|
28
|
+
if (listener) listener({ e, srcElement })
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const getListenerFromScript = ({ script, event }) => {
|
|
33
|
+
if (!script) return null
|
|
34
|
+
if (script[event]) return script[event]
|
|
35
|
+
const prev = Object.keys(script)?.find((key) => script[key][event])
|
|
36
|
+
if (!prev) return null
|
|
37
|
+
return script[prev][event]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const fetchListeners = async ({ srcElement, event, e }) => {
|
|
41
|
+
if (!srcElement?.getAttribute) return
|
|
42
|
+
|
|
43
|
+
const scriptNames = srcElement?.getAttribute('on-' + event)
|
|
44
|
+
if (!scriptNames) return
|
|
45
|
+
|
|
46
|
+
if (scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(event)) e.preventDefault()
|
|
47
|
+
|
|
48
|
+
const scripts = await Promise.all(
|
|
49
|
+
scriptNames?.split(',')?.map((scriptName) => {
|
|
50
|
+
const scriptToImport = '/' + scriptName?.trim() + '.js'
|
|
51
|
+
return import(scriptToImport)?.catch((err) => { })
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
const listeners = scripts?.map((script) => getListenerFromScript({ script, event }))
|
|
56
|
+
|
|
57
|
+
return listeners
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const addScripts = () => {
|
|
61
|
+
const scriptsToLoad = [...document.querySelectorAll('script[data-script-to-load]')]
|
|
62
|
+
return Promise.all(
|
|
63
|
+
scriptsToLoad?.map((scriptToLoad) => {
|
|
64
|
+
const id = scriptToLoad?.getAttribute('data-script-to-load')
|
|
65
|
+
scriptToLoad.removeAttribute('data-script-to-load')
|
|
66
|
+
|
|
67
|
+
const attrs = scriptToLoad?.getAttributeNames()?.reduce((acc, attrName) => {
|
|
68
|
+
const attrValue = scriptToLoad.getAttribute(attrName)
|
|
69
|
+
if (attrValue !== 'text/script-to-load') acc[attrName] = attrValue
|
|
70
|
+
return acc
|
|
71
|
+
}, {})
|
|
72
|
+
|
|
73
|
+
const content = scriptToLoad?.textContent
|
|
74
|
+
|
|
75
|
+
scriptToLoad?.remove()
|
|
76
|
+
|
|
77
|
+
return loadScript({ id, attrs, content }).catch((err) => {
|
|
78
|
+
console.error(err)
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const loadScript = ({ id, attrs, content }) => {
|
|
85
|
+
const script = document?.createElement('script')
|
|
86
|
+
|
|
87
|
+
Object.keys(attrs)?.forEach((attrKey) => script?.setAttribute(attrKey, attrs[attrKey]))
|
|
88
|
+
script.id = id
|
|
89
|
+
|
|
90
|
+
if (content) script?.insertAdjacentHTML('beforeend', content)
|
|
91
|
+
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
if (!attrs.src) {
|
|
94
|
+
resolve()
|
|
95
|
+
document?.body?.insertAdjacentElement('beforeend', script)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
script.onload = script.onreadystatechange = function () {
|
|
100
|
+
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
|
|
101
|
+
resolve()
|
|
102
|
+
script.onload = script.onreadystatechange = null
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
script.onerror = () => {
|
|
107
|
+
console.error('script failed to load')
|
|
108
|
+
reject(new Error('Failed to load script with src ' + script.src))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
document?.body?.insertAdjacentElement('beforeend', script)
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// load
|
|
116
|
+
const fireLoadListener = () => {
|
|
117
|
+
const event = 'load'
|
|
118
|
+
const srcElements = document?.querySelectorAll('[on-' + event + ']')
|
|
119
|
+
|
|
120
|
+
srcElements?.forEach(async (srcElement) => {
|
|
121
|
+
const listeners = await fetchListeners({ srcElement, event, e: null })
|
|
122
|
+
executeListeners({ e: null, srcElement, listeners })
|
|
123
|
+
|
|
124
|
+
srcElement?.removeAttribute('on-' + event)
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// invalid
|
|
129
|
+
const fireInvalidListener = () => {
|
|
130
|
+
const event = 'invalid'
|
|
131
|
+
const srcElements = document?.querySelectorAll('[on-' + event + ']')
|
|
132
|
+
|
|
133
|
+
srcElements?.forEach(async (srcElement) => {
|
|
134
|
+
const listeners = await fetchListeners({ srcElement, event, e: null })
|
|
135
|
+
addListener({ srcElement, event, listeners })
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// blur
|
|
140
|
+
const fireBlurListener = () => {
|
|
141
|
+
const event = 'blur'
|
|
142
|
+
const srcElements = document?.querySelectorAll('[on-' + event + ']')
|
|
143
|
+
|
|
144
|
+
srcElements?.forEach(async (srcElement) => {
|
|
145
|
+
const listeners = await fetchListeners({ srcElement, event, e: null })
|
|
146
|
+
addListener({ srcElement, event, listeners })
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// focus
|
|
151
|
+
const fireFocusListener = () => {
|
|
152
|
+
const event = 'focus'
|
|
153
|
+
const srcElements = document?.querySelectorAll('[on-' + event + ']')
|
|
154
|
+
|
|
155
|
+
srcElements?.forEach(async (srcElement) => {
|
|
156
|
+
const listeners = await fetchListeners({ srcElement, event, e: null })
|
|
157
|
+
addListener({ srcElement, event, listeners })
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// observers
|
|
162
|
+
const fireObserverListeners = () => {
|
|
163
|
+
const srcElements = [...document.querySelectorAll('[on-observe]')]
|
|
164
|
+
|
|
165
|
+
const uniqueScriptNames = [...srcElements?.reduce((acc, srcElement) => {
|
|
166
|
+
const attribute = srcElement?.getAttribute('on-observe')
|
|
167
|
+
if (attribute === 'undefined') return acc
|
|
168
|
+
|
|
169
|
+
const scriptNames = attribute?.split(',')
|
|
170
|
+
scriptNames?.forEach((scriptName) => acc?.set(scriptName, 1))
|
|
171
|
+
|
|
172
|
+
return acc
|
|
173
|
+
}, new Map())?.keys()]
|
|
174
|
+
|
|
175
|
+
uniqueScriptNames?.forEach(async (scriptName) => {
|
|
176
|
+
const observedSrcElements = document.querySelectorAll('[on-observe*="' + scriptName + '"]')
|
|
177
|
+
|
|
178
|
+
const script = await import('/' + scriptName?.trim() + '.js')?.catch((err) => { })
|
|
179
|
+
const listener = getListenerFromScript({ script, event: 'observe' })
|
|
180
|
+
if (!listener) return
|
|
181
|
+
|
|
182
|
+
const observer = new IntersectionObserver((entries) => {
|
|
183
|
+
entries.forEach((entry) => listener({ entry, observer }))
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
observedSrcElements?.forEach((observerSrcElement) => {
|
|
187
|
+
observer.observe(observerSrcElement)
|
|
188
|
+
|
|
189
|
+
const observerAttr = observerSrcElement?.getAttribute('on-observe')
|
|
190
|
+
const updatedObserverAttr = observerAttr?.replaceAll(scriptName + ', ', '')?.replaceAll(', ' + scriptName, '')?.replaceAll(scriptName, '')
|
|
191
|
+
|
|
192
|
+
if (updatedObserverAttr === '') observerSrcElement.removeAttribute('on-observe')
|
|
193
|
+
else observerSrcElement.setAttribute('on-observe', updatedObserverAttr)
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const getSrcElement = ({ srcElement, event }) => {
|
|
199
|
+
if (!srcElement?.hasAttribute) return srcElement
|
|
200
|
+
const attribute = 'on-' + event
|
|
201
|
+
const hasScriptName = srcElement?.hasAttribute(attribute)
|
|
202
|
+
if (hasScriptName) return srcElement
|
|
203
|
+
|
|
204
|
+
const query = ':is(a, button, li)[' + attribute + ']'
|
|
205
|
+
const closestButton = srcElement?.closest(query)
|
|
206
|
+
if (closestButton) return closestButton
|
|
207
|
+
|
|
208
|
+
return srcElement
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const fireListeners = () => {
|
|
212
|
+
EVENTS_FIRE_DOCUMENT_BODY_LISTENERS?.forEach((event) => {
|
|
213
|
+
document.body['on' + event] = async (e) => {
|
|
214
|
+
await addScripts()
|
|
215
|
+
|
|
216
|
+
fireLoadListener()
|
|
217
|
+
fireObserverListeners()
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
EVENTS?.forEach((event) => {
|
|
222
|
+
document.body['on' + event] = async (e) => {
|
|
223
|
+
const srcElement = getSrcElement({ srcElement: e?.srcElement, event })
|
|
224
|
+
const listeners = await fetchListeners({ srcElement, event, e })
|
|
225
|
+
|
|
226
|
+
executeListeners({ e, srcElement, listeners })
|
|
227
|
+
addListener({ srcElement, event, listeners })
|
|
228
|
+
|
|
229
|
+
if (srcElement?.removeAttribute) srcElement.removeAttribute('on-' + event)
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fireListeners()
|
|
235
|
+
|
|
236
|
+
window.onload = () => {
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
document?.body?.click()
|
|
239
|
+
}, 2_500)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const getScriptListener = () => {
|
|
244
|
+
return `<script defer>(${listener.toString()})()</script>`
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export {
|
|
248
|
+
listener,
|
|
249
|
+
getScriptListener,
|
|
250
|
+
}
|
package/src/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { promises as fsPromises,
|
|
2
|
-
import { join
|
|
1
|
+
import { promises as fsPromises, unlinkSync, existsSync } from 'fs'
|
|
2
|
+
import { join } from 'path'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const listFiles = async ({ path }) => {
|
package/vite.config.js
CHANGED
|
@@ -12,6 +12,7 @@ export default defineConfig({
|
|
|
12
12
|
'cloudflare-worker': resolve(__dirname, 'src/cloudflare-worker.js'),
|
|
13
13
|
cookie: resolve(__dirname, 'src/cookie.js'),
|
|
14
14
|
html: resolve(__dirname, 'src/html.js'),
|
|
15
|
+
listener: resolve(__dirname, 'src/listener.js'),
|
|
15
16
|
router: resolve(__dirname, 'src/router.js'),
|
|
16
17
|
'urlpattern': resolve(__dirname, 'src/urlpattern.js'),
|
|
17
18
|
util: resolve(__dirname, 'src/util.js'),
|
|
Binary file
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "cloudflare-worker-server",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "server.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"watch:dev": "ENV=dev vite build --watch",
|
|
8
|
-
"watch:qa": "ENV=qa vite build --watch",
|
|
9
|
-
"watch:prod": "ENV=prod vite build --watch",
|
|
10
|
-
"build:dev": "ENV=dev vite build",
|
|
11
|
-
"build:qa": "ENV=qa vite build",
|
|
12
|
-
"build:prod": "ENV=prod vite build",
|
|
13
|
-
"local:dev": "wrangler dev --env=dev",
|
|
14
|
-
"local:qa": "wrangler dev --env=qa",
|
|
15
|
-
"local:prod": "wrangler dev --env=prod",
|
|
16
|
-
"deploy:dev": "npm run build:dev && wrangler deploy --env=dev",
|
|
17
|
-
"deploy:qa": "npm run build:qa && wrangler deploy --env=qa",
|
|
18
|
-
"deploy:prod": "npm run build:prod && wrangler deploy --env=prod",
|
|
19
|
-
"build-worker:dev": "wrangler deploy --dry-run --outdir=dist-worker"
|
|
20
|
-
},
|
|
21
|
-
"keywords": [],
|
|
22
|
-
"author": "",
|
|
23
|
-
"license": "ISC",
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@cloudflare/kv-asset-handler": "^0.3.4",
|
|
26
|
-
"@jaimytacovega/salo": "^0.0.28",
|
|
27
|
-
"vite": "^5.4.2"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { findPatternFromUrl, getRedirectResponse, getForbiddenResponse, getRoute, getNotFoundResponse, getServerOnlyResponse } from '@jaimytacovega/salo/router'
|
|
2
|
-
import { getStaticResponse } from '@jaimytacovega/salo/cloudflare-worker'
|
|
3
|
-
import { addRoute } from '@jaimytacovega/salo/router'
|
|
4
|
-
import { html, stream } from '@jaimytacovega/salo/html'
|
|
5
|
-
import { LISTENER_SCRIPT } from '@jaimytacovega/salo/actions'
|
|
6
|
-
|
|
7
|
-
import manifestJSON from '__STATIC_CONTENT_MANIFEST'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const isRedirectableCallback = ({ pathname }) => {
|
|
11
|
-
return pathname !== '/' && pathname.endsWith('/')
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const isForbiddenCallback = ({ request }) => {
|
|
15
|
-
const forbiddenURLs = []
|
|
16
|
-
return forbiddenURLs.find((filename) => request?.url?.endsWith(filename))
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const isServerOnlyCallback = ({ request }) => {
|
|
20
|
-
const serverOnlyURLs = []
|
|
21
|
-
return serverOnlyURLs?.find((filename) => request?.url?.endsWith(filename))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(() => {
|
|
26
|
-
addRoute({
|
|
27
|
-
pathname: '/',
|
|
28
|
-
route: ({ request, env }) => {
|
|
29
|
-
return stream({
|
|
30
|
-
head: () => html`
|
|
31
|
-
<meta charset="UTF-8">
|
|
32
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
33
|
-
<title>Cloudflare Worker Server</title>
|
|
34
|
-
`,
|
|
35
|
-
body: () => html`
|
|
36
|
-
|
|
37
|
-
<form
|
|
38
|
-
on-submit="submit"
|
|
39
|
-
>
|
|
40
|
-
<h1
|
|
41
|
-
on-load="load"
|
|
42
|
-
>
|
|
43
|
-
Hello world!
|
|
44
|
-
</h1>
|
|
45
|
-
<input
|
|
46
|
-
type="text"
|
|
47
|
-
on-input="input"
|
|
48
|
-
/>
|
|
49
|
-
<button type="submit">Submit!</button>
|
|
50
|
-
</form>
|
|
51
|
-
`,
|
|
52
|
-
scripts: () => html`
|
|
53
|
-
${LISTENER_SCRIPT}
|
|
54
|
-
<script>
|
|
55
|
-
console.log('Hello world!')
|
|
56
|
-
</script>
|
|
57
|
-
`,
|
|
58
|
-
env,
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
})()
|
|
64
|
-
|
|
65
|
-
const handleFetch = async ({ request, env, ctx }) => {
|
|
66
|
-
const url = new URL(request.url)
|
|
67
|
-
const { origin, pathname } = url
|
|
68
|
-
|
|
69
|
-
const pattern = findPatternFromUrl({ url })
|
|
70
|
-
|
|
71
|
-
const redirectResult = getRedirectResponse({ origin, pathname, isRedirectableCallback })
|
|
72
|
-
if (redirectResult?.response) return redirectResult.response
|
|
73
|
-
|
|
74
|
-
const forbiddenResult = getForbiddenResponse({ origin, request, isForbiddenCallback })
|
|
75
|
-
if (forbiddenResult?.response) return forbiddenResult.response
|
|
76
|
-
|
|
77
|
-
const serverOnlyResult = getServerOnlyResponse({ origin, request, isServerOnlyCallback })
|
|
78
|
-
if (serverOnlyResult?.response) return serverOnlyResult.response
|
|
79
|
-
|
|
80
|
-
const route = getRoute({ pathname: pattern?.pathname })
|
|
81
|
-
const routeResult = route ? await route({ request, pattern, env }) : null
|
|
82
|
-
if (routeResult?.response) return routeResult.response
|
|
83
|
-
|
|
84
|
-
const staticResult = await getStaticResponse({ request, waitUntil: ctx.waitUntil.bind(ctx), manifestJSON, env })
|
|
85
|
-
if (staticResult?.response) return staticResult?.response
|
|
86
|
-
|
|
87
|
-
const notFoundResult = await getNotFoundResponse({ request })
|
|
88
|
-
return notFoundResult?.response
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export default {
|
|
92
|
-
fetch: (request, env, ctx) => handleFetch({ request, env, ctx })
|
|
93
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
define: {
|
|
6
|
-
__ENV__: `'${process.env.ENV}'`,
|
|
7
|
-
__BUILD_TIME__: `'${new Date().toISOString()}'`,
|
|
8
|
-
__APP_NAME__: `'cloudflare-worker-server'`,
|
|
9
|
-
},
|
|
10
|
-
plugins: [],
|
|
11
|
-
build: {
|
|
12
|
-
outDir: './dist',
|
|
13
|
-
manifest: true,
|
|
14
|
-
emptyOutDir: true,
|
|
15
|
-
minify: false,
|
|
16
|
-
rollupOptions: {
|
|
17
|
-
input: {},
|
|
18
|
-
output: {
|
|
19
|
-
entryFileNames: `[name].js`,
|
|
20
|
-
chunkFileNames: `[name].js`,
|
|
21
|
-
assetFileNames: `[name].[ext]`,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
name = "cloudflare-worker-actions"
|
|
2
|
-
main = "server.js"
|
|
3
|
-
compatibility_date = "2022-11-01"
|
|
4
|
-
compatibility_flags = ["transformstream_enable_standard_constructor", "streams_enable_constructors"]
|
|
5
|
-
minify = false
|
|
6
|
-
#node_compat = true
|
|
7
|
-
|
|
8
|
-
[site]
|
|
9
|
-
bucket = "./public"
|
|
10
|
-
|
|
11
|
-
[env]
|
|
12
|
-
|
|
13
|
-
[env.prod]
|
|
14
|
-
experimental-local = true
|
|
15
|
-
|
|
16
|
-
[env.prod.vars]
|
|
17
|
-
IS_CLOUDFLARE_WORKER = true
|
|
18
|
-
ENV = "prod"
|
|
19
|
-
APP_NAME = "cloudflare-worker-actions"
|
|
20
|
-
|
|
21
|
-
[env.qa]
|
|
22
|
-
experimental-local = true
|
|
23
|
-
|
|
24
|
-
[env.qa.vars]
|
|
25
|
-
IS_CLOUDFLARE_WORKER = true
|
|
26
|
-
ENV = "qa"
|
|
27
|
-
APP_NAME = "cloudflare-worker-actions"
|
|
28
|
-
|
|
29
|
-
[env.dev]
|
|
30
|
-
experimental-local = true
|
|
31
|
-
|
|
32
|
-
[env.dev.vars]
|
|
33
|
-
IS_CLOUDFLARE_WORKER = true
|
|
34
|
-
ENV = "dev"
|
|
35
|
-
APP_NAME = "cloudflare-worker-actions"
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "cloudflare-worker-server",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "server.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"watch:dev": "ENV=dev vite build --watch",
|
|
8
|
-
"watch:qa": "ENV=qa vite build --watch",
|
|
9
|
-
"watch:prod": "ENV=prod vite build --watch",
|
|
10
|
-
"build:dev": "ENV=dev vite build",
|
|
11
|
-
"build:qa": "ENV=qa vite build",
|
|
12
|
-
"build:prod": "ENV=prod vite build",
|
|
13
|
-
"local:dev": "wrangler dev --env=dev",
|
|
14
|
-
"local:qa": "wrangler dev --env=qa",
|
|
15
|
-
"local:prod": "wrangler dev --env=prod",
|
|
16
|
-
"deploy:dev": "npm run build:dev && wrangler deploy --env=dev",
|
|
17
|
-
"deploy:qa": "npm run build:qa && wrangler deploy --env=qa",
|
|
18
|
-
"deploy:prod": "npm run build:prod && wrangler deploy --env=prod",
|
|
19
|
-
"build-worker:dev": "wrangler deploy --dry-run --outdir=dist-worker"
|
|
20
|
-
},
|
|
21
|
-
"keywords": [],
|
|
22
|
-
"author": "",
|
|
23
|
-
"license": "ISC",
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@cloudflare/kv-asset-handler": "^0.3.4",
|
|
26
|
-
"@jaimytacovega/salo": "^0.0.16",
|
|
27
|
-
"vite": "^5.4.2"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { findPatternFromUrl, getRedirectResponse, getForbiddenResponse, getRoute, getNotFoundResponse, getServerOnlyResponse } from '@jaimytacovega/salo/router'
|
|
2
|
-
import { getStaticResponse } from '@jaimytacovega/salo/cloudflare-worker'
|
|
3
|
-
import { addRoute } from '@jaimytacovega/salo/router'
|
|
4
|
-
import { html, stream } from '@jaimytacovega/salo/html'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const isRedirectableCallback = ({ pathname }) => {
|
|
8
|
-
return pathname !== '/' && pathname.endsWith('/')
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const isForbiddenCallback = ({ request }) => {
|
|
12
|
-
const forbiddenURLs = []
|
|
13
|
-
return forbiddenURLs.find((filename) => request?.url?.endsWith(filename))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const isServerOnlyCallback = ({ request }) => {
|
|
17
|
-
const serverOnlyURLs = []
|
|
18
|
-
return serverOnlyURLs?.find((filename) => request?.url?.endsWith(filename))
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
(() => {
|
|
23
|
-
addRoute({
|
|
24
|
-
pathname: '/',
|
|
25
|
-
route: ({ request, env }) => {
|
|
26
|
-
return stream({
|
|
27
|
-
head: () => html`
|
|
28
|
-
<meta charset="UTF-8">
|
|
29
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
30
|
-
<title>Cloudflare Worker Server</title>
|
|
31
|
-
`,
|
|
32
|
-
body: () => html`
|
|
33
|
-
<h1>Hello world!</h1>
|
|
34
|
-
`,
|
|
35
|
-
scripts: () => html`
|
|
36
|
-
<script>
|
|
37
|
-
console.log('Hello world!')
|
|
38
|
-
</script>
|
|
39
|
-
`,
|
|
40
|
-
env,
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
})()
|
|
46
|
-
|
|
47
|
-
const handleFetch = async ({ request, env, ctx }) => {
|
|
48
|
-
const url = new URL(request.url)
|
|
49
|
-
const { origin, pathname } = url
|
|
50
|
-
|
|
51
|
-
const pattern = findPatternFromUrl({ url })
|
|
52
|
-
|
|
53
|
-
const redirectResult = getRedirectResponse({ origin, pathname, isRedirectableCallback })
|
|
54
|
-
if (redirectResult?.response) return redirectResult.response
|
|
55
|
-
|
|
56
|
-
const forbiddenResult = getForbiddenResponse({ origin, request, isForbiddenCallback })
|
|
57
|
-
if (forbiddenResult?.response) return forbiddenResult.response
|
|
58
|
-
|
|
59
|
-
const serverOnlyResult = getServerOnlyResponse({ origin, request, isServerOnlyCallback })
|
|
60
|
-
if (serverOnlyResult?.response) return serverOnlyResult.response
|
|
61
|
-
|
|
62
|
-
const route = getRoute({ pathname: pattern?.pathname })
|
|
63
|
-
const routeResult = route ? await route({ request, pattern, env }) : null
|
|
64
|
-
if (routeResult?.response) return routeResult.response
|
|
65
|
-
|
|
66
|
-
const staticResult = await getStaticResponse({ request, waitUntil: ctx.waitUntil.bind(ctx), env })
|
|
67
|
-
if (staticResult?.response) return staticResult?.response
|
|
68
|
-
|
|
69
|
-
const notFoundResult = await getNotFoundResponse({ request })
|
|
70
|
-
return notFoundResult?.response
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export default {
|
|
74
|
-
fetch: (request, env, ctx) => handleFetch({ request, env, ctx })
|
|
75
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
define: {
|
|
6
|
-
__ENV__: `'${process.env.ENV}'`,
|
|
7
|
-
__BUILD_TIME__: `'${new Date().toISOString()}'`,
|
|
8
|
-
__APP_NAME__: `'cloudflare-worker-server'`,
|
|
9
|
-
},
|
|
10
|
-
plugins: [],
|
|
11
|
-
build: {
|
|
12
|
-
outDir: './dist',
|
|
13
|
-
manifest: true,
|
|
14
|
-
emptyOutDir: true,
|
|
15
|
-
minify: false,
|
|
16
|
-
rollupOptions: {
|
|
17
|
-
input: {},
|
|
18
|
-
output: {
|
|
19
|
-
entryFileNames: `[name].js`,
|
|
20
|
-
chunkFileNames: `[name].js`,
|
|
21
|
-
assetFileNames: `[name].[ext]`,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
name = "cloudflare-worker-server"
|
|
2
|
-
main = "server.js"
|
|
3
|
-
compatibility_date = "2022-11-01"
|
|
4
|
-
compatibility_flags = ["transformstream_enable_standard_constructor", "streams_enable_constructors"]
|
|
5
|
-
minify = false
|
|
6
|
-
#node_compat = true
|
|
7
|
-
|
|
8
|
-
[env]
|
|
9
|
-
|
|
10
|
-
[env.prod]
|
|
11
|
-
experimental-local = true
|
|
12
|
-
|
|
13
|
-
[env.prod.vars]
|
|
14
|
-
IS_CLOUDFLARE_WORKER = true
|
|
15
|
-
ENV = "prod"
|
|
16
|
-
APP_NAME = "cloudflare-worker-server"
|
|
17
|
-
|
|
18
|
-
[env.qa]
|
|
19
|
-
experimental-local = true
|
|
20
|
-
|
|
21
|
-
[env.qa.vars]
|
|
22
|
-
IS_CLOUDFLARE_WORKER = true
|
|
23
|
-
ENV = "qa"
|
|
24
|
-
APP_NAME = "cloudflare-worker-server"
|
|
25
|
-
|
|
26
|
-
[env.dev]
|
|
27
|
-
experimental-local = true
|
|
28
|
-
|
|
29
|
-
[env.dev.vars]
|
|
30
|
-
IS_CLOUDFLARE_WORKER = true
|
|
31
|
-
ENV = "dev"
|
|
32
|
-
APP_NAME = "cloudflare-worker-server"
|