@digigov/cli-app 2.4.3-nextjs-16.27-07-26-15-19 → 2.5.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/CHANGELOG.md +9 -8
- package/next.common.cjs +3 -2
- package/package.json +6 -6
- package/subcommands/start.js +33 -6
- package/utils/proxy-server.js +45 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
# Change Log - @digigov/cli-app
|
|
2
2
|
|
|
3
|
-
<!-- This log was last generated on Mon, 27 Jul 2026
|
|
3
|
+
<!-- This log was last generated on Mon, 27 Jul 2026 17:23:56 GMT and should not be manually modified. -->
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
-
## 2.
|
|
7
|
+
## 2.5.0
|
|
8
8
|
|
|
9
|
-
Mon, 27 Jul 2026
|
|
9
|
+
Mon, 27 Jul 2026 17:23:56 GMT
|
|
10
10
|
|
|
11
11
|
### Minor changes
|
|
12
12
|
|
|
13
|
-
- Next.js 13.1.1 -> 16.2.12: builds now use static export (output: 'export', next export was removed in Next 14) while next dev keeps the regular dev server, and digigov app start serves out/ statically (-p/--port, -H/--hostname). Drop next-images/url-loader/babel-loader in favor of built-in static image imports, remove the rimraf peer dependency, and modernize the dev proxy to http-proxy-middleware v3 running in-process. (sangelopoulos@admin.grnet.gr)
|
|
14
|
-
- Bump @digigov/cli-build to v2.
|
|
15
|
-
- Bump @digigov/cli to v2.
|
|
16
|
-
- Bump @digigov/cli-lint to v2.
|
|
17
|
-
- Bump @digigov/css to v2.
|
|
13
|
+
- Next.js 13.1.1 -> 16.2.12: builds now use static export (output: 'export', next export was removed in Next 14) while next dev keeps the regular dev server, and digigov app start serves out/ statically (-p/--port, -H/--hostname). Drop next-images/url-loader/babel-loader in favor of built-in static image imports, remove the rimraf peer dependency, and modernize the dev proxy to http-proxy-middleware v3 running in-process, arming websocket upgrades for ws: true proxy entries at startup so sockets reconnecting right after a restart are not dropped. (sangelopoulos@admin.grnet.gr)
|
|
14
|
+
- Bump @digigov/cli-build to v2.5.0
|
|
15
|
+
- Bump @digigov/cli to v2.5.0
|
|
16
|
+
- Bump @digigov/cli-lint to v2.5.0
|
|
17
|
+
- Bump @digigov/css to v2.5.0
|
|
18
18
|
|
|
19
19
|
### Patches
|
|
20
20
|
|
|
21
21
|
- default images.unoptimized in dev as well as build so dev image rendering matches the exported artifact and @digigov/nextjs Image's basePath prepend behaves the same everywhere (sangelopoulos@admin.grnet.gr)
|
|
22
|
+
- route dev proxy and Next config output through the @digigov/cli logger instead of bare console calls (sangelopoulos@admin.grnet.gr)
|
|
22
23
|
|
|
23
24
|
## 2.4.2
|
|
24
25
|
|
package/next.common.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const lib = require('@digigov/cli/lib');
|
|
2
|
+
const { logger } = require('@digigov/cli/lib/logger');
|
|
2
3
|
const { PHASE_DEVELOPMENT_SERVER } = require('next/constants');
|
|
3
4
|
let aliases = lib.aliases(true);
|
|
4
5
|
|
|
@@ -23,7 +24,7 @@ function withStaticExport(config, phase) {
|
|
|
23
24
|
...common,
|
|
24
25
|
};
|
|
25
26
|
if (exported.output === 'export' && exported.i18n) {
|
|
26
|
-
|
|
27
|
+
logger.warn(
|
|
27
28
|
'Built-in i18n routing is not supported with static export; ' +
|
|
28
29
|
'dropping the `i18n` config for this build. Locale routing must be ' +
|
|
29
30
|
'handled in userland (e.g. i18next without the Next.js `i18n` key).'
|
|
@@ -42,7 +43,7 @@ function makeBaseConfig(dir) {
|
|
|
42
43
|
...digigov.aliases,
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
logger.info(`Creating aliases for ${Object.keys(aliases).join(', ')}`);
|
|
46
47
|
return {
|
|
47
48
|
poweredByHeader: false,
|
|
48
49
|
trailingSlash: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digigov/cli-app",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "@digigov developer cli tool",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"commander": "12.1.0",
|
|
14
14
|
"globby": "11.0.0",
|
|
15
15
|
"publint": "0.1.8",
|
|
16
|
-
"@digigov/cli-build": "2.
|
|
16
|
+
"@digigov/cli-build": "2.5.0"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"typescript": "5.6.2",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"autoprefixer": "10.4.16",
|
|
23
23
|
"postcss": "8.4.4",
|
|
24
24
|
"tailwindcss": "3.4.13",
|
|
25
|
-
"@digigov/cli": "2.
|
|
26
|
-
"@digigov/css": "2.
|
|
25
|
+
"@digigov/cli": "2.5.0",
|
|
26
|
+
"@digigov/css": "2.5.0"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
".": "./index.js",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"typescript": "5.6.2",
|
|
42
42
|
"eslint": "9.16.0",
|
|
43
43
|
"prettier": "3.4.2",
|
|
44
|
-
"@digigov/cli": "2.
|
|
45
|
-
"@digigov/cli-lint": "2.
|
|
44
|
+
"@digigov/cli": "2.5.0",
|
|
45
|
+
"@digigov/cli-lint": "2.5.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"publint": "publint",
|
package/subcommands/start.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import { createRequire } from 'module';
|
|
2
3
|
|
|
3
4
|
import express from 'express';
|
|
5
|
+
import { PHASE_PRODUCTION_SERVER } from 'next/constants.js';
|
|
4
6
|
import { DigigovCommand, resolveProject, logger } from '@digigov/cli/lib';
|
|
5
7
|
import { EXEC_CONFIG } from '../common.js';
|
|
6
8
|
import path from 'path';
|
|
@@ -19,12 +21,32 @@ startCommand
|
|
|
19
21
|
)
|
|
20
22
|
.option('-H, --hostname <hostname>', 'Hostname to bind to', '0.0.0.0')
|
|
21
23
|
.action(async (options, ctx) => {
|
|
24
|
+
const port = parseInt(options.port, 10);
|
|
25
|
+
if (Number.isNaN(port)) {
|
|
26
|
+
logger.error(`Invalid port: ${options.port}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
22
29
|
const outDir = path.join(project.root, 'out');
|
|
23
30
|
if (!fs.existsSync(outDir)) {
|
|
24
31
|
await ctx.exec('next', ['build'], EXEC_CONFIG);
|
|
25
32
|
}
|
|
33
|
+
// The exported HTML references pages and assets under `basePath`, so the
|
|
34
|
+
// static site must be mounted there — as `next start` used to do.
|
|
35
|
+
const configPath = path.join(project.root, 'next.config.js');
|
|
36
|
+
let conf = {};
|
|
37
|
+
if (fs.existsSync(configPath)) {
|
|
38
|
+
const confModule = createRequire(configPath)(configPath);
|
|
39
|
+
conf =
|
|
40
|
+
typeof confModule === 'function'
|
|
41
|
+
? await confModule(PHASE_PRODUCTION_SERVER, { defaultConfig: {} })
|
|
42
|
+
: confModule;
|
|
43
|
+
}
|
|
44
|
+
const basePath = conf.basePath ?? '';
|
|
26
45
|
const server = express();
|
|
27
|
-
server.use(
|
|
46
|
+
server.use(
|
|
47
|
+
basePath || '/',
|
|
48
|
+
express.static(outDir, { extensions: ['html'] })
|
|
49
|
+
);
|
|
28
50
|
server.use((_req, res) => {
|
|
29
51
|
const notFoundPage = path.join(outDir, '404.html');
|
|
30
52
|
if (fs.existsSync(notFoundPage)) {
|
|
@@ -33,11 +55,16 @@ startCommand
|
|
|
33
55
|
res.status(404).send('Not Found');
|
|
34
56
|
}
|
|
35
57
|
});
|
|
36
|
-
server
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
58
|
+
server
|
|
59
|
+
.listen(port, options.hostname, () => {
|
|
60
|
+
logger.info(
|
|
61
|
+
`Serving ${outDir} on http://${options.hostname}:${port}${basePath}`
|
|
62
|
+
);
|
|
63
|
+
})
|
|
64
|
+
.on('error', (err) => {
|
|
65
|
+
logger.error(`Unable to start server: ${err.message}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
41
68
|
});
|
|
42
69
|
|
|
43
70
|
export default startCommand;
|
package/utils/proxy-server.js
CHANGED
|
@@ -3,8 +3,14 @@ import next from 'next';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
5
|
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
6
|
+
// `next` publishes no `exports` map, so the subpath needs the explicit
|
|
7
|
+
// extension to resolve under ESM.
|
|
8
|
+
import {
|
|
9
|
+
PHASE_DEVELOPMENT_SERVER,
|
|
10
|
+
PHASE_PRODUCTION_SERVER,
|
|
11
|
+
} from 'next/constants.js';
|
|
6
12
|
|
|
7
|
-
import { resolveProject } from '@digigov/cli/lib';
|
|
13
|
+
import { resolveProject, logger } from '@digigov/cli/lib';
|
|
8
14
|
|
|
9
15
|
const port = parseInt(process.env['PORT'] ?? '3000', 10);
|
|
10
16
|
const isDev = process.env.NODE_ENV !== 'production';
|
|
@@ -13,7 +19,17 @@ const project = resolveProject();
|
|
|
13
19
|
const devProxy = project.digigov.proxy;
|
|
14
20
|
|
|
15
21
|
const require = createRequire(import.meta.url);
|
|
16
|
-
const
|
|
22
|
+
const confModule = require(path.join(project.root, 'next.config.js'));
|
|
23
|
+
|
|
24
|
+
// nextrc exports a phase → config function; `next({ conf })` spreads the
|
|
25
|
+
// value without invoking it, so the phase must be resolved here.
|
|
26
|
+
const conf =
|
|
27
|
+
typeof confModule === 'function'
|
|
28
|
+
? await confModule(
|
|
29
|
+
isDev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_SERVER,
|
|
30
|
+
{ defaultConfig: {} }
|
|
31
|
+
)
|
|
32
|
+
: confModule;
|
|
17
33
|
|
|
18
34
|
// Next 16 removed the CJS `.default` interop export: `module.exports` itself is
|
|
19
35
|
// the server factory (on 13 too), but the d.ts still types the module as a
|
|
@@ -34,20 +50,42 @@ try {
|
|
|
34
50
|
const server = express();
|
|
35
51
|
|
|
36
52
|
// Set up the proxy.
|
|
53
|
+
const wsProxies = [];
|
|
37
54
|
if (isDev && devProxy) {
|
|
38
55
|
for (const [pathFilter, options] of Object.entries(devProxy)) {
|
|
39
|
-
|
|
56
|
+
const proxy = createProxyMiddleware({ pathFilter, ...options });
|
|
57
|
+
server.use(proxy);
|
|
58
|
+
if (options.ws) {
|
|
59
|
+
wsProxies.push(proxy);
|
|
60
|
+
}
|
|
40
61
|
}
|
|
41
62
|
}
|
|
42
63
|
|
|
43
64
|
// Default catch-all handler to allow Next.js to handle all other routes
|
|
44
65
|
server.use((req, res) => handle(req, res));
|
|
45
66
|
|
|
46
|
-
server.listen(port, () => {
|
|
47
|
-
|
|
67
|
+
const httpServer = server.listen(port, () => {
|
|
68
|
+
logger.info(`Ready on port ${port}`);
|
|
48
69
|
});
|
|
70
|
+
|
|
71
|
+
// Next and http-proxy-middleware each register their own `upgrade` listener,
|
|
72
|
+
// but only lazily — on the first HTTP request they see. A websocket that
|
|
73
|
+
// connects right after a restart, before any HTTP request (e.g. an open tab
|
|
74
|
+
// reconnecting through a `ws: true` proxy), finds no listener and hangs.
|
|
75
|
+
// Arm the ws proxies up front: `upgrade` checks its own pathFilter and
|
|
76
|
+
// no-ops once the proxy's internal listener exists, so nothing is handled
|
|
77
|
+
// twice. Next needs no arming — its HMR socket always follows a page load.
|
|
78
|
+
if (wsProxies.length > 0) {
|
|
79
|
+
httpServer.on('upgrade', (req, socket, head) => {
|
|
80
|
+
for (const proxy of wsProxies) {
|
|
81
|
+
proxy.upgrade(req, socket, head);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
49
85
|
} catch (err) {
|
|
50
|
-
|
|
51
|
-
|
|
86
|
+
logger.error(
|
|
87
|
+
'Unable to start the server:',
|
|
88
|
+
err instanceof Error ? err.stack : err
|
|
89
|
+
);
|
|
52
90
|
process.exit(1);
|
|
53
91
|
}
|