@dhis2/create-app 5.4.0-alpha.1 → 5.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2/create-app",
3
- "version": "5.4.0-alpha.1",
3
+ "version": "5.4.0",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ const { input, select } = require('@inquirer/prompts')
5
5
  const fg = require('fast-glob')
6
6
  const fs = require('fs-extra')
7
7
  const { default: getPackageManager } = require('./utils/getPackageManager')
8
+ const resolveExternalTemplateSource = require('./utils/resolveExternalTemplateSource')
8
9
 
9
10
  process.on('uncaughtException', (error) => {
10
11
  if (error instanceof Error && error.name === 'ExitPromptError') {
@@ -45,7 +46,8 @@ const commandHandler = {
45
46
  alias: ['ts', 'typeScript'],
46
47
  },
47
48
  template: {
48
- description: 'Which template to use (Basic, With React Router)',
49
+ description:
50
+ 'Which template to use (Basic, With React Router, or GitHub template specifier)',
49
51
  type: 'string',
50
52
  },
51
53
  packageManager: {
@@ -56,10 +58,16 @@ const commandHandler = {
56
58
  },
57
59
  }
58
60
 
59
- const getTemplateDirectory = (templateName) => {
60
- return templateName === 'react-router'
61
- ? templates.templateWithReactRouter
62
- : templates.templateWithList
61
+ const getBuiltInTemplateDirectory = (templateName) => {
62
+ if (templateName === 'basic') {
63
+ return templates.templateWithList
64
+ }
65
+
66
+ if (templateName === 'react-router') {
67
+ return templates.templateWithReactRouter
68
+ }
69
+
70
+ return null
63
71
  }
64
72
 
65
73
  const command = {
@@ -86,7 +94,7 @@ const command = {
86
94
  typeScript: argv.typescript ?? true,
87
95
  packageManager:
88
96
  argv.packageManager ?? getPackageManager() ?? 'pnpm',
89
- templateName: argv.template ?? 'basic',
97
+ templateSource: argv.template ?? 'basic',
90
98
  }
91
99
 
92
100
  if (!useDefauls) {
@@ -106,17 +114,29 @@ const command = {
106
114
  if (argv.template === undefined) {
107
115
  const template = await select({
108
116
  message: 'Select a template',
109
- default: 'ts',
117
+ default: 'basic',
110
118
  choices: [
111
119
  { name: 'Basic Template', value: 'basic' },
112
120
  {
113
121
  name: 'Template with React Router',
114
122
  value: 'react-router',
115
123
  },
124
+ {
125
+ name: 'Custom template from Git',
126
+ value: 'custom-git',
127
+ },
116
128
  ],
117
129
  })
118
130
 
119
- selectedOptions.templateName = template
131
+ if (template === 'custom-git') {
132
+ selectedOptions.templateSource = await input({
133
+ message:
134
+ 'Enter GitHub template specifier (e.g. owner/repo#main)',
135
+ required: true,
136
+ })
137
+ } else {
138
+ selectedOptions.templateSource = template
139
+ }
120
140
  }
121
141
  }
122
142
 
@@ -158,8 +178,30 @@ const command = {
158
178
  }
159
179
 
160
180
  reporter.info('Copying template files')
161
- const templateFiles = getTemplateDirectory(selectedOptions.templateName)
162
- fs.copySync(templateFiles, cwd)
181
+ let resolvedExternalTemplate
182
+ try {
183
+ const builtInTemplatePath = getBuiltInTemplateDirectory(
184
+ selectedOptions.templateSource
185
+ )
186
+
187
+ if (builtInTemplatePath) {
188
+ fs.copySync(builtInTemplatePath, cwd)
189
+ } else {
190
+ resolvedExternalTemplate = await resolveExternalTemplateSource(
191
+ selectedOptions.templateSource
192
+ )
193
+ fs.copySync(resolvedExternalTemplate.templatePath, cwd)
194
+ }
195
+ } catch (error) {
196
+ reporter.error(
197
+ error instanceof Error ? error.message : String(error)
198
+ )
199
+ process.exit(1)
200
+ } finally {
201
+ if (resolvedExternalTemplate) {
202
+ await resolvedExternalTemplate.cleanup()
203
+ }
204
+ }
163
205
 
164
206
  const paths = {
165
207
  base: cwd,
@@ -0,0 +1,162 @@
1
+ const githubHosts = new Set(['github.com', 'www.github.com'])
2
+ const ownerPattern = /^[a-zA-Z0-9_.-]+$/
3
+
4
+ const parseRef = (rawTemplateSource, refPart) => {
5
+ if (refPart === undefined) {
6
+ return null
7
+ }
8
+ if (!refPart) {
9
+ throw new Error(
10
+ `Invalid template source "${rawTemplateSource}". Ref cannot be empty after "#".`
11
+ )
12
+ }
13
+ if (refPart.includes(':')) {
14
+ throw new Error(
15
+ `Invalid template source "${rawTemplateSource}". Use "owner/repo" or "owner/repo#ref".`
16
+ )
17
+ }
18
+
19
+ return refPart
20
+ }
21
+
22
+ const parseGithubUrlSource = (sourceWithoutRef) => {
23
+ const parsedUrl = new URL(sourceWithoutRef)
24
+ if (!githubHosts.has(parsedUrl.host)) {
25
+ throw new Error(
26
+ `Unsupported template host "${parsedUrl.host}". Only github.com repositories are supported.`
27
+ )
28
+ }
29
+
30
+ const pathParts = parsedUrl.pathname.split('/').filter(Boolean).slice(0, 2)
31
+ if (pathParts.length < 2) {
32
+ throw new Error(
33
+ `Invalid GitHub repository path in "${sourceWithoutRef}". Use "owner/repo".`
34
+ )
35
+ }
36
+
37
+ return {
38
+ owner: pathParts[0],
39
+ repo: pathParts[1],
40
+ }
41
+ }
42
+
43
+ const parseGithubShorthandSource = (rawTemplateSource, sourceWithoutRef) => {
44
+ const separatorIndex = sourceWithoutRef.indexOf('/')
45
+ const hasSingleSeparator =
46
+ separatorIndex > 0 &&
47
+ separatorIndex === sourceWithoutRef.lastIndexOf('/')
48
+ if (!hasSingleSeparator) {
49
+ throw new Error(
50
+ `Invalid template source "${rawTemplateSource}". Use "owner/repo" or "owner/repo#ref".`
51
+ )
52
+ }
53
+
54
+ const owner = sourceWithoutRef.slice(0, separatorIndex)
55
+ const repo = sourceWithoutRef.slice(separatorIndex + 1)
56
+ if (
57
+ !ownerPattern.test(owner) ||
58
+ !repo ||
59
+ /\s/.test(repo) ||
60
+ repo.includes('/')
61
+ ) {
62
+ throw new Error(
63
+ `Invalid template source "${rawTemplateSource}". Use "owner/repo" or "owner/repo#ref".`
64
+ )
65
+ }
66
+
67
+ return {
68
+ owner,
69
+ repo,
70
+ }
71
+ }
72
+
73
+ const isValidRefPart = (refPart) => {
74
+ if (refPart === undefined) {
75
+ return true
76
+ }
77
+
78
+ return Boolean(refPart) && !refPart.includes(':')
79
+ }
80
+
81
+ const isValidShorthandSource = (sourceWithoutRef) => {
82
+ const separatorIndex = sourceWithoutRef.indexOf('/')
83
+ const hasSingleSeparator =
84
+ separatorIndex > 0 &&
85
+ separatorIndex === sourceWithoutRef.lastIndexOf('/')
86
+ if (!hasSingleSeparator) {
87
+ return false
88
+ }
89
+
90
+ const owner = sourceWithoutRef.slice(0, separatorIndex)
91
+ const repo = sourceWithoutRef.slice(separatorIndex + 1)
92
+
93
+ return (
94
+ ownerPattern.test(owner) &&
95
+ Boolean(repo) &&
96
+ !/\s/.test(repo) &&
97
+ !repo.includes('/')
98
+ )
99
+ }
100
+
101
+ const parseGitTemplateSpecifier = (templateSource) => {
102
+ const rawTemplateSource = String(templateSource || '').trim()
103
+ if (!rawTemplateSource) {
104
+ throw new Error('Template source cannot be empty.')
105
+ }
106
+
107
+ const [sourceWithoutRef, refPart, ...rest] = rawTemplateSource.split('#')
108
+ if (rest.length > 0) {
109
+ throw new Error(
110
+ `Invalid template source "${rawTemplateSource}". Use at most one "#" to specify a ref.`
111
+ )
112
+ }
113
+
114
+ const ref = parseRef(rawTemplateSource, refPart)
115
+ const sourceInfo = sourceWithoutRef.startsWith('https://')
116
+ ? parseGithubUrlSource(sourceWithoutRef)
117
+ : parseGithubShorthandSource(rawTemplateSource, sourceWithoutRef)
118
+
119
+ const owner = sourceInfo.owner
120
+ let repo = sourceInfo.repo
121
+
122
+ if (repo.endsWith('.git')) {
123
+ repo = repo.slice(0, -4)
124
+ }
125
+
126
+ if (!owner || !repo) {
127
+ throw new Error(
128
+ `Invalid template source "${rawTemplateSource}". Missing GitHub owner or repository name.`
129
+ )
130
+ }
131
+
132
+ return {
133
+ owner,
134
+ repo,
135
+ ref,
136
+ repoUrl: `https://github.com/${owner}/${repo}.git`,
137
+ raw: rawTemplateSource,
138
+ }
139
+ }
140
+
141
+ const isGitTemplateSpecifier = (templateSource) => {
142
+ const rawTemplateSource = String(templateSource || '').trim()
143
+ if (!rawTemplateSource) {
144
+ return false
145
+ }
146
+
147
+ if (rawTemplateSource.startsWith('https://')) {
148
+ return true
149
+ }
150
+
151
+ const [sourceWithoutRef, refPart, ...rest] = rawTemplateSource.split('#')
152
+ if (rest.length > 0 || !isValidRefPart(refPart)) {
153
+ return false
154
+ }
155
+
156
+ return isValidShorthandSource(sourceWithoutRef)
157
+ }
158
+
159
+ module.exports = {
160
+ isGitTemplateSpecifier,
161
+ parseGitTemplateSpecifier,
162
+ }
@@ -0,0 +1,66 @@
1
+ const os = require('node:os')
2
+ const path = require('node:path')
3
+ const { exec } = require('@dhis2/cli-helpers-engine')
4
+ const fs = require('fs-extra')
5
+ const {
6
+ isGitTemplateSpecifier,
7
+ parseGitTemplateSpecifier,
8
+ } = require('./isGitTemplateSpecifier')
9
+ const validateTemplateDirectory = require('./validateTemplateDirectory')
10
+
11
+ const resolveExternalTemplateSource = async (templateSource) => {
12
+ const normalizedTemplateSource = String(templateSource || '').trim()
13
+
14
+ if (!isGitTemplateSpecifier(normalizedTemplateSource)) {
15
+ throw new Error(
16
+ `Unknown template "${normalizedTemplateSource}". Use one of [basic, react-router] or a GitHub template specifier like "owner/repo#ref".`
17
+ )
18
+ }
19
+
20
+ const parsedSpecifier = parseGitTemplateSpecifier(normalizedTemplateSource)
21
+ const tempBase = fs.mkdtempSync(
22
+ path.join(os.tmpdir(), 'd2-create-template-source-')
23
+ )
24
+ const clonedRepoPath = path.join(tempBase, 'repo')
25
+
26
+ try {
27
+ const gitCloneArgs = parsedSpecifier.ref
28
+ ? [
29
+ 'clone',
30
+ '--depth',
31
+ '1',
32
+ '--branch',
33
+ parsedSpecifier.ref,
34
+ parsedSpecifier.repoUrl,
35
+ clonedRepoPath,
36
+ ]
37
+ : ['clone', '--depth', '1', parsedSpecifier.repoUrl, clonedRepoPath]
38
+
39
+ await exec({
40
+ cmd: 'git',
41
+ args: gitCloneArgs,
42
+ pipe: false,
43
+ })
44
+
45
+ validateTemplateDirectory(clonedRepoPath, normalizedTemplateSource)
46
+
47
+ return {
48
+ templatePath: clonedRepoPath,
49
+ cleanup: async () => {
50
+ fs.removeSync(tempBase)
51
+ },
52
+ }
53
+ } catch (error) {
54
+ fs.removeSync(tempBase)
55
+ if (error instanceof Error && error.message) {
56
+ throw new Error(
57
+ `Failed to resolve template "${normalizedTemplateSource}": ${error.message}`
58
+ )
59
+ }
60
+ throw new Error(
61
+ `Failed to resolve template "${normalizedTemplateSource}".`
62
+ )
63
+ }
64
+ }
65
+
66
+ module.exports = resolveExternalTemplateSource
@@ -0,0 +1,26 @@
1
+ const path = require('node:path')
2
+ const fs = require('fs-extra')
3
+
4
+ const validateTemplateDirectory = (templatePath, templateSource) => {
5
+ if (!fs.existsSync(templatePath)) {
6
+ throw new Error(
7
+ `Template path "${templatePath}" from source "${templateSource}" does not exist.`
8
+ )
9
+ }
10
+
11
+ const stats = fs.statSync(templatePath)
12
+ if (!stats.isDirectory()) {
13
+ throw new Error(
14
+ `Template path "${templatePath}" from source "${templateSource}" is not a directory.`
15
+ )
16
+ }
17
+
18
+ const packageJsonPath = path.join(templatePath, 'package.json')
19
+ if (!fs.existsSync(packageJsonPath)) {
20
+ throw new Error(
21
+ `Template source "${templateSource}" is missing "package.json" at "${templatePath}".`
22
+ )
23
+ }
24
+ }
25
+
26
+ module.exports = validateTemplateDirectory
@@ -15,7 +15,7 @@
15
15
  "react-dom": "^18.3.1"
16
16
  },
17
17
  "devDependencies": {
18
- "@dhis2/cli-app-scripts": "12.8.0-alpha.3",
18
+ "@dhis2/cli-app-scripts": "12.10.3",
19
19
  "@dhis2/config-eslint": "^0.2.2",
20
20
  "@dhis2/config-prettier": "^0.2.2",
21
21
  "@eslint/compat": "^2.0.0",
@@ -2873,19 +2873,19 @@
2873
2873
  }
2874
2874
  },
2875
2875
  "node_modules/@dhis2/app-adapter": {
2876
- "version": "12.8.0-alpha.3",
2877
- "resolved": "https://registry.npmjs.org/@dhis2/app-adapter/-/app-adapter-12.8.0-alpha.3.tgz",
2878
- "integrity": "sha512-8i2aVxlNPpA/rzzGnpzUycIc94f89j6VntPw1NqAcXAKpjTLaKaFqEW+TM3Un19iLOahIgTDND8qsgIE9hgMaQ==",
2876
+ "version": "12.10.3",
2877
+ "resolved": "https://registry.npmjs.org/@dhis2/app-adapter/-/app-adapter-12.10.3.tgz",
2878
+ "integrity": "sha512-eCO1iPl2V8XTt6x4IkOCHc2qz4EJBv/Hd9am7u3IbRwD9sMNaQ1sQQqQpbbNS+9plq5GbZ5ADFhWHWLDYvb8pw==",
2879
2879
  "dev": true,
2880
2880
  "license": "BSD-3-Clause",
2881
2881
  "dependencies": {
2882
- "@dhis2/pwa": "12.8.0-alpha.3",
2882
+ "@dhis2/pwa": "12.10.3",
2883
2883
  "moment": "^2.24.0"
2884
2884
  },
2885
2885
  "peerDependencies": {
2886
2886
  "@dhis2/app-runtime": "^3.11.1",
2887
- "@dhis2/d2-i18n": "^1",
2888
- "@dhis2/ui": ">=10.7.1",
2887
+ "@dhis2/d2-i18n": "^1.2.0",
2888
+ "@dhis2/ui": ">=10.9.2",
2889
2889
  "classnames": "^2",
2890
2890
  "moment": "^2",
2891
2891
  "prop-types": "^15",
@@ -2999,17 +2999,17 @@
2999
2999
  }
3000
3000
  },
3001
3001
  "node_modules/@dhis2/app-shell": {
3002
- "version": "12.8.0-alpha.3",
3003
- "resolved": "https://registry.npmjs.org/@dhis2/app-shell/-/app-shell-12.8.0-alpha.3.tgz",
3004
- "integrity": "sha512-/Zc9VLBN56B8lS1K3OyXmVYbjsT56/bg54/ZPa4tHGo5L52phweU9afmLbcNulm9SmzaCMGUeC92OsdGS90g5A==",
3002
+ "version": "12.10.3",
3003
+ "resolved": "https://registry.npmjs.org/@dhis2/app-shell/-/app-shell-12.10.3.tgz",
3004
+ "integrity": "sha512-yAEV4lftl+iFLzqzDWyAnl7jKLfgU/9FbnAqo1bIqTNeEfbhT4d6i7+FwjPvUyO0/f61C9mqAxP+/m5LfXRWDA==",
3005
3005
  "dev": true,
3006
3006
  "license": "BSD-3-Clause",
3007
3007
  "dependencies": {
3008
- "@dhis2/app-adapter": "12.8.0-alpha.3",
3008
+ "@dhis2/app-adapter": "12.10.3",
3009
3009
  "@dhis2/app-runtime": "^3.14.3",
3010
- "@dhis2/d2-i18n": "^1.1.1",
3011
- "@dhis2/pwa": "12.8.0-alpha.3",
3012
- "@dhis2/ui": "^10.7.8",
3010
+ "@dhis2/d2-i18n": "^1.2.0",
3011
+ "@dhis2/pwa": "12.10.3",
3012
+ "@dhis2/ui": "^10.9.2",
3013
3013
  "classnames": "^2.2.6",
3014
3014
  "moment": "^2.29.1",
3015
3015
  "post-robot": "^10.0.46",
@@ -3024,9 +3024,9 @@
3024
3024
  }
3025
3025
  },
3026
3026
  "node_modules/@dhis2/cli-app-scripts": {
3027
- "version": "12.8.0-alpha.3",
3028
- "resolved": "https://registry.npmjs.org/@dhis2/cli-app-scripts/-/cli-app-scripts-12.8.0-alpha.3.tgz",
3029
- "integrity": "sha512-4xrL9XgCn0Apoh0Yg8FYJWVhgbjm4yhuLbT6f9GvB7adt9G6kJuNl8CjcQUIZNLutCks4Pu61OLacMVBC7dupA==",
3027
+ "version": "12.10.3",
3028
+ "resolved": "https://registry.npmjs.org/@dhis2/cli-app-scripts/-/cli-app-scripts-12.10.3.tgz",
3029
+ "integrity": "sha512-p32iy1TTzaGPFUDZEmK8eLDpMTvDKrRchLOOEZn2c/63acpc3fIfI/xR82VHV7AQlq9ahmIm54XiUPAh/MCadQ==",
3030
3030
  "dev": true,
3031
3031
  "license": "BSD-3-Clause",
3032
3032
  "dependencies": {
@@ -3036,10 +3036,12 @@
3036
3036
  "@babel/plugin-transform-class-properties": "^7.27.1",
3037
3037
  "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
3038
3038
  "@babel/plugin-transform-optional-chaining": "^7.27.1",
3039
+ "@babel/plugin-transform-private-methods": "^7.27.1",
3040
+ "@babel/plugin-transform-private-property-in-object": "^7.27.1",
3039
3041
  "@babel/preset-env": "^7.27.2",
3040
3042
  "@babel/preset-react": "^7.0.0",
3041
3043
  "@babel/preset-typescript": "^7.27.1",
3042
- "@dhis2/app-shell": "12.8.0-alpha.3",
3044
+ "@dhis2/app-shell": "12.10.3",
3043
3045
  "@dhis2/cli-helpers-engine": "^3.2.2",
3044
3046
  "@jest/core": "^27.0.6",
3045
3047
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
@@ -3666,9 +3668,9 @@
3666
3668
  }
3667
3669
  },
3668
3670
  "node_modules/@dhis2/pwa": {
3669
- "version": "12.8.0-alpha.3",
3670
- "resolved": "https://registry.npmjs.org/@dhis2/pwa/-/pwa-12.8.0-alpha.3.tgz",
3671
- "integrity": "sha512-sFEeKtTnNncG0sUx9cIJIsfb7LrWQd1/+JCkSeM9dBzdr5Rt2SCkSlDNUf09RbxRAcXUbUt6JNlECke+Hi/DLg==",
3671
+ "version": "12.10.3",
3672
+ "resolved": "https://registry.npmjs.org/@dhis2/pwa/-/pwa-12.10.3.tgz",
3673
+ "integrity": "sha512-WXWgtmjb95t5jU8vFYCdlJ1mczkLGDCXL69ZC/kUa2XTAby6cpLkoZMNFfOyoVOOtbq0J88UEaXrDGK1zoGfbg==",
3672
3674
  "dev": true,
3673
3675
  "license": "BSD-3-Clause",
3674
3676
  "dependencies": {
@@ -20,7 +20,7 @@
20
20
  "react-dom": "^18.3.1"
21
21
  },
22
22
  "devDependencies": {
23
- "@dhis2/cli-app-scripts": "12.8.0-alpha.3",
23
+ "@dhis2/cli-app-scripts": "12.10.3",
24
24
  "@dhis2/config-eslint": "^0.2.2",
25
25
  "@dhis2/config-prettier": "^0.2.2",
26
26
  "@eslint/compat": "^2.0.0",
@@ -22,8 +22,8 @@ importers:
22
22
  version: 18.3.1(react@18.3.1)
23
23
  devDependencies:
24
24
  '@dhis2/cli-app-scripts':
25
- specifier: 12.8.0-alpha.3
26
- version: 12.8.0-alpha.3(@types/babel__core@7.20.5)(@types/node@25.0.3)(react@18.3.1)(terser@5.44.1)(type-fest@0.21.3)(typescript@5.9.3)
25
+ specifier: 12.10.3
26
+ version: 12.10.3(@types/babel__core@7.20.5)(@types/node@25.0.3)(react@18.3.1)(terser@5.44.1)(type-fest@0.21.3)(typescript@5.9.3)
27
27
  '@dhis2/config-eslint':
28
28
  specifier: ^0.2.2
29
29
  version: 0.2.2(eslint@9.39.2)
@@ -1056,12 +1056,12 @@ packages:
1056
1056
  react-dom: ^16.13 || ^18
1057
1057
  styled-jsx: ^4
1058
1058
 
1059
- '@dhis2/app-adapter@12.8.0-alpha.3':
1060
- resolution: {integrity: sha512-8i2aVxlNPpA/rzzGnpzUycIc94f89j6VntPw1NqAcXAKpjTLaKaFqEW+TM3Un19iLOahIgTDND8qsgIE9hgMaQ==}
1059
+ '@dhis2/app-adapter@12.10.3':
1060
+ resolution: {integrity: sha512-eCO1iPl2V8XTt6x4IkOCHc2qz4EJBv/Hd9am7u3IbRwD9sMNaQ1sQQqQpbbNS+9plq5GbZ5ADFhWHWLDYvb8pw==}
1061
1061
  peerDependencies:
1062
1062
  '@dhis2/app-runtime': ^3.11.1
1063
- '@dhis2/d2-i18n': ^1
1064
- '@dhis2/ui': '>=10.7.1'
1063
+ '@dhis2/d2-i18n': ^1.2.0
1064
+ '@dhis2/ui': '>=10.9.2'
1065
1065
  classnames: ^2
1066
1066
  moment: ^2
1067
1067
  prop-types: ^15
@@ -1115,12 +1115,12 @@ packages:
1115
1115
  react: ^16.8.6 || ^18
1116
1116
  react-dom: ^16.8.6 || ^18
1117
1117
 
1118
- '@dhis2/app-shell@12.8.0-alpha.3':
1119
- resolution: {integrity: sha512-/Zc9VLBN56B8lS1K3OyXmVYbjsT56/bg54/ZPa4tHGo5L52phweU9afmLbcNulm9SmzaCMGUeC92OsdGS90g5A==}
1118
+ '@dhis2/app-shell@12.10.3':
1119
+ resolution: {integrity: sha512-yAEV4lftl+iFLzqzDWyAnl7jKLfgU/9FbnAqo1bIqTNeEfbhT4d6i7+FwjPvUyO0/f61C9mqAxP+/m5LfXRWDA==}
1120
1120
  engines: {node: ^18.0.0 || >=20.0.0}
1121
1121
 
1122
- '@dhis2/cli-app-scripts@12.8.0-alpha.3':
1123
- resolution: {integrity: sha512-4xrL9XgCn0Apoh0Yg8FYJWVhgbjm4yhuLbT6f9GvB7adt9G6kJuNl8CjcQUIZNLutCks4Pu61OLacMVBC7dupA==}
1122
+ '@dhis2/cli-app-scripts@12.10.3':
1123
+ resolution: {integrity: sha512-p32iy1TTzaGPFUDZEmK8eLDpMTvDKrRchLOOEZn2c/63acpc3fIfI/xR82VHV7AQlq9ahmIm54XiUPAh/MCadQ==}
1124
1124
  engines: {node: ^18.0.0 || >=20.0.0}
1125
1125
  hasBin: true
1126
1126
 
@@ -1152,8 +1152,8 @@ packages:
1152
1152
  peerDependencies:
1153
1153
  prop-types: ^15
1154
1154
 
1155
- '@dhis2/pwa@12.8.0-alpha.3':
1156
- resolution: {integrity: sha512-sFEeKtTnNncG0sUx9cIJIsfb7LrWQd1/+JCkSeM9dBzdr5Rt2SCkSlDNUf09RbxRAcXUbUt6JNlECke+Hi/DLg==}
1155
+ '@dhis2/pwa@12.10.3':
1156
+ resolution: {integrity: sha512-WXWgtmjb95t5jU8vFYCdlJ1mczkLGDCXL69ZC/kUa2XTAby6cpLkoZMNFfOyoVOOtbq0J88UEaXrDGK1zoGfbg==}
1157
1157
 
1158
1158
  '@dhis2/ui-constants@10.11.0':
1159
1159
  resolution: {integrity: sha512-uEFrVwXV0+3vwg8DlDrZXhltqTx7k9i4I3tPsC1msjVtWUndOb7j8Mc3Xukp+PXF4Vb8WuHwzNXaei2s6HrWtg==}
@@ -5245,6 +5245,7 @@ packages:
5245
5245
  tar@4.4.19:
5246
5246
  resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}
5247
5247
  engines: {node: '>=4.5'}
5248
+ deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
5248
5249
 
5249
5250
  temp-dir@2.0.0:
5250
5251
  resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
@@ -7284,11 +7285,11 @@ snapshots:
7284
7285
  react-dom: 18.3.1(react@18.3.1)
7285
7286
  styled-jsx: 4.0.1(@babel/core@7.28.5)(react@18.3.1)
7286
7287
 
7287
- '@dhis2/app-adapter@12.8.0-alpha.3(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(@dhis2/ui@10.11.0(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1)))(classnames@2.5.1)(moment@2.30.1)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1))':
7288
+ '@dhis2/app-adapter@12.10.3(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(@dhis2/ui@10.11.0(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1)))(classnames@2.5.1)(moment@2.30.1)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1))':
7288
7289
  dependencies:
7289
7290
  '@dhis2/app-runtime': 3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
7290
7291
  '@dhis2/d2-i18n': 1.2.0
7291
- '@dhis2/pwa': 12.8.0-alpha.3
7292
+ '@dhis2/pwa': 12.10.3
7292
7293
  '@dhis2/ui': 10.11.0(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1))
7293
7294
  classnames: 2.5.1
7294
7295
  moment: 2.30.1
@@ -7356,12 +7357,12 @@ snapshots:
7356
7357
  react: 18.3.1
7357
7358
  react-dom: 18.3.1(react@18.3.1)
7358
7359
 
7359
- '@dhis2/app-shell@12.8.0-alpha.3(@babel/core@7.28.5)':
7360
+ '@dhis2/app-shell@12.10.3(@babel/core@7.28.5)':
7360
7361
  dependencies:
7361
- '@dhis2/app-adapter': 12.8.0-alpha.3(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(@dhis2/ui@10.11.0(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1)))(classnames@2.5.1)(moment@2.30.1)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1))
7362
+ '@dhis2/app-adapter': 12.10.3(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(@dhis2/ui@10.11.0(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1)))(classnames@2.5.1)(moment@2.30.1)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1))
7362
7363
  '@dhis2/app-runtime': 3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
7363
7364
  '@dhis2/d2-i18n': 1.2.0
7364
- '@dhis2/pwa': 12.8.0-alpha.3
7365
+ '@dhis2/pwa': 12.10.3
7365
7366
  '@dhis2/ui': 10.11.0(@dhis2/app-runtime@3.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dhis2/d2-i18n@1.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-jsx@4.0.1(@babel/core@7.28.5)(react@18.3.1))
7366
7367
  classnames: 2.5.1
7367
7368
  moment: 2.30.1
@@ -7375,7 +7376,7 @@ snapshots:
7375
7376
  - '@babel/core'
7376
7377
  - react-native
7377
7378
 
7378
- '@dhis2/cli-app-scripts@12.8.0-alpha.3(@types/babel__core@7.20.5)(@types/node@25.0.3)(react@18.3.1)(terser@5.44.1)(type-fest@0.21.3)(typescript@5.9.3)':
7379
+ '@dhis2/cli-app-scripts@12.10.3(@types/babel__core@7.20.5)(@types/node@25.0.3)(react@18.3.1)(terser@5.44.1)(type-fest@0.21.3)(typescript@5.9.3)':
7379
7380
  dependencies:
7380
7381
  '@babel/core': 7.28.5
7381
7382
  '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.5)
@@ -7383,10 +7384,12 @@ snapshots:
7383
7384
  '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.5)
7384
7385
  '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.5)
7385
7386
  '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5)
7387
+ '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.5)
7388
+ '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.5)
7386
7389
  '@babel/preset-env': 7.28.5(@babel/core@7.28.5)
7387
7390
  '@babel/preset-react': 7.28.5(@babel/core@7.28.5)
7388
7391
  '@babel/preset-typescript': 7.28.5(@babel/core@7.28.5)
7389
- '@dhis2/app-shell': 12.8.0-alpha.3(@babel/core@7.28.5)
7392
+ '@dhis2/app-shell': 12.10.3(@babel/core@7.28.5)
7390
7393
  '@dhis2/cli-helpers-engine': 3.2.2
7391
7394
  '@jest/core': 27.5.1
7392
7395
  '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.11.0)(type-fest@0.21.3)(webpack@5.104.1)
@@ -7512,7 +7515,7 @@ snapshots:
7512
7515
  dependencies:
7513
7516
  prop-types: 15.8.1
7514
7517
 
7515
- '@dhis2/pwa@12.8.0-alpha.3':
7518
+ '@dhis2/pwa@12.10.3':
7516
7519
  dependencies:
7517
7520
  idb: 6.1.5
7518
7521
  workbox-precaching: 7.4.0
@@ -21,7 +21,7 @@
21
21
  "react-router": "^7.11.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@dhis2/cli-app-scripts": "12.8.0-alpha.3",
24
+ "@dhis2/cli-app-scripts": "12.10.3",
25
25
  "@dhis2/config-eslint": "^0.2.2",
26
26
  "@dhis2/config-prettier": "^0.2.2",
27
27
  "@eslint/compat": "^2.0.0",