@thinhnguyencth1204/nextcli 0.7.0 → 0.8.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.
Files changed (33) hide show
  1. package/README.md +12 -2
  2. package/dist/cli.js +3 -3
  3. package/package.json +5 -3
  4. package/templates/features/supabase/src/lib/supabase/rich-text-image-sync.ts +28 -0
  5. package/templates/next-base/PROJECT_STRUCTURE.md +29 -18
  6. package/templates/next-base/bun.lock +59 -414
  7. package/templates/next-base/next-env.d.ts +1 -1
  8. package/templates/next-base/package.json +5 -0
  9. package/templates/next-base/src/app/blog-demo/page.tsx +9 -0
  10. package/templates/next-base/src/app/globals.css +57 -0
  11. package/templates/next-base/src/components/rich-text/adapters/textarea-field.tsx +50 -0
  12. package/templates/next-base/src/components/rich-text/client-only.tsx +23 -0
  13. package/templates/next-base/src/components/rich-text/editor-field.tsx +62 -0
  14. package/templates/next-base/src/components/rich-text/examples/blog-rich-text-demo.tsx +218 -0
  15. package/templates/next-base/src/components/rich-text/index.ts +11 -0
  16. package/templates/next-base/src/components/rich-text/lexical/extension.ts +37 -0
  17. package/templates/next-base/src/components/rich-text/lexical/nodes/image-node.tsx +187 -0
  18. package/templates/next-base/src/components/rich-text/lexical/plugins/image-plugin.tsx +40 -0
  19. package/templates/next-base/src/components/rich-text/lexical/plugins/initial-state-plugin.tsx +26 -0
  20. package/templates/next-base/src/components/rich-text/lexical/plugins/on-change-plugin.tsx +26 -0
  21. package/templates/next-base/src/components/rich-text/lexical/plugins/toolbar-plugin.tsx +190 -0
  22. package/templates/next-base/src/components/rich-text/lexical/rich-text-editor.tsx +121 -0
  23. package/templates/next-base/src/components/rich-text/lexical/theme.ts +18 -0
  24. package/templates/next-base/src/components/rich-text/rich-text-renderer.tsx +72 -0
  25. package/templates/next-base/src/components/rich-text/types.ts +60 -0
  26. package/templates/next-base/src/hooks/index.ts +1 -1
  27. package/templates/next-base/src/lib/rich-text/default-image-removal.ts +10 -0
  28. package/templates/next-base/src/lib/rich-text/image-urls.ts +41 -0
  29. package/templates/next-base/src/lib/rich-text/index.ts +12 -0
  30. package/templates/next-base/src/lib/rich-text/supabase-url.ts +67 -0
  31. package/templates/next-base/src/lib/rich-text/sync-removed-images.ts +48 -0
  32. package/templates/next-base/src/types/index.ts +0 -2
  33. package/templates/next-base/tsconfig.tsbuildinfo +1 -0
package/README.md CHANGED
@@ -32,9 +32,18 @@ This command is fully interactive:
32
32
  - normalizes project directory name into a safe project slug for generated `package.json` and env placeholders
33
33
  - ships `SETUP.md` and `PROJECT_STRUCTURE.md` in the generated project root
34
34
 
35
- **Default output is minimal:** Next.js shell, branding, theme, and UI primitives only. Database, auth, dashboard, and other stacks are added only when selected.
35
+ **Default output is minimal:** Next.js shell, branding, theme, UI primitives, and Lexical rich text adapters only. Database, auth, dashboard, and other stacks are added only when selected.
36
36
 
37
- ## Optional modules
37
+ ## Rich text (base)
38
+
39
+ All generated projects include Lexical rich text building blocks:
40
+
41
+ - `EditorField` — swappable `textarea` or `lexical` adapter for forms
42
+ - `RichTextRenderer` — read-only playback of Lexical JSON from API data
43
+ - Toolbar: bold/italic/underline, emoji picker, image URL insertion
44
+ - Demo page: `/blog-demo`
45
+
46
+ Lexical content is stored as JSON (`SerializedEditorState`). With the `supabase` module, removed Supabase-managed image URLs trigger storage cleanup via `syncRemovedSupabaseRichTextImages`.
38
47
 
