create-nextly-app 0.0.2-alpha.42 → 0.0.2-alpha.44

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 (58) hide show
  1. package/dist/cli.cjs +1 -1
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.mjs +1 -1
  4. package/dist/cli.mjs.map +1 -1
  5. package/package.json +4 -4
  6. package/templates/base/.env.example +16 -0
  7. package/templates/base/README.md +30 -0
  8. package/templates/base/eslint.config.mjs +18 -0
  9. package/templates/base/next.config.ts +15 -0
  10. package/templates/base/postcss.config.mjs +7 -0
  11. package/templates/base/public/file.svg +1 -0
  12. package/templates/base/public/globe.svg +1 -0
  13. package/templates/base/public/next.svg +1 -0
  14. package/templates/base/public/vercel.svg +1 -0
  15. package/templates/base/public/window.svg +1 -0
  16. package/templates/base/src/app/admin/[[...params]]/layout.tsx +20 -0
  17. package/templates/base/src/app/admin/[[...params]]/page.tsx +18 -0
  18. package/templates/base/src/app/admin/api/[[...params]]/route.ts +12 -0
  19. package/templates/base/src/app/admin/api/media/[[...path]]/route.ts +26 -0
  20. package/templates/base/src/app/api/health/route.ts +7 -0
  21. package/templates/base/src/app/api/media/[[...path]]/route.ts +34 -0
  22. package/templates/base/src/app/favicon.ico +0 -0
  23. package/templates/base/src/app/globals.css +55 -0
  24. package/templates/base/src/app/layout.tsx +43 -0
  25. package/templates/base/src/app/page.tsx +65 -0
  26. package/templates/base/src/types/generated/.gitkeep +0 -0
  27. package/templates/base/src/types/generated/nextly-types.ts +12 -0
  28. package/templates/base/tsconfig.json +36 -0
  29. package/templates/blank/.env.example +8 -0
  30. package/templates/blank/README.md +63 -0
  31. package/templates/blank/nextly.config.ts +14 -0
  32. package/templates/blank/src/app/(frontend)/components/README.md +10 -0
  33. package/templates/blank/src/app/(frontend)/components/ThemeToggle.tsx +113 -0
  34. package/templates/blank/src/app/(frontend)/page.tsx +176 -0
  35. package/templates/blank/src/app/globals.css +79 -0
  36. package/templates/blank/src/app/layout.tsx +46 -0
  37. package/templates/blank/template.json +14 -0
  38. package/templates/plugin/README.md +44 -0
  39. package/templates/plugin/dev/.env.example +8 -0
  40. package/templates/plugin/dev/instrumentation.ts +10 -0
  41. package/templates/plugin/dev/next.config.ts +30 -0
  42. package/templates/plugin/dev/nextly.config.ts +17 -0
  43. package/templates/plugin/dev/src/app/admin/[[...params]]/page.tsx +9 -0
  44. package/templates/plugin/dev/src/app/admin/api/[[...params]]/route.ts +19 -0
  45. package/templates/plugin/dev/src/app/layout.tsx +13 -0
  46. package/templates/plugin/dev/tsconfig.json +22 -0
  47. package/templates/plugin/eslint.config.mjs +8 -0
  48. package/templates/plugin/src/admin/SettingsPage.tsx +13 -0
  49. package/templates/plugin/src/admin/index.ts +21 -0
  50. package/templates/plugin/src/collections/example.ts +13 -0
  51. package/templates/plugin/src/index.ts +6 -0
  52. package/templates/plugin/src/plugin.test.ts +29 -0
  53. package/templates/plugin/src/plugin.ts +48 -0
  54. package/templates/plugin/src/types.ts +17 -0
  55. package/templates/plugin/template.json +14 -0
  56. package/templates/plugin/tsconfig.json +18 -0
  57. package/templates/plugin/tsup.config.ts +22 -0
  58. package/templates/plugin/vitest.config.ts +8 -0
