create-outsystems-astro 0.7.2 → 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 (30) hide show
  1. package/README.md +1 -0
  2. package/bin/cli.js +10 -1
  3. package/package.json +1 -1
  4. package/template/.github/workflows/test.yml +13 -13
  5. package/template/.prettierrc +1 -1
  6. package/template/AGENTS.md +74 -2
  7. package/template/astro.config.mjs +5 -0
  8. package/template/bun.lock +640 -190
  9. package/template/deno.json +1 -17
  10. package/template/deno.lock +889 -461
  11. package/template/eslint.config.mjs +5 -0
  12. package/template/package-lock.json +7593 -3817
  13. package/template/package.json +44 -84
  14. package/template/pnpm-lock.yaml +1602 -733
  15. package/template/src/framework/solid/Demo.tsx +85 -0
  16. package/template/src/framework/solid/Store.tsx +31 -0
  17. package/template/src/images/solid.png +0 -0
  18. package/template/src/pages/multi/store.astro +3 -1
  19. package/template/src/pages/solid/solid-demo.astro +65 -0
  20. package/template/src/stores/framework.ts +1 -0
  21. package/template/test/e2e/solid/solid-demo.spec.ts +42 -0
  22. package/template/test/integration/solid/Demo.test.tsx +90 -0
  23. package/template/vitest.config.ts +12 -0
  24. package/template/yarn.lock +945 -392
  25. /package/template/patches/{@angular+build+21.2.2.patch → @angular+build+21.2.5.patch} +0 -0
  26. /package/template/test/e2e/angular/{angular-counter.spec.ts → angular-demo.spec.ts} +0 -0
  27. /package/template/test/e2e/preact/{preact-counter.spec.ts → preact-demo.spec.ts} +0 -0
  28. /package/template/test/e2e/react/{react-counter.spec.ts → react-demo.spec.ts} +0 -0
  29. /package/template/test/e2e/svelte/{svelte-counter.spec.ts → svelte-demo.spec.ts} +0 -0
  30. /package/template/test/e2e/vue/{vue-counter.spec.ts → vue-demo.spec.ts} +0 -0
@@ -0,0 +1,85 @@
1
+ /** @jsxImportSource solid-js */
2
+ import { useStore } from "@nanostores/solid";
3
+ import { createSignal, type JSX } from "solid-js";
4
+
5
+ import AstroLogo from "../../images/astro.png?url";
6
+ import OutSystemsLogo from "../../images/outsystems.png?url";
7
+ import { Operation, setCounterCount } from "../../lib/setCounterCount";
8
+ import { setupStore } from "../../stores/demo";
9
+
10
+ interface DemoProps {
11
+ children?: JSX.Element;
12
+ header?: JSX.Element;
13
+ initialCount: number;
14
+ showMessage: string;
15
+ }
16
+
17
+ export default function Demo(props: DemoProps) {
18
+ const [count, setCount] = createSignal(props.initialCount);
19
+
20
+ const store = setupStore("solidStore");
21
+ const nanoStoreValue = useStore(store);
22
+
23
+ const add = () => setCount((i) => setCounterCount(i, Operation.Add));
24
+ const subtract = () =>
25
+ setCount((i) => setCounterCount(i, Operation.Subtract));
26
+
27
+ const showParentMessage = () => {
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ const messageFunc = (window as any)[props.showMessage];
30
+ if (typeof messageFunc === "function") {
31
+ messageFunc(count());
32
+ }
33
+ };
34
+
35
+ return (
36
+ <>
37
+ {props.header}
38
+
39
+ <div class="card-grid">
40
+ <div class="card">
41
+ <strong>Solid counter component</strong>
42
+ <div class="card-content">
43
+ Internal counter controls. It keeps state within the component.
44
+ <div class="counter-controls">
45
+ <button onClick={subtract}>-</button>
46
+ <pre>{count()}</pre>
47
+ <button onClick={add}>+</button>
48
+ </div>
49
+ </div>
50
+ The button sends the current count value to a function in the parent
51
+ component.
52
+ <div class="card-content">
53
+ <div>
54
+ <button class="card-btn" onClick={showParentMessage}>
55
+ Send value
56
+ </button>
57
+ </div>
58
+ </div>
59
+ </div>
60
+
61
+ <div class="card">
62
+ <strong>Nano Stores</strong>
63
+ <div class="card-content">
64
+ <div>
65
+ <strong>Value:</strong>
66
+ <div id="nanostore">{nanoStoreValue()}</div>
67
+ </div>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="card">
72
+ <strong>Slot content</strong>
73
+ <div class="card-content">
74
+ <div>{props.children}</div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+
79
+ <div class="counter-logos">
80
+ <img alt="OutSystems logo" src={OutSystemsLogo} />
81
+ <img alt="Astro logo" src={AstroLogo} />
82
+ </div>
83
+ </>
84
+ );
85
+ }
@@ -0,0 +1,31 @@
1
+ /** @jsxImportSource solid-js */
2
+ import { useStore } from "@nanostores/solid";
3
+
4
+ import SolidLogo from "../../images/solid.png?url";
5
+ import { framework } from "../../stores/framework";
6
+
7
+ export default function Store() {
8
+ const selectedFramework = useStore(framework);
9
+
10
+ const setFramework = () => {
11
+ framework.set("Solid");
12
+ };
13
+
14
+ return (
15
+ <div class="card">
16
+ <strong>Solid Store</strong>
17
+ <div class="card-content">
18
+ <img alt="Solid logo" height={150} src={SolidLogo} />
19
+ <div>
20
+ <strong>Value:</strong>
21
+ <div id="nanostore">{selectedFramework()}</div>
22
+ </div>
23
+ <div>
24
+ <button class="card-btn" onClick={setFramework}>
25
+ Select React
26
+ </button>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ );
31
+ }
Binary file
@@ -2,6 +2,7 @@
2
2
  import AngularStore from "../../framework/angular/Store.component"