39
48
  Available during `create` and `add module`:
40
49
 
@@ -174,6 +183,7 @@ Optional flags:
174
183
  - shadcn-style shared UI folder (base)
175
184
  - Zod validation (base)
176
185
  - Sonner notifications (base)
186
+ - Lexical rich text editor + renderer (base)
177
187
  - Optional: chat, supabase-realtime, seo, email
178
188
 
179
189
  ## Template structure
package/dist/cli.js CHANGED
@@ -811,7 +811,7 @@ import { readdir as readdir3, readFile as readFile6, writeFile as writeFile6 } f
811
811
  import path7 from "path";
812
812
  import { readdir as readdir2, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
813
813
  var defaultManifest = {
814
- cli: "0.7.0",
814
+ cli: "0.8.0",
815
815
  defaultLocale: "vi",
816
816
  locales: [],
817
817
  namespaces: [],
@@ -2113,7 +2113,7 @@ function registerAddCommand(program2) {
2113
2113
  // src/commands/create.ts
2114
2114
  import { spawn as spawn2 } from "child_process";
2115
2115
  import path11 from "path";
2116
- var CLI_VERSION = "0.7.0";
2116
+ var CLI_VERSION = "0.8.0";
2117
2117
  async function runInstall(packageManager, cwd) {
2118
2118
  const installArgsMap = {
2119
2119
  npm: ["install"],
@@ -2494,7 +2494,7 @@ var NexTCLICommand = class _NexTCLICommand extends Command {
2494
2494
 
2495
2495
  // src/cli.ts
2496
2496
  var program = new NexTCLICommand();
2497
- program.name("nextcli").description("Scaffold outsource-ready Next.js projects").version("0.7.0");
2497
+ program.name("nextcli").description("Scaffold outsource-ready Next.js projects").version("0.8.0");
2498
2498
  registerCreateCommand(program);
2499
2499
  registerAddCommand(program);
2500
2500
  registerMigrateCommand(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinhnguyencth1204/nextcli",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "CLI scaffolder for outsourced Next.js projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,8 +15,9 @@
15
15
  "build": "tsup",
16
16
  "dev": "tsup --watch",
17
17
  "typecheck": "tsc --noEmit",
18
- "test": "bun test src/core/add-feature.test.ts",
19
- "test:add-feature": "bun run build && bun test src/core/add-feature.test.ts",
18
+ "test": "bun test tests",
19
+ "test:add-feature": "bun run build && bun test tests/core",
20
+ "test:rich-text": "bun test tests/templates/next-base",
20
21
  "smoke": "node dist/cli.js --help",
21
22
  "smoke:full": "bun run build && bun run test && bun run scripts/pre-publish-smoke.ts",
22
23
  "prepublishOnly": "npm run build"
@@ -40,6 +41,7 @@
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/node": "^22.15.29",
44
+ "lexical": "^0.45.0",
43
45
  "tsup": "^8.1.0",
44
46
  "typescript": "^5.5.4"
45
47
  }
@@ -0,0 +1,28 @@
1
+ import { removeResource } from "@/lib/supabase/storage";
2
+ import {
3
+ isSupabaseManagedImageUrl,
4
+ syncRemovedRichTextImages,
5
+ type RemoveManagedImageFn,
6
+ } from "@/lib/rich-text";
7
+ import type { SerializedEditorState } from "lexical";
8
+
9
+ export const removeSupabaseManagedImage: RemoveManagedImageFn = async (
10
+ _url,
11
+ ref,
12
+ ) => {
13
+ await removeResource(ref.path, ref.bucket);
14
+ };
15
+
16
+ /**
17
+ * Deletes Supabase storage objects for images removed from rich text content.
18
+ * Only URLs belonging to this project's configured Supabase bucket are removed.
19
+ */
20
+ export async function syncRemovedSupabaseRichTextImages(
21
+ previous: SerializedEditorState | null | undefined,
22
+ next: SerializedEditorState | null | undefined,
23
+ ) {
24
+ return syncRemovedRichTextImages(previous, next, {
25
+ isManagedUrl: isSupabaseManagedImageUrl,
26
+ removeManagedImage: removeSupabaseManagedImage,
27
+ });
28
+ }
@@ -17,6 +17,7 @@ Generated by NexTCLI. Folders marked **(module)** appear only when that add-on i
17
17
  | ------------- | --------------------------------------- |
18
18
  | `layout.tsx` | Root layout, metadata from `branding` |
19
19
  | `page.tsx` | Welcome landing page |
20
+ | `blog-demo/` | Rich text create/edit/read demo |
20
21
  | `globals.css` | Design tokens (`nextcli:theme` markers) |
21
22
 
22
23
  ## `src/config/`
@@ -27,27 +28,37 @@ Generated by NexTCLI. Folders marked **(module)** appear only when that add-on i
27
28
 
28
29
  ## `src/components/`
29
30
 
30
- | Path | Purpose |
31
- | ------------------- | ----------------------- |
32
- | `branding/logo.tsx` | Logo + project name |
33
- | `ui/` | shadcn-style primitives |
34
- | `providers/` | Theme provider |
31
+ | Path | Purpose |
32
+ | ------------------- | --------------------------------------- |
33
+ | `branding/logo.tsx` | Logo + project name |
34
+ | `rich-text/` | Lexical editor adapters, renderer, demo |
35
+ | `ui/` | shadcn-style primitives |
36
+ | `providers/` | Theme provider |
37
+
38
+ ## `src/lib/rich-text/` (base)
39
+
40
+ | Path | Purpose |
41
+ | -------------------------- | ---------------------------------------------------- |
42
+ | `image-urls.ts` | Extract image URLs from Lexical JSON |
43
+ | `supabase-url.ts` | Map Supabase public URLs to storage paths |
44
+ | `sync-removed-images.ts` | Lifecycle helper for removed images |
45
+ | `default-image-removal.ts` | No-op remover (swap when `supabase` module is added) |
35
46
 
36
47
  ## Optional modules (via `nextcli add module`)
37
48
 
38
- | Module | Adds |
39
- | ------------------- | ------------------------------------------------------------ |
40
- | `database` | Prisma schema, client, `DATABASE_URL`, db scripts |
41
- | `supabase` | Supabase browser client + Storage helpers |
42
- | `auth` | Better Auth, sign-in pages, user APIs, bootstrap admin |
43
- | `api` | Axios client, API envelope helpers, React Query provider |
44
- | `i18n` | next-intl config, messages, locale switcher |
45
- | `dashboard` | Protected dashboard shell, sidebar, data-table UI |
46
- | `example` | Starter CRUD demo feature + `Example` Prisma model |
47
- | `chat` | Chat routes, hooks, Prisma chat models (+ auto deps) |
48
- | `supabase-realtime` | Realtime channel helpers (+ auto `supabase`) |
49
- | `seo` | robots/sitemap/JSON-LD helpers |
50
- | `email` | `src/lib/email/*`, `src/emails/*` (provider: SMTP or Resend) |
49
+ | Module | Adds |
50
+ | ------------------- | --------------------------------------------------------------------- |
51
+ | `database` | Prisma schema, client, `DATABASE_URL`, db scripts |
52
+ | `supabase` | Supabase browser client + Storage helpers + `rich-text-image-sync.ts` |
53
+ | `auth` | Better Auth, sign-in pages, user APIs, bootstrap admin |
54
+ | `api` | Axios client, API envelope helpers, React Query provider |
55
+ | `i18n` | next-intl config, messages, locale switcher |
56
+ | `dashboard` | Protected dashboard shell, sidebar, data-table UI |
57
+ | `example` | Starter CRUD demo feature + `Example` Prisma model |
58
+ | `chat` | Chat routes, hooks, Prisma chat models (+ auto deps) |
59
+ | `supabase-realtime` | Realtime channel helpers (+ auto `supabase`) |
60
+ | `seo` | robots/sitemap/JSON-LD helpers |
61
+ | `email` | `src/lib/email/*`, `src/emails/*` (provider: SMTP or Resend) |
51
62
 
52
63
  Module **env variables** and where to find them: see `SETUP.md` → **Optional module environment**.
53
64