@backtickjs/core 0.3.2 → 0.4.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 CHANGED
@@ -38,13 +38,13 @@ export async function Home() {
38
38
 
39
39
  `$node` and `$Counter` are splices: `node` is a server variable, written into the bundle as data; `Counter` is a script. `$useState` is a splice too, of an export the client provides. What can be spliced is `Spliceable`: data, and scripts. [Thinking in Backtick](https://backtickjs.dev/docs/thinking-in-backtick/) has what can cross, what can't, and how server and client components compose.
40
40
 
41
- A script every component shares, like a context or a store, is made once with `once`: one value for the bundle, where an expression script would run again at each read.
41
+ A script is one value for the bundle, made when it loads, as a module-level `const` is: a context or a store every component shares is written as one. Code that runs at each use is a function, called where it's used.
42
42
 
43
43
  ```tsx
44
- import { cs, once } from "@backtickjs/core";
44
+ import { cs } from "@backtickjs/core";
45
45
  import { createContext, useContext } from "react" with { backtick: "client" };
46
46
 
47
- const ThemeContext = once(cs`$createContext("light")`);
47
+ const ThemeContext = cs`$createContext("light")`;
48
48
  const Label = cs`() => <p>{$useContext($ThemeContext)}</p>`;
49
49
  // In a script: <$ThemeContext.Provider value="dark"><$Label /></$ThemeContext.Provider>
50
50
  ```
@@ -112,7 +112,6 @@ A test draws a screen with a module map of its own, stand-ins included; its modu
112
112
 
113
113
  - `cs`: the tag for client scripts. Compiled at build time; throws if called uncompiled.
114
114
  - `Client<T>`: the type of a script that stands for a `T` on the client.
115
- - `once(script)`: the script as one value for the bundle, made at its top; each call is one value. Refused for a script that reads a variable of the script around it.
116
115
  - `Spliceable`: what a server may splice into a script.
117
116
  - `Spliced<T>`: what a spliceable value becomes on the client (`Client<U>` becomes `U`; arrays and objects map member by member).
118
117
  - `createImport<T>({ name, from, version })`: an export of a module the client provides, as a value a script can splice.
@@ -125,7 +124,7 @@ A test draws a screen with a module map of its own, stand-ins included; its modu
125
124
  - `exec`: in a script, `$exec(bundle)` runs another bundle as the script's own was run, with the same modules, to a promise of its value.
126
125
  - `isClientExec`, `ClientExec`: its check and type.
127
126
  - `SplicesAs<T>`: `T` as a splice checks it, member by member. Used by the bundler to check its input.
128
- - `createJsxElement`, `isJsxElement`, `JsxElement`, `JsxElementOf`, `JsxElementTypeOf`: what a server-side JSX tag evaluates to before bundling. Used by the JSX packages' runtimes.
127
+ - `createJsxElement`, `isJsxElement`, `JsxElement`, `JsxElementOf`, `ServerComponent`: what a server-side JSX tag evaluates to before bundling, and what a server component answers. Used by the JSX packages' runtimes.
129
128
  - `create`, `isClientScript`, `ClientScript`, `ScriptModule`, `Param`: the compiled form of a script, written by the compiler and read by the bundler. Not for application code.
130
129
 
131
130
  ## Related
@@ -18,7 +18,6 @@ export interface ClientScript {
18
18
  readonly "@backtickjs": "ClientScript";
19
19
  readonly module: ScriptModule;
20
20
  readonly args: readonly Spliceable[];
21
- readonly once?: true;
22
21
  }
23
22
  export declare function isClientScript(value: unknown): value is ClientScript;
24
23
  export declare function create(module: ScriptModule, args: readonly Spliceable[]): ClientScript;
@@ -1 +1 @@
1
- {"version":3,"file":"ClientScript.js","sourceRoot":"","sources":["../src/ClientScript.ts"],"names":[],"mappings":"AA6CA,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,aAAa,IAAI,KAAK;QACtB,KAAK,CAAC,aAAa,CAAC,KAAK,cAAc,CACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CACpB,MAAoB,EACpB,IAA2B;IAE3B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"ClientScript.js","sourceRoot":"","sources":["../src/ClientScript.ts"],"names":[],"mappings":"AA0CA,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,aAAa,IAAI,KAAK;QACtB,KAAK,CAAC,aAAa,CAAC,KAAK,cAAc,CACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CACpB,MAAoB,EACpB,IAA2B;IAE3B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACzD,CAAC"}
@@ -20,9 +20,7 @@ export declare function createJsxElement(type: string | ((props: never) => unkno
20
20
  */
21
21
  export type JsxElementOf<T> = T & Client<T>;
22
22
  /**
23
- * What a tag may name: an intrinsic element; a component as a script sees it,
24
- * answering what the framework draws (a client component, or a server
25
- * component lowered); or a server component on the host, answering a script
26
- * that draws, or nothing.
23
+ * A server component on the host: it answers a script that draws a `T`, or
24
+ * nothing, which the bundler expands where its element stands.
27
25
  */
28
- export type JsxElementTypeOf<T> = string | ((props: never) => T) | ((props: never) => Client<T> | null | Promise<Client<T> | null>);
26
+ export type ServerComponent<T> = (props: never) => Client<T> | null | Promise<Client<T> | null>;
package/dist/cs.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { Client } from "./Client.js";
2
2
  import { create } from "./ClientScript.js";
3
3
  import type { Spliceable, SplicesAs, Spliced } from "./Spliceable.js";
4
- declare function lift<T>(_: T): Client<T>;
4
+ type NoValue = "a script that makes no value: a script is one value, made at load. To run code where it's used, make it a function, cs`() => …`, and call it";
5
+ declare function lift<T extends (<U>() => U extends T ? 1 : 2) extends <U>() => U extends void ? 1 : 2 ? NoValue : unknown>(_: T): Client<T>;
5
6
  declare function splice<T extends [T] extends [SplicesAs<T>] ? unknown : Spliceable>(_: T): unknown extends Spliced<T> ? any : Spliced<T>;
6
7
  declare function awaited<T>(_: T): Awaited<T>;
7
8
  /**
package/dist/cs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cs.js","sourceRoot":"","sources":["../src/cs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,uBAAuB;AACvB,SAAS,IAAI,CAAI,CAAI;IACnB,MAAM,IAAI,KAAK,CACb,+DAA+D;QAC7D,6DAA6D,CAChE,CAAC;AACJ,CAAC;AAED,uEAAuE;AACvE,0EAA0E;AAC1E,yEAAyE;AACzE,gFAAgF;AAChF,sEAAsE;AACtE,uEAAuE;AACvE,SAAS,MAAM,CACb,CAAI;IAEJ,MAAM,IAAI,KAAK,CACb,iEAAiE;QAC/D,6DAA6D,CAChE,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,gDAAgD;AAChD,SAAS,OAAO,CAAI,CAAI;IACtB,MAAM,IAAI,KAAK,CACb,kEAAkE;QAChE,6DAA6D,CAChE,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAC7B,CAAC,QAA8B,EAAE,GAAG,OAAkB,EAAmB,EAAE;IACzE,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;AACJ,CAAC,EACD,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAClC,CAAC"}
1
+ {"version":3,"file":"cs.js","sourceRoot":"","sources":["../src/cs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAQ3C,uBAAuB;AACvB,SAAS,IAAI,CAQX,CAAI;IACJ,MAAM,IAAI,KAAK,CACb,+DAA+D;QAC7D,6DAA6D,CAChE,CAAC;AACJ,CAAC;AAED,uEAAuE;AACvE,0EAA0E;AAC1E,yEAAyE;AACzE,gFAAgF;AAChF,sEAAsE;AACtE,uEAAuE;AACvE,SAAS,MAAM,CACb,CAAI;IAEJ,MAAM,IAAI,KAAK,CACb,iEAAiE;QAC/D,6DAA6D,CAChE,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,gDAAgD;AAChD,SAAS,OAAO,CAAI,CAAI;IACtB,MAAM,IAAI,KAAK,CACb,kEAAkE;QAChE,6DAA6D,CAChE,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAC7B,CAAC,QAA8B,EAAE,GAAG,OAAkB,EAAmB,EAAE;IACzE,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;AACJ,CAAC,EACD,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAClC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -4,12 +4,11 @@
4
4
  */
5
5
  export { cs } from "./cs.js";
6
6
  export type { Client } from "./Client.js";
7
- export { once } from "./once.js";
8
7
  export type { Spliceable, SplicesAs, Spliced } from "./Spliceable.js";
9
8
  export { createImport, isClientImport, type ClientImport, } from "./ClientImport.js";
10
9
  export type { ClientModule } from "./ClientModule.js";
11
10
  export type { Bundle } from "./Bundle.js";
12
11
  export { exec, isClientExec, type ClientExec } from "./exec.js";
13
- export { createJsxElement, isJsxElement, type JsxElement, type JsxElementOf, type JsxElementTypeOf, } from "./JsxElement.js";
12
+ export { createJsxElement, isJsxElement, type JsxElement, type JsxElementOf, type ServerComponent, } from "./JsxElement.js";
14
13
  export { create, type ScriptModule, type ClientScript, isClientScript, type Param, } from "./ClientScript.js";
15
14
  export { modulesOf, type ModuleMap } from "./modulesOf.js";
package/dist/index.js CHANGED
@@ -5,7 +5,6 @@
5
5
  // The tag, and how a host language spells a script standing in for a value;
6
6
  // a script as one value for the bundle.
7
7
  export { cs } from "./cs.js";
8
- export { once } from "./once.js";
9
8
  export { createImport, isClientImport, } from "./ClientImport.js";
10
9
  export { exec, isClientExec } from "./exec.js";
11
10
  // A drawing as a host builds one: what a JSX package's runtime makes, and
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,4EAA4E;AAC5E,wCAAwC;AACxC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAKjC,OAAO,EACL,YAAY,EACZ,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAmB,MAAM,WAAW,CAAC;AAEhE,0EAA0E;AAC1E,4BAA4B;AAC5B,OAAO,EACL,gBAAgB,EAChB,YAAY,GAIb,MAAM,iBAAiB,CAAC;AAEzB,6EAA6E;AAC7E,qCAAqC;AACrC,OAAO,EACL,MAAM,EAGN,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAE3B,2EAA2E;AAC3E,gDAAgD;AAChD,OAAO,EAAE,SAAS,EAAkB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,4EAA4E;AAC5E,wCAAwC;AACxC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAM7B,OAAO,EACL,YAAY,EACZ,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAmB,MAAM,WAAW,CAAC;AAEhE,0EAA0E;AAC1E,4BAA4B;AAC5B,OAAO,EACL,gBAAgB,EAChB,YAAY,GAIb,MAAM,iBAAiB,CAAC;AAEzB,6EAA6E;AAC7E,qCAAqC;AACrC,OAAO,EACL,MAAM,EAGN,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAE3B,2EAA2E;AAC3E,gDAAgD;AAChD,OAAO,EAAE,SAAS,EAAkB,MAAM,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backtickjs/core",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "The cs tag for Backtick client scripts, and the types for the values that cross from server to client",
5
5
  "keywords": [
6
6
  "backtick",
@@ -38,9 +38,6 @@ export interface ClientScript {
38
38
  readonly module: ScriptModule;
39
39
  // one per splice, in parameter order
40
40
  readonly args: readonly Spliceable[];
41
- // one value for the bundle, made at its top, rather than code run at each
42
- // read: see `once`
43
- readonly once?: true;
44
41
  }
45
42
 
46
43
  export function isClientScript(value: unknown): value is ClientScript {
package/src/JsxElement.ts CHANGED
@@ -42,12 +42,9 @@ export function createJsxElement(
42
42
  export type JsxElementOf<T> = T & Client<T>;
43
43
 
44
44
  /**
45
- * What a tag may name: an intrinsic element; a component as a script sees it,
46
- * answering what the framework draws (a client component, or a server
47
- * component lowered); or a server component on the host, answering a script
48
- * that draws, or nothing.
45
+ * A server component on the host: it answers a script that draws a `T`, or
46
+ * nothing, which the bundler expands where its element stands.
49
47
  */
50
- export type JsxElementTypeOf<T> =
51
- | string
52
- | ((props: never) => T)
53
- | ((props: never) => Client<T> | null | Promise<Client<T> | null>);
48
+ export type ServerComponent<T> = (
49
+ props: never,
50
+ ) => Client<T> | null | Promise<Client<T> | null>;
package/src/cs.ts CHANGED
@@ -2,8 +2,21 @@ import type { Client } from "./Client.js";
2
2
  import { create } from "./ClientScript.js";
3
3
  import type { Spliceable, SplicesAs, Spliced } from "./Spliceable.js";
4
4
 
5
+ // A string, so the error says it: `void` has no properties for TypeScript to
6
+ // name as missing.
7
+ type NoValue =
8
+ "a script that makes no value: a script is one value, made at load. To run code where it's used, make it a function, cs`() => …`, and call it";
9
+
5
10
  // The root of a script
6
- function lift<T>(_: T): Client<T> {
11
+ function lift<
12
+ // Whether `T` is exactly `void`: two such functions are the same type only
13
+ // when `T` and `void` are, so `never`, `any` and `undefined` pass.
14
+ T extends (<U>() => U extends T ? 1 : 2) extends <U>() => U extends void
15
+ ? 1
16
+ : 2
17
+ ? NoValue
18
+ : unknown,
19
+ >(_: T): Client<T> {
7
20
  throw new Error(
8
21
  "Don't call `cs.lift` directly; it's used to generate virtual " +
9
22
  "code for the typechecker. Write code using cs`...` instead.",
package/src/index.ts CHANGED
@@ -7,7 +7,6 @@
7
7
  // a script as one value for the bundle.
8
8
  export { cs } from "./cs.js";
9
9
  export type { Client } from "./Client.js";
10
- export { once } from "./once.js";
11
10
 
12
11
  // What a host may hand a client: data, a script, or an export of a module the
13
12
  // client provides.
@@ -31,7 +30,7 @@ export {
31
30
  isJsxElement,
32
31
  type JsxElement,
33
32
  type JsxElementOf,
34
- type JsxElementTypeOf,
33
+ type ServerComponent,
35
34
  } from "./JsxElement.js";
36
35
 
37
36
  // What a template compiles to: the compiler writes one and the bundler reads
package/dist/once.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import type { Client } from "./Client.js";
2
- /**
3
- * A script as one value for the bundle: its code runs once, at the top of the
4
- * bundle, and every read is that value, as a module-level `const` is in plain
5
- * TypeScript. For what every component shares, a context or a store, which an
6
- * expression would make again at each read. Each call of `once` is one value.
7
- *
8
- * Refused for a script that reads a variable of the script around it: at the
9
- * top of the bundle, nothing encloses it.
10
- */
11
- export declare function once<T>(script: Client<T>): Client<T>;
package/dist/once.js DELETED
@@ -1,31 +0,0 @@
1
- import { isClientScript, } from "./ClientScript.js";
2
- /**
3
- * A script as one value for the bundle: its code runs once, at the top of the
4
- * bundle, and every read is that value, as a module-level `const` is in plain
5
- * TypeScript. For what every component shares, a context or a store, which an
6
- * expression would make again at each read. Each call of `once` is one value.
7
- *
8
- * Refused for a script that reads a variable of the script around it: at the
9
- * top of the bundle, nothing encloses it.
10
- */
11
- export function once(script) {
12
- if (!isClientScript(script)) {
13
- throw new Error("`once` takes a script, cs`…`.");
14
- }
15
- const capture = script.module.params.find(isCapture);
16
- if (capture !== undefined) {
17
- throw new Error(`Can't make this script \`once\`: it reads \`${sourceName(capture.key)}\` ` +
18
- "from the script around it, and a `once` value is made at the top " +
19
- "of the bundle, outside every script.");
20
- }
21
- const made = { ...script, once: true };
22
- return made;
23
- }
24
- function isCapture(param) {
25
- return param.kind === "capture";
26
- }
27
- // A binding key is `<name>$<fileHash>$<n>`.
28
- function sourceName(key) {
29
- return key.replace(/\$[0-9a-z]+\$\d+$/, "");
30
- }
31
- //# sourceMappingURL=once.js.map
package/dist/once.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"once.js","sourceRoot":"","sources":["../src/once.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;GAQG;AACH,MAAM,UAAU,IAAI,CAAI,MAAiB;IACvC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,+CAA+C,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK;YACzE,mEAAmE;YACnE,sCAAsC,CACzC,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAiB,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACrD,OAAO,IAA4B,CAAC;AACtC,CAAC;AAED,SAAS,SAAS,CAAC,KAAY;IAC7B,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;AAClC,CAAC;AAED,4CAA4C;AAC5C,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;AAC9C,CAAC"}
package/src/once.ts DELETED
@@ -1,40 +0,0 @@
1
- import type { Client } from "./Client.js";
2
- import {
3
- type ClientScript,
4
- isClientScript,
5
- type Param,
6
- } from "./ClientScript.js";
7
-
8
- /**
9
- * A script as one value for the bundle: its code runs once, at the top of the
10
- * bundle, and every read is that value, as a module-level `const` is in plain
11
- * TypeScript. For what every component shares, a context or a store, which an
12
- * expression would make again at each read. Each call of `once` is one value.
13
- *
14
- * Refused for a script that reads a variable of the script around it: at the
15
- * top of the bundle, nothing encloses it.
16
- */
17
- export function once<T>(script: Client<T>): Client<T> {
18
- if (!isClientScript(script)) {
19
- throw new Error("`once` takes a script, cs`…`.");
20
- }
21
- const capture = script.module.params.find(isCapture);
22
- if (capture !== undefined) {
23
- throw new Error(
24
- `Can't make this script \`once\`: it reads \`${sourceName(capture.key)}\` ` +
25
- "from the script around it, and a `once` value is made at the top " +
26
- "of the bundle, outside every script.",
27
- );
28
- }
29
- const made: ClientScript = { ...script, once: true };
30
- return made as unknown as Client<T>;
31
- }
32
-
33
- function isCapture(param: Param): param is Extract<Param, { kind: "capture" }> {
34
- return param.kind === "capture";
35
- }
36
-
37
- // A binding key is `<name>$<fileHash>$<n>`.
38
- function sourceName(key: string): string {
39
- return key.replace(/\$[0-9a-z]+\$\d+$/, "");
40
- }