3
3
  import PreactStore from "../../framework/preact/Store";
4
4
  import ReactStore from "../../framework/react/Store";
5
+ import SolidStore from "../../framework/solid/Store";
5
6
  import SvelteStore from "../../framework/svelte/Store.svelte";
6
7
  import VueStore from "../../framework/vue/Store.vue";
7
8
  import styles from "../../styles/index.css?url";
@@ -12,9 +13,10 @@ import styles from "../../styles/index.css?url";
12
13
  </head>
13
14
  <body>
14
15
  <div class="card-grid">
15
- <AngularStore client:visible />
16
+ <AngularStore client:load />
16
17
  <PreactStore client:only="preact" />
17
18
  <ReactStore client:only="react" />
19
+ <SolidStore client:only="solid-js" />
18
20
  <SvelteStore client:only="svelte" />
19
21
  <VueStore client:only="vue" />
20
22
  </div>
@@ -0,0 +1,65 @@
1
+ ---
2
+ import DemoComponent from "../../framework/solid/Demo";
3
+ import styles from "../../styles/index.css?url";
4
+ const initialCount = 5;
5
+ const showMessage = "showMessage";
6
+ ---
7
+ <html lang="en">
8
+ <head>
9
+ <link href={styles} rel="stylesheet" />
10
+ <script>
11
+ import { setupStore } from "../../stores/demo";
12
+ setupStore("solidStore");
13
+ window["showMessage"] = (count) => {
14
+ document.getElementById("counter").textContent = count;
15
+ };
16
+ document.addEventListener("DOMContentLoaded", function () {
17
+ const input = document.getElementById("store");
18
+ input.value = window.Stores["solidStore"].get();
19
+ });
20
+ </script>
21
+ </head>
22
+ <body>
23
+ <div class="counter-title">Astro Page</div>
24
+ <div class="card-grid">
25
+ <div class="card">
26
+ <strong>Counter component</strong>
27
+ <div class="card-content">
28
+ <div style="text-align: center; margin-top: 30px;">
29
+ Counter value:
30
+ <div>
31
+ <span id="counter"></span>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <div class="card">
37
+ <strong>Nano Stores</strong>
38
+ <div class="card-content">
39
+ <div style="text-align: center; margin-top: 30px;">
40
+ <input
41
+ id="store"
42
+ placeholder="Type something..."
43
+ type="text"
44
+ /><button
45
+ class="card-btn"
46
+ onclick="window.Stores['solidStore'].set(document.getElementById('store').value)"
47
+ >Update Store</button
48
+ >
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <hr />
54
+ <DemoComponent
55
+ client:only="solid-js"
56
+ initialCount={initialCount}
57
+ showMessage={showMessage}
58
+ >
59
+ <div class="counter-title" slot="header">Solid Demo Component</div>
60
+ <div style="text-align: center;">
61
+ <p><em>This is content passed into the component.</em></p>
62
+ </div>
63
+ </DemoComponent>
64
+ </body>
65
+ </html>
@@ -4,6 +4,7 @@ export type CurrentSelectedFramework =
4
4
  | ""
5
5
  | "Preact"
6
6
  | "React"
7
+ | "Solid"
7
8
  | "Svelte"
8
9
  | "Vue";
9
10
 
