@abgov/nx-adsp 13.5.0 → 13.6.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.
Files changed (23) hide show
  1. package/generators.json +6 -0
  2. package/package.json +1 -1
  3. package/src/generators/vue-app/files/AGENTS.md__tmpl__ +35 -0
  4. package/src/generators/vue-app/files/vite.config.ts__tmpl__ +4 -0
  5. package/src/generators/vue-app/vue-app.js +8 -1
  6. package/src/generators/vue-app/vue-app.js.map +1 -1
  7. package/src/generators/vue-app/vue-app.spec.ts +25 -0
  8. package/src/generators/vue-components/files/AGENTS.md__tmpl__ +145 -0
  9. package/src/generators/vue-components/files/src/index.ts__tmpl__ +12 -0
  10. package/src/generators/vue-components/files/src/lib/GoabButton.vue__tmpl__ +16 -0
  11. package/src/generators/vue-components/files/src/lib/GoabCheckbox.vue__tmpl__ +19 -0
  12. package/src/generators/vue-components/files/src/lib/GoabDropdown.vue__tmpl__ +21 -0
  13. package/src/generators/vue-components/files/src/lib/GoabInput.vue__tmpl__ +22 -0
  14. package/src/generators/vue-components/files/src/lib/GoabModal.vue__tmpl__ +33 -0
  15. package/src/generators/vue-components/files/src/lib/GoabRadioGroup.vue__tmpl__ +22 -0
  16. package/src/generators/vue-components/files/src/lib/GoabTextarea.vue__tmpl__ +17 -0
  17. package/src/generators/vue-components/files/src/vue-components.spec.ts__tmpl__ +21 -0
  18. package/src/generators/vue-components/schema.d.ts +2 -0
  19. package/src/generators/vue-components/schema.json +10 -0
  20. package/src/generators/vue-components/vue-components.d.ts +5 -0
  21. package/src/generators/vue-components/vue-components.js +113 -0
  22. package/src/generators/vue-components/vue-components.js.map +1 -0
  23. package/src/generators/vue-components/vue-components.spec.ts +90 -0
package/generators.json CHANGED
@@ -49,6 +49,12 @@
49
49
  "schema": "./src/generators/vue-app/schema.json",
50
50
  "description": "Generator that creates a Vue 3 frontend application using GoA web components."
51
51
  },
