@shivaedev/create-app 0.37.0 → 0.38.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/CHANGELOG.md +42 -0
- package/README.md +19 -0
- package/dist/addResource.d.ts +4 -0
- package/dist/addResource.d.ts.map +1 -0
- package/dist/addResource.js +45 -0
- package/dist/addResource.js.map +1 -0
- package/dist/cli.js +312 -77
- package/dist/packTemplate.js +1 -1
- package/dist/packTemplate.js.map +1 -1
- package/dist/resource/contract.d.ts +3 -0
- package/dist/resource/contract.d.ts.map +1 -0
- package/dist/resource/contract.js +37 -0
- package/dist/resource/contract.js.map +1 -0
- package/dist/resource/files.d.ts +5 -0
- package/dist/resource/files.d.ts.map +1 -0
- package/dist/resource/files.js +18 -0
- package/dist/resource/files.js.map +1 -0
- package/dist/resource/kit.d.ts +4 -0
- package/dist/resource/kit.d.ts.map +1 -0
- package/dist/resource/kit.js +107 -0
- package/dist/resource/kit.js.map +1 -0
- package/dist/resource/names.d.ts +10 -0
- package/dist/resource/names.d.ts.map +1 -0
- package/dist/resource/names.js +11 -0
- package/dist/resource/names.js.map +1 -0
- package/dist/resource/persistence.d.ts +5 -0
- package/dist/resource/persistence.d.ts.map +1 -0
- package/dist/resource/persistence.js +64 -0
- package/dist/resource/persistence.js.map +1 -0
- package/dist/resource/registration.d.ts +4 -0
- package/dist/resource/registration.d.ts.map +1 -0
- package/dist/resource/registration.js +46 -0
- package/dist/resource/registration.js.map +1 -0
- package/dist/template.d.ts.map +1 -1
- package/dist/template.js +11 -3
- package/dist/template.js.map +1 -1
- package/package.json +4 -4
- package/src/addResource.ts +45 -0
- package/src/cli.ts +9 -2
- package/src/packTemplate.ts +1 -1
- package/src/resource/contract.ts +38 -0
- package/src/resource/files.ts +19 -0
- package/src/resource/kit.ts +109 -0
- package/src/resource/names.ts +13 -0
- package/src/resource/persistence.ts +67 -0
- package/src/resource/registration.ts +48 -0
- package/src/template.ts +15 -3
- package/template.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.38.0 - 2026-11-03
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Generated apps let client modules declare optional menu entries, overlays and footer content beside their routes. The shared shell renders each slot in module registration order; modules without slots keep their existing output.
|
|
8
|
+
- Add `create-app resource <name>` to scaffold an authenticated resource's contract, service, repository, numbered PostgreSQL migration, client and story kit in a generated app, with one server module registration. Existing destination files are named and preserved; admin pages and jobs remain optional.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Generated applications provide identity's user directory for admin user lists, pagination and role changes.
|
|
13
|
+
- Generated apps use identity's Better Auth client adapters and pass their Effects to React's atom helpers.
|
|
14
|
+
- Generated apps compose server admin handlers and the Jobs inventory from the server feature list; browser registrations retain only page declarations, queue schemas and client bindings.
|
|
15
|
+
- Generated Railway configurations compose the deploy package for web migrations, proxy settings and worker draining. The generated README lists all required shared variables, including production email settings.
|
|
16
|
+
- Generated apps run lint, typecheck and tests through the shared heavy lock, and rerun failed tests in a fresh process by default. Test reports stay out of Git and generated templates.
|
|
17
|
+
- Generated apps assert job results through application responses and clone a database template prepared by the production initializer. Deployment and backfill stories select an empty database with a trait.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Generated apps receive the current story-testing guidance and exercise email delivery failures through the real mailer and a refusing Resend HTTP endpoint.
|
|
22
|
+
- Generate starter apps with the new admin view imports and Tailwind source paths.
|
|
23
|
+
- Generated apps compose module bindings through contract and pass the rendering registry into every client registration, including the signed-out router.
|
|
24
|
+
- Supply the Crypto layer in generated applications' standalone migration entry point.
|
|
25
|
+
- Generated apps adapt the default module factory to the session connection callback. The callback's registry argument no longer replaces the factory's optional registrations list, so signed-in and anonymous screens render without the `Not a valid effect: ~effect/reactivity/AtomRegistry` failure. Existing apps can apply the template update or change the default connection in `SessionApp` to `(session) => clientModules(session)`.
|
|
26
|
+
- The local notes scenario allows the host’s normal 30-second session revalidation period and checks the current sign-in screen after sign-out.
|
|
27
|
+
- Generated minimal apps remove the notes module from the shared host and worker list without retaining a separate worker registry. Updating an older minimal app removes its unmodified worker registry when workers move into application modules.
|
|
28
|
+
- Generated notes test hosts supply the authenticated viewer alongside identity and session data so native contract reads use the fixture's session.
|
|
29
|
+
- Generate the foundation migration loader with Effect's Path service so new apps pass adapter import checks and their initial Quality hook.
|
|
30
|
+
- Generated starters pass the redacted auth email URL directly to their email queue, preserving redaction until the mailer renders it.
|
|
31
|
+
- Generated apps rely on identity's scoped auth mount for startup readiness, including admin creation and session fixtures, without an application-owned readiness adapter.
|
|
32
|
+
- Generate apps with the jobs factory imported from its adapter path so they compile with the scoped jobs engine.
|
|
33
|
+
- Generated apps include the rate-limit store migration so authentication emails use the shared PostgreSQL window.
|
|
34
|
+
- Generated apps serve public assets and authorized admin documents with the server's shared cache and security headers.
|
|
35
|
+
- Generated starter Users screen stories exercise the app's real PostgreSQL role management and permission enforcement instead of a replacement backend.
|
|
36
|
+
- Generate application stories with the test-story adapter imports so new applications pass their initial quality gate.
|
|
37
|
+
- Resolve application aliases through package imports so generated apps do not redirect a dependency’s private imports into application files.
|
|
38
|
+
|
|
39
|
+
### Breaking
|
|
40
|
+
|
|
41
|
+
- Generated app client registrations and custom connection callbacks return construction Effects. Wrap existing synchronous registration values in `Effect.succeed`, or read `AtomRegistry.AtomRegistry` in the Effect for session-scoped bindings. Return `clientModules(session, registrationEffects)` from custom connections; `SessionApp` provides the rendering registry.
|
|
42
|
+
- Generates the notes browser scenario in full apps under `tooling/notes/browser-check` (minimal apps omit it) and exposes it as `browser-check:live-notes`. After applying a template update, replace `pnpm browser-check --live-notes` with `pnpm browser-check:live-notes`; `--url` and the existing credential variables still apply.
|
|
43
|
+
- Generated apps import role declarations from identity. Update customized starter role declarations to import `AssignRoles` from `@shivaedev/identity/roles.ts` instead of `@shivaedev/access/roles.ts`.
|
|
44
|
+
|
|
3
45
|
## 0.37.0 - 2026-11-02
|
|
4
46
|
|
|
5
47
|
### Added
|
package/README.md
CHANGED
|
@@ -50,6 +50,23 @@ Run `pnpm run setup` after cloning the generated repository to install dependenc
|
|
|
50
50
|
|
|
51
51
|
The app selects `story-testing` from `@shivaedev/skills`. Setup syncs the installed instructions to `.agents/skills/story-testing/`, and `AGENTS.md` links to that local copy. `pnpm lint` rejects edits to managed skills. After changing the skills dependency, run `pnpm skills:sync` and commit the copies and manifest.
|
|
52
52
|
|
|
53
|
+
### Add a resource
|
|
54
|
+
|
|
55
|
+
From the generated app directory, run:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
pnpm dlx @shivaedev/create-app resource bookmarks
|
|
59
|
+
pnpm format
|
|
60
|
+
pnpm migrate
|
|
61
|
+
pnpm test src/modules/bookmarks/server/lifecycle.spec.ts
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The command creates a resource module with an authenticated list query and create command, an account-owned PostgreSQL table, a service, a repository, a bound client and a story kit. Its generated stories exercise creation, persistence, private lists and anonymous refusals through the real application host. Both full and minimal apps accept resources; the migration takes the next number across the app's migration folders.
|
|
65
|
+
|
|
66
|
+
The resource registers once in the server application's `modules` list in `src/server/modules.ts`. The command expects the starter's `const modules = [...] as const;` declaration and refuses an unsupported list before writing. Existing destination files are named and left intact. Resource names use lowercase letters and digits with optional hyphens; `reading-lists` produces a `reading_lists` table and a `ReadingListsContract` contract.
|
|
67
|
+
|
|
68
|
+
The generated module has no admin pages or jobs. Add those fields to its server registration when needed. Its browser-safe client is available from `src/modules/bookmarks/client/make.ts`; use it in your own route and screen, following the [resource guide](https://github.com/ShivaeDev/platform/blob/main/docs/framework/add-a-feature.md).
|
|
69
|
+
|
|
53
70
|
### Take starter updates
|
|
54
71
|
|
|
55
72
|
Run `pnpm dlx @shivaedev/create-app@latest update` in a generated app with a clean app directory in Git to take later starter changes. Apps inside an enclosing repository receive the changes within their own directory; sibling files and unrelated staged changes stay untouched. Only the app directory must be clean. A nonempty starter delta that applies no changes fails without advancing `.create-app.json`. The command reads `.create-app.json`, downloads the recorded generator’s starter and uses Git’s three-way merge to replay its changes against the current starter; app edits survive, deleted files stay deleted, and conflicts are listed and left for you to resolve. Once the starter changes apply, including a merge with conflicts, `.create-app.json` records the current generator version. The command runs `pnpm install` and the app’s `pnpm run typecheck`, lists every non-ignored file with conflict markers and any unresolved Git conflicts, and exits nonzero while those or either check’s failures remain. Resolve the reported problems and rerun install and typecheck before committing. If pnpm reports a trust downgrade, the command preserves the rejected package and version and gives `pnpm update --depth Infinity` to re-resolve transitive dependencies under the existing trust policy; an exact manifest or catalog pin must first be changed to a trusted version. An update adds the admin Users registration and route to an app that lacks them, and lists conflicts where the app customized those parts.
|
|
@@ -71,3 +88,5 @@ const template = packTemplate("/path/to/starter", "/path/to/template.json");
|
|
|
71
88
|
### Requirements
|
|
72
89
|
|
|
73
90
|
Use Node 24 or newer and pnpm. See the [framework quickstart](https://github.com/ShivaeDev/platform/blob/main/docs/framework/quickstart.md) for the starter's application and deployment workflow.
|
|
91
|
+
|
|
92
|
+
The [packed starter check](https://github.com/ShivaeDev/platform/blob/main/examples/starter/README.md) runs package adoption proofs inside its existing generated app. Add a fixture folder and its stories to that shared check; packages do not add adoption CI jobs or separate generated-app installs.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Effect, FileSystem, Path } from "effect";
|
|
2
|
+
import { CreateAppError } from "#CreateAppError.ts";
|
|
3
|
+
export declare const addResource: (folder: string, name: string) => Effect.Effect<undefined, CreateAppError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path>;
|
|
4
|
+
//# sourceMappingURL=addResource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addResource.d.ts","sourceRoot":"","sources":["../src/addResource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKpD,eAAO,MAAM,WAAW,8JAqCtB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Console, Effect, FileSystem, Path } from "effect";
|
|
2
|
+
import { MIGRATION_FILE_PATTERN } from "@shivaedev/sql/migrationConvention.ts";
|
|
3
|
+
import { CreateAppError } from "#CreateAppError.ts";
|
|
4
|
+
import { GENERATION_FILE } from "#generation.ts";
|
|
5
|
+
import { resourceFiles } from "#resource/files.ts";
|
|
6
|
+
import { resourceNames } from "#resource/names.ts";
|
|
7
|
+
export const addResource = Effect.fn("CreateApp.addResource")(function* (folder, name) {
|
|
8
|
+
const fs = yield* FileSystem.FileSystem;
|
|
9
|
+
const path = yield* Path.Path;
|
|
10
|
+
const root = path.resolve(folder);
|
|
11
|
+
const names = yield* resourceNames(name);
|
|
12
|
+
if (!(yield* fs.exists(path.join(root, GENERATION_FILE)))) {
|
|
13
|
+
return yield* new CreateAppError({ message: `Run create-app resource from a generated app (${GENERATION_FILE} is missing).` });
|
|
14
|
+
}
|
|
15
|
+
const registry = "src/server/modules.ts";
|
|
16
|
+
const source = yield* fs.readFileString(path.join(root, registry));
|
|
17
|
+
const declaration = /const modules = \[[\s\S]*?\] as const;/gu;
|
|
18
|
+
if ([...source.matchAll(declaration)].length !== 1) {
|
|
19
|
+
return yield* new CreateAppError({ message: `Cannot register ${name}: ${registry} must declare const modules = [...] as const;` });
|
|
20
|
+
}
|
|
21
|
+
const files = yield* fs.readDirectory(path.join(root, "src"), { recursive: true });
|
|
22
|
+
const ids = files
|
|
23
|
+
.filter((file) => path.basename(path.dirname(file)) === "migrations" && MIGRATION_FILE_PATTERN.test(path.basename(file)))
|
|
24
|
+
.map((file) => Number(path.basename(file).slice(0, 4)));
|
|
25
|
+
const migration = String(Math.max(0, ...ids) + 1).padStart(4, "0");
|
|
26
|
+
const generated = resourceFiles(names, migration);
|
|
27
|
+
const existing = [];
|
|
28
|
+
for (const file of Object.keys(generated)) {
|
|
29
|
+
if (yield* fs.exists(path.join(root, file))) {
|
|
30
|
+
existing.push(file);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (existing.length > 0) {
|
|
34
|
+
return yield* new CreateAppError({ message: `Refusing to overwrite existing files:\n${existing.join("\n")}` });
|
|
35
|
+
}
|
|
36
|
+
for (const [file, content] of Object.entries(generated)) {
|
|
37
|
+
yield* fs.makeDirectory(path.dirname(path.join(root, file)), { recursive: true });
|
|
38
|
+
yield* fs.writeFileString(path.join(root, file), content, { flag: "wx", mode: 0o644 });
|
|
39
|
+
}
|
|
40
|
+
const registration = `${names.camel}Registration`;
|
|
41
|
+
const imported = `import { ${registration} } from "#modules/${name}/server/registration.ts";\n`;
|
|
42
|
+
yield* fs.writeFileString(path.join(root, registry), imported + source.replace("const modules = [", `const modules = [${registration}, `));
|
|
43
|
+
yield* Console.log(`Added ${name}.\n\nNext steps:\n pnpm format\n pnpm migrate\n pnpm test src/modules/${name}/server/lifecycle.spec.ts`);
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=addResource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addResource.js","sourceRoot":"","sources":["../src/addResource.ts"],"names":[],"mappings":"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"}
|