@shivaedev/build 0.1.0 → 0.1.1
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/CHANGELOG.md +10 -0
- package/README.md +10 -10
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +7 -4
- package/dist/files.js.map +1 -1
- package/package.json +3 -3
- package/src/files.ts +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 - 2026-11-11
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- The README's examples name a module file after its export, as in `src/modules/notes/Notes.ts` and `#generated/modules/notes/Notes.ts`, and import operations from the module's `server/` folder, as applications write them.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Generating no longer leaves an empty `.<file>.XXXXXX` folder beside every file it writes, under `src/generated` and in `node_modules/.cache/@shivaedev/build`. Each write still replaces the file in one rename, and its temporary folder is removed when the write ends, also when it fails or is interrupted. Folders left by earlier versions stay until you delete them.
|
|
12
|
+
|
|
3
13
|
## 0.1.0 - 2026-11-11
|
|
4
14
|
|
|
5
15
|
### Added
|
package/README.md
CHANGED
|
@@ -8,10 +8,10 @@ An operation written as `payload` and `*run` has its success and rejections only
|
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
import { defineModule } from "@shivaedev/contract/defineModule.ts";
|
|
11
|
-
import { notesWire } from "#generated/modules/notes/
|
|
12
|
-
import { Create } from "#modules/notes/
|
|
13
|
-
import { List } from "#modules/notes/
|
|
14
|
-
import { NotesStore } from "#modules/notes/
|
|
11
|
+
import { notesWire } from "#generated/modules/notes/Notes.ts";
|
|
12
|
+
import { Create } from "#modules/notes/server/Create.ts";
|
|
13
|
+
import { List } from "#modules/notes/server/List.ts";
|
|
14
|
+
import { NotesStore } from "#modules/notes/server/Store.ts";
|
|
15
15
|
|
|
16
16
|
export const Notes = defineModule({ name: "notes", operations: [List, Create], requires: [NotesStore], wire: notesWire });
|
|
17
17
|
```
|
|
@@ -21,7 +21,7 @@ shivaedev-build generate
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
```text
|
|
24
|
-
src/generated/modules/notes/
|
|
24
|
+
src/generated/modules/notes/Notes.ts: written
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Using it
|
|
@@ -68,7 +68,7 @@ The application's `package.json` runs the generator before anything that reads t
|
|
|
68
68
|
}
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
pnpm does not run `prepare` on a production install (`pnpm install --prod`), so a production install without development dependencies succeeds without the generator; the files must already be written, as `pnpm build` writes them through the Vite plugin. The folder's contents stay out of Git except a README that names the command, and
|
|
71
|
+
pnpm does not run `prepare` on a production install (`pnpm install --prod`), so a production install without development dependencies succeeds without the generator; the files must already be written, as `pnpm build` writes them through the Vite plugin. The folder's contents stay out of Git except a README that names the command, and `quality lint` runs the `generate` script before it reads the sources, so no configuration names the folder:
|
|
72
72
|
|
|
73
73
|
```gitignore
|
|
74
74
|
src/generated/*
|
|
@@ -123,19 +123,19 @@ With a generated client the browser never needs a module or its operations, so t
|
|
|
123
123
|
The build fails with the import chain from the client entry to that module:
|
|
124
124
|
|
|
125
125
|
```text
|
|
126
|
-
Server code reached the browser bundle: src/modules/notes/
|
|
126
|
+
Server code reached the browser bundle: src/modules/notes/Notes.ts is a module file: it calls defineModule. The import chain from the client entry:
|
|
127
127
|
index.html
|
|
128
128
|
→ src/client.ts
|
|
129
129
|
→ src/screens/notes.ts
|
|
130
|
-
→ src/modules/notes/
|
|
130
|
+
→ src/modules/notes/Notes.ts
|
|
131
131
|
The browser reaches a defined module through its generated client in src/generated and imports no server code.
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
The browser imports `Notes` from `#generated/modules/notes/
|
|
134
|
+
The browser imports `Notes` from `#generated/modules/notes/Notes.ts` instead.
|
|
135
135
|
|
|
136
136
|
### The generated file
|
|
137
137
|
|
|
138
|
-
For the module above, the file starts with a line saying it is generated from `src/modules/notes/
|
|
138
|
+
For the module above, the file starts with a line saying it is generated from `src/modules/notes/Notes.ts`, must not be edited and is not committed. It exports the module's wire, named after the module's `name`, the browser's contract under the module's own export name, built by `clientContract`, and a closing `ClientMatchesModule` assertion:
|
|
139
139
|
|
|
140
140
|
```ts
|
|
141
141
|
export const notesWire = {
|
package/dist/files.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE1D,eAAO,MAAM,aAAa,6HAMxB,CAAC;
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE1D,eAAO,MAAM,aAAa,6HAMxB,CAAC;AAIH,eAAO,MAAM,eAAe,sIAW1B,CAAC"}
|
package/dist/files.js
CHANGED
|
@@ -3,13 +3,16 @@ export const readIfPresent = Effect.fn("Build.readIfPresent")(function* (file) {
|
|
|
3
3
|
const fs = yield* FileSystem.FileSystem;
|
|
4
4
|
return yield* fs.readFileString(file).pipe(Effect.map(Option.some), Effect.catchReason("PlatformError", "NotFound", () => Effect.succeed(Option.none())));
|
|
5
5
|
});
|
|
6
|
-
// A reader never sees half a file: the text goes to a fresh file beside the target, which then replaces it in one rename.
|
|
6
|
+
// A reader never sees half a file: the text goes to a fresh file beside the target, which then replaces it in one rename. The
|
|
7
|
+
// draft lives in a temporary folder of its own, removed when the write ends however it ends.
|
|
7
8
|
export const writeAtomically = Effect.fn("Build.writeAtomically")(function* (file, text) {
|
|
8
9
|
const fs = yield* FileSystem.FileSystem;
|
|
9
10
|
const path = yield* Path.Path;
|
|
10
11
|
yield* fs.makeDirectory(path.dirname(file), { recursive: true });
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
yield* Effect.scoped(Effect.gen(function* () {
|
|
13
|
+
const draft = yield* fs.makeTempFileScoped({ directory: path.dirname(file), prefix: `.${path.basename(file)}.` });
|
|
14
|
+
yield* fs.writeFileString(draft, text);
|
|
15
|
+
yield* fs.rename(draft, file);
|
|
16
|
+
}));
|
|
14
17
|
});
|
|
15
18
|
//# sourceMappingURL=files.js.map
|
package/dist/files.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE1D,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAY;IACpF,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CACzC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EACvB,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAU,CAAC,CAAC,CAC5F,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE1D,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAY;IACpF,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CACzC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EACvB,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAU,CAAC,CAAC,CAC5F,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,8HAA8H;AAC9H,6FAA6F;AAC7F,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAY,EAAE,IAAY;IACtG,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAC9B,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAClH,KAAK,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACvC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CACF,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/build",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "An application's build setup: its Vite and Vitest configuration, and the generated wire and browser contract of each defined module",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/build#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@shivaedev/heavy-lock": "0.11.2",
|
|
48
|
-
"@shivaedev/quality": "0.
|
|
48
|
+
"@shivaedev/quality": "0.78.0",
|
|
49
49
|
"typescript": "npm:@typescript/typescript6@6.0.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@shivaedev/changes": "0.12.0",
|
|
55
55
|
"@shivaedev/contract": "0.44.0",
|
|
56
56
|
"@shivaedev/errors": "0.12.0",
|
|
57
|
-
"@shivaedev/test-story": "0.47.
|
|
57
|
+
"@shivaedev/test-story": "0.47.1",
|
|
58
58
|
"@types/node": "24.19.2",
|
|
59
59
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
60
60
|
"effect": "4.1.2",
|
package/src/files.ts
CHANGED
|
@@ -8,12 +8,17 @@ export const readIfPresent = Effect.fn("Build.readIfPresent")(function* (file: s
|
|
|
8
8
|
);
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
// A reader never sees half a file: the text goes to a fresh file beside the target, which then replaces it in one rename.
|
|
11
|
+
// A reader never sees half a file: the text goes to a fresh file beside the target, which then replaces it in one rename. The
|
|
12
|
+
// draft lives in a temporary folder of its own, removed when the write ends however it ends.
|
|
12
13
|
export const writeAtomically = Effect.fn("Build.writeAtomically")(function* (file: string, text: string) {
|
|
13
14
|
const fs = yield* FileSystem.FileSystem;
|
|
14
15
|
const path = yield* Path.Path;
|
|
15
16
|
yield* fs.makeDirectory(path.dirname(file), { recursive: true });
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
yield* Effect.scoped(
|
|
18
|
+
Effect.gen(function* () {
|
|
19
|
+
const draft = yield* fs.makeTempFileScoped({ directory: path.dirname(file), prefix: `.${path.basename(file)}.` });
|
|
20
|
+
yield* fs.writeFileString(draft, text);
|
|
21
|
+
yield* fs.rename(draft, file);
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
19
24
|
});
|