52
+ "vue-components": {
53
+ "factory": "./src/generators/vue-components/vue-components",
54
+ "schema": "./src/generators/vue-components/schema.json",
55
+ "description": "Ensures the shared GoA Vue wrapper library (interim). Invoked by vue-app; runnable directly to repair.",
56
+ "hidden": true
57
+ },
52
58
  "mean": {
53
59
  "factory": "./src/generators/mean/mean",
54
60
  "schema": "./src/generators/mean/schema.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-adsp",
3
- "version": "13.5.0",
3
+ "version": "13.6.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for ADSP apps.",
@@ -119,6 +119,41 @@ clashing with native browser events); bind them with Vue's `@` syntax:
119
119
  ```
120
120
 
121
121
  Use `@_click` for buttons and `@_change` for inputs, dropdowns, and checkboxes.
122
+ Note `goa-*` elements do **not** support Vue's `v-model` — you must wire
123
+ `:value` + `@_change` by hand (the event carries the new value on
124
+ `$event.detail.value`, or `.detail.checked` for a checkbox).
125
+
126
+ ### Prefer the `Goab*` wrappers for form controls
127
+
128
+ To avoid that friction (and the temptation to reach for a raw `<input>`, which
129
+ breaks the design system), the workspace has a shared **`<%= goaImportPath %>`**
130
+ library of thin wrappers that add real `v-model` support: `GoabInput`,
131
+ `GoabTextarea`, `GoabDropdown`, `GoabCheckbox`, `GoabRadioGroup`, `GoabButton`,
132
+ `GoabModal`.
133
+
134
+ ```vue
135
+ <script setup lang="ts">
136
+ import { ref } from 'vue';
137
+ import { GoabInput, GoabButton } from '<%= goaImportPath %>';
138
+ const email = ref('');
139
+ </script>
140
+
141
+ <template>
142
+ <GoabInput v-model="email" name="email" type="email" placeholder="you@alberta.ca" />
143
+ <GoabButton type="primary" @click="save">Save</GoabButton>
144
+ </template>
145
+ ```
146
+
147
+ Extra props/events fall through to the underlying `goa-*` element, so anything
148
+ the design system supports still works. For components without a wrapper, use the
149
+ `goa-*` element directly with the manual wiring above. The library is shared
150
+ across every Vue app in this workspace — fix or extend a wrapper once in
151
+ `libs/vue-components` (or run `nx g @abgov/nx-adsp:vue-components` to restore it).
152
+
153
+ > **Interim:** these wrappers are a stopgap until GoA DS ships an official
154
+ > `@abgov/vue-components`. When it lands, delete the `vue-components` lib and
155
+ > repoint imports at that package — the names/props are intended to match, so
156
+ > it's a scope swap.
122
157
 
123
158
  ## Adding a view
124
159
 
@@ -1,6 +1,7 @@
1
1
  /// <reference types='vitest' />
2
2
  import { defineConfig } from 'vite';
3
3
  import vue from '@vitejs/plugin-vue';
4
+ import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
4
5
 
5
6
  export default defineConfig({
6
7
  root: __dirname,
@@ -21,10 +22,13 @@ export default defineConfig({
21
22
  template: {
22
23
  compilerOptions: {
23
24
  // Treat goa-* custom elements as web components, not Vue components.
25
+ // Applies to the shared vue-components lib too (compiled from source).
24
26
  isCustomElement: (tag) => tag.startsWith('goa-'),
25
27
  },
26
28
  },
27
29
  }),
30
+ // Resolve workspace TS path aliases (e.g. the shared @<scope>/vue-components lib).
31
+ nxViteTsPaths(),
28
32
  ],
29
33
 
30
34
  test: {
@@ -9,6 +9,7 @@ const plugin_version_1 = require("../../utils/plugin-version");
9
9
  const quality_1 = require("../../utils/quality");
10
10
  const devkit_1 = require("@nx/devkit");
11
11
  const path = require("path");
12
+ const vue_components_1 = require("../vue-components/vue-components");
12
13
  function normalizeOptions(host, options) {
13
14
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
14
15
  const projectName = (0, devkit_1.names)(options.name).fileName;
@@ -25,7 +26,9 @@ function normalizeOptions(host, options) {
25
26
  }
26
27
  function addFiles(host, options) {
27
28
  var _a;
28
- const templateOptions = Object.assign(Object.assign(Object.assign({}, options), options.adsp), { offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.projectRoot), pairedProject: (_a = options.pairedProject) !== null && _a !== void 0 ? _a : null, tmpl: '' });
29
+ const templateOptions = Object.assign(Object.assign(Object.assign({}, options), options.adsp), { offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.projectRoot), pairedProject: (_a = options.pairedProject) !== null && _a !== void 0 ? _a : null,
30
+ // Import specifier for the shared GoA wrapper lib (AGENTS.md references it).
31
+ goaImportPath: (0, vue_components_1.vueComponentsImportPath)(host), tmpl: '' });
29
32
  (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), options.projectRoot, templateOptions);
30
33
  const addProxyConf = options.nginxProxies.length > 0;
31
34
  if (addProxyConf) {
@@ -66,6 +69,10 @@ function default_1(host, options) {
66
69
  // Let the Playwright e2e target the deployed URL (BASE_URL) in CI instead of
67
70
  // always starting a local dev server — see the nx-oc pipeline's e2e jobs.
68
71
  (0, quality_1.guardPlaywrightWebServer)(host, `${normalizedOptions.projectRoot}-e2e`);
72
+ // Ensure the shared GoA wrapper library exists (idempotent — created once per
73
+ // workspace, refreshed on later runs). Apps import it instead of each carrying
74
+ // their own copy, so it's one place to swap for @abgov/vue-components later.
75
+ yield (0, vue_components_1.default)(host);
69
76
  (0, devkit_1.addDependenciesToPackageJson)(host, {
70
77
  '@abgov/design-tokens': '2.9.0',
71
78
  '@abgov/web-components': '2.3.0',
@@ -1 +1 @@
1
- {"version":3,"file":"vue-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-app/vue-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vue-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-app/vue-app.ts"],"names":[],"mappings":"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"}
@@ -72,6 +72,31 @@ describe('Vue App Generator', () => {
72
72
  expect(agents).not.toContain('ui-components.alberta.ca');
73
73
  }, 30000);
74
74
 
75
+ it('provisions the shared GoA wrapper library and points the app at it', async () => {
76
+ await generator(host, options);
77
+
78
+ // Wrappers live in a shared workspace lib, not copied into the app.
79
+ const base = 'libs/vue-components/src/lib';
80
+ for (const name of [
81
+ 'GoabInput', 'GoabTextarea', 'GoabDropdown', 'GoabCheckbox',
82
+ 'GoabRadioGroup', 'GoabButton', 'GoabModal',
83
+ ]) {
84
+ expect(host.exists(`${base}/${name}.vue`)).toBeTruthy();
85
+ }
86
+ expect(host.exists('apps/test/src/components/goa')).toBeFalsy();
87
+
88
+ // Real v-model wiring: bind :value and read the new value off the GoA event.
89
+ const input = host.read(`${base}/GoabInput.vue`).toString();
90
+ expect(input).toContain('defineModel');
91
+ expect(input).toContain('.detail.value');
92
+
93
+ // App resolves the lib alias (vite path plugin) and AGENTS.md points at it.
94
+ const vite = host.read('apps/test/vite.config.ts').toString();
95
+ expect(vite).toContain('nxViteTsPaths');
96
+ const agents = host.read('apps/test/AGENTS.md').toString();
97
+ expect(agents).toContain('/vue-components');
98
+ }, 30000);
99
+
75
100
  it('inits Keycloak with no hidden iframes so init never hangs', async () => {
76
101
  await generator(host, options);
77
102
  // Strip // comments — they legitimately reference the disabled iframe options
@@ -0,0 +1,145 @@
1
+ # AGENTS.md — vue-components (GoA Design System Vue wrappers)
2
+
3
+ A shared, workspace-local library of thin Vue wrappers over the GoA Design System
4
+ `goa-*` web components (`@abgov/web-components`). Every Vue app in this workspace
5
+ imports these instead of carrying its own copy. Generated by
6
+ `@abgov/nx-adsp:vue-components`.
7
+
8
+ > **⚠️ Interim library — do not invest in it as permanent.** It exists only
9
+ > because GoA DS has not yet published an official Vue wrapper package. When
10
+ > `@abgov/vue-components` ships, delete this library and repoint imports at it —
11
+ > the component names and props are deliberately kept matching, so it should be a
12
+ > scope swap, not a rewrite. Don't add features here that would make that swap
13
+ > harder (see "Don't" below).
14
+
15
+ ## What these wrappers do (and why they're needed)
16
+
17
+ `goa-*` are framework-agnostic custom elements (built with Svelte). Three quirks
18
+ make them awkward in Vue, and each wrapper exists to smooth exactly one of them:
19
+
20
+ - **No `v-model`.** The elements emit a **`_`-prefixed** custom event (`_change`,
21
+ `_click`, `_close` — the prefix avoids colliding with native DOM events), *not*
22
+ the `input`/`change` events Vue's `v-model` listens for. So a plain
23
+ `<goa-input>` needs manual `:value` + `@_change` wiring every time.
24
+ - **The new value arrives on `event.detail`, not `event.target.value`.** You read
25
+ `$event.detail.value` (or `.checked` for a checkbox) — reading `.target.value`
26
+ silently gives you nothing useful.
27
+ - **Bindings are properties, not attributes.** Bind `:value` / `:checked` /
28
+ `:open` and Vue sets them as element properties, which is what these components
29
+ read.
30
+
31
+ Each wrapper adds real `v-model` (via `defineModel`) over exactly **one** `goa-*`
32
+ element and lets every other prop/event fall through (`inheritAttrs`), so anything
33
+ the design system supports keeps working without being re-declared.
34
+
35
+ ## Event contract (read the value off the GoA event)
36
+
37
+ | Wrapper | Underlying element | Model | Read from event |
38
+ |---|---|---|---|
39
+ | `GoabInput`, `GoabTextarea`, `GoabDropdown`, `GoabRadioGroup` | `goa-input` / `-textarea` / `-dropdown` / `-radio-group` | `string` | `$event.detail.value` |
40
+ | `GoabCheckbox` | `goa-checkbox` | `boolean` | `$event.detail.checked` |
41
+ | `GoabButton` | `goa-button` | — (re-exposes `_click` as `@click`) | — |
42
+ | `GoabModal` | `goa-modal` | `open: boolean` (`v-model:open`) | `_close` clears it |
43
+
44
+ Most value elements put the value on `detail.value`; some carry extra keys
45
+ (dropdown adds `label`, radio-group adds `labels`) you can ignore unless you need
46
+ them. Always confirm against the component's page — see below.
47
+
48
+ ## Wrapping a new component
49
+
50
+ ### 1. Find the event contract
51
+
52
+ The source of truth is the component's page at
53
+ [design.alberta.ca/components](https://design.alberta.ca/components/) — check its
54
+ **Events** and **Properties**. If the detail shape isn't spelled out there,
55
+ confirm it against the shipped source (the elements dispatch a `CustomEvent` whose
56
+ `detail` object names its keys):
57
+
58
+ ```bash
59
+ # event names an element dispatches (all are _-prefixed):
60
+ grep -oE '"_[a-zA-Z]+"' node_modules/@abgov/web-components/index.js | sort -u
61
+
62
+ # the detail keys for a change (e.g. an input dispatches { name, value };
63
+ # a checkbox { name, checked, value }) — search near the element's dispatch:
64
+ grep -oE 'detail:[^}]*\}' node_modules/@abgov/web-components/index.js | head
65
+ ```
66
+
67
+ ### 2. Pick the pattern by the element's shape
68
+
69
+ | Element shape | Model | Skeleton |
70
+ |---|---|---|
71
+ | Text-like value (input, textarea, dropdown, date, …) | `string` | **A** |
72
+ | Boolean toggle (checkbox, switch) | `boolean` | **B** |
73
+ | Action only, no value (button) | — | **C** |
74
+ | Open/close overlay (modal, drawer) | `boolean` via `v-model:open` | **D** |
75
+ | Container with `*-item` children (dropdown, radio-group) | `string` | **A** + pass items through `<slot />` |
76
+
77
+ ### 3. Copy the matching skeleton
78
+
79
+ Keep the `INTERIM WRAPPER` header comment (see the existing files), swap the
80
+ element name and the `detail` key, then `export` it from `src/index.ts`.
81
+
82
+ **A — value component**
83
+ ```vue
84
+ <script setup lang="ts">
85
+ const model = defineModel<string>();
86
+ function onChange(e: Event) {
87
+ model.value = (e as CustomEvent<{ value: string }>).detail.value;
88
+ }
89
+ </script>
90
+ <template>
91
+ <goa-thing :value="model" @_change="onChange"><slot /></goa-thing>
92
+ </template>
93
+ ```
94
+
95
+ **B — boolean component** (bind `:checked`, read `detail.checked`)
96
+ ```vue
97
+ <script setup lang="ts">
98
+ const model = defineModel<boolean>();
99
+ function onChange(e: Event) {
100
+ model.value = (e as CustomEvent<{ checked: boolean }>).detail.checked;
101
+ }
102
+ </script>
103
+ <template>
104
+ <goa-thing :checked="model" @_change="onChange"><slot /></goa-thing>
105
+ </template>
106
+ ```
107
+
108
+ **C — action only** (no model; re-expose the `_`-event as a plain one)
109
+ ```vue
110
+ <script setup lang="ts">
111
+ const emit = defineEmits<{ click: [event: CustomEvent] }>();
112
+ </script>
113
+ <template>
114
+ <goa-thing @_click="emit('click', $event as CustomEvent)"><slot /></goa-thing>
115
+ </template>
116
+ ```
117
+
118
+ **D — open/close overlay** (named model so it's `v-model:open`)
119
+ ```vue
120
+ <script setup lang="ts">
121
+ const open = defineModel<boolean>('open');
122
+ </script>
123
+ <template>
124
+ <goa-thing :open="open" @_close="open = false"><slot /></goa-thing>
125
+ </template>
126
+ ```
127
+
128
+ Don't re-declare props you don't transform — let them fall through. `name` in
129
+ particular is required by most `goa-*` form elements (it's echoed in the event
130
+ detail); just leave it to fall through from the caller.
131
+
132
+ ## Don't
133
+
134
+ - **Don't build net-new visual components or design primitives here.** That's GoA
135
+ DS's job; this library is only *choreography* (adding `v-model`/idiomatic events
136
+ to elements that already exist). New primitives would have no home in
137
+ `@abgov/vue-components` and would block the swap.
138
+ - **Don't add app-specific logic** (fetching, routing, business rules) — this is
139
+ shared across every app in the workspace. Keep wrappers presentational.
140
+
141
+ ## Testing
142
+
143
+ Wrappers are compile-checked and covered by the generator's tests. If you add a
144
+ component test that mounts a wrapper, ensure the vite/vitest config treats `goa-*`
145
+ as custom elements (`isCustomElement: (tag) => tag.startsWith('goa-')`).
@@ -0,0 +1,12 @@
1
+ // GoA Design System Vue wrappers — INTERIM shared library.
2
+ // These add v-model / idiomatic events over the framework-agnostic goa-* custom
3
+ // elements. Remove this library and import from @abgov/vue-components once GoA DS
4
+ // publishes it (see the repo's UX view-patterns spec, foundational gap #2) — the
5
+ // component names/props are intended to match, so it should be a scope swap.
6
+ export { default as GoabInput } from './lib/GoabInput.vue';
7
+ export { default as GoabTextarea } from './lib/GoabTextarea.vue';
8
+ export { default as GoabDropdown } from './lib/GoabDropdown.vue';
9
+ export { default as GoabCheckbox } from './lib/GoabCheckbox.vue';
10
+ export { default as GoabRadioGroup } from './lib/GoabRadioGroup.vue';
11
+ export { default as GoabButton } from './lib/GoabButton.vue';
12
+ export { default as GoabModal } from './lib/GoabModal.vue';
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components (see
3
+ // GoabInput.vue for the full rationale). No v-model (a button has no value); this
4
+ // re-exposes goa-button's `_click` as a plain `@click` so views don't have to
5
+ // remember the underscore convention. Props (type, size, disabled, leadingicon,
6
+ // …) fall through to <goa-button>.
7
+ //
8
+ // Usage: <GoabButton type="primary" @click="save">Save</GoabButton>
9
+ const emit = defineEmits<{ click: [event: CustomEvent] }>();
10
+ </script>
11
+
12
+ <template>
13
+ <goa-button @_click="emit('click', $event as CustomEvent)">
14
+ <slot />
15
+ </goa-button>
16
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components (see
3
+ // GoabInput.vue for the full rationale). Adds v-model to <goa-checkbox>. Note the
4
+ // model is the boolean `checked` state (from the event's `detail.checked`), not
5
+ // the checkbox's `value` attribute.
6
+ //
7
+ // Usage: <GoabCheckbox v-model="agreed" name="agreed" text="I agree" />
8
+ const model = defineModel<boolean>();
9
+
10
+ function onChange(e: Event) {
11
+ model.value = (e as CustomEvent<{ checked: boolean }>).detail.checked;
12
+ }
13
+ </script>
14
+
15
+ <template>
16
+ <goa-checkbox :checked="model" @_change="onChange">
17
+ <slot />
18
+ </goa-checkbox>
19
+ </template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components (see
3
+ // GoabInput.vue for the full rationale). Adds v-model to <goa-dropdown>.
4
+ //
5
+ // Usage:
6
+ // <GoabDropdown v-model="province" name="province">
7
+ // <goa-dropdown-item value="ab" label="Alberta" />
8
+ // <goa-dropdown-item value="bc" label="British Columbia" />
9
+ // </GoabDropdown>
10
+ const model = defineModel<string>();
11
+
12
+ function onChange(e: Event) {
13
+ model.value = (e as CustomEvent<{ value: string }>).detail.value;
14
+ }
15
+ </script>
16
+
17
+ <template>
18
+ <goa-dropdown :value="model" @_change="onChange">
19
+ <slot />
20
+ </goa-dropdown>
21
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components; then
3
+ // import from there instead. See the repo's UX view-patterns spec (foundational
4
+ // gap #2). goa-* custom elements don't support Vue's v-model (they emit a
5
+ // non-standard `_change` event, not `input`), so a plain `<goa-input>` needs
6
+ // manual :value + @_change wiring every time. This wrapper adds real v-model.
7
+ //
8
+ // Usage: <GoabInput v-model="email" name="email" type="email" placeholder="…" />
9
+ // Any extra attrs (name, type, error, disabled, width, …) fall through to
10
+ // <goa-input>; extra events (@_blur, @_focus) fall through too.
11
+ const model = defineModel<string>();
12
+
13
+ function onChange(e: Event) {
14
+ model.value = (e as CustomEvent<{ value: string }>).detail.value;
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <goa-input :value="model" @_change="onChange">
20
+ <slot />
21
+ </goa-input>
22
+ </template>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components (see
3
+ // GoabInput.vue for the full rationale). Adds `v-model:open` to <goa-modal> and
4
+ // re-exposes its `_close` (X / backdrop) by clearing that model. Other attrs
5
+ // (heading, …) fall through. Put footer buttons in the `actions` slot.
6
+ //
7
+ // Usage:
8
+ // <GoabModal v-model:open="showConfirm" heading="Delete?">
9
+ // <p>This cannot be undone.</p>
10
+ // <template #actions>
11
+ // <GoabButton type="tertiary" @click="showConfirm = false">Cancel</GoabButton>
12
+ // <GoabButton type="primary" @click="confirm">Delete</GoabButton>
13
+ // </template>
14
+ // </GoabModal>
15
+ import { useSlots } from 'vue';
16
+
17
+ const open = defineModel<boolean>('open');
18
+ const slots = useSlots();
19
+
20
+ function onClose() {
21
+ open.value = false;
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <goa-modal :open="open" @_close="onClose">
27
+ <slot />
28
+ <!-- `slot="actions"` is goa-modal's native web-component slot, not the Vue 2 slot syntax. The vue/no-deprecated-slot-attribute rule is turned off for this lib (see .eslintrc.json). -->
29
+ <div v-if="slots.actions" slot="actions">
30
+ <slot name="actions" />
31
+ </div>
32
+ </goa-modal>
33
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components (see
3
+ // GoabInput.vue for the full rationale). Adds v-model to <goa-radio-group>.
4
+ // `name` is required by the underlying element and falls through.
5
+ //
6
+ // Usage:
7
+ // <GoabRadioGroup v-model="contact" name="contact">
8
+ // <goa-radio-item value="email" label="Email" />
9
+ // <goa-radio-item value="phone" label="Phone" />
10
+ // </GoabRadioGroup>
11
+ const model = defineModel<string>();
12
+
13
+ function onChange(e: Event) {
14
+ model.value = (e as CustomEvent<{ value: string }>).detail.value;
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <goa-radio-group :value="model" @_change="onChange">
20
+ <slot />
21
+ </goa-radio-group>
22
+ </template>
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ // INTERIM WRAPPER — remove once GoA DS publishes @abgov/vue-components (see
3
+ // GoabInput.vue for the full rationale). Adds v-model to <goa-textarea>.
4
+ //
5
+ // Usage: <GoabTextarea v-model="notes" name="notes" :rows="4" />
6
+ const model = defineModel<string>();
7
+
8
+ function onChange(e: Event) {
9
+ model.value = (e as CustomEvent<{ value: string }>).detail.value;
10
+ }
11
+ </script>
12
+
13
+ <template>
14
+ <goa-textarea :value="model" @_change="onChange">
15
+ <slot />
16
+ </goa-textarea>
17
+ </template>
@@ -0,0 +1,21 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import * as lib from './index';
3
+
4
+ // Smoke test: the barrel resolves and every wrapper SFC compiles under the test
5
+ // runner. It also gives the library a test target with real content, so
6
+ // `nx test vue-components` doesn't fail on "no test files found".
7
+ describe('vue-components', () => {
8
+ it('exports every GoA wrapper', () => {
9
+ for (const name of [
10
+ 'GoabInput',
11
+ 'GoabTextarea',
12
+ 'GoabDropdown',
13
+ 'GoabCheckbox',
14
+ 'GoabRadioGroup',
15
+ 'GoabButton',
16
+ 'GoabModal',
17
+ ]) {
18
+ expect(lib[name as keyof typeof lib]).toBeTruthy();
19
+ }
20
+ });
21
+ });
@@ -0,0 +1,2 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
2
+ export interface Schema {}
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "id": "NxAdspVueComponents",
4
+ "title": "GoA Vue component library (interim)",
5
+ "description": "Ensures a shared, workspace-local vue-components library of GoA Design System v-model wrappers exists. Idempotent — creates it on first run, refreshes the wrappers on later runs. Normally invoked by vue-app; runnable directly to repair/refresh.",
6
+ "type": "object",
7
+ "properties": {},
8
+ "required": [],
9
+ "additionalProperties": false
10
+ }
@@ -0,0 +1,5 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function ensurePackageExports(host: Tree, libRoot: string): void;
3
+ export declare const LIB_NAME = "vue-components";
4
+ export declare function vueComponentsImportPath(host: Tree): string;
5
+ export default function (host: Tree): Promise<void>;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LIB_NAME = void 0;
4
+ exports.ensurePackageExports = ensurePackageExports;
5
+ exports.vueComponentsImportPath = vueComponentsImportPath;
6
+ exports.default = default_1;
7
+ const tslib_1 = require("tslib");
8
+ const devkit_1 = require("@nx/devkit");
9
+ const path = require("path");
10
+ // Backfills package.json module-resolution fields for the library. In a TS-solution
11
+ // workspace @nx/vue's library resolves via package.json `exports`, but its
12
+ // programmatic default (useProjectJson skips writing them here) leaves them off, so
13
+ // the import path fails to resolve and the build breaks. Point them at the source
14
+ // entry (the lib is non-buildable — consumers compile it). A no-op in legacy
15
+ // path-alias workspaces (no lib package.json — resolution is via tsconfig paths),
16
+ // and idempotent (never clobbers fields @nx/vue did write).
17
+ function ensurePackageExports(host, libRoot) {
18
+ const pkgPath = `${libRoot}/package.json`;
19
+ if (!host.exists(pkgPath))
20
+ return;
21
+ const SRC = './src/index.ts';
22
+ (0, devkit_1.updateJson)(host, pkgPath, (pkg) => {
23
+ var _a, _b, _c, _d;
24
+ (_a = pkg.main) !== null && _a !== void 0 ? _a : (pkg.main = SRC);
25
+ (_b = pkg.module) !== null && _b !== void 0 ? _b : (pkg.module = SRC);
26
+ (_c = pkg.types) !== null && _c !== void 0 ? _c : (pkg.types = SRC);
27
+ (_d = pkg.exports) !== null && _d !== void 0 ? _d : (pkg.exports = {
28
+ './package.json': './package.json',
29
+ '.': { types: SRC, import: SRC, default: SRC },
30
+ });
31
+ return pkg;
32
+ });
33
+ }
34
+ // Turns off vue/no-deprecated-slot-attribute for the lib. GoabModal projects into
35
+ // goa-modal's native web-component slot via `slot="actions"` — legitimate custom-
36
+ // element usage, not the deprecated Vue 2 component-slot syntax the rule targets.
37
+ // The whole lib wraps web components, so it's scoped to the lib (consuming apps,
38
+ // which use `<template #actions>`, are unaffected).
39
+ function disableSlotAttributeRule(host, libRoot) {
40
+ const eslintrc = `${libRoot}/.eslintrc.json`;
41
+ if (!host.exists(eslintrc)) {
42
+ console.warn(`\n⚠ ${eslintrc} not found — could not disable vue/no-deprecated-slot-attribute.\n` +
43
+ ` GoabModal uses goa-modal's native \`slot\` attribute; if lint flags it, turn\n` +
44
+ ` that rule off for this library.\n`);
45
+ return;
46
+ }
47
+ (0, devkit_1.updateJson)(host, eslintrc, (json) => {
48
+ var _a, _b;
49
+ const overrides = ((_a = json.overrides) !== null && _a !== void 0 ? _a : (json.overrides = []));
50
+ let vueOverride = overrides.find((o) => { var _a; return (_a = o.files) === null || _a === void 0 ? void 0 : _a.some((f) => f.includes('vue')); });
51
+ if (!vueOverride) {
52
+ vueOverride = { files: ['*.vue'], rules: {} };
53
+ overrides.push(vueOverride);
54
+ }
55
+ ((_b = vueOverride.rules) !== null && _b !== void 0 ? _b : (vueOverride.rules = {}))['vue/no-deprecated-slot-attribute'] = 'off';
56
+ return json;
57
+ });
58
+ }
59
+ exports.LIB_NAME = 'vue-components';
60
+ // Import specifier for the shared wrapper lib, derived from the workspace npm
61
+ // scope so it mirrors the eventual official `@abgov/vue-components` (same tail —
62
+ // swapping to it is a scope change). Falls back to a scope built from the root
63
+ // package name when the workspace isn't scoped.
64
+ function vueComponentsImportPath(host) {
65
+ var _a, _b;
66
+ let name = 'workspace';
67
+ try {
68
+ name = JSON.parse((_b = (_a = host.read('package.json')) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '{}').name || name;
69
+ }
70
+ catch (_c) {
71
+ /* keep fallback */
72
+ }
73
+ const scope = name.startsWith('@') ? name.split('/')[0] : `@${name}`;
74
+ return `${scope}/${exports.LIB_NAME}`;
75
+ }
76
+ // Ensures the shared, workspace-local GoA wrapper library exists, then writes the
77
+ // current wrapper set into it. Idempotent: the @nx/vue library is only scaffolded
78
+ // when absent (so it's safe to call from every vue-app generation), and the
79
+ // wrapper files are always (re)written so a direct run also repairs/refreshes them.
80
+ function default_1(host) {
81
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
82
+ const libRoot = `${(0, devkit_1.getWorkspaceLayout)(host).libsDir}/${exports.LIB_NAME}`;
83
+ let exists = true;
84
+ try {
85
+ (0, devkit_1.readProjectConfiguration)(host, exports.LIB_NAME);
86
+ }
87
+ catch (_a) {
88
+ exists = false;
89
+ }
90
+ if (!exists) {
91
+ const { libraryGenerator } = yield Promise.resolve().then(() => require('@nx/vue')).catch(() => {
92
+ throw new Error("The 'vue-components' generator requires the '@nx/vue' plugin. Install it and re-run:\n npm i -D @nx/vue");
93
+ });
94
+ yield libraryGenerator(host, {
95
+ directory: libRoot,
96
+ name: exports.LIB_NAME,
97
+ linter: 'eslint',
98
+ unitTestRunner: 'vitest',
99
+ // No demo component/spec to clean up, and no build step: apps consume the
100
+ // source and compile it with their own vite (whose isCustomElement already
101
+ // handles goa-*), so it resolves via the tsconfig path alias.
102
+ component: false,
103
+ bundler: 'none',
104
+ importPath: vueComponentsImportPath(host),
105
+ skipFormat: true,
106
+ });
107
+ disableSlotAttributeRule(host, libRoot);
108
+ ensurePackageExports(host, libRoot);
109
+ }
110
+ (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), libRoot, { tmpl: '' });
111
+ });
112
+ }
113
+ //# sourceMappingURL=vue-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue-components.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-components/vue-components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import { readProjectConfiguration, Tree } from '@nx/devkit';
2
+ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
3
+ import generator, { ensurePackageExports, vueComponentsImportPath } from './vue-components';
4
+
5
+ jest.mock('@nx/devkit', () => ({
6
+ ...jest.requireActual('@nx/devkit'),
7
+ formatFiles: jest.fn().mockResolvedValue(undefined),
8
+ }));
9
+
10
+ describe('Vue Components Generator', () => {
11
+ let host: Tree;
12
+
13
+ beforeEach(() => {
14
+ host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
15
+ });
16
+
17
+ it('creates the shared wrapper library with all wrappers and a barrel', async () => {
18
+ await generator(host);
19
+
20
+ const config = readProjectConfiguration(host, 'vue-components');
21
+ expect(config.root).toBe('libs/vue-components');
22
+
23
+ const base = 'libs/vue-components/src/lib';
24
+ for (const name of [
25
+ 'GoabInput', 'GoabTextarea', 'GoabDropdown', 'GoabCheckbox',
26
+ 'GoabRadioGroup', 'GoabButton', 'GoabModal',
27
+ ]) {
28
+ expect(host.exists(`${base}/${name}.vue`)).toBeTruthy();
29
+ }
30
+ const index = host.read('libs/vue-components/src/index.ts').toString();
31
+ expect(index).toContain("export { default as GoabInput }");
32
+ expect(index).toContain('@abgov/vue-components'); // interim marker
33
+
34
+ // Ships a spec so the vitest test target isn't empty (vitest exits non-zero
35
+ // on "no test files found").
36
+ expect(host.exists('libs/vue-components/src/vue-components.spec.ts')).toBeTruthy();
37
+
38
+ // GoabModal uses goa-modal's native `slot` attribute (web component, not the
39
+ // deprecated Vue 2 slot syntax) — the rule is turned off for this lib.
40
+ const eslintrc = host.read('libs/vue-components/.eslintrc.json').toString();
41
+ expect(eslintrc).toContain('"vue/no-deprecated-slot-attribute": "off"');
42
+
43
+ // Ships agent direction for maintaining the (interim) lib, incl. a recipe
44
+ // for wrapping additional components.
45
+ expect(host.exists('libs/vue-components/AGENTS.md')).toBeTruthy();
46
+ const agents = host.read('libs/vue-components/AGENTS.md').toString();
47
+ expect(agents).toContain('Interim');
48
+ expect(agents).toContain('detail.value');
49
+ expect(agents).toContain('Wrapping a new component');
50
+ expect(agents).toContain('defineModel<boolean>');
51
+ }, 30000);
52
+
53
+ it('is idempotent — a second run does not throw and keeps the wrappers', async () => {
54
+ await generator(host);
55
+ await expect(generator(host)).resolves.not.toThrow();
56
+ expect(host.exists('libs/vue-components/src/lib/GoabInput.vue')).toBeTruthy();
57
+ }, 30000);
58
+
59
+ it('derives the import path from the workspace scope', () => {
60
+ expect(vueComponentsImportPath(host)).toMatch(/\/vue-components$/);
61
+ });
62
+
63
+ describe('ensurePackageExports (TS-solution resolution fix)', () => {
64
+ it('backfills exports/main/types when a lib package.json exists', () => {
65
+ host.write('libs/vue-components/package.json', JSON.stringify({ name: '@proj/vue-components' }));
66
+ ensurePackageExports(host, 'libs/vue-components');
67
+
68
+ const pkg = JSON.parse(host.read('libs/vue-components/package.json').toString());
69
+ expect(pkg.main).toBe('./src/index.ts');
70
+ expect(pkg.types).toBe('./src/index.ts');
71
+ expect(pkg.exports['.'].import).toBe('./src/index.ts');
72
+ });
73
+
74
+ it('does not clobber exports @nx/vue already wrote', () => {
75
+ host.write(
76
+ 'libs/vue-components/package.json',
77
+ JSON.stringify({ name: '@proj/vue-components', exports: { '.': './dist/index.js' } })
78
+ );
79
+ ensurePackageExports(host, 'libs/vue-components');
80
+
81
+ const pkg = JSON.parse(host.read('libs/vue-components/package.json').toString());
82
+ expect(pkg.exports['.']).toBe('./dist/index.js');
83
+ });
84
+
85
+ it('is a no-op for a legacy lib with no package.json', () => {
86
+ ensurePackageExports(host, 'libs/vue-components');
87
+ expect(host.exists('libs/vue-components/package.json')).toBeFalsy();
88
+ });
89
+ });
90
+ });