@maka/maka-cli 5.12.0 → 5.13.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/bundle/typescript/package.json +2 -1
- package/bundle/typescript/src/commands/aws/ci.sub.cmd.js +1 -0
- package/bundle/typescript/src/commands/aws/ci.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/commands/build/build.js +13 -37
- package/bundle/typescript/src/commands/build/build.js.map +1 -1
- package/bundle/typescript/src/commands/create.js +13 -28
- package/bundle/typescript/src/commands/create.js.map +1 -1
- package/bundle/typescript/src/commands/deploy/_index.d.ts +1 -0
- package/bundle/typescript/src/commands/deploy/_index.js +1 -0
- package/bundle/typescript/src/commands/deploy/_index.js.map +1 -1
- package/bundle/typescript/src/commands/deploy/deploy.command.js +1 -0
- package/bundle/typescript/src/commands/deploy/deploy.command.js.map +1 -1
- package/bundle/typescript/src/commands/deploy/github.sub.cmd.d.ts +1 -0
- package/bundle/typescript/src/commands/deploy/github.sub.cmd.js +147 -0
- package/bundle/typescript/src/commands/deploy/github.sub.cmd.js.map +1 -0
- package/bundle/typescript/src/commands/run/run.command.js +31 -31
- package/bundle/typescript/src/commands/run/run.command.js.map +1 -1
- package/bundle/typescript/src/templates/meteor/config/deploy.sh.template +73 -0
- package/bundle/typescript/src/templates/meteor/config/nginx.conf.template +31 -0
- package/bundle/typescript/src/templates/meteor/github/workflows/deploy.yaml +82 -0
- package/bundle/typescript/src/tools/mpi/mpi.class.d.ts +18 -0
- package/bundle/typescript/src/tools/mpi/mpi.class.js +233 -3
- package/bundle/typescript/src/tools/mpi/mpi.class.js.map +1 -1
- package/bundle/typescript/src/tools/mpi/sdk-runtime.d.ts +5 -0
- package/bundle/typescript/src/tools/mpi/sdk-runtime.js +41 -0
- package/bundle/typescript/src/tools/mpi/sdk-runtime.js.map +1 -0
- package/bundle/typescript/src/tools/pkg/pkg.class.js +79 -78
- package/bundle/typescript/src/tools/pkg/pkg.class.js.map +1 -1
- package/bundle/typescript/src/tools/scaffold/scaffold.class.js +16 -7
- package/bundle/typescript/src/tools/scaffold/scaffold.class.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
2
3
|
import { rimraf } from 'rimraf';
|
|
3
|
-
import { execSync } from 'child_process';
|
|
4
4
|
import MakaGen from '../../generators/maka.gen.js';
|
|
5
5
|
import { Command } from '../../command.js';
|
|
6
6
|
import { Log } from '../../tools/log/log.class.js';
|
|
@@ -97,15 +97,6 @@ const Run = Command.create({
|
|
|
97
97
|
],
|
|
98
98
|
}, async function (args, opts) {
|
|
99
99
|
try {
|
|
100
|
-
if (this.mpi.isMeteorInstalled()) {
|
|
101
|
-
Log.notice('Meteor is installed.');
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
Log.notice('Meteor is not installed or cannot be found in your path. Installing...');
|
|
105
|
-
execSync('maka install --force', { stdio: 'inherit' });
|
|
106
|
-
}
|
|
107
|
-
// Check for meteor package requirements
|
|
108
|
-
await this.pkg.checkMeteorPackage('autoupdate', { shouldInstall: true });
|
|
109
100
|
await this.pkg.ensureAllDependenciesInstalled();
|
|
110
101
|
// Invoke the specified generator
|
|
111
102
|
const command = args[0];
|
|
@@ -120,6 +111,21 @@ const Run = Command.create({
|
|
|
120
111
|
if (opts['mobileServer'] && typeof opts['mobileServer'] === 'boolean') {
|
|
121
112
|
throw new Error('Please provide a URL where your mobile app should connect to your server (e.g., -m | --mobile-server=https://example-server.com)');
|
|
122
113
|
}
|
|
114
|
+
// Flags with no equivalent in sdk.createAppRunner() (port, mongoUrl,
|
|
115
|
+
// once, settingsFile, buildOptions only) -- warn rather than silently
|
|
116
|
+
// drop them now that run no longer shells out to a real meteor binary.
|
|
117
|
+
const unsupportedFlags = [
|
|
118
|
+
[opts.inspect, '--inspect'],
|
|
119
|
+
[opts['mobileServer'], '--mobile-server'],
|
|
120
|
+
[opts['excludeArchs'], '--exclude-archs'],
|
|
121
|
+
[opts['extraPackages'], '--extra-packages'],
|
|
122
|
+
[opts['rawLogs'], '--raw-logs'],
|
|
123
|
+
];
|
|
124
|
+
for (const [value, flag] of unsupportedFlags) {
|
|
125
|
+
if (value) {
|
|
126
|
+
Log.warn(`${flag} isn't supported by maka run yet and will be ignored.`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
123
129
|
// always ensure local exists
|
|
124
130
|
const localExists = this.cfg.checkConfigExists('local');
|
|
125
131
|
if (!localExists) {
|
|
@@ -150,14 +156,12 @@ const Run = Command.create({
|
|
|
150
156
|
Log.info('Cannot find Node Environment file, creating: ' + relativeDotEnvPath);
|
|
151
157
|
await this.fsi.createFile({ filePath: processDotEnvPath, data: '' });
|
|
152
158
|
}
|
|
159
|
+
let resolvedSettingsPath;
|
|
153
160
|
if (this.fsi.isFile(settingsPath)) {
|
|
154
161
|
// Use path.relative to compute the relative path
|
|
155
162
|
const relativeSettingsPath = path.relative(process.cwd(), settingsPath);
|
|
156
163
|
Log.notice('Meteor Settings: ' + relativeSettingsPath);
|
|
157
|
-
|
|
158
|
-
'--settings',
|
|
159
|
-
settingsPath
|
|
160
|
-
]);
|
|
164
|
+
resolvedSettingsPath = settingsPath;
|
|
161
165
|
}
|
|
162
166
|
else {
|
|
163
167
|
const relativeSettingsPath = path.relative(process.cwd(), settingsPath);
|
|
@@ -165,24 +169,20 @@ const Run = Command.create({
|
|
|
165
169
|
}
|
|
166
170
|
const splitPath = configPath.split(path.sep);
|
|
167
171
|
const envKey = splitPath[splitPath.length - 1];
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
//
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (arg === '-e') {
|
|
180
|
-
processArgv.splice(idx, 2);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
await this.mpi.invokeMeteorCommand('run', args.concat(processArgv), {
|
|
172
|
+
const port = await this.fsi.getAvailablePort(opts.port ? parseInt(String(opts.port), 10) : 3000);
|
|
173
|
+
const appDir = this.fsi.findAppDirectory();
|
|
174
|
+
// See build.ts's matching comment: use the app's raw .meteor/release
|
|
175
|
+
// content, not fsi.getProjectMeteorVersion()'s semver-padded value.
|
|
176
|
+
const release = fs.readFileSync(path.join(appDir, '.meteor', 'release'), 'utf8').trim();
|
|
177
|
+
await this.mpi.runViaSdk({
|
|
178
|
+
appDir,
|
|
179
|
+
port,
|
|
180
|
+
release,
|
|
181
|
+
settingsPath: resolvedSettingsPath,
|
|
182
|
+
production: envKey === 'production',
|
|
184
183
|
enableLogging: !opts.noLog && !opts['no-log'],
|
|
185
|
-
env
|
|
184
|
+
env,
|
|
185
|
+
mongoUrl: process.env.MONGO_URL,
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
188
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.command.js","sourceRoot":"","sources":["../../../../../src/commands/run/run.command.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"run.command.js","sourceRoot":"","sources":["../../../../../src/commands/run/run.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
sudo apt-get update
|
|
2
|
+
# install git and nginx
|
|
3
|
+
sudo apt install build-essential git nginx -y
|
|
4
|
+
# setup node and npm with the proper node version using nvm
|
|
5
|
+
git clone https://gist.github.com/c427ccd6f4377b39299b9d402f5d51fe.git ~/maka-env/nvm-install
|
|
6
|
+
rm -rf ~/.bash_profile ~/.bashrc
|
|
7
|
+
touch ~/.bash_profile ~/.bashrc
|
|
8
|
+
echo "test -f ~/.bashrc && . ~/.bashrc" > ~/.bash_profile
|
|
9
|
+
chmod +x ~/maka-env/nvm-install/nvm-install.sh && ~/maka-env/nvm-install/nvm-install.sh
|
|
10
|
+
source ~/.bashrc
|
|
11
|
+
nvm install <%= nodeVersion %> || nvm install <%= fallbackVersion %>
|
|
12
|
+
[ "$(nvm current)" == "<%= nodeVersion %>" ] && nvm alias default <%= nodeVersion %> || nvm alias default <%= fallbackVersion %>
|
|
13
|
+
npm install -g pm2@latest
|
|
14
|
+
npm install -g @dotenvx/dotenvx@latest
|
|
15
|
+
pm2 install pm2-logrotate
|
|
16
|
+
pm2 set pm2-logrotate:max_size 20M
|
|
17
|
+
pm2 set pm2-logrotate:compress true
|
|
18
|
+
pm2 set pm2-logrotate:retain 30
|
|
19
|
+
rm -rf ~/maka-env/nvm-install
|
|
20
|
+
# Prepare nginx
|
|
21
|
+
[ -d /etc/systemd/system/nginx.service.d ] && echo "nginx.service.d exists" || sudo mkdir /etc/systemd/system/nginx.service.d
|
|
22
|
+
printf "[Service]\nExecStartPost=/bin/sleep 0.1\n" > override.conf
|
|
23
|
+
sudo cp override.conf /etc/systemd/system/nginx.service.d/override.conf
|
|
24
|
+
sudo systemctl daemon-reload || null
|
|
25
|
+
sudo systemctl stop nginx
|
|
26
|
+
sudo nginx -s stop
|
|
27
|
+
sudo cp ~/nginx.conf /etc/nginx/sites-enabled/default
|
|
28
|
+
sudo systemctl daemon-reload && sudo systemctl start nginx
|
|
29
|
+
# Ensure certbot is installed and re-inject the SSL server block that
|
|
30
|
+
# `sudo cp` above just overwrote (domain/email from letsencrypt.json).
|
|
31
|
+
# certbot --nginx is idempotent: skips reissuing a still-valid cert but
|
|
32
|
+
# always makes sure the nginx config has the SSL block wired in.
|
|
33
|
+
sudo snap install core >/dev/null 2>&1
|
|
34
|
+
sudo snap refresh core >/dev/null 2>&1
|
|
35
|
+
sudo snap install --classic certbot >/dev/null 2>&1 || true
|
|
36
|
+
[ -L /usr/bin/certbot ] || sudo ln -s /snap/bin/certbot /usr/bin/certbot
|
|
37
|
+
sudo certbot --nginx --agree-tos --expand -n --domains <%= domainNames %> --email <%= emailUpdate %>
|
|
38
|
+
# Decompress the bundle
|
|
39
|
+
echo "Attempting to decompress the bundle"
|
|
40
|
+
if [ -f app.tar.gz ]; then
|
|
41
|
+
echo "Bundle found, decompressing"
|
|
42
|
+
tar -xf app.tar.gz
|
|
43
|
+
elif [ -f app.tar.gz.bk ]; then
|
|
44
|
+
echo "No bundle found, using backup"
|
|
45
|
+
cp app.tar.gz.bk app.tar.gz
|
|
46
|
+
tar -xf app.tar.gz
|
|
47
|
+
else
|
|
48
|
+
echo "Could not find app.tar.gz, exiting!"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
cd bundle/programs/server
|
|
52
|
+
npm install
|
|
53
|
+
npm audit fix --force
|
|
54
|
+
cd ~
|
|
55
|
+
# Reset pm2
|
|
56
|
+
pm2 delete all
|
|
57
|
+
# updating PM2 to latest
|
|
58
|
+
pm2 update
|
|
59
|
+
# Bring up pm2 with environment
|
|
60
|
+
if [ -f ~/process.env ]; then
|
|
61
|
+
dotenvx run -f ~/process.env -- pm2 start ~/pm2.config.js
|
|
62
|
+
else
|
|
63
|
+
pm2 start ~/pm2.config.js
|
|
64
|
+
fi
|
|
65
|
+
# Configure pm2 to start on boot
|
|
66
|
+
pm2 startup
|
|
67
|
+
sudo env PATH=$PATH:$(which npm) $(which pm2) startup systemd -u <%= ec2User %> --hp /home/<%= ec2User %>
|
|
68
|
+
pm2 save
|
|
69
|
+
# remove backup tar, if any
|
|
70
|
+
# rm -f ~/app.tar.gz.bk
|
|
71
|
+
# backup tar bundle
|
|
72
|
+
mv ~/app.tar.gz ~/app.tar.gz.bk
|
|
73
|
+
exit 0
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
server_tokens off;
|
|
2
|
+
map $http_upgrade $connection_upgrade {
|
|
3
|
+
default upgrade;
|
|
4
|
+
'' close;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
server {
|
|
8
|
+
listen 80 default_server;
|
|
9
|
+
listen [::]:80 default_server ipv6only=on;
|
|
10
|
+
<% if (domainNames) { -%>
|
|
11
|
+
server_name <%= domainNames.split(',').map(function(d) { return d.trim(); }).join(' ') %>;
|
|
12
|
+
<% } -%>
|
|
13
|
+
if ($http_user_agent ~ "MSIE" ) {
|
|
14
|
+
return 303 https://browser-update.org/update.html;
|
|
15
|
+
}
|
|
16
|
+
location = /favicon.ico {
|
|
17
|
+
alias /home/<%= ec2User %>/bundle/programs/web.browser/app;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
location / {
|
|
21
|
+
proxy_pass http://0.0.0.0:3000;
|
|
22
|
+
proxy_http_version 1.1;
|
|
23
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
24
|
+
proxy_set_header Connection "upgrade";
|
|
25
|
+
proxy_set_header X-Forwarded-For $remote_addr;
|
|
26
|
+
proxy_set_header Host $host;
|
|
27
|
+
if ($uri != '/') {
|
|
28
|
+
expires 30d;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: Deploy to EC2
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [<%= branch %>]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: deploy-<%= envName %>
|
|
10
|
+
cancel-in-progress: false
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
deploy:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
environment: <%= envName %>
|
|
19
|
+
env:
|
|
20
|
+
EC2_HOST: <%= ec2Host %>
|
|
21
|
+
EC2_USER: <%= ec2User %>
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- uses: actions/setup-node@v4
|
|
26
|
+
with:
|
|
27
|
+
node-version: "<%= nodeVersion %>"
|
|
28
|
+
|
|
29
|
+
- name: Install root dependencies (maka-cli)
|
|
30
|
+
run: npm ci
|
|
31
|
+
|
|
32
|
+
- name: Install Meteor
|
|
33
|
+
run: node_modules/.bin/maka install meteor
|
|
34
|
+
|
|
35
|
+
- name: Install app dependencies
|
|
36
|
+
run: npm ci
|
|
37
|
+
working-directory: app
|
|
38
|
+
|
|
39
|
+
- name: Build production bundle
|
|
40
|
+
run: node_modules/.bin/maka build --force
|
|
41
|
+
|
|
42
|
+
- name: Configure SSH
|
|
43
|
+
env:
|
|
44
|
+
EC2_PEM_KEY: ${{ secrets.EC2_<%= envUpper %>_PEM }}
|
|
45
|
+
run: |
|
|
46
|
+
install -m 700 -d ~/.ssh
|
|
47
|
+
install -m 600 /dev/null ~/.ssh/deploy_key
|
|
48
|
+
printf '%s\n' "$EC2_PEM_KEY" > ~/.ssh/deploy_key
|
|
49
|
+
ssh-keyscan -H "$EC2_HOST" >> ~/.ssh/known_hosts
|
|
50
|
+
|
|
51
|
+
- name: Write dotenvx decryption key
|
|
52
|
+
env:
|
|
53
|
+
DOTENV_PRIVATE_KEY_<%= dotenvKeyName %>: ${{ secrets.DOTENV_PRIVATE_KEY_<%= dotenvKeyName %> }}
|
|
54
|
+
run: |
|
|
55
|
+
install -m 600 /dev/null /tmp/.env.keys
|
|
56
|
+
echo "DOTENV_PRIVATE_KEY_<%= dotenvKeyName %>=$DOTENV_PRIVATE_KEY_<%= dotenvKeyName %>" > /tmp/.env.keys
|
|
57
|
+
|
|
58
|
+
- name: Upload bundle and config
|
|
59
|
+
run: |
|
|
60
|
+
scp -i ~/.ssh/deploy_key build/app.tar.gz "$EC2_USER@$EC2_HOST:~/app.tar.gz"
|
|
61
|
+
scp -i ~/.ssh/deploy_key config/<%= envName %>/pm2.config.js "$EC2_USER@$EC2_HOST:~/pm2.config.js"
|
|
62
|
+
scp -i ~/.ssh/deploy_key config/<%= envName %>/settings.json "$EC2_USER@$EC2_HOST:~/settings.json"
|
|
63
|
+
scp -i ~/.ssh/deploy_key config/<%= envName %>/nginx.conf "$EC2_USER@$EC2_HOST:~/nginx.conf"
|
|
64
|
+
scp -i ~/.ssh/deploy_key config/<%= envName %>/deploy.sh "$EC2_USER@$EC2_HOST:~/deploy.sh"
|
|
65
|
+
scp -i ~/.ssh/deploy_key config/<%= envName %>/process.env "$EC2_USER@$EC2_HOST:~/process.env"
|
|
66
|
+
scp -i ~/.ssh/deploy_key /tmp/.env.keys "$EC2_USER@$EC2_HOST:~/.env.keys"
|
|
67
|
+
rm -f /tmp/.env.keys
|
|
68
|
+
|
|
69
|
+
- name: Release
|
|
70
|
+
run: ssh -i ~/.ssh/deploy_key "$EC2_USER@$EC2_HOST" "chmod 600 ~/process.env ~/.env.keys && chmod +x ~/deploy.sh && ~/deploy.sh"
|
|
71
|
+
|
|
72
|
+
- name: Post-deploy health check
|
|
73
|
+
if: always()
|
|
74
|
+
run: |
|
|
75
|
+
ssh -i ~/.ssh/deploy_key "$EC2_USER@$EC2_HOST" '
|
|
76
|
+
echo "--- pm2 status ---"
|
|
77
|
+
pm2 status
|
|
78
|
+
echo "--- pm2 logs (last 60 lines) ---"
|
|
79
|
+
pm2 logs --lines 60 --nostream
|
|
80
|
+
echo "--- localhost:3000 ---"
|
|
81
|
+
curl -sS -o /dev/null -w "HTTP %{http_code}\n" http://localhost:3000/ || true
|
|
82
|
+
'
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { FSI } from '../fsi/fsi.class.js';
|
|
2
2
|
import { CFG } from '../cfg/cfg.class.js';
|
|
3
3
|
import { PKG } from '../pkg/pkg.class.js';
|
|
4
|
+
export interface IBuildViaSdkOptions {
|
|
5
|
+
appDir: string;
|
|
6
|
+
outputPath: string;
|
|
7
|
+
directory: boolean;
|
|
8
|
+
release: string;
|
|
9
|
+
}
|
|
10
|
+
export interface IRunViaSdkOptions {
|
|
11
|
+
appDir: string;
|
|
12
|
+
port: number;
|
|
13
|
+
release: string;
|
|
14
|
+
mongoUrl?: string;
|
|
15
|
+
settingsPath?: string;
|
|
16
|
+
production?: boolean;
|
|
17
|
+
enableLogging?: boolean;
|
|
18
|
+
env?: string;
|
|
19
|
+
}
|
|
4
20
|
export declare class MPI {
|
|
5
21
|
private static instance;
|
|
6
22
|
private fsi;
|
|
@@ -23,4 +39,6 @@ export declare class MPI {
|
|
|
23
39
|
enableLogging?: boolean;
|
|
24
40
|
env?: string;
|
|
25
41
|
}): Promise<void>;
|
|
42
|
+
buildViaSdk(options: IBuildViaSdkOptions): Promise<void>;
|
|
43
|
+
runViaSdk(options: IRunViaSdkOptions): Promise<void>;
|
|
26
44
|
}
|
|
@@ -4,11 +4,24 @@ import fs from 'fs';
|
|
|
4
4
|
import os from 'os';
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
6
|
import spawn from 'cross-spawn';
|
|
7
|
+
import * as tar from 'tar';
|
|
8
|
+
import { createRequire } from 'module';
|
|
7
9
|
import { pascalCase } from "change-case";
|
|
10
|
+
import sdk, { ensureSdkInit, hardExit } from './sdk-runtime.js';
|
|
8
11
|
import { Log } from '../log/log.class.js';
|
|
9
12
|
import { Actions } from '../actions/actions.class.js';
|
|
10
13
|
import { MustBeInProjectError } from '../../error.js';
|
|
11
14
|
const homeDir = os.homedir();
|
|
15
|
+
// @maka/meteor-sdk's "./tools/*" exports subpath serves raw, untranspiled
|
|
16
|
+
// tools/ source files that rely on the SDK's own Babel/.ts-extension
|
|
17
|
+
// require hook (installed lazily by sdk.init(), inside its bootstrap()).
|
|
18
|
+
// A static ESM `import ... from '@maka/meteor-sdk/tools/...'` bypasses
|
|
19
|
+
// that hook entirely -- Node's own ESM resolver statically links the raw
|
|
20
|
+
// file before the hook ever runs, and fails on the first extensionless
|
|
21
|
+
// `import ... from '../fs/watch'` inside it (ERR_MODULE_NOT_FOUND).
|
|
22
|
+
// Loading it via a real CJS require(), lazily, *after* ensureSdkInit()
|
|
23
|
+
// has run, goes through the hook correctly instead. See runViaSdk().
|
|
24
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
12
25
|
const errorHandler = (caller, error) => {
|
|
13
26
|
if (process.env['MAKA_DEV'] === 'True') {
|
|
14
27
|
Log.error(`Error in ${caller}`);
|
|
@@ -271,9 +284,15 @@ export class MPI {
|
|
|
271
284
|
}
|
|
272
285
|
async invokeMeteorCommand(cmd, args, options) {
|
|
273
286
|
try {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
287
|
+
// 'publish' runs from a plain Meteor package directory (just a
|
|
288
|
+
// package.js), which has no .maka project marker at all -- see the
|
|
289
|
+
// cwd computation below, which already special-cases 'publish' for
|
|
290
|
+
// the same reason.
|
|
291
|
+
if (cmd !== 'publish') {
|
|
292
|
+
const projectDir = this.fsi.findProjectDirectory();
|
|
293
|
+
if (!projectDir) {
|
|
294
|
+
throw new MustBeInProjectError();
|
|
295
|
+
}
|
|
277
296
|
}
|
|
278
297
|
if (cmd === 'run') {
|
|
279
298
|
const portIdx = args.indexOf('-p');
|
|
@@ -526,5 +545,216 @@ export class MPI {
|
|
|
526
545
|
process.exit(1);
|
|
527
546
|
}
|
|
528
547
|
}
|
|
548
|
+
// Found while testing buildViaSdk(): a plain process.exit() reliably
|
|
549
|
+
// hung (never actually terminated) after a successful build going
|
|
550
|
+
// through the SDK, specifically on Windows -- process.getActiveResourcesInfo()
|
|
551
|
+
// showed one pending FSReqCallback at that point. Root cause traced to
|
|
552
|
+
// tools/tool-env/cleanup.js's `process.on('exit', runHandlers)`, where
|
|
553
|
+
// runHandlers is async (a real Node anti-pattern: 'exit' handlers must
|
|
554
|
+
// be synchronous) -- on Windows this can wedge normal process.exit()
|
|
555
|
+
// when a handler's fire-and-forget async work races shutdown.
|
|
556
|
+
// process.reallyExit() (undocumented, but long-standing in Node)
|
|
557
|
+
// bypasses 'exit' listeners entirely and terminates immediately;
|
|
558
|
+
// falling back to process.exit() if it's ever unavailable.
|
|
559
|
+
// SDK-backed replacement for invokeMeteorCommand('build', ...). Unlike
|
|
560
|
+
// the real `meteor build` (proxied via invokeMeteorCommand elsewhere in
|
|
561
|
+
// this file for every other command), this never shells out to a
|
|
562
|
+
// meteor binary at all.
|
|
563
|
+
async buildViaSdk(options) {
|
|
564
|
+
// Cleaned up inline before each hardExit() call below, not via a
|
|
565
|
+
// `finally` block: hardExit() uses process.reallyExit() (see its own
|
|
566
|
+
// comment), which can cut off a pending `finally` the same way it
|
|
567
|
+
// cuts off everything else after it's called.
|
|
568
|
+
let tempDir = null;
|
|
569
|
+
const cleanupTempDir = () => {
|
|
570
|
+
if (!tempDir)
|
|
571
|
+
return;
|
|
572
|
+
try {
|
|
573
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
574
|
+
}
|
|
575
|
+
catch {
|
|
576
|
+
// Best-effort cleanup only.
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
try {
|
|
580
|
+
await ensureSdkInit(options.release);
|
|
581
|
+
const project = await sdk.loadProject(options.appDir);
|
|
582
|
+
if (options.directory) {
|
|
583
|
+
await sdk.bundle(project, {
|
|
584
|
+
outputPath: options.outputPath,
|
|
585
|
+
minifyMode: 'production',
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
// sdk.bundle() (like bundler.bundle() underneath it) only ever
|
|
590
|
+
// writes a raw directory -- the app.tar.gz step lived in the now-
|
|
591
|
+
// deleted CLI's own build command, never in the bundler itself.
|
|
592
|
+
// Reproduce it here with the tar dependency this package already has.
|
|
593
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'maka-build-'));
|
|
594
|
+
await sdk.bundle(project, {
|
|
595
|
+
outputPath: tempDir,
|
|
596
|
+
minifyMode: 'production',
|
|
597
|
+
});
|
|
598
|
+
fs.mkdirSync(path.dirname(options.outputPath), { recursive: true });
|
|
599
|
+
await tar.create({ gzip: true, file: options.outputPath, cwd: tempDir }, fs.readdirSync(tempDir));
|
|
600
|
+
}
|
|
601
|
+
Log.success(`Build complete: ${options.outputPath}`);
|
|
602
|
+
cleanupTempDir();
|
|
603
|
+
hardExit(0);
|
|
604
|
+
}
|
|
605
|
+
catch (e) {
|
|
606
|
+
errorHandler('buildViaSdk()', e);
|
|
607
|
+
cleanupTempDir();
|
|
608
|
+
hardExit(1);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
// SDK-backed replacement for invokeMeteorCommand('run', ...). Unlike
|
|
612
|
+
// `meteor run`, meteor-sdk's createAppRunner() doesn't manage a mongod
|
|
613
|
+
// process for us (see its README) -- that lifecycle now belongs here,
|
|
614
|
+
// reusing the exact same MongoRunner class the real `meteor run`
|
|
615
|
+
// command itself is built on.
|
|
616
|
+
async runViaSdk(options) {
|
|
617
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
618
|
+
let mongoRunner = null;
|
|
619
|
+
let handle = null;
|
|
620
|
+
let logStream = null;
|
|
621
|
+
let logFilePath = null;
|
|
622
|
+
const getTimestamp = () => {
|
|
623
|
+
const now = new Date();
|
|
624
|
+
const pad = (n, len = 2) => String(n).padStart(len, '0');
|
|
625
|
+
return `[${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}.${pad(now.getMilliseconds(), 3)}]`;
|
|
626
|
+
};
|
|
627
|
+
const writeLog = (line) => {
|
|
628
|
+
if (!logStream)
|
|
629
|
+
return;
|
|
630
|
+
logStream.write(`${getTimestamp()} ${line}\n`);
|
|
631
|
+
};
|
|
632
|
+
const shutdown = async (exitCode, signal) => {
|
|
633
|
+
try {
|
|
634
|
+
if (handle)
|
|
635
|
+
await handle.stop();
|
|
636
|
+
}
|
|
637
|
+
catch (e) {
|
|
638
|
+
errorHandler('runViaSdk() handle.stop()', e);
|
|
639
|
+
}
|
|
640
|
+
try {
|
|
641
|
+
mongoRunner?.stop();
|
|
642
|
+
}
|
|
643
|
+
catch (e) {
|
|
644
|
+
errorHandler('runViaSdk() mongoRunner.stop()', e);
|
|
645
|
+
}
|
|
646
|
+
if (logStream) {
|
|
647
|
+
const timestamp = new Date().toISOString();
|
|
648
|
+
logStream.write(`\n${'='.repeat(80)}\n`);
|
|
649
|
+
logStream.write(`Session ${signal ? 'Interrupted' : 'Ended'}: ${timestamp}\n`);
|
|
650
|
+
if (signal)
|
|
651
|
+
logStream.write(`Signal: ${signal}\n`);
|
|
652
|
+
logStream.write(`${'='.repeat(80)}\n\n`);
|
|
653
|
+
logStream.end();
|
|
654
|
+
}
|
|
655
|
+
// Deliberately not calling sdk.close() here: for a one-shot process
|
|
656
|
+
// that's about to exit anyway, skipping close() and exiting
|
|
657
|
+
// directly avoids a real @parcel/watcher-teardown crash on Windows
|
|
658
|
+
// under Git Bash/MSYS2, verified this session and documented in
|
|
659
|
+
// @maka/meteor-sdk@0.1.3's own README.
|
|
660
|
+
hardExit(exitCode);
|
|
661
|
+
};
|
|
662
|
+
try {
|
|
663
|
+
// sdk.init() (inside ensureSdkInit) installs the Babel/.ts require
|
|
664
|
+
// hook that MongoRunner's own raw tools/ source depends on -- must
|
|
665
|
+
// happen before we require() it below.
|
|
666
|
+
await ensureSdkInit(options.release);
|
|
667
|
+
let mongoUrl = options.mongoUrl;
|
|
668
|
+
let oplogUrl;
|
|
669
|
+
if (!mongoUrl) {
|
|
670
|
+
const { MongoRunner } = requireFromHere('@maka/meteor-sdk/tools/runners/run-mongo.js');
|
|
671
|
+
const mongoPort = await this.fsi.getAvailablePort(3001);
|
|
672
|
+
const projectLocalDir = path.join(options.appDir, '.meteor', 'local');
|
|
673
|
+
fs.mkdirSync(projectLocalDir, { recursive: true });
|
|
674
|
+
mongoRunner = new MongoRunner({ projectLocalDir, port: mongoPort });
|
|
675
|
+
await mongoRunner.start();
|
|
676
|
+
mongoUrl = mongoRunner.mongoUrl();
|
|
677
|
+
oplogUrl = mongoRunner.oplogUrl();
|
|
678
|
+
}
|
|
679
|
+
const project = await sdk.loadProject(options.appDir);
|
|
680
|
+
if (options.enableLogging) {
|
|
681
|
+
const env = options.env || 'local';
|
|
682
|
+
logFilePath = this.fsi.getLogFilePath(env, 'run');
|
|
683
|
+
logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
|
|
684
|
+
this.fsi.rotateLogs(env, 'run', 10);
|
|
685
|
+
const logsDir = this.fsi.getLogsDirectory();
|
|
686
|
+
const latestLogPath = path.join(logsDir, `run-${env}-latest.log`);
|
|
687
|
+
if (fs.existsSync(latestLogPath)) {
|
|
688
|
+
try {
|
|
689
|
+
fs.unlinkSync(latestLogPath);
|
|
690
|
+
}
|
|
691
|
+
catch { /* ignore */ }
|
|
692
|
+
}
|
|
693
|
+
try {
|
|
694
|
+
if (process.platform === 'win32') {
|
|
695
|
+
fs.copyFileSync(logFilePath, latestLogPath);
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
fs.symlinkSync(path.basename(logFilePath), latestLogPath);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
catch { /* not critical */ }
|
|
702
|
+
const timestamp = new Date().toISOString();
|
|
703
|
+
logStream.write(`\n${'='.repeat(80)}\n`);
|
|
704
|
+
logStream.write(`Maka Run Session Started: ${timestamp}\n`);
|
|
705
|
+
logStream.write(`Environment: ${env}\n`);
|
|
706
|
+
logStream.write(`${'='.repeat(80)}\n\n`);
|
|
707
|
+
Log.notice(`Logging to: ${path.relative(process.cwd(), logFilePath)}`);
|
|
708
|
+
}
|
|
709
|
+
handle = await sdk.createAppRunner(project, {
|
|
710
|
+
port: options.port,
|
|
711
|
+
mongoUrl,
|
|
712
|
+
oplogUrl,
|
|
713
|
+
once: false,
|
|
714
|
+
settingsFile: options.settingsPath,
|
|
715
|
+
buildOptions: {
|
|
716
|
+
minifyMode: options.production ? 'production' : 'development',
|
|
717
|
+
},
|
|
718
|
+
});
|
|
719
|
+
handle.on('exit', (result) => {
|
|
720
|
+
// Not JSON.stringify(result) as a whole -- some outcomes (e.g. a
|
|
721
|
+
// version mismatch) attach a full WatchSet, whose own toJSON()
|
|
722
|
+
// isn't safe to call in every case (hit a real crash here:
|
|
723
|
+
// "Cannot read properties of undefined (reading 'map')" inside
|
|
724
|
+
// tools/fs/watch.ts's WatchSet.toJSON()). Just the fields that
|
|
725
|
+
// matter for a log line.
|
|
726
|
+
const summary = `outcome=${result.outcome}` +
|
|
727
|
+
(result.code !== undefined ? ` code=${result.code}` : '') +
|
|
728
|
+
(result.signal !== undefined ? ` signal=${result.signal}` : '');
|
|
729
|
+
Log.notice(`Exited: ${summary}`);
|
|
730
|
+
writeLog(`Exited: ${summary}`);
|
|
731
|
+
});
|
|
732
|
+
const safeStringify = (value) => {
|
|
733
|
+
try {
|
|
734
|
+
return JSON.stringify(value);
|
|
735
|
+
}
|
|
736
|
+
catch {
|
|
737
|
+
return String(value);
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
sdk.on('log', ({ args }) => {
|
|
741
|
+
const line = args.map((a) => (typeof a === 'string' ? a : safeStringify(a))).join(' ');
|
|
742
|
+
process.stdout.write(line + '\n'); // console: no timestamps
|
|
743
|
+
writeLog(line); // log file: with timestamps
|
|
744
|
+
});
|
|
745
|
+
await handle.start();
|
|
746
|
+
Log.success(`Running: http://localhost:${options.port}`);
|
|
747
|
+
process.on('SIGINT', () => { void shutdown(0, 'SIGINT'); });
|
|
748
|
+
process.on('SIGTERM', () => { void shutdown(0, 'SIGTERM'); });
|
|
749
|
+
// Block here for the lifetime of the run, same as the execSync/
|
|
750
|
+
// spawn-based invokeMeteorCommand('run', ...) path did -- only the
|
|
751
|
+
// SIGINT/SIGTERM handlers above ever resolve this.
|
|
752
|
+
await new Promise(() => { });
|
|
753
|
+
}
|
|
754
|
+
catch (e) {
|
|
755
|
+
errorHandler('runViaSdk()', e);
|
|
756
|
+
await shutdown(1);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
529
759
|
}
|
|
530
760
|
//# sourceMappingURL=mpi.class.js.map
|