fg-devkit 1.17.3 → 1.19.2
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/.cursor/rules/core-coding-standards.mdc +24 -0
- package/README.md +25 -0
- package/configs/dependency-policy.vue-workspace.json +30 -30
- package/package.json +17 -14
- package/scaffold/vue/package.json +12 -12
- package/scripts/fg-devkit.mjs +154 -2
- package/scripts/piwik-common.mjs +653 -0
- package/scripts/piwik-dimensions.mjs +785 -0
- package/scripts/piwik-dimensions.test.mjs +400 -0
- package/scripts/piwik.mjs +502 -0
|
@@ -128,6 +128,30 @@ const { data, isLoading, error } = useGetDetails(id)
|
|
|
128
128
|
- Prefer `props: true` and typed route params in components instead of reading raw params everywhere.
|
|
129
129
|
- Prefer named-route navigation for internal flows (`{ name, params, query }`) and reserve raw path pushes for simple/static redirects.
|
|
130
130
|
- Preserve existing query params intentionally when updating filters, pagination, or tab state.
|
|
131
|
+
- Returning to a view whose filters live in the URL: call `usePreviousLocation` from `fds-vue-core` in setup. `router.push('/path')` drops that query. Browser back keeps it.
|
|
132
|
+
- Use `hrefFor` on `router-link` and `FdsTabsItem`, and `goTo` on back buttons, only when the target is that same view. Leave other navigations unchanged.
|
|
133
|
+
- `hrefFor(path)` reuses the previous history entry, including `_search`, `_page`, and filters, when its pathname matches. Otherwise it returns the path only.
|
|
134
|
+
- `goTo(fallback, matchPaths?)` calls `router.back()` when the previous entry matches, so scroll is kept. Otherwise it pushes the fallback path.
|
|
135
|
+
- Pass `matchPaths` when several paths count as the same place. Without it, only the fallback path is compared.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { usePreviousLocation } from 'fds-vue-core'
|
|
139
|
+
|
|
140
|
+
const { hrefFor, goTo } = usePreviousLocation()
|
|
141
|
+
|
|
142
|
+
const goBack = () => {
|
|
143
|
+
goTo('/services/J4', ['/services/J4', '/services'])
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```vue
|
|
148
|
+
<router-link :to="hrefFor(breadcrumb.path)">
|
|
149
|
+
{{ breadcrumb.name }}
|
|
150
|
+
</router-link>
|
|
151
|
+
<FdsTabsItem :to="hrefFor(tab.path)" />
|
|
152
|
+
<FdsButtonMinor :text="t('common.back')" icon="left" @click="goBack" />
|
|
153
|
+
```
|
|
154
|
+
|
|
131
155
|
- Lazy-load route components with dynamic imports to keep initial bundles smaller.
|
|
132
156
|
- Name organisation route params by domain meaning, not generic `id`:
|
|
133
157
|
- top org: `:topClientNumber`
|
package/README.md
CHANGED
|
@@ -183,6 +183,31 @@ export default {
|
|
|
183
183
|
}
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
+
## Piwik PRO custom dimensions
|
|
187
|
+
|
|
188
|
+
Compare the local slot map with a Piwik PRO site, then create missing dimensions or rename existing ones. Run it from a consuming repo (`bokningsverktyget-ui`, `webbportalen-ui`, `feelgood-app`, and the same layout in other apps) or from the Electron maintainer UI under **Piwik**.
|
|
189
|
+
|
|
190
|
+
The local map is `src/analytics/dimensions.ts` (`customDimensions` = event, `sessionDimensions` = session) or `src/util/piwikDimensions.ts` (`CustomDimensions` / `SessionCustomDimensions`). The site defaults to the first non-production entry in `src/config/env.ts`, such as preprod. Pass `--env production` to target production. In the Electron app, Piwik actions show one radio per distinct `piwikId`. Environments that share an id, such as localhost, development, and preprod, appear once as **preprod**.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
pnpm exec fgd piwik list
|
|
194
|
+
pnpm exec fgd piwik list --local
|
|
195
|
+
pnpm exec fgd piwik diff
|
|
196
|
+
pnpm exec fgd piwik add --dry-run
|
|
197
|
+
pnpm exec fgd piwik sync --yes
|
|
198
|
+
pnpm exec fgd piwik pull --env preprod --dry-run
|
|
199
|
+
pnpm exec fgd piwik compare --from preprod --to production
|
|
200
|
+
pnpm exec fgd piwik migrate --from preprod --to production --dry-run
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`sync` copies the local map up to the selected Piwik site: it creates missing dimensions, then renames existing ones. It does not edit the repo. `pull` copies tracking ids from that site down into the local map for keys with the same name. In the Electron app, **Sync** has From and To radios. **Local map** is the repo. A site as To writes up to Piwik. **Local map** as To writes down into the repo. Two sites migrate between environments.
|
|
204
|
+
|
|
205
|
+
`compare` checks two sites from `src/config/env.ts` against each other. Event and session dimensions match on `tracking_id`, so a different slot on the other site is still in sync. `migrate` copies names, descriptions, and missing dimensions from `--from` onto `--to`, one create at a time. It stops if Piwik assigns a different `tracking_id`. Dimensions that exist only on the target stay there.
|
|
206
|
+
|
|
207
|
+
Set `PIWIK_CLIENT_ID` and `PIWIK_CLIENT_SECRET` in the environment, `.env.local`, or `env.local`. Optional `piwik/.piwik.json` can set `account`, `websiteId`, `environment`, `dimensionsFile`, and `names` (local key to Piwik label).
|
|
208
|
+
|
|
209
|
+
Session and event slots are assigned by Piwik as the next free number in that scope. The command creates one dimension at a time and stops if the returned slot is not the local slot. Deactivating a dimension does not free the slot. Product dimensions send the local slot (1–20).
|
|
210
|
+
|
|
186
211
|
## Local development with pnpm link
|
|
187
212
|
|
|
188
213
|
Use this flow to test local `fg-devkit` changes in a consuming repo.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"toolchain": {
|
|
3
|
-
"packageManager": "pnpm@12.
|
|
3
|
+
"packageManager": "pnpm@12.8.1",
|
|
4
4
|
"node": {
|
|
5
5
|
"nvmrc": "22",
|
|
6
6
|
"engines": ">=22.13.0",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"@lexical/list": "0.49.0",
|
|
17
17
|
"@lexical/rich-text": "0.49.0",
|
|
18
18
|
"@lexical/link": "0.49.0",
|
|
19
|
-
"@piwikpro/vue-piwik-pro": "
|
|
20
|
-
"@sentry/vue": "
|
|
21
|
-
"@tanstack/vue-query": "5.
|
|
19
|
+
"@piwikpro/vue-piwik-pro": "2.0.0",
|
|
20
|
+
"@sentry/vue": "11.1.0",
|
|
21
|
+
"@tanstack/vue-query": "5.104.0",
|
|
22
22
|
"@types/leaflet": "1.9.22",
|
|
23
23
|
"@unhead/vue": "2.0.5",
|
|
24
24
|
"@vue-leaflet/vue-leaflet": "0.10.1",
|
|
@@ -29,25 +29,25 @@
|
|
|
29
29
|
"chart.js": "4.5.1",
|
|
30
30
|
"content-disposition-header": "0.6.0",
|
|
31
31
|
"date-fns": "4.4.0",
|
|
32
|
-
"element-plus": "2.14.
|
|
33
|
-
"fds-vue-core": "8.
|
|
32
|
+
"element-plus": "2.14.7",
|
|
33
|
+
"fds-vue-core": "8.10.0",
|
|
34
34
|
"imask": "7.6.1",
|
|
35
35
|
"leaflet": "1.9.4",
|
|
36
36
|
"lexical": "0.49.0",
|
|
37
37
|
"lodash": "4.18.1",
|
|
38
38
|
"lodash-es": "4.18.1",
|
|
39
39
|
"markdown-it": "14.3.0",
|
|
40
|
-
"pinia": "
|
|
40
|
+
"pinia": "4.0.3",
|
|
41
41
|
"playwright": "1.63.0",
|
|
42
42
|
"quill": "2.0.3",
|
|
43
43
|
"randexp": "0.5.3",
|
|
44
44
|
"register-service-worker": "1.7.2",
|
|
45
|
-
"vega-embed": "7.
|
|
45
|
+
"vega-embed": "7.3.0",
|
|
46
46
|
"vega-lite": "6.4.3",
|
|
47
47
|
"vue-chartjs": "5.3.4",
|
|
48
|
-
"vue-i18n": "11.4.
|
|
48
|
+
"vue-i18n": "11.4.12",
|
|
49
49
|
"vue-quilly": "1.1.6",
|
|
50
|
-
"vue-router": "
|
|
50
|
+
"vue-router": "5.3.1",
|
|
51
51
|
"vue3-touch-keyboard": "1.3.9",
|
|
52
52
|
"vuex": "4.1.0",
|
|
53
53
|
"vuex-persist": "3.1.3",
|
|
@@ -58,33 +58,33 @@
|
|
|
58
58
|
"@eslint/js": "9.39.1",
|
|
59
59
|
"@intlify/unplugin-vue-i18n": "11.2.5",
|
|
60
60
|
"@playwright/test": "1.63.0",
|
|
61
|
-
"@storybook/addon-a11y": "10.6.
|
|
62
|
-
"@storybook/addon-docs": "10.6.
|
|
63
|
-
"@storybook/addon-vitest": "10.6.
|
|
64
|
-
"@storybook/vue3": "10.6.
|
|
65
|
-
"@storybook/vue3-vite": "10.6.
|
|
66
|
-
"@tanstack/vue-query-devtools": "6.
|
|
61
|
+
"@storybook/addon-a11y": "10.6.1",
|
|
62
|
+
"@storybook/addon-docs": "10.6.1",
|
|
63
|
+
"@storybook/addon-vitest": "10.6.1",
|
|
64
|
+
"@storybook/vue3": "10.6.1",
|
|
65
|
+
"@storybook/vue3-vite": "10.6.1",
|
|
66
|
+
"@tanstack/vue-query-devtools": "6.3.0",
|
|
67
67
|
"@tsconfig/node22": "22.0.6",
|
|
68
68
|
"@types/lodash-es": "4.17.12",
|
|
69
69
|
"@types/node": "22.16.5",
|
|
70
|
-
"@vitest/browser": "
|
|
71
|
-
"@vue/compiler-dom": "3.5.
|
|
70
|
+
"@vitest/browser": "5.0.3",
|
|
71
|
+
"@vue/compiler-dom": "3.5.43",
|
|
72
72
|
"@vue/eslint-config-standard": "8.0.1",
|
|
73
|
-
"@vue/server-renderer": "3.5.
|
|
74
|
-
"@vue/test-utils": "2.5.
|
|
73
|
+
"@vue/server-renderer": "3.5.43",
|
|
74
|
+
"@vue/test-utils": "2.5.1",
|
|
75
75
|
"arg": "5.0.2",
|
|
76
76
|
"babel-eslint": "10.1.0",
|
|
77
|
-
"eslint-plugin-storybook": "10.6.
|
|
77
|
+
"eslint-plugin-storybook": "10.6.1",
|
|
78
78
|
"globals": "15.11.0",
|
|
79
|
-
"jsdom": "
|
|
80
|
-
"sass": "1.
|
|
81
|
-
"storybook": "10.6.
|
|
82
|
-
"tsx": "4.23.
|
|
79
|
+
"jsdom": "30.1.1",
|
|
80
|
+
"sass": "1.105.1",
|
|
81
|
+
"storybook": "10.6.1",
|
|
82
|
+
"tsx": "4.23.15",
|
|
83
83
|
"vega": "6.4.0",
|
|
84
|
-
"vite-plugin-dts": "
|
|
84
|
+
"vite-plugin-dts": "5.1.1",
|
|
85
85
|
"vite-plugin-vue-devtools": "8.2.1",
|
|
86
86
|
"vite-plugin-vue-inspector": "7.0.0",
|
|
87
|
-
"vitest": "
|
|
87
|
+
"vitest": "5.0.3",
|
|
88
88
|
"yaml": "2.9.1"
|
|
89
89
|
}
|
|
90
90
|
},
|
|
@@ -92,10 +92,10 @@
|
|
|
92
92
|
"@tailwindcss/vite": "4.3.3",
|
|
93
93
|
"@vitejs/plugin-vue": "6.0.9",
|
|
94
94
|
"axios": "1.20.0",
|
|
95
|
-
"dotenv": "
|
|
95
|
+
"dotenv": "18.0.5",
|
|
96
96
|
"qrcode.vue": "3.11.0",
|
|
97
97
|
"tailwindcss": "4.3.3",
|
|
98
|
-
"vite": "
|
|
99
|
-
"vue": "3.5.
|
|
98
|
+
"vite": "8.3.1",
|
|
99
|
+
"vue": "3.5.43"
|
|
100
100
|
}
|
|
101
101
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fg-devkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.2",
|
|
4
4
|
"description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -63,6 +63,9 @@
|
|
|
63
63
|
"./scripts/refresh-dependency-policy-from-repos.mjs": "./scripts/refresh-dependency-policy-from-repos.mjs",
|
|
64
64
|
"./scripts/sync-scaffold-vue-deps.mjs": "./scripts/sync-scaffold-vue-deps.mjs",
|
|
65
65
|
"./scripts/poeditor-common.mjs": "./scripts/poeditor-common.mjs",
|
|
66
|
+
"./scripts/piwik.mjs": "./scripts/piwik.mjs",
|
|
67
|
+
"./scripts/piwik-common.mjs": "./scripts/piwik-common.mjs",
|
|
68
|
+
"./scripts/piwik-dimensions.mjs": "./scripts/piwik-dimensions.mjs",
|
|
66
69
|
"./scripts/poeditor-download.mjs": "./scripts/poeditor-download.mjs",
|
|
67
70
|
"./scripts/poeditor-upload.mjs": "./scripts/poeditor-upload.mjs",
|
|
68
71
|
"./scripts/scaffold-vue.mjs": "./scripts/scaffold-vue.mjs",
|
|
@@ -84,6 +87,8 @@
|
|
|
84
87
|
"configs",
|
|
85
88
|
"release-notes",
|
|
86
89
|
"scaffold",
|
|
90
|
+
"!**/node_modules",
|
|
91
|
+
"!**/node_modules/**",
|
|
87
92
|
"scripts",
|
|
88
93
|
"tsconfig.json",
|
|
89
94
|
".cursor/rules/core-coding-standards.mdc"
|
|
@@ -104,26 +109,26 @@
|
|
|
104
109
|
}
|
|
105
110
|
},
|
|
106
111
|
"dependencies": {
|
|
107
|
-
"@inquirer/checkbox": "
|
|
112
|
+
"@inquirer/checkbox": "5.2.5",
|
|
108
113
|
"@inquirer/confirm": "6.3.2",
|
|
109
114
|
"@inquirer/input": "5.1.6",
|
|
110
115
|
"@inquirer/select": "5.2.5",
|
|
111
116
|
"@intlify/eslint-plugin-vue-i18n": "4.5.1",
|
|
112
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
113
|
-
"@typescript-eslint/parser": "8.
|
|
117
|
+
"@typescript-eslint/eslint-plugin": "8.71.0",
|
|
118
|
+
"@typescript-eslint/parser": "8.71.0",
|
|
114
119
|
"@vitest/eslint-plugin": "1.6.27",
|
|
115
120
|
"@vue/eslint-config-prettier": "10.2.0",
|
|
116
121
|
"@vue/eslint-config-typescript": "14.9.0",
|
|
117
122
|
"@vue/tsconfig": "0.9.1",
|
|
118
|
-
"eslint": "10.
|
|
123
|
+
"eslint": "10.11.0",
|
|
119
124
|
"eslint-plugin-prettier": "5.5.6",
|
|
120
|
-
"eslint-plugin-vue": "10.11.
|
|
121
|
-
"fallow": "
|
|
122
|
-
"git-cliff": "2.
|
|
123
|
-
"lefthook": "2.1.
|
|
124
|
-
"npm-check-updates": "
|
|
125
|
-
"prettier": "3.9.
|
|
126
|
-
"tsx": "4.23.
|
|
125
|
+
"eslint-plugin-vue": "10.11.1",
|
|
126
|
+
"fallow": "3.31.0",
|
|
127
|
+
"git-cliff": "2.14.2",
|
|
128
|
+
"lefthook": "2.1.15",
|
|
129
|
+
"npm-check-updates": "23.1.0",
|
|
130
|
+
"prettier": "3.9.9",
|
|
131
|
+
"tsx": "4.23.15",
|
|
127
132
|
"typescript": "5.9.3",
|
|
128
133
|
"vue-eslint-parser": "10.4.1",
|
|
129
134
|
"vue-tsc": "3.3.11"
|
|
@@ -133,8 +138,6 @@
|
|
|
133
138
|
"czg": "1.14.0"
|
|
134
139
|
},
|
|
135
140
|
"scripts": {
|
|
136
|
-
"maintainer-ui": "pnpm --dir electron/maintainer-ui start",
|
|
137
|
-
"maintainer-ui:install": "pnpm --dir electron/maintainer-ui install",
|
|
138
141
|
"fgd-ui": "pnpm --dir electron/maintainer-ui start",
|
|
139
142
|
"fgd-ui:install": "pnpm --dir electron/maintainer-ui install"
|
|
140
143
|
}
|
|
@@ -16,30 +16,30 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@tailwindcss/vite": "4.3.3",
|
|
19
|
-
"@tanstack/vue-query": "5.
|
|
19
|
+
"@tanstack/vue-query": "5.104.0",
|
|
20
20
|
"axios": "1.20.0",
|
|
21
21
|
"content-disposition-header": "0.6.0",
|
|
22
22
|
"date-fns": "4.4.0",
|
|
23
|
-
"dotenv": "
|
|
24
|
-
"fds-vue-core": "8.
|
|
25
|
-
"pinia": "
|
|
23
|
+
"dotenv": "18.0.5",
|
|
24
|
+
"fds-vue-core": "8.10.0",
|
|
25
|
+
"pinia": "4.0.3",
|
|
26
26
|
"qrcode.vue": "3.11.0",
|
|
27
|
-
"vue": "3.5.
|
|
28
|
-
"vue-i18n": "11.4.
|
|
29
|
-
"vue-router": "
|
|
27
|
+
"vue": "3.5.43",
|
|
28
|
+
"vue-i18n": "11.4.12",
|
|
29
|
+
"vue-router": "5.3.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@intlify/unplugin-vue-i18n": "11.2.5",
|
|
33
|
-
"@tanstack/vue-query-devtools": "6.
|
|
33
|
+
"@tanstack/vue-query-devtools": "6.3.0",
|
|
34
34
|
"@types/node": "22.16.5",
|
|
35
|
-
"fg-devkit": "1.
|
|
35
|
+
"fg-devkit": "1.19.2",
|
|
36
36
|
"@vitejs/plugin-vue": "6.0.9",
|
|
37
37
|
"tailwindcss": "4.3.3",
|
|
38
|
-
"tsx": "4.23.
|
|
39
|
-
"vite": "
|
|
38
|
+
"tsx": "4.23.15",
|
|
39
|
+
"vite": "8.3.1",
|
|
40
40
|
"vite-plugin-vue-inspector": "7.0.0"
|
|
41
41
|
},
|
|
42
|
-
"packageManager": "pnpm@12.
|
|
42
|
+
"packageManager": "pnpm@12.8.1",
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=22.13.0"
|
|
45
45
|
}
|
package/scripts/fg-devkit.mjs
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* pnpm exec fg-devkit dead-code [fallow-args...] (same as: fallow dead-code [args...])
|
|
42
42
|
* pnpm exec fg-devkit poeditor-download [args...] (download translations using poeditor/.poeditor.json + env token)
|
|
43
43
|
* pnpm exec fg-devkit poeditor-upload [args...] (upload translations using poeditor/.poeditor.json + env token)
|
|
44
|
+
* pnpm exec fg-devkit piwik <list|diff|add|update|sync|compare|migrate> (Piwik PRO custom dimensions)
|
|
44
45
|
* Interactive menu (no subcommand):
|
|
45
46
|
* pnpm exec fg-devkit
|
|
46
47
|
*
|
|
@@ -489,6 +490,7 @@ const DIRECT_COMMANDS = {
|
|
|
489
490
|
'sync-scaffold-vue-deps': 'sync-scaffold-vue-deps.mjs',
|
|
490
491
|
'poeditor-download': 'poeditor-download.mjs',
|
|
491
492
|
'poeditor-upload': 'poeditor-upload.mjs',
|
|
493
|
+
piwik: 'piwik.mjs',
|
|
492
494
|
}
|
|
493
495
|
|
|
494
496
|
function printHelp() {
|
|
@@ -568,6 +570,7 @@ Commands:
|
|
|
568
570
|
dead-code [fallow-args...] Run Fallow dead code analysis (shortcut for: fallow dead-code)
|
|
569
571
|
poeditor-download [args...] Download locale files via PoEditor (reads poeditor/.poeditor.json by default)
|
|
570
572
|
poeditor-upload [args...] Upload locale file via PoEditor (reads poeditor/.poeditor.json by default; --sync-terms deletes missing terms)
|
|
573
|
+
piwik <list|diff|add|update|sync|compare|migrate> Compare and sync Piwik PRO custom dimensions with the local slot map, or between environments
|
|
571
574
|
scaffold-vue <target-dir> [--name …] [--slug …] [--force] …
|
|
572
575
|
Copy the bundled Vue scaffold into target-dir (see script header)
|
|
573
576
|
sync-scaffold-vue-deps [policy-file]
|
|
@@ -663,15 +666,19 @@ async function runInteractiveMenu() {
|
|
|
663
666
|
name: '8) Fallow analysis',
|
|
664
667
|
value: 'fallow-analysis',
|
|
665
668
|
},
|
|
669
|
+
{
|
|
670
|
+
name: '9) Piwik',
|
|
671
|
+
value: 'piwik',
|
|
672
|
+
},
|
|
666
673
|
]
|
|
667
674
|
if (isMaintainer) {
|
|
668
675
|
groups.push({
|
|
669
|
-
name: '
|
|
676
|
+
name: '10) Maintainer',
|
|
670
677
|
value: 'maintainer',
|
|
671
678
|
})
|
|
672
679
|
}
|
|
673
680
|
groups.push({
|
|
674
|
-
name: isMaintainer ? '
|
|
681
|
+
name: isMaintainer ? '11) Exit' : '10) Exit',
|
|
675
682
|
value: 'exit',
|
|
676
683
|
})
|
|
677
684
|
|
|
@@ -810,6 +817,151 @@ async function runInteractiveMenu() {
|
|
|
810
817
|
return runSelectedAction(() => runNode('poeditor-upload.mjs', uploadArgs))
|
|
811
818
|
}
|
|
812
819
|
|
|
820
|
+
if (group === 'piwik') {
|
|
821
|
+
const choice = await selectPrompt({
|
|
822
|
+
message: 'Piwik PRO custom dimensions',
|
|
823
|
+
choices: [
|
|
824
|
+
{ name: 'List dimensions in Piwik', value: 'list' },
|
|
825
|
+
{ name: 'List local dimension map', value: 'list-local' },
|
|
826
|
+
{ name: 'Compare local map with Piwik', value: 'diff' },
|
|
827
|
+
{ name: 'Add missing dimensions', value: 'add' },
|
|
828
|
+
{ name: 'Update dimension names', value: 'update' },
|
|
829
|
+
{ name: 'Sync from one side to another', value: 'sync' },
|
|
830
|
+
{ name: 'Compare environments', value: 'compare' },
|
|
831
|
+
{ name: 'Migrate between environments', value: 'migrate' },
|
|
832
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
833
|
+
],
|
|
834
|
+
default: 'diff',
|
|
835
|
+
loop: false,
|
|
836
|
+
})
|
|
837
|
+
if (choice === 'cancel') continue
|
|
838
|
+
if (choice === 'list') return runSelectedAction(() => runNode('piwik.mjs', ['list']))
|
|
839
|
+
if (choice === 'list-local') return runSelectedAction(() => runNode('piwik.mjs', ['list', '--local']))
|
|
840
|
+
if (choice === 'diff') return runSelectedAction(() => runNode('piwik.mjs', ['diff']))
|
|
841
|
+
if (choice === 'compare' || choice === 'migrate') {
|
|
842
|
+
const { defaultEnvironmentPair, listPiwikEnvironments } = await import('./piwik-common.mjs')
|
|
843
|
+
const environments = listPiwikEnvironments(process.cwd())
|
|
844
|
+
if (environments.length < 2) {
|
|
845
|
+
console.log('[piwik] Need two Piwik sites in src/config/env.ts.')
|
|
846
|
+
continue
|
|
847
|
+
}
|
|
848
|
+
const defaults = defaultEnvironmentPair(environments)
|
|
849
|
+
const from = await selectPrompt({
|
|
850
|
+
message: 'From',
|
|
851
|
+
choices: environments.map((site) => ({ name: site.environment, value: site.environment })),
|
|
852
|
+
default: defaults.from,
|
|
853
|
+
loop: false,
|
|
854
|
+
})
|
|
855
|
+
const toChoices = environments.filter((site) => site.environment !== from)
|
|
856
|
+
const to = await selectPrompt({
|
|
857
|
+
message: 'To',
|
|
858
|
+
choices: toChoices.map((site) => ({ name: site.environment, value: site.environment })),
|
|
859
|
+
default: toChoices.some((site) => site.environment === defaults.to) ? defaults.to : toChoices[0].environment,
|
|
860
|
+
loop: false,
|
|
861
|
+
})
|
|
862
|
+
if (choice === 'compare') {
|
|
863
|
+
return runSelectedAction(() => runNode('piwik.mjs', ['compare', '--from', from, '--to', to]))
|
|
864
|
+
}
|
|
865
|
+
const writeMode = await selectPrompt({
|
|
866
|
+
message: `Write dimensions from ${from} to ${to}?`,
|
|
867
|
+
choices: [
|
|
868
|
+
{ name: 'Dry run', value: 'dry-run' },
|
|
869
|
+
{ name: 'Apply', value: 'apply' },
|
|
870
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
871
|
+
],
|
|
872
|
+
default: 'dry-run',
|
|
873
|
+
loop: false,
|
|
874
|
+
})
|
|
875
|
+
if (writeMode === 'cancel') continue
|
|
876
|
+
const migrateArgs = ['migrate', '--from', from, '--to', to]
|
|
877
|
+
if (writeMode === 'dry-run') migrateArgs.push('--dry-run')
|
|
878
|
+
if (writeMode === 'apply') {
|
|
879
|
+
const confirmed = await confirmPrompt({
|
|
880
|
+
message: `This writes custom dimensions on ${to}. tracking_id is assigned by Piwik and cannot be reused. Continue?`,
|
|
881
|
+
default: false,
|
|
882
|
+
})
|
|
883
|
+
if (!confirmed) continue
|
|
884
|
+
migrateArgs.push('--yes')
|
|
885
|
+
}
|
|
886
|
+
return runSelectedAction(() => runNode('piwik.mjs', migrateArgs))
|
|
887
|
+
}
|
|
888
|
+
if (choice === 'sync') {
|
|
889
|
+
const { listPiwikEnvironments } = await import('./piwik-common.mjs')
|
|
890
|
+
const environments = listPiwikEnvironments(process.cwd())
|
|
891
|
+
const endpoints = [
|
|
892
|
+
{ name: 'Local map', value: 'local' },
|
|
893
|
+
...environments.map((site) => ({ name: site.environment, value: site.environment })),
|
|
894
|
+
]
|
|
895
|
+
const from = await selectPrompt({
|
|
896
|
+
message: 'From',
|
|
897
|
+
choices: endpoints,
|
|
898
|
+
default: 'local',
|
|
899
|
+
loop: false,
|
|
900
|
+
})
|
|
901
|
+
const toChoices = endpoints.filter((item) => item.value !== from)
|
|
902
|
+
if (toChoices.length === 0) {
|
|
903
|
+
console.log('[piwik] Need a local dimension map and a Piwik site in src/config/env.ts.')
|
|
904
|
+
continue
|
|
905
|
+
}
|
|
906
|
+
const defaultTo = toChoices.find((item) => item.value !== 'production' && item.value !== 'local')?.value || toChoices[0]?.value
|
|
907
|
+
const to = await selectPrompt({
|
|
908
|
+
message: 'To',
|
|
909
|
+
choices: toChoices,
|
|
910
|
+
default: defaultTo,
|
|
911
|
+
loop: false,
|
|
912
|
+
})
|
|
913
|
+
const writeMode = await selectPrompt({
|
|
914
|
+
message: from === 'local' ? `Write the local map up to ${to}?` : to === 'local' ? `Write tracking ids from ${from} into the local map?` : `Write dimensions from ${from} to ${to}?`,
|
|
915
|
+
choices: [
|
|
916
|
+
{ name: 'Dry run', value: 'dry-run' },
|
|
917
|
+
{ name: 'Apply', value: 'apply' },
|
|
918
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
919
|
+
],
|
|
920
|
+
default: 'dry-run',
|
|
921
|
+
loop: false,
|
|
922
|
+
})
|
|
923
|
+
if (writeMode === 'cancel') continue
|
|
924
|
+
/** @type {string[]} */
|
|
925
|
+
let syncArgs
|
|
926
|
+
if (from === 'local') syncArgs = ['sync', '--env', to]
|
|
927
|
+
else if (to === 'local') syncArgs = ['pull', '--env', from]
|
|
928
|
+
else syncArgs = ['migrate', '--from', from, '--to', to]
|
|
929
|
+
if (writeMode === 'dry-run') syncArgs.push('--dry-run')
|
|
930
|
+
if (writeMode === 'apply') {
|
|
931
|
+
const confirmed = await confirmPrompt({
|
|
932
|
+
message: to === 'local' ? 'This rewrites tracking ids in the local dimension map. Continue?' : `This writes custom dimensions on ${to}. tracking_id cannot be chosen for session and event. Continue?`,
|
|
933
|
+
default: false,
|
|
934
|
+
})
|
|
935
|
+
if (!confirmed) continue
|
|
936
|
+
syncArgs.push('--yes')
|
|
937
|
+
}
|
|
938
|
+
return runSelectedAction(() => runNode('piwik.mjs', syncArgs))
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
const writeMode = await selectPrompt({
|
|
942
|
+
message: 'Write to Piwik?',
|
|
943
|
+
choices: [
|
|
944
|
+
{ name: 'Dry run', value: 'dry-run' },
|
|
945
|
+
{ name: 'Apply', value: 'apply' },
|
|
946
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
947
|
+
],
|
|
948
|
+
default: 'dry-run',
|
|
949
|
+
loop: false,
|
|
950
|
+
})
|
|
951
|
+
if (writeMode === 'cancel') continue
|
|
952
|
+
const piwikArgs = [choice]
|
|
953
|
+
if (writeMode === 'dry-run') piwikArgs.push('--dry-run')
|
|
954
|
+
if (writeMode === 'apply') {
|
|
955
|
+
const confirmed = await confirmPrompt({
|
|
956
|
+
message: 'This writes custom dimensions in Piwik PRO. Slots cannot be reused after creation. Continue?',
|
|
957
|
+
default: false,
|
|
958
|
+
})
|
|
959
|
+
if (!confirmed) continue
|
|
960
|
+
piwikArgs.push('--yes')
|
|
961
|
+
}
|
|
962
|
+
return runSelectedAction(() => runNode('piwik.mjs', piwikArgs))
|
|
963
|
+
}
|
|
964
|
+
|
|
813
965
|
if (group === 'dependency-policy') {
|
|
814
966
|
const choice = await selectPrompt({
|
|
815
967
|
message: 'Dependecy policy',
|