@@ -0,0 +1,42 @@
1
+ import { expect, test } from "@playwright/test";
2
+
3
+ test.beforeEach(async ({ page }) => {
4
+ await page.goto("/solid/solid-demo");
5
+ });
6
+
7
+ test.describe("Has values", () => {
8
+ test("Should have header", async ({ page }) => {
9
+ await expect(page.getByText("Solid Demo Component")).toBeVisible();
10
+ });
11
+
12
+ test("Should have slot content", async ({ page }) => {
13
+ await expect(
14
+ page.getByText("This is content passed into the component"),
15
+ ).toBeVisible();
16
+ });
17
+ });
18
+
19
+ test.describe("Change counter", () => {
20
+ test("Should increment counter when clicking + button", async ({ page }) => {
21
+ await page.getByRole("button", { name: "+" }).click();
22
+ await expect(page.locator("pre")).toContainText("6");
23
+ });
24
+
25
+ test("Should decrement counter when clicking - button", async ({ page }) => {
26
+ await page.getByRole("button", { name: "-" }).click();
27
+ await expect(page.locator("pre")).toContainText("4");
28
+ });
29
+
30
+ test("Should show message on Send value", async ({ page }) => {
31
+ await page.getByRole("button", { name: "Send value" }).click();
32
+ await expect(page.locator("span#counter")).toContainText("5");
33
+ });
34
+ });
35
+
36
+ test.describe("Update Nano Store", () => {
37
+ test("Should update Nano Store", async ({ page }) => {
38
+ await page.locator("#store").fill("Updated Value");
39
+ await page.getByRole("button", { name: "Update Store" }).click();
40
+ await expect(page.locator("#nanostore")).toHaveText("Updated Value");
41
+ });
42
+ });
@@ -0,0 +1,90 @@
1
+ /** @jsxImportSource solid-js */
2
+ import { cleanup, fireEvent, render, screen } from "@solidjs/testing-library";
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+
5
+ import Demo from "../../../src/framework/solid/Demo";
6
+
7
+ describe("Demo", () => {
8
+ const defaultProps = {
9
+ children: <div>Test Children</div>,
10
+ header: <h1>Test Header</h1>,
11
+ initialCount: 5,
12
+ showMessage: "mockFunction",
13
+ };
14
+
15
+ let capturedListener: ((val: string) => void) | undefined;
16
+ let storeValue = "Mocked Nano Value";
17
+
18
+ beforeEach(() => {
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ (window as any).mockFunction = vi.fn();
21
+
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ (window as any).Stores = {
24
+ solidStore: {
25
+ get: vi.fn(() => storeValue),
26
+ listen: vi.fn((callback) => {
27
+ capturedListener = callback;
28
+ callback(storeValue);
29
+ return () => {};
30
+ }),
31
+ subscribe: vi.fn((callback) => {
32
+ capturedListener = callback;
33
+ callback(storeValue);
34
+ return () => {};
35
+ }),
36
+ },
37
+ };
38
+ });
39
+
40
+ afterEach(() => {
41
+ cleanup();
42
+ vi.clearAllMocks();
43
+ capturedListener = undefined;
44
+ storeValue = "Mocked Nano Value";
45
+ });
46
+
47
+ it("renders the initial count", () => {
48
+ render(() => <Demo {...defaultProps} />);
49
+ expect(screen.getByText("5")).toBeInTheDocument();
50
+ });
51
+
52
+ it("renders header", () => {
53
+ render(() => <Demo {...defaultProps} />);
54
+ expect(screen.getByText("Test Header")).toBeInTheDocument();
55
+ });
56
+
57
+ it("renders children", () => {
58
+ render(() => <Demo {...defaultProps} />);
59
+ expect(screen.getByText("Test Children")).toBeInTheDocument();
60
+ });
61
+
62
+ it("increments count when add button is clicked", () => {
63
+ render(() => <Demo {...defaultProps} />);
64
+ fireEvent.click(screen.getByRole("button", { name: "+" }));
65
+ expect(screen.getByText("6")).toBeInTheDocument();
66
+ });
67
+
68
+ it("decrements count when subtract button is clicked", () => {
69
+ render(() => <Demo {...defaultProps} />);
70
+ fireEvent.click(screen.getByRole("button", { name: "-" }));
71
+ expect(screen.getByText("4")).toBeInTheDocument();
72
+ });
73
+
74
+ it("calls the show message function", () => {
75
+ render(() => <Demo {...defaultProps} />);
76
+ fireEvent.click(screen.getByRole("button", { name: "Send value" }));
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ expect((window as any).mockFunction).toHaveBeenCalledWith(5);
79
+ });
80
+
81
+ it("updates the component when the nanostore value changes", async () => {
82
+ render(() => <Demo {...defaultProps} />);
83
+ expect(screen.getByText(/Mocked Nano Value/i)).toBeInTheDocument();
84
+
85
+ storeValue = "Updated Nano Value";
86
+ capturedListener?.("Updated Nano Value");
87
+
88
+ expect(await screen.findByText(/Updated Nano Value/i)).toBeInTheDocument();
89
+ });
90
+ });
@@ -4,6 +4,7 @@ import preact from "@preact/preset-vite";
4
4
  import { svelte } from "@sveltejs/vite-plugin-svelte";
5
5
  import react from "@vitejs/plugin-react";
6
6
  import vue from "@vitejs/plugin-vue";
7
+ import solid from "vite-plugin-solid";
7
8
  import { defineConfig } from "vitest/config";
8
9
 
9
10
  export default defineConfig(({ mode }) => ({
@@ -43,6 +44,17 @@ export default defineConfig(({ mode }) => ({
43
44
  setupFiles: ["test/setup-test-env.ts"],
44
45
  },
45
46
  },
47
+ {
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ plugins: [solid() as any],
50
+ test: {
51
+ environment: "happy-dom",
52
+ globals: true,
53
+ include: ["test/integration/solid/**/*.test.tsx"],
54
+ name: "solid",
55
+ setupFiles: ["test/setup-test-env.ts"],
56
+ },
57
+ },
46
58
  {
47
59
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
60
  plugins: [svelte() as any],