@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 +4 -5
- package/dist/ClientScript.d.ts +0 -1
- package/dist/ClientScript.js.map +1 -1
- package/dist/JsxElement.d.ts +3 -5
- package/dist/cs.d.ts +2 -1
- package/dist/cs.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ClientScript.ts +0 -3
- package/src/JsxElement.ts +5 -8
- package/src/cs.ts +14 -1
- package/src/index.ts +1 -2
- package/dist/once.d.ts +0 -11
- package/dist/once.js +0 -31
- package/dist/once.js.map +0 -1
- package/src/once.ts +0 -40
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
|
|
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
|
|
44
|
+
import { cs } from "@backtickjs/core";
|
|
45
45
|
import { createContext, useContext } from "react" with { backtick: "client" };
|
|
46
46
|
|
|
47
|
-
const ThemeContext =
|
|
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`, `
|
|
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
|
package/dist/ClientScript.d.ts
CHANGED
|
@@ -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;
|
package/dist/ClientScript.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientScript.js","sourceRoot":"","sources":["../src/ClientScript.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/JsxElement.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
24
|
-
*
|
|
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
|
|
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
|
-
|
|
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;
|
|
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
|
|
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;
|
|
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
package/src/ClientScript.ts
CHANGED
|
@@ -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
|
-
*
|
|
46
|
-
*
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
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<
|
|
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
|
|
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
|
-
}
|