kopular 0.21.0 → 0.21.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.
Files changed (3) hide show
  1. package/LLM.md +27 -2
  2. package/package.json +2 -2
  3. package/src/testing.js +20 -7
package/LLM.md CHANGED
@@ -169,6 +169,28 @@ FormField<string> email = new FormField<string>("", (string v) => Validators.Ema
169
169
  `{ get; }`) — `extern class` supports a plain field declaration for exactly this case,
170
170
  not just get/set accessor pairs.
171
171
 
172
+ `Computed1`/`Computed2`/`Resource<T>` (needs `kopscript >= 0.24.0` for `extern enum`,
173
+ which `AsyncStatus` requires):
174
+
175
+ ```ks
176
+ extern class Computed1<A, R> {
177
+ constructor(state<A> source, (A) => R compute);
178
+ state<R> Value;
179
+ } from "kopular/computed";
180
+ extern class Computed2<A, B, R> {
181
+ constructor(state<A> a, state<B> b, (A, B) => R compute);
182
+ state<R> Value;
183
+ } from "kopular/computed";
184
+
185
+ extern enum AsyncStatus { Loading, Success, Failure } from "kopular/resource";
186
+ extern class Resource<T> {
187
+ constructor(task<T> operation);
188
+ state<AsyncStatus> Status;
189
+ state<T?> Data;
190
+ state<string?> Error;
191
+ } from "kopular/resource";
192
+ ```
193
+
172
194
  You also need your own ambient DOM `extern` block (`document`, `Element`, `Event`, ...) —
173
195
  Kopular's own copy in `dom.ks` isn't reachable across the package boundary; redeclare the
174
196
  handful of members you actually use. See KopularDemo's `src/kopular_bindings.ks` for a
@@ -636,7 +658,7 @@ import { runKopularApp } from "kopular/testing";
636
658
 
637
659
  const { window, cleanup } = await runKopularApp(srcDir, "app.ks", {
638
660
  includeKopularPackage: true, // app consumes Kopular via `extern`, not relative `using`
639
- extraFiles: ["http_runtime.js"], // non-.ks/.html siblings a `using` graph needs at runtime
661
+ extraFiles: ["config.json"], // any sibling with an extension besides .ks/.html/.js
640
662
  fetchMock: (...args) => Promise.resolve({ ok: true, status: 200, text: () => Promise.resolve("body") }),
641
663
  url: "http://localhost/",
642
664
  });
@@ -650,7 +672,10 @@ try {
650
672
  Compiles `entryFileName` (plus everything else in `srcDir` it `using`s) via kopscript's
651
673
  `compileGraph`, binds jsdom onto `globalThis` (`document`/`Element`/`Event`/`location`/
652
674
  `history`/`window`/`fetch`) for the compiled ambient `extern` declarations to find, and
653
- runs it. `runKopularFixture(source, options)` is the sibling export for an inline fixture
675
+ runs it. Every `.ks`/`.html`/`.js` file in `srcDir` is copied along with it `.js`
676
+ included specifically so a hand-written (not compiled) sibling like a `Router.AddLazyRoute`
677
+ loader shim just works with no extra setup; `extraFiles` is only for a real dependency with
678
+ some OTHER extension (e.g. a `.json` config file). `runKopularFixture(source, options)` is the sibling export for an inline fixture
654
679
  string instead of a real file (used by Kopular's own test suite; copies Kopular's *own*
655
680
  `.ks` sources alongside the fixture, so `using "./component"` resolves — only meaningful
656
681
  for testing Kopular itself, not an external consumer, which should use `runKopularApp`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kopular",
3
- "version": "0.21.0",
3
+ "version": "0.21.2",
4
4
  "description": "Kopular: a small component framework for KopScript — components, reactive state, constructor-injected services, routing, real compiled templates, and HTTP, with no DI container",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -62,7 +62,7 @@
62
62
  "@types/jsdom": "^30.0.0",
63
63
  "@types/node": "^20.14.0",
64
64
  "jsdom": "^25.0.1",
65
- "kopscript": "^0.23.0",
65
+ "kopscript": "^0.24.0",
66
66
  "typescript": "^5.5.0",
67
67
  "vitest": "^4.1.11"
68
68
  },
package/src/testing.js CHANGED
@@ -39,13 +39,25 @@ const OWN_SRC_DIR = dirname(fileURLToPath(import.meta.url));
39
39
  // than anything wrong with the copied files themselves.
40
40
  const TEMP_ROOT = join(OWN_SRC_DIR, "..", ".kopular-testing-tmp");
41
41
 
42
- // Copies every .ks/.html file from `srcDir` into `dir`, plus any filename
43
- // listed in `extraFiles` (e.g. http_runtime.js a hand-written sibling a
44
- // compiled `using` graph needs at runtime, which the compiler wouldn't know
45
- // to copy on its own).
42
+ // Copies every .ks/.html/.js file from `srcDir` into `dir`, plus any
43
+ // filename listed in `extraFiles` for anything with a different extension.
44
+ // `.js` is included alongside `.ks`/`.html` (not just left to `extraFiles`)
45
+ // because a hand-written, not-compiled-from-`.ks` companion file is a
46
+ // real, documented pattern now, not a one-off — most commonly a dynamic-
47
+ // `import()` loader shim for `Router.AddLazyRoute` (see kopscript's own
48
+ // LLM.md/README.md "extern" section, and Kopular's own "Lazy routes"
49
+ // docs), reached via a RELATIVE `extern ... from "./whatever";` the test
50
+ // author can't always know the exact filename of in advance — unlike
51
+ // http_runtime.js (a fixed name Kopular itself ships and controls, still
52
+ // the right fit for `extraFiles`), an app's own loader shim can be named
53
+ // anything. Any pre-existing `.js` with the same name as a `.ks` file
54
+ // gets harmlessly overwritten moments later by that `.ks`'s own fresh
55
+ // compiled output — copying it first only matters for a `.js` with no
56
+ // `.ks` counterpart at all, which is exactly the hand-written case this
57
+ // exists for.
46
58
  function copySources(srcDir, dir, extraFiles) {
47
59
  for (const name of readdirSync(srcDir)) {
48
- if (name.endsWith(".ks") || name.endsWith(".html") || extraFiles.includes(name)) {
60
+ if (name.endsWith(".ks") || name.endsWith(".html") || name.endsWith(".js") || extraFiles.includes(name)) {
49
61
  cpSync(join(srcDir, name), join(dir, name));
50
62
  }
51
63
  }
@@ -155,8 +167,9 @@ async function compileAndRun(dir, entryFileName, options) {
155
167
  * installed `kopular` package into a temp node_modules/, for an entry
156
168
  * that consumes Kopular via `extern ... from "kopular/..."` rather than
157
169
  * relative `using`. Default false.
158
- * @param {string[]} [options.extraFiles] - extra filenames (not .ks/.html)
159
- * to copy from srcDir, e.g. ["http_runtime.js"].
170
+ * @param {string[]} [options.extraFiles] - extra filenames to copy from
171
+ * srcDir beyond .ks/.html/.js (which are always copied), for anything
172
+ * with a different extension.
160
173
  * @param {(...args: unknown[]) => unknown} [options.fetchMock] - replaces
161
174
  * the global `fetch` for the duration of the run, for testing `Http`.
162
175
  * @param {string} [options.url] - the jsdom document's URL. Default