@@ -0,0 +1,13 @@
1
+ import { defineCollection, text, textarea } from "nextly/config";
2
+
3
+ /**
4
+ * An example plugin-owned collection. Replace or remove it with your own.
5
+ * Plugin collections are merged into the host schema automatically (D3/D12)
6
+ * and get a real table on `nextly migrate` / boot.
7
+ */
8
+ export const Examples = defineCollection({
9
+ slug: "examples",
10
+ labels: { singular: "Example", plural: "Examples" },
11
+ fields: [text({ name: "title", required: true }), textarea({ name: "body" })],
12
+ admin: { useAsTitle: "title" },
13
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * {{pluginName}} — public entry. The default `.` export is React-free
3
+ * (Node-safe). Admin React components live on the `./admin` subpath.
4
+ */
5
+ export { myPlugin } from "./plugin";
6
+ export type { MyPluginOptions } from "./types";
@@ -0,0 +1,29 @@
1
+ import { createTestNextly } from "@nextlyhq/plugin-sdk/testing";
2
+ import { afterEach, beforeEach, expect, it } from "vitest";
3
+
4
+ import { myPlugin } from "./index";
5
+
6
+ let t: Awaited<ReturnType<typeof createTestNextly>>;
7
+
8
+ beforeEach(async () => {
9
+ const plugin = myPlugin();
10
+ t = await createTestNextly({
11
+ plugins: [plugin],
12
+ // Pass the plugin's collections so the harness creates their SQLite tables.
13
+ collections: plugin.contributes?.collections,
14
+ });
15
+ });
16
+
17
+ afterEach(async () => {
18
+ await t.destroy();
19
+ });
20
+
21
+ it("boots and exposes the plugin's example collection (real table)", async () => {
22
+ // Creating an entry proves the contributed collection got a real table and
23
+ // the plugin's lifecycle ran. Replace with assertions for your own behavior.
24
+ const created = await t.nextly.create("examples", { title: "First example" });
25
+ expect(created.item.id).toBeDefined();
26
+
27
+ const fetched = await t.nextly.findById("examples", created.item.id);
28
+ expect(fetched?.title).toBe("First example");
29
+ });
@@ -0,0 +1,48 @@
1
+ import { definePlugin } from "@nextlyhq/plugin-sdk";
2
+
3
+ import { Examples } from "./collections/example";
4
+ import type { MyPluginOptions } from "./types";
5
+
6
+ /**
7
+ * Your plugin factory. Call it in a host app's `defineConfig({ plugins: [...] })`.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { myPlugin } from "{{pluginName}}";
12
+ * export default defineConfig({ plugins: [myPlugin({ greeting: "Hi" })] });
13
+ * ```
14
+ */
15
+ export const myPlugin = (opts: MyPluginOptions = {}) =>
16
+ definePlugin({
17
+ name: "{{pluginName}}",
18
+ version: "0.1.0",
19
+ nextly: "{{nextlyRange}}",
20
+ enabled: opts.enabled,
21
+ contributes: {
22
+ collections: [Examples],
23
+ permissions: [
24
+ { action: "manage", resource: "examples", label: "Manage Examples" },
25
+ ],
26
+ admin: {
27
+ menu: [
28
+ {
29
+ label: "Examples",
30
+ to: "/admin/collections/examples",
31
+ icon: "Sparkles",
32
+ },
33
+ ],
34
+ settings: { component: "{{pluginName}}/admin#SettingsPage" },
35
+ },
36
+ },
37
+ init(ctx) {
38
+ const greeting = opts.greeting ?? "Hello";
39
+ // Resolve your own slug via ctx.self so this keeps working if the host
40
+ // renames the collection (D54). React to the post-commit create event.
41
+ ctx.events.on(`collection.${ctx.self.collections.examples}.created`, () =>
42
+ ctx.logger.info(`${greeting} from {{pluginName}} — example created`)
43
+ );
44
+ },
45
+ destroy() {
46
+ // Clean up here (subscriptions are auto-dropped on registry reset).
47
+ },
48
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Options accepted by your plugin factory. These are JSDoc-documented so editors
3
+ * surface them at the call site (D44).
4
+ */
5
+ export interface MyPluginOptions {
6
+ /**
7
+ * Greeting prefix used by the example collection's `afterCreate` hook.
8
+ * @default "Hello"
9
+ */
10
+ greeting?: string;
11
+
12
+ /**
13
+ * Disable the plugin's behavior (init/hooks/events/routes/admin) while still
14
+ * applying its schema contributions. Default `true`.
15
+ */
16
+ enabled?: boolean;
17
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "plugin",
3
+ "label": "Plugin",
4
+ "description": "Build a reusable Nextly plugin (publishable npm package)",
5
+ "hint": "Plugin package + embedded /dev playground; no schema approach",
6
+ "approaches": [],
7
+ "defaultApproach": null,
8
+ "collections": [],
9
+ "singles": [],
10
+ "hasDemoData": false,
11
+ "hasFrontendPages": false,
12
+ "recommendedDatabase": "sqlite",
13
+ "release": "alpha"
14
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "noEmit": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "verbatimModuleSyntax": false
15
+ },
16
+ "include": ["src"],
17
+ "exclude": ["node_modules", "dist", "dev"]
18
+ }
@@ -0,0 +1,22 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ // Builds the publishable plugin. `dev/` is NOT an entry — it never ships.
4
+ // nextly / admin / react are peers, kept external.
5
+ export default defineConfig({
6
+ entry: ["src/index.ts", "src/admin/index.ts"],
7
+ format: ["esm"],
8
+ dts: true,
9
+ clean: true,
10
+ sourcemap: true,
11
+ treeshake: true,
12
+ external: [
13
+ "nextly",
14
+ "@nextlyhq/admin",
15
+ "@nextlyhq/plugin-sdk",
16
+ "react",
17
+ "react-dom",
18
+ ],
19
+ outExtension() {
20
+ return { js: ".mjs" };
21
+ },
22
+ });
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["src/**/*.test.ts"],
7
+ },
8
+ });