@popina/cli 5.1.2-20260911175301Z → 5.1.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/CHANGELOG.md +7 -0
- package/build/index.js +229 -201
- package/build/index.js.map +1 -1
- package/package.json +3 -3
package/build/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Command as Command17 } from "@commander-js/extra-typings";
|
|
|
10
10
|
import { $ as $24 } from "zx/core";
|
|
11
11
|
|
|
12
12
|
// src/cmd/backup.ts
|
|
13
|
-
import * as
|
|
13
|
+
import * as p10 from "@clack/prompts";
|
|
14
14
|
import { Command } from "@commander-js/extra-typings";
|
|
15
15
|
import fse3 from "fs-extra";
|
|
16
16
|
import color from "picocolors";
|
|
@@ -135,23 +135,58 @@ async function checkGCloud() {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
// src/utils/gcloud/fetch-env.ts
|
|
138
|
+
import * as p5 from "@clack/prompts";
|
|
139
|
+
import { backOff } from "exponential-backoff";
|
|
140
|
+
import { $ as $8 } from "zx/core";
|
|
141
|
+
|
|
142
|
+
// src/utils/run-with-inherited-stdio.ts
|
|
138
143
|
import { $ as $7 } from "zx/core";
|
|
144
|
+
var inheritedStdioShell = $7({ stdio: "inherit" });
|
|
145
|
+
async function runWithInheritedStdio(command, args) {
|
|
146
|
+
await inheritedStdioShell`${command} ${args}`;
|
|
147
|
+
}
|
|
139
148
|
|
|
140
149
|
// src/utils/variables.ts
|
|
141
150
|
var PRAGMA_REPO = "popina/pragma-web";
|
|
142
151
|
var PROJECT_ID = "pragma-project";
|
|
143
152
|
|
|
144
153
|
// src/utils/gcloud/fetch-env.ts
|
|
154
|
+
var MAX_ATTEMPTS = 3;
|
|
145
155
|
async function fetchEnv(email3) {
|
|
146
|
-
await
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
await backOff(
|
|
157
|
+
async () => await $8({
|
|
158
|
+
input: process.stdin,
|
|
159
|
+
quiet: false
|
|
160
|
+
})`gcloud secrets versions access latest --secret=DEV_ENVIRONMENT_VARIABLES > .env --project=${PROJECT_ID}`,
|
|
161
|
+
{
|
|
162
|
+
numOfAttempts: MAX_ATTEMPTS,
|
|
163
|
+
retry: async (error51, attemptNumber) => {
|
|
164
|
+
const diagnostic = error51.stderr || error51.message;
|
|
165
|
+
const hasMissingCredentials = diagnostic.includes(
|
|
166
|
+
"You do not currently have an active account selected."
|
|
167
|
+
) || diagnostic.includes("does not have any valid credentials");
|
|
168
|
+
const isTokenExpired = diagnostic.includes(
|
|
169
|
+
// cspell: disable-next-line
|
|
170
|
+
"There was a problem refreshing your current auth tokens: Reauthentication failed"
|
|
171
|
+
);
|
|
172
|
+
if (!hasMissingCredentials && !isTokenExpired || attemptNumber >= MAX_ATTEMPTS) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
p5.log.info(
|
|
176
|
+
`\u23F3 Auth tokens required/expired, manual authentication required`
|
|
177
|
+
);
|
|
178
|
+
await runWithInheritedStdio("gcloud", ["auth", "login", email3]);
|
|
179
|
+
p5.log.success("\u2705 Manual re-authentication succeeded");
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
await $8`echo "\nINITIAL_SUPER_ADMIN_EMAIL=${email3}" >> .env`.quiet();
|
|
150
185
|
}
|
|
151
186
|
|
|
152
187
|
// src/utils/gcloud/login-to-google.ts
|
|
153
|
-
import * as
|
|
154
|
-
import { backOff } from "exponential-backoff";
|
|
188
|
+
import * as p6 from "@clack/prompts";
|
|
189
|
+
import { backOff as backOff2 } from "exponential-backoff";
|
|
155
190
|
|
|
156
191
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
157
192
|
var external_exports = {};
|
|
@@ -3386,7 +3421,7 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
|
|
|
3386
3421
|
defineLazy(inst._zod, "pattern", () => {
|
|
3387
3422
|
if (def.options.every((o) => o._zod.pattern)) {
|
|
3388
3423
|
const patterns = def.options.map((o) => o._zod.pattern);
|
|
3389
|
-
return new RegExp(`^(${patterns.map((
|
|
3424
|
+
return new RegExp(`^(${patterns.map((p23) => cleanRegex(p23.source)).join("|")})$`);
|
|
3390
3425
|
}
|
|
3391
3426
|
return void 0;
|
|
3392
3427
|
});
|
|
@@ -10504,9 +10539,9 @@ var $ZodRegistry = class {
|
|
|
10504
10539
|
return this;
|
|
10505
10540
|
}
|
|
10506
10541
|
get(schema) {
|
|
10507
|
-
const
|
|
10508
|
-
if (
|
|
10509
|
-
const pm = { ...this.get(
|
|
10542
|
+
const p23 = schema._zod.parent;
|
|
10543
|
+
if (p23) {
|
|
10544
|
+
const pm = { ...this.get(p23) ?? {} };
|
|
10510
10545
|
delete pm.id;
|
|
10511
10546
|
const f = { ...pm, ...this._map.get(schema) };
|
|
10512
10547
|
return Object.keys(f).length ? f : void 0;
|
|
@@ -14668,11 +14703,11 @@ function date4(params) {
|
|
|
14668
14703
|
config(en_default());
|
|
14669
14704
|
|
|
14670
14705
|
// src/utils/gcloud/login-to-google.ts
|
|
14671
|
-
import { $ as $
|
|
14706
|
+
import { $ as $9 } from "zx/core";
|
|
14672
14707
|
var EMAIL_REGEX = /[\w.+-]+@[\w.-]+\.[a-z]{2,}/i;
|
|
14673
14708
|
async function loginGoogle() {
|
|
14674
|
-
return await
|
|
14675
|
-
async () => await $
|
|
14709
|
+
return await backOff2(
|
|
14710
|
+
async () => await $9({
|
|
14676
14711
|
input: process.stdin,
|
|
14677
14712
|
quiet: true
|
|
14678
14713
|
})`gcloud config get-value account`.then((processOutput) => {
|
|
@@ -14684,7 +14719,7 @@ async function loginGoogle() {
|
|
|
14684
14719
|
{
|
|
14685
14720
|
retry: async (error51, attemptNumber) => {
|
|
14686
14721
|
if (attemptNumber > 3) {
|
|
14687
|
-
|
|
14722
|
+
p6.log.error(
|
|
14688
14723
|
`\u{1F534} Couldn't manually re-authenticate (exceeded max 3 attempts): ${error51.message}`
|
|
14689
14724
|
);
|
|
14690
14725
|
process.exit(1);
|
|
@@ -14695,14 +14730,16 @@ async function loginGoogle() {
|
|
|
14695
14730
|
"There was a problem refreshing your current auth tokens: Reauthentication failed"
|
|
14696
14731
|
);
|
|
14697
14732
|
if (!isNewAccount && !isTokenExpired) {
|
|
14698
|
-
|
|
14733
|
+
p6.log.error(`\u{1F534} gcloud get-value account failed: ${error51.message}`);
|
|
14699
14734
|
process.exit(1);
|
|
14700
14735
|
}
|
|
14701
|
-
|
|
14702
|
-
|
|
14703
|
-
|
|
14736
|
+
p6.log.info(
|
|
14737
|
+
`\u23F3 Auth tokens required/expired, manual authentication required`
|
|
14738
|
+
);
|
|
14739
|
+
await $9({ input: process.stdin, quiet: true })`gcloud auth login`.then(() => {
|
|
14740
|
+
p6.log.success("\u2705 Manual re-authentication succeeded");
|
|
14704
14741
|
}).catch((error52) => {
|
|
14705
|
-
|
|
14742
|
+
p6.log.error(`\u{1F534} Couldn't re-authenticate: ${error52.message}`);
|
|
14706
14743
|
});
|
|
14707
14744
|
return true;
|
|
14708
14745
|
}
|
|
@@ -14711,12 +14748,12 @@ async function loginGoogle() {
|
|
|
14711
14748
|
const [email3] = processOutput.lines();
|
|
14712
14749
|
const parsedEmail = external_exports.email({ pattern: EMAIL_REGEX }).safeParse(email3);
|
|
14713
14750
|
if (!parsedEmail.success) {
|
|
14714
|
-
|
|
14751
|
+
p6.log.error(
|
|
14715
14752
|
`\u{1F534} Couldn't parse user email (${email3}): ${external_exports.prettifyError(parsedEmail.error)}`
|
|
14716
14753
|
);
|
|
14717
14754
|
process.exit(1);
|
|
14718
14755
|
}
|
|
14719
|
-
|
|
14756
|
+
p6.log.info(`\u2139\uFE0F Logged in as ${parsedEmail.data}`);
|
|
14720
14757
|
return parsedEmail.data;
|
|
14721
14758
|
});
|
|
14722
14759
|
}
|
|
@@ -14765,7 +14802,7 @@ var removeEnvConfig = (envConfigCopyPath) => {
|
|
|
14765
14802
|
};
|
|
14766
14803
|
|
|
14767
14804
|
// package.json
|
|
14768
|
-
var version2 = "5.1.2
|
|
14805
|
+
var version2 = "5.1.2";
|
|
14769
14806
|
|
|
14770
14807
|
// src/utils/get-package-info.ts
|
|
14771
14808
|
async function getPackageInfo() {
|
|
@@ -14777,14 +14814,14 @@ async function getPackageInfo() {
|
|
|
14777
14814
|
}
|
|
14778
14815
|
|
|
14779
14816
|
// src/utils/gh/check-github-access.ts
|
|
14780
|
-
import * as
|
|
14781
|
-
import { $ as $
|
|
14817
|
+
import * as p8 from "@clack/prompts";
|
|
14818
|
+
import { $ as $10 } from "zx/core";
|
|
14782
14819
|
|
|
14783
14820
|
// src/utils/gh/login-to-github.ts
|
|
14784
|
-
import * as
|
|
14821
|
+
import * as p7 from "@clack/prompts";
|
|
14785
14822
|
import { spawnSync } from "child_process";
|
|
14786
14823
|
async function loginGH() {
|
|
14787
|
-
|
|
14824
|
+
p7.log.info("Logging in with GitHub CLI using device authentication...");
|
|
14788
14825
|
const result = spawnSync("gh", ["auth", "login", "-p", "ssh"], {
|
|
14789
14826
|
stdio: "inherit"
|
|
14790
14827
|
});
|
|
@@ -14793,43 +14830,43 @@ async function loginGH() {
|
|
|
14793
14830
|
"GitHub authentication did not complete. Run `gh auth login -p ssh`, then try popina init again."
|
|
14794
14831
|
);
|
|
14795
14832
|
}
|
|
14796
|
-
|
|
14833
|
+
p7.log.success("Authenticated with GitHub CLI.");
|
|
14797
14834
|
}
|
|
14798
14835
|
|
|
14799
14836
|
// src/utils/gh/check-github-access.ts
|
|
14800
14837
|
async function checkGitHubAccess() {
|
|
14801
|
-
const hasGH = await $
|
|
14838
|
+
const hasGH = await $10`command -v gh`.quiet().then(() => true).catch(() => false);
|
|
14802
14839
|
if (!hasGH) {
|
|
14803
14840
|
throw new Error(
|
|
14804
14841
|
"GitHub CLI is required. Install it with `brew install gh`, then try again."
|
|
14805
14842
|
);
|
|
14806
14843
|
}
|
|
14807
|
-
const isLoggedIn = await $
|
|
14844
|
+
const isLoggedIn = await $10`gh auth status`.quiet().then(() => true).catch(() => false);
|
|
14808
14845
|
if (!isLoggedIn) {
|
|
14809
14846
|
await loginGH();
|
|
14810
|
-
|
|
14847
|
+
p8.log.success("You are now logged in to GitHub.");
|
|
14811
14848
|
}
|
|
14812
|
-
const hasRepoAccess = await $
|
|
14849
|
+
const hasRepoAccess = await $10`gh repo view ${PRAGMA_REPO} --json nameWithOwner --jq '.nameWithOwner'`.quiet().then(({ stdout }) => stdout.trim() === PRAGMA_REPO).catch(() => false);
|
|
14813
14850
|
if (!hasRepoAccess) {
|
|
14814
14851
|
throw new Error(
|
|
14815
14852
|
"Your GitHub account cannot access popina/pragma-web. Ask the Popina team to add you, then run popina init again."
|
|
14816
14853
|
);
|
|
14817
14854
|
}
|
|
14818
|
-
|
|
14855
|
+
p8.log.success("GitHub access to popina/pragma-web is ready.");
|
|
14819
14856
|
}
|
|
14820
14857
|
|
|
14821
14858
|
// src/utils/gh/clone-github-project.ts
|
|
14822
|
-
import { $ as $
|
|
14859
|
+
import { $ as $12 } from "zx/core";
|
|
14823
14860
|
|
|
14824
14861
|
// src/utils/gh/ensure-github-known-host.ts
|
|
14825
14862
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
14826
14863
|
import { homedir } from "os";
|
|
14827
14864
|
import { join as join2 } from "path";
|
|
14828
|
-
import { $ as $
|
|
14865
|
+
import { $ as $11 } from "zx/core";
|
|
14829
14866
|
var githubHost = "github.com";
|
|
14830
14867
|
async function hasGitHubKnownHost(knownHostsPath) {
|
|
14831
14868
|
try {
|
|
14832
|
-
const { stdout } = await $
|
|
14869
|
+
const { stdout } = await $11`ssh-keygen -F ${githubHost} -f ${knownHostsPath}`.quiet();
|
|
14833
14870
|
return stdout.trim().length > 0;
|
|
14834
14871
|
} catch {
|
|
14835
14872
|
return false;
|
|
@@ -14841,7 +14878,7 @@ function isMissingFileError(error51) {
|
|
|
14841
14878
|
async function ensureGitHubKnownHost(sshDirectory = join2(homedir(), ".ssh")) {
|
|
14842
14879
|
const knownHostsPath = join2(sshDirectory, "known_hosts");
|
|
14843
14880
|
if (await hasGitHubKnownHost(knownHostsPath)) return;
|
|
14844
|
-
const { stdout } = await $
|
|
14881
|
+
const { stdout } = await $11`gh api meta --jq '.ssh_keys[]'`.quiet();
|
|
14845
14882
|
const hostKeys = stdout.split(/\r?\n/).map((key) => key.trim()).filter(Boolean);
|
|
14846
14883
|
if (hostKeys.length === 0 || hostKeys.some((key) => !/^[A-Za-z0-9@._+-]+ [A-Za-z0-9+/=]+$/.test(key))) {
|
|
14847
14884
|
throw new Error("GitHub did not return valid SSH host keys. Try again.");
|
|
@@ -14869,24 +14906,24 @@ async function ensureGitHubKnownHost(sshDirectory = join2(homedir(), ".ssh")) {
|
|
|
14869
14906
|
async function cloneProject(destination) {
|
|
14870
14907
|
await ensureGitHubKnownHost();
|
|
14871
14908
|
const sshCommand = "ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o ConnectTimeout=15";
|
|
14872
|
-
await $
|
|
14909
|
+
await $12`GIT_TERMINAL_PROMPT=0 GIT_SSH_COMMAND=${sshCommand} gh repo clone ${PRAGMA_REPO} ${destination}`.quiet();
|
|
14873
14910
|
}
|
|
14874
14911
|
|
|
14875
14912
|
// src/utils/mise/check-mise.ts
|
|
14876
|
-
import * as
|
|
14877
|
-
import { $ as $
|
|
14913
|
+
import * as p9 from "@clack/prompts";
|
|
14914
|
+
import { $ as $13 } from "zx/core";
|
|
14878
14915
|
async function checkMise() {
|
|
14879
|
-
const { stdout } = await $
|
|
14916
|
+
const { stdout } = await $13`mise --version`.quiet().catch(() => {
|
|
14880
14917
|
throw new Error(
|
|
14881
14918
|
"mise is not installed. Install it with `brew install mise`, then try again."
|
|
14882
14919
|
);
|
|
14883
14920
|
});
|
|
14884
14921
|
const [version3] = stdout.trim().split(" ");
|
|
14885
|
-
|
|
14922
|
+
p9.log.success(`mise ${version3} is installed.`);
|
|
14886
14923
|
}
|
|
14887
14924
|
|
|
14888
14925
|
// src/utils/mise/run-mise.ts
|
|
14889
|
-
import { $ as $
|
|
14926
|
+
import { $ as $14 } from "zx/core";
|
|
14890
14927
|
function getMiseSetupTasks(shouldSetupDatabase) {
|
|
14891
14928
|
if (!shouldSetupDatabase) return ["setup:dependencies"];
|
|
14892
14929
|
return [
|
|
@@ -14897,7 +14934,7 @@ function getMiseSetupTasks(shouldSetupDatabase) {
|
|
|
14897
14934
|
];
|
|
14898
14935
|
}
|
|
14899
14936
|
async function checkMiseSetupTasks() {
|
|
14900
|
-
const { stdout } = await $
|
|
14937
|
+
const { stdout } = await $14`mise tasks --json`.quiet();
|
|
14901
14938
|
const tasks = JSON.parse(stdout);
|
|
14902
14939
|
const taskNames = new Set(
|
|
14903
14940
|
Array.isArray(tasks) ? tasks.flatMap((task) => {
|
|
@@ -14917,25 +14954,25 @@ async function checkMiseSetupTasks() {
|
|
|
14917
14954
|
}
|
|
14918
14955
|
}
|
|
14919
14956
|
async function installMiseTools() {
|
|
14920
|
-
await $
|
|
14957
|
+
await $14`mise install`.quiet();
|
|
14921
14958
|
await checkMiseSetupTasks();
|
|
14922
14959
|
}
|
|
14923
14960
|
async function runMiseTask(task) {
|
|
14924
|
-
const { stdout } = await $
|
|
14961
|
+
const { stdout } = await $14`mise run ${task}`.quiet();
|
|
14925
14962
|
return stdout;
|
|
14926
14963
|
}
|
|
14927
14964
|
|
|
14928
14965
|
// src/cmd/backup.ts
|
|
14929
14966
|
var backup = new Command().name("backup").description("Back up the database to a file").action(async () => {
|
|
14930
14967
|
console.clear();
|
|
14931
|
-
|
|
14932
|
-
|
|
14968
|
+
p10.intro(`${color.bgCyan(color.black(" Popina CLI - DB Backup "))}`);
|
|
14969
|
+
p10.log.step("Creating database backup...");
|
|
14933
14970
|
const defaultBranchName = await getGitBranch();
|
|
14934
14971
|
const defaultName = `${defaultBranchName}-${getTimestamp()}`;
|
|
14935
14972
|
const backupDir = "./docker/database/backups";
|
|
14936
|
-
const userInput = await
|
|
14973
|
+
const userInput = await p10.group(
|
|
14937
14974
|
{
|
|
14938
|
-
backupName: () =>
|
|
14975
|
+
backupName: () => p10.text({
|
|
14939
14976
|
message: "Enter a name for the backup:",
|
|
14940
14977
|
defaultValue: defaultName,
|
|
14941
14978
|
placeholder: `Default is branch name: ${defaultBranchName}`
|
|
@@ -14943,7 +14980,7 @@ var backup = new Command().name("backup").description("Back up the database to a
|
|
|
14943
14980
|
},
|
|
14944
14981
|
{
|
|
14945
14982
|
onCancel: () => {
|
|
14946
|
-
|
|
14983
|
+
p10.cancel("Backup process was canceled.");
|
|
14947
14984
|
process.exit(0);
|
|
14948
14985
|
}
|
|
14949
14986
|
}
|
|
@@ -14951,12 +14988,12 @@ var backup = new Command().name("backup").description("Back up the database to a
|
|
|
14951
14988
|
const backupFileName = `${sanitizeFilename(userInput.backupName)}.tar.gz`;
|
|
14952
14989
|
const backupFilePath = `${backupDir}/${backupFileName}`;
|
|
14953
14990
|
if (await fse3.exists(backupFilePath)) {
|
|
14954
|
-
|
|
14991
|
+
p10.log.warn(
|
|
14955
14992
|
`A backup with the name '${backupFileName}' already exists. Please choose a different name.`
|
|
14956
14993
|
);
|
|
14957
14994
|
process.exit(0);
|
|
14958
14995
|
}
|
|
14959
|
-
const spinner10 =
|
|
14996
|
+
const spinner10 = p10.spinner();
|
|
14960
14997
|
const startTime = Date.now();
|
|
14961
14998
|
spinner10.start(`\u{1F4E6} Creating backup`);
|
|
14962
14999
|
await fse3.mkdir(backupDir, { recursive: true });
|
|
@@ -14966,26 +15003,17 @@ var backup = new Command().name("backup").description("Back up the database to a
|
|
|
14966
15003
|
const elapsedTime = ((endTime - startTime) / 1e3).toFixed(2);
|
|
14967
15004
|
const backupStats = await fse3.stat(backupFilePath);
|
|
14968
15005
|
const backupSize = (backupStats.size / 1024 / 1024).toFixed(2);
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
14972
|
-
|
|
14973
|
-
|
|
15006
|
+
p10.log.info(`Backup file: ${backupFileName}`);
|
|
15007
|
+
p10.log.info(`Backup size: ${backupSize} MB`);
|
|
15008
|
+
p10.log.info(`Backup location: ${backupDir}`);
|
|
15009
|
+
p10.log.info(`Elapsed time: ${elapsedTime} seconds`);
|
|
15010
|
+
p10.outro("\u2728 Database backup complete!");
|
|
14974
15011
|
});
|
|
14975
15012
|
|
|
14976
15013
|
// src/cmd/demo.ts
|
|
14977
|
-
import * as
|
|
15014
|
+
import * as p11 from "@clack/prompts";
|
|
14978
15015
|
import { Command as Command2 } from "@commander-js/extra-typings";
|
|
14979
15016
|
import color2 from "picocolors";
|
|
14980
|
-
|
|
14981
|
-
// src/utils/run-with-inherited-stdio.ts
|
|
14982
|
-
import { $ as $14 } from "zx/core";
|
|
14983
|
-
var inheritedStdioShell = $14({ stdio: "inherit" });
|
|
14984
|
-
async function runWithInheritedStdio(command, args) {
|
|
14985
|
-
await inheritedStdioShell`${command} ${args}`;
|
|
14986
|
-
}
|
|
14987
|
-
|
|
14988
|
-
// src/cmd/demo.ts
|
|
14989
15017
|
function getDateDaysAgo(days) {
|
|
14990
15018
|
const date5 = /* @__PURE__ */ new Date();
|
|
14991
15019
|
date5.setUTCDate(date5.getUTCDate() - days);
|
|
@@ -15004,9 +15032,9 @@ function validateSeed(value) {
|
|
|
15004
15032
|
}
|
|
15005
15033
|
var demo = new Command2().name("demo").description("Install deterministic local discovery data").option("--location <location-id>", "Target a specific local location").action(async ({ location }) => {
|
|
15006
15034
|
console.clear();
|
|
15007
|
-
|
|
15035
|
+
p11.intro(`${color2.bgCyan(color2.black(" Popina CLI - Demo data "))}`);
|
|
15008
15036
|
await checkRootProjectDirectory();
|
|
15009
|
-
const mode = await
|
|
15037
|
+
const mode = await p11.select({
|
|
15010
15038
|
initialValue: "generate",
|
|
15011
15039
|
message: "What should be prepared?",
|
|
15012
15040
|
options: [
|
|
@@ -15027,8 +15055,8 @@ var demo = new Command2().name("demo").description("Install deterministic local
|
|
|
15027
15055
|
}
|
|
15028
15056
|
]
|
|
15029
15057
|
});
|
|
15030
|
-
if (
|
|
15031
|
-
|
|
15058
|
+
if (p11.isCancel(mode)) {
|
|
15059
|
+
p11.cancel("Demo data setup canceled.");
|
|
15032
15060
|
return;
|
|
15033
15061
|
}
|
|
15034
15062
|
const locationArgument = location ? [`--location=${location}`] : [];
|
|
@@ -15043,15 +15071,15 @@ var demo = new Command2().name("demo").description("Install deterministic local
|
|
|
15043
15071
|
"reset",
|
|
15044
15072
|
...locationArgument
|
|
15045
15073
|
]);
|
|
15046
|
-
|
|
15074
|
+
p11.outro("Generated sales removed.");
|
|
15047
15075
|
return;
|
|
15048
15076
|
}
|
|
15049
|
-
const shouldReplaceCatalog = await
|
|
15077
|
+
const shouldReplaceCatalog = await p11.confirm({
|
|
15050
15078
|
initialValue: true,
|
|
15051
15079
|
message: "Replace this location catalog with the idempotent Comme un Vendredi preset?"
|
|
15052
15080
|
});
|
|
15053
|
-
if (
|
|
15054
|
-
|
|
15081
|
+
if (p11.isCancel(shouldReplaceCatalog) || !shouldReplaceCatalog) {
|
|
15082
|
+
p11.cancel("Demo data setup canceled; the catalog was not changed.");
|
|
15055
15083
|
return;
|
|
15056
15084
|
}
|
|
15057
15085
|
if (mode === "catalog") {
|
|
@@ -15065,26 +15093,26 @@ var demo = new Command2().name("demo").description("Install deterministic local
|
|
|
15065
15093
|
"catalog",
|
|
15066
15094
|
...locationArgument
|
|
15067
15095
|
]);
|
|
15068
|
-
|
|
15096
|
+
p11.outro("Comme un Vendredi is ready for discovery.");
|
|
15069
15097
|
return;
|
|
15070
15098
|
}
|
|
15071
|
-
const settings = await
|
|
15099
|
+
const settings = await p11.group(
|
|
15072
15100
|
{
|
|
15073
|
-
from: () =>
|
|
15101
|
+
from: () => p11.text({
|
|
15074
15102
|
defaultValue: getDateDaysAgo(90),
|
|
15075
15103
|
initialValue: getDateDaysAgo(90),
|
|
15076
15104
|
message: "First business date",
|
|
15077
15105
|
placeholder: getDateDaysAgo(90),
|
|
15078
15106
|
validate: validateDate
|
|
15079
15107
|
}),
|
|
15080
|
-
to: () =>
|
|
15108
|
+
to: () => p11.text({
|
|
15081
15109
|
defaultValue: getDateDaysAgo(1),
|
|
15082
15110
|
initialValue: getDateDaysAgo(1),
|
|
15083
15111
|
message: "Last business date",
|
|
15084
15112
|
placeholder: getDateDaysAgo(1),
|
|
15085
15113
|
validate: validateDate
|
|
15086
15114
|
}),
|
|
15087
|
-
activity: () =>
|
|
15115
|
+
activity: () => p11.select({
|
|
15088
15116
|
initialValue: "typical",
|
|
15089
15117
|
message: "Sales activity",
|
|
15090
15118
|
options: [
|
|
@@ -15093,7 +15121,7 @@ var demo = new Command2().name("demo").description("Install deterministic local
|
|
|
15093
15121
|
{ label: "Busy", value: "busy" }
|
|
15094
15122
|
]
|
|
15095
15123
|
}),
|
|
15096
|
-
complexity: () =>
|
|
15124
|
+
complexity: () => p11.select({
|
|
15097
15125
|
initialValue: "realistic",
|
|
15098
15126
|
message: "Data complexity",
|
|
15099
15127
|
options: [
|
|
@@ -15114,31 +15142,31 @@ var demo = new Command2().name("demo").description("Install deterministic local
|
|
|
15114
15142
|
}
|
|
15115
15143
|
]
|
|
15116
15144
|
}),
|
|
15117
|
-
seed: () =>
|
|
15145
|
+
seed: () => p11.text({
|
|
15118
15146
|
defaultValue: "comme-un-vendredi",
|
|
15119
15147
|
initialValue: "comme-un-vendredi",
|
|
15120
15148
|
message: "Deterministic seed",
|
|
15121
15149
|
placeholder: "comme-un-vendredi",
|
|
15122
15150
|
validate: validateSeed
|
|
15123
15151
|
}),
|
|
15124
|
-
liveOrders: () =>
|
|
15152
|
+
liveOrders: () => p11.confirm({
|
|
15125
15153
|
initialValue: true,
|
|
15126
15154
|
message: "Populate today's live orders?"
|
|
15127
15155
|
})
|
|
15128
15156
|
},
|
|
15129
15157
|
{
|
|
15130
15158
|
onCancel: () => {
|
|
15131
|
-
|
|
15159
|
+
p11.cancel("Demo data setup canceled.");
|
|
15132
15160
|
process.exit(0);
|
|
15133
15161
|
}
|
|
15134
15162
|
}
|
|
15135
15163
|
);
|
|
15136
15164
|
if (settings.from > settings.to) {
|
|
15137
|
-
|
|
15165
|
+
p11.log.error("The first business date must not be after the last one.");
|
|
15138
15166
|
process.exitCode = 1;
|
|
15139
15167
|
return;
|
|
15140
15168
|
}
|
|
15141
|
-
|
|
15169
|
+
p11.log.step(
|
|
15142
15170
|
"Generating restaurant-medium. Progress will be printed for every business day."
|
|
15143
15171
|
);
|
|
15144
15172
|
const startedAt = Date.now();
|
|
@@ -15160,11 +15188,11 @@ var demo = new Command2().name("demo").description("Install deterministic local
|
|
|
15160
15188
|
...locationArgument
|
|
15161
15189
|
]);
|
|
15162
15190
|
const elapsedSeconds = Math.round((Date.now() - startedAt) / 1e3);
|
|
15163
|
-
|
|
15191
|
+
p11.outro(`Discovery data ready in ${elapsedSeconds}s.`);
|
|
15164
15192
|
});
|
|
15165
15193
|
|
|
15166
15194
|
// src/cmd/dev.ts
|
|
15167
|
-
import * as
|
|
15195
|
+
import * as p12 from "@clack/prompts";
|
|
15168
15196
|
import { Command as Command3 } from "@commander-js/extra-typings";
|
|
15169
15197
|
import clipboardy from "clipboardy";
|
|
15170
15198
|
import color3 from "picocolors";
|
|
@@ -15531,16 +15559,16 @@ var dev = new Command3().name("dev").description(
|
|
|
15531
15559
|
"Interactively select which apps and services to run in development mode"
|
|
15532
15560
|
).action(async () => {
|
|
15533
15561
|
console.clear();
|
|
15534
|
-
|
|
15562
|
+
p12.intro(
|
|
15535
15563
|
`${color3.bgCyan(color3.black(" Popina CLI - Dev command generator "))}
|
|
15536
15564
|
`
|
|
15537
15565
|
);
|
|
15538
|
-
const s =
|
|
15566
|
+
const s = p12.spinner();
|
|
15539
15567
|
try {
|
|
15540
15568
|
const services = await discoverServices();
|
|
15541
15569
|
if (services.length === 0) {
|
|
15542
|
-
|
|
15543
|
-
|
|
15570
|
+
p12.log.error("No services found with dev scripts");
|
|
15571
|
+
p12.outro("Please check your apps directory");
|
|
15544
15572
|
process.exit(1);
|
|
15545
15573
|
}
|
|
15546
15574
|
const sortedServices = groupServices(services);
|
|
@@ -15549,17 +15577,17 @@ var dev = new Command3().name("dev").description(
|
|
|
15549
15577
|
label: `${service.displayName}`,
|
|
15550
15578
|
hint: service.description || service.path
|
|
15551
15579
|
}));
|
|
15552
|
-
const selected = await
|
|
15580
|
+
const selected = await p12.multiselect({
|
|
15553
15581
|
message: "Select services to start:",
|
|
15554
15582
|
options,
|
|
15555
15583
|
required: true
|
|
15556
15584
|
});
|
|
15557
|
-
if (
|
|
15558
|
-
|
|
15585
|
+
if (p12.isCancel(selected)) {
|
|
15586
|
+
p12.cancel("Operation cancelled");
|
|
15559
15587
|
process.exit(0);
|
|
15560
15588
|
}
|
|
15561
15589
|
const selectedPackages = selected;
|
|
15562
|
-
const logOrder = await
|
|
15590
|
+
const logOrder = await p12.select({
|
|
15563
15591
|
message: "Select log UI:",
|
|
15564
15592
|
options: [
|
|
15565
15593
|
{
|
|
@@ -15580,8 +15608,8 @@ var dev = new Command3().name("dev").description(
|
|
|
15580
15608
|
],
|
|
15581
15609
|
initialValue: "tui"
|
|
15582
15610
|
});
|
|
15583
|
-
if (
|
|
15584
|
-
|
|
15611
|
+
if (p12.isCancel(logOrder)) {
|
|
15612
|
+
p12.cancel("Operation cancelled");
|
|
15585
15613
|
process.exit(0);
|
|
15586
15614
|
}
|
|
15587
15615
|
const command = buildCommand(selectedPackages, logOrder);
|
|
@@ -15589,19 +15617,19 @@ var dev = new Command3().name("dev").description(
|
|
|
15589
15617
|
await clipboardy.write(command);
|
|
15590
15618
|
} catch {
|
|
15591
15619
|
}
|
|
15592
|
-
|
|
15620
|
+
p12.log.message(
|
|
15593
15621
|
`
|
|
15594
15622
|
${color3.bold("Generated command:")}
|
|
15595
15623
|
${color3.cyan(command)}
|
|
15596
15624
|
`
|
|
15597
15625
|
);
|
|
15598
|
-
|
|
15626
|
+
p12.outro(`${color3.green("\u2713")} Command copied to clipboard`);
|
|
15599
15627
|
} catch (err) {
|
|
15600
15628
|
s.stop("Error occurred");
|
|
15601
|
-
|
|
15629
|
+
p12.log.error(
|
|
15602
15630
|
`Failed to discover services: ${err instanceof Error ? err.message : String(err)}`
|
|
15603
15631
|
);
|
|
15604
|
-
|
|
15632
|
+
p12.outro(
|
|
15605
15633
|
`Problems? ${color3.underline(color3.cyan("https://linear.new/team/web/new?labels=cli"))}`
|
|
15606
15634
|
);
|
|
15607
15635
|
process.exit(1);
|
|
@@ -15609,12 +15637,12 @@ ${color3.cyan(command)}
|
|
|
15609
15637
|
});
|
|
15610
15638
|
|
|
15611
15639
|
// src/cmd/env.ts
|
|
15612
|
-
import * as
|
|
15640
|
+
import * as p16 from "@clack/prompts";
|
|
15613
15641
|
import { Command as Command7 } from "@commander-js/extra-typings";
|
|
15614
15642
|
import color5 from "picocolors";
|
|
15615
15643
|
|
|
15616
15644
|
// src/cmd/env-app.ts
|
|
15617
|
-
import * as
|
|
15645
|
+
import * as p13 from "@clack/prompts";
|
|
15618
15646
|
import { Command as Command4 } from "@commander-js/extra-typings";
|
|
15619
15647
|
import fse4 from "fs-extra";
|
|
15620
15648
|
import glob2 from "tiny-glob";
|
|
@@ -15632,17 +15660,17 @@ var getPragmaDependencies = (packageJsonPath) => {
|
|
|
15632
15660
|
}
|
|
15633
15661
|
return [];
|
|
15634
15662
|
} catch (error51) {
|
|
15635
|
-
|
|
15663
|
+
p13.log.error(`Error reading or parsing ${packageJsonPath}: ${error51}`);
|
|
15636
15664
|
process.exit(1);
|
|
15637
15665
|
}
|
|
15638
15666
|
};
|
|
15639
15667
|
var explorePackagesDependencies = (packages) => {
|
|
15640
15668
|
const newPackages = [
|
|
15641
15669
|
...packages,
|
|
15642
|
-
...packages.map((
|
|
15643
|
-
const packageJsonPath = `${CURRENT_DIR}/packages/${
|
|
15670
|
+
...packages.map((p23) => {
|
|
15671
|
+
const packageJsonPath = `${CURRENT_DIR}/packages/${p23}/package.json`;
|
|
15644
15672
|
return getPragmaDependencies(packageJsonPath);
|
|
15645
|
-
}).flat().filter((
|
|
15673
|
+
}).flat().filter((p23) => !packages.includes(p23))
|
|
15646
15674
|
];
|
|
15647
15675
|
return newPackages.length === packages.length ? newPackages : explorePackagesDependencies(newPackages);
|
|
15648
15676
|
};
|
|
@@ -15690,13 +15718,13 @@ var getSingleAppOrPackageEnvList = async (appOrPackage) => {
|
|
|
15690
15718
|
async function getAppEnvList(app) {
|
|
15691
15719
|
const apps = getAppDirList();
|
|
15692
15720
|
if (!app) {
|
|
15693
|
-
app = await
|
|
15721
|
+
app = await p13.select({
|
|
15694
15722
|
message: "Select an app:",
|
|
15695
15723
|
options: apps.map((app2) => ({ value: app2, label: app2 }))
|
|
15696
15724
|
});
|
|
15697
15725
|
}
|
|
15698
15726
|
if (app && !apps.includes(app)) {
|
|
15699
|
-
|
|
15727
|
+
p13.log.error(`App ${app} does not exist in the code base.`);
|
|
15700
15728
|
process.exit(1);
|
|
15701
15729
|
}
|
|
15702
15730
|
const packageJsonPath = `./apps/${app}/package.json`;
|
|
@@ -15704,7 +15732,7 @@ async function getAppEnvList(app) {
|
|
|
15704
15732
|
const packageList = Array.from(
|
|
15705
15733
|
new Set(explorePackagesDependencies(packagesLvl0))
|
|
15706
15734
|
).sort();
|
|
15707
|
-
|
|
15735
|
+
p13.log.info(`List of pragma dependencies:
|
|
15708
15736
|
${packageList.join(" \n")}`);
|
|
15709
15737
|
const appAndPackagesToExplore = [app, ...packageList];
|
|
15710
15738
|
let envKeysList = [];
|
|
@@ -15715,23 +15743,23 @@ ${packageList.join(" \n")}`);
|
|
|
15715
15743
|
envList = Array.from(/* @__PURE__ */ new Set([...envList, ...currentEnvList]));
|
|
15716
15744
|
}
|
|
15717
15745
|
envKeysList = envKeysList.filter((curr, index, self) => self.indexOf(curr) === index).sort();
|
|
15718
|
-
|
|
15746
|
+
p13.log.info(
|
|
15719
15747
|
`List of env keys from @pragma/config/env:
|
|
15720
15748
|
${envKeysList.join(" \n")}`
|
|
15721
15749
|
);
|
|
15722
15750
|
envList = envList.filter((curr, index, self) => self.indexOf(curr) === index).sort();
|
|
15723
|
-
|
|
15751
|
+
p13.log.info(`Environment variables for ${app}:
|
|
15724
15752
|
${envList.join("\n")}`);
|
|
15725
|
-
|
|
15753
|
+
p13.outro("\u2728 Done!");
|
|
15726
15754
|
}
|
|
15727
15755
|
|
|
15728
15756
|
// src/cmd/env-diff.ts
|
|
15729
|
-
import * as
|
|
15757
|
+
import * as p14 from "@clack/prompts";
|
|
15730
15758
|
import { Command as Command5 } from "@commander-js/extra-typings";
|
|
15731
15759
|
import fse5 from "fs-extra";
|
|
15732
15760
|
import glob3 from "tiny-glob";
|
|
15733
15761
|
var envDiff = new Command5().command("diff").description("Diff relative commands").action(
|
|
15734
|
-
async () =>
|
|
15762
|
+
async () => p14.select({
|
|
15735
15763
|
message: "Select a microservice:",
|
|
15736
15764
|
options: [...getAppDirList(), ...getPackagesDirList()].map(
|
|
15737
15765
|
(microService) => ({
|
|
@@ -15774,7 +15802,7 @@ var getEnvFromCode = async (microServiceName) => {
|
|
|
15774
15802
|
};
|
|
15775
15803
|
var getEnvDiff = async (microServiceName) => {
|
|
15776
15804
|
if (!microServiceName) {
|
|
15777
|
-
microServiceName = await
|
|
15805
|
+
microServiceName = await p14.select({
|
|
15778
15806
|
message: "Select a microservice:",
|
|
15779
15807
|
options: [...getAppDirList(), ...getPackagesDirList()].map(
|
|
15780
15808
|
(microService) => ({
|
|
@@ -15785,7 +15813,7 @@ var getEnvDiff = async (microServiceName) => {
|
|
|
15785
15813
|
});
|
|
15786
15814
|
}
|
|
15787
15815
|
const { envList: importedEnv } = await getSingleAppOrPackageEnvList(microServiceName);
|
|
15788
|
-
|
|
15816
|
+
p14.log.info(
|
|
15789
15817
|
`[ ${microServiceName} ] Imported env variables:
|
|
15790
15818
|
${importedEnv.join(
|
|
15791
15819
|
"\n"
|
|
@@ -15793,7 +15821,7 @@ ${importedEnv.join(
|
|
|
15793
15821
|
Total imported env var: ${importedEnv.length}`
|
|
15794
15822
|
);
|
|
15795
15823
|
const envUsed = await getEnvFromCode(microServiceName);
|
|
15796
|
-
|
|
15824
|
+
p14.log.info(
|
|
15797
15825
|
`[ ${microServiceName} ] Used env variables:
|
|
15798
15826
|
${envUsed.join(
|
|
15799
15827
|
"\n"
|
|
@@ -15802,26 +15830,26 @@ Total used env var: ${envUsed.length}`
|
|
|
15802
15830
|
);
|
|
15803
15831
|
const unusedEnvList = importedEnv.filter((env2) => !envUsed.includes(env2));
|
|
15804
15832
|
if (unusedEnvList.length > 0) {
|
|
15805
|
-
|
|
15833
|
+
p14.log.warning(
|
|
15806
15834
|
`[ ${microServiceName} ] \u2757\uFE0F Unused env variables in the app:
|
|
15807
15835
|
${unusedEnvList.join(
|
|
15808
15836
|
" \n"
|
|
15809
15837
|
)}`
|
|
15810
15838
|
);
|
|
15811
|
-
|
|
15839
|
+
p14.log.warning(`Total unused env var: ${unusedEnvList.length}`);
|
|
15812
15840
|
} else {
|
|
15813
|
-
|
|
15841
|
+
p14.log.success(`[ ${microServiceName} ] \u2705 No unused env variables found!`);
|
|
15814
15842
|
}
|
|
15815
15843
|
};
|
|
15816
15844
|
|
|
15817
15845
|
// src/cmd/env-pull.ts
|
|
15818
|
-
import * as
|
|
15846
|
+
import * as p15 from "@clack/prompts";
|
|
15819
15847
|
import { Command as Command6 } from "@commander-js/extra-typings";
|
|
15820
15848
|
import color4 from "picocolors";
|
|
15821
15849
|
var envPull = new Command6().name("pull").description("Fetch environment variables from Google Cloud Secret Manager").action(getEnvPull);
|
|
15822
15850
|
async function getEnvPull() {
|
|
15823
|
-
|
|
15824
|
-
const spinner10 =
|
|
15851
|
+
p15.intro(`${color4.bgCyan(color4.black(" Popina CLI - Env "))}`);
|
|
15852
|
+
const spinner10 = p15.spinner();
|
|
15825
15853
|
spinner10.start("\u{1F4C1} Check if you are in the root of a Popina project.");
|
|
15826
15854
|
await checkRootProjectDirectory();
|
|
15827
15855
|
spinner10.stop("\u2705 You are in the root of a Popina project.");
|
|
@@ -15834,13 +15862,13 @@ async function getEnvPull() {
|
|
|
15834
15862
|
spinner10.start("\u{1F511} Fetching secrets from Google Cloud Secret Manager ...");
|
|
15835
15863
|
await fetchEnv(email3);
|
|
15836
15864
|
spinner10.stop("\u2705 Secrets fetched from Google Cloud Secret Manager.");
|
|
15837
|
-
|
|
15865
|
+
p15.outro("\u2705 Environment variables are ready to use!");
|
|
15838
15866
|
}
|
|
15839
15867
|
|
|
15840
15868
|
// src/cmd/env.ts
|
|
15841
15869
|
var env = new Command7().name("env").description("Env relative commands").action(async () => {
|
|
15842
|
-
|
|
15843
|
-
await
|
|
15870
|
+
p16.intro(`${color5.bgCyan(color5.black(" Popina CLI - Env "))}`);
|
|
15871
|
+
await p16.select({
|
|
15844
15872
|
message: "Select an action:",
|
|
15845
15873
|
options: [
|
|
15846
15874
|
{ label: "Pull", value: "pull", hint: "Pull env vars from google" },
|
|
@@ -15857,7 +15885,7 @@ var env = new Command7().name("env").description("Env relative commands").action
|
|
|
15857
15885
|
]
|
|
15858
15886
|
}).then(async (action) => {
|
|
15859
15887
|
const selectedAction = action;
|
|
15860
|
-
|
|
15888
|
+
p16.log.info(`You selected: ${selectedAction}`);
|
|
15861
15889
|
switch (selectedAction) {
|
|
15862
15890
|
case "pull":
|
|
15863
15891
|
await getEnvPull();
|
|
@@ -15938,14 +15966,14 @@ var gen = new Command12().name("gen").alias("g").description("Generate a new com
|
|
|
15938
15966
|
gen.addCommand(ui).addCommand(api);
|
|
15939
15967
|
|
|
15940
15968
|
// src/cmd/init.ts
|
|
15941
|
-
import * as
|
|
15969
|
+
import * as p17 from "@clack/prompts";
|
|
15942
15970
|
import { Command as Command13 } from "@commander-js/extra-typings";
|
|
15943
15971
|
import { resolve } from "path";
|
|
15944
15972
|
import color6 from "picocolors";
|
|
15945
15973
|
import { cd } from "zx";
|
|
15946
15974
|
var canceled = /* @__PURE__ */ Symbol("canceled");
|
|
15947
15975
|
function cancelInitialization(message) {
|
|
15948
|
-
|
|
15976
|
+
p17.cancel(message);
|
|
15949
15977
|
throw canceled;
|
|
15950
15978
|
}
|
|
15951
15979
|
function getErrorMessage(error51) {
|
|
@@ -15958,7 +15986,7 @@ function quoteShellArgument(value) {
|
|
|
15958
15986
|
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
15959
15987
|
}
|
|
15960
15988
|
async function runStep(message, successMessage, action) {
|
|
15961
|
-
const spinner10 =
|
|
15989
|
+
const spinner10 = p17.spinner({ indicator: "timer" });
|
|
15962
15990
|
spinner10.start(message);
|
|
15963
15991
|
try {
|
|
15964
15992
|
const result = await action();
|
|
@@ -16011,12 +16039,12 @@ async function runProjectSetup(shouldSetupDatabase) {
|
|
|
16011
16039
|
const readiness = output.match(
|
|
16012
16040
|
/CockroachDB is ready after \d+ attempts?\./
|
|
16013
16041
|
)?.[0];
|
|
16014
|
-
|
|
16042
|
+
p17.log.success(readiness ?? "CockroachDB is ready.");
|
|
16015
16043
|
}
|
|
16016
16044
|
}
|
|
16017
16045
|
}
|
|
16018
16046
|
async function getProjectDirectory(workspacePath) {
|
|
16019
|
-
|
|
16047
|
+
p17.note(
|
|
16020
16048
|
`A workspace is the parent folder where you keep your code repositories.
|
|
16021
16049
|
Current workspace: ${workspacePath}
|
|
16022
16050
|
|
|
@@ -16024,7 +16052,7 @@ We recommend keeping pragma-web here alongside your future repositories.`,
|
|
|
16024
16052
|
"Your workspace"
|
|
16025
16053
|
);
|
|
16026
16054
|
while (true) {
|
|
16027
|
-
const answer = await
|
|
16055
|
+
const answer = await p17.text({
|
|
16028
16056
|
message: "Project folder name",
|
|
16029
16057
|
initialValue: "pragma-project",
|
|
16030
16058
|
validate: (value) => {
|
|
@@ -16035,7 +16063,7 @@ We recommend keeping pragma-web here alongside your future repositories.`,
|
|
|
16035
16063
|
}
|
|
16036
16064
|
}
|
|
16037
16065
|
});
|
|
16038
|
-
if (
|
|
16066
|
+
if (p17.isCancel(answer)) {
|
|
16039
16067
|
cancelInitialization(
|
|
16040
16068
|
"Project setup canceled. Run popina init when ready."
|
|
16041
16069
|
);
|
|
@@ -16046,44 +16074,44 @@ We recommend keeping pragma-web here alongside your future repositories.`,
|
|
|
16046
16074
|
return { name, path: projectPath, shouldClone: true };
|
|
16047
16075
|
}
|
|
16048
16076
|
if (!await dirAlreadyExist(projectPath)) {
|
|
16049
|
-
|
|
16077
|
+
p17.log.warn(
|
|
16050
16078
|
`${projectPath} is a file. Move it or choose another folder name.`
|
|
16051
16079
|
);
|
|
16052
16080
|
continue;
|
|
16053
16081
|
}
|
|
16054
16082
|
if (!await isPopinaProjectDirectory(projectPath)) {
|
|
16055
|
-
|
|
16083
|
+
p17.log.warn(
|
|
16056
16084
|
`${projectPath} is not a Popina repository. Choose another folder name.`
|
|
16057
16085
|
);
|
|
16058
16086
|
continue;
|
|
16059
16087
|
}
|
|
16060
|
-
const shouldResume = await
|
|
16088
|
+
const shouldResume = await p17.confirm({
|
|
16061
16089
|
message: `Resume setup in the existing ${name} repository?`,
|
|
16062
16090
|
initialValue: true
|
|
16063
16091
|
});
|
|
16064
|
-
if (
|
|
16092
|
+
if (p17.isCancel(shouldResume)) {
|
|
16065
16093
|
cancelInitialization(
|
|
16066
16094
|
"Existing project left unchanged. Run popina init when ready."
|
|
16067
16095
|
);
|
|
16068
16096
|
}
|
|
16069
16097
|
if (!shouldResume) {
|
|
16070
|
-
|
|
16098
|
+
p17.log.info(
|
|
16071
16099
|
"The existing project was left unchanged. Choose another name."
|
|
16072
16100
|
);
|
|
16073
16101
|
continue;
|
|
16074
16102
|
}
|
|
16075
|
-
|
|
16103
|
+
p17.log.info(`Resuming the existing Popina checkout at ${projectPath}.`);
|
|
16076
16104
|
return { name, path: projectPath, shouldClone: false };
|
|
16077
16105
|
}
|
|
16078
16106
|
}
|
|
16079
16107
|
async function runInitialization() {
|
|
16080
16108
|
const workspacePath = process.cwd();
|
|
16081
|
-
|
|
16082
|
-
|
|
16109
|
+
p17.intro(color6.bgCyan(color6.black(" Popina CLI \xB7 Project setup ")));
|
|
16110
|
+
p17.box(
|
|
16083
16111
|
"This is the official @popina/cli setup wizard.\nIt will clone pragma-web, install the repository-pinned toolchain,\nfetch development secrets, and optionally prepare CockroachDB.",
|
|
16084
16112
|
"What happens next"
|
|
16085
16113
|
);
|
|
16086
|
-
|
|
16114
|
+
p17.log.info("Checking GitHub access and required tools...");
|
|
16087
16115
|
await checkGitHubAccess();
|
|
16088
16116
|
await checkMise();
|
|
16089
16117
|
const project = await getProjectDirectory(workspacePath);
|
|
@@ -16100,11 +16128,11 @@ async function runInitialization() {
|
|
|
16100
16128
|
"Popina toolchain is ready.",
|
|
16101
16129
|
installMiseTools
|
|
16102
16130
|
);
|
|
16103
|
-
const shouldFetchEnv = await
|
|
16131
|
+
const shouldFetchEnv = await p17.confirm({
|
|
16104
16132
|
message: "Fetch the shared development secrets?",
|
|
16105
16133
|
initialValue: true
|
|
16106
16134
|
});
|
|
16107
|
-
if (
|
|
16135
|
+
if (p17.isCancel(shouldFetchEnv)) {
|
|
16108
16136
|
cancelInitialization(
|
|
16109
16137
|
"Secrets setup canceled. Your repository is preserved."
|
|
16110
16138
|
);
|
|
@@ -16122,11 +16150,11 @@ async function runInitialization() {
|
|
|
16122
16150
|
() => fetchEnv(email3)
|
|
16123
16151
|
);
|
|
16124
16152
|
}
|
|
16125
|
-
const shouldSetupDatabase = await
|
|
16153
|
+
const shouldSetupDatabase = await p17.confirm({
|
|
16126
16154
|
message: "Start CockroachDB, apply its schema, and add development data?",
|
|
16127
16155
|
initialValue: true
|
|
16128
16156
|
});
|
|
16129
|
-
if (
|
|
16157
|
+
if (p17.isCancel(shouldSetupDatabase)) {
|
|
16130
16158
|
cancelInitialization(
|
|
16131
16159
|
"Database setup canceled. Your repository and completed setup are preserved."
|
|
16132
16160
|
);
|
|
@@ -16141,12 +16169,12 @@ async function runInitialization() {
|
|
|
16141
16169
|
"popina demo # optional discovery data",
|
|
16142
16170
|
"popina dev"
|
|
16143
16171
|
].join("\n");
|
|
16144
|
-
|
|
16145
|
-
|
|
16172
|
+
p17.note(nextSteps, "Next steps");
|
|
16173
|
+
p17.note(
|
|
16146
16174
|
"popina dev lets you choose services and copies the generated command.\nDeveloper guide: https://knowledge.popina.com/docs\nQuestions: ask in Slack #web.",
|
|
16147
16175
|
"Need help?"
|
|
16148
16176
|
);
|
|
16149
|
-
|
|
16177
|
+
p17.outro(
|
|
16150
16178
|
`Problems? ${color6.underline(
|
|
16151
16179
|
color6.cyan("https://linear.new/team/web/new?labels=cli")
|
|
16152
16180
|
)}`
|
|
@@ -16162,8 +16190,8 @@ var init = new Command13().name("init").alias("i").description(
|
|
|
16162
16190
|
process.exitCode = 130;
|
|
16163
16191
|
return;
|
|
16164
16192
|
}
|
|
16165
|
-
|
|
16166
|
-
|
|
16193
|
+
p17.log.error(getErrorMessage(error51));
|
|
16194
|
+
p17.outro(
|
|
16167
16195
|
"Setup stopped. Fix the issue, then run popina init again to resume."
|
|
16168
16196
|
);
|
|
16169
16197
|
process.exitCode = 1;
|
|
@@ -16171,12 +16199,12 @@ var init = new Command13().name("init").alias("i").description(
|
|
|
16171
16199
|
});
|
|
16172
16200
|
|
|
16173
16201
|
// src/cmd/list.ts
|
|
16174
|
-
import * as
|
|
16202
|
+
import * as p19 from "@clack/prompts";
|
|
16175
16203
|
import { Command as Command14 } from "@commander-js/extra-typings";
|
|
16176
16204
|
import color8 from "picocolors";
|
|
16177
16205
|
|
|
16178
16206
|
// src/template.ts
|
|
16179
|
-
import * as
|
|
16207
|
+
import * as p18 from "@clack/prompts";
|
|
16180
16208
|
import color7 from "picocolors";
|
|
16181
16209
|
var MARGIN = ` `;
|
|
16182
16210
|
function printAppsList(apps) {
|
|
@@ -16187,7 +16215,7 @@ ${MARGIN}${description}
|
|
|
16187
16215
|
${MARGIN}${color7.underline(
|
|
16188
16216
|
color7.blue(url2)
|
|
16189
16217
|
)} - ${color7.italic(color7.blue(path2))}`;
|
|
16190
|
-
return
|
|
16218
|
+
return p18.log.message(`${apps.map(appRow).join("\n")}`);
|
|
16191
16219
|
}
|
|
16192
16220
|
|
|
16193
16221
|
// src/cmd/list.ts
|
|
@@ -16200,23 +16228,23 @@ var cmdList = new Command14().name("list").description(
|
|
|
16200
16228
|
const docList = getDocServices();
|
|
16201
16229
|
const otherList = getOtherServices();
|
|
16202
16230
|
const databaseList = getDatabaseTools();
|
|
16203
|
-
|
|
16204
|
-
|
|
16231
|
+
p19.intro(`${color8.bgCyan(color8.black(` Popina CLI - list `))}`);
|
|
16232
|
+
p19.log.message(`
|
|
16205
16233
|
${color8.bold("API Services:")}`);
|
|
16206
16234
|
printAppsList(apiList);
|
|
16207
|
-
|
|
16235
|
+
p19.log.message(`
|
|
16208
16236
|
${color8.bold("Web Applications:")}`);
|
|
16209
16237
|
printAppsList(appsList);
|
|
16210
|
-
|
|
16238
|
+
p19.log.message(`
|
|
16211
16239
|
${color8.bold("Documentations:")}`);
|
|
16212
16240
|
printAppsList(docList);
|
|
16213
|
-
|
|
16241
|
+
p19.log.message(`
|
|
16214
16242
|
${color8.bold("Background services:")}`);
|
|
16215
16243
|
printAppsList(otherList);
|
|
16216
|
-
|
|
16244
|
+
p19.log.message(`
|
|
16217
16245
|
${color8.bold("Database tools:")}`);
|
|
16218
16246
|
printAppsList(databaseList);
|
|
16219
|
-
|
|
16247
|
+
p19.outro(
|
|
16220
16248
|
`Problems? ${color8.underline(
|
|
16221
16249
|
color8.cyan("https://linear.new/team/web/new?labels=cli")
|
|
16222
16250
|
)}`
|
|
@@ -16296,24 +16324,24 @@ var localization = new Command15().name("localization").description("Review loca
|
|
|
16296
16324
|
});
|
|
16297
16325
|
|
|
16298
16326
|
// src/cmd/restore.ts
|
|
16299
|
-
import * as
|
|
16327
|
+
import * as p22 from "@clack/prompts";
|
|
16300
16328
|
import { Argument, Command as Command16, Option } from "@commander-js/extra-typings";
|
|
16301
16329
|
import fse8 from "fs-extra";
|
|
16302
16330
|
import color9 from "picocolors";
|
|
16303
16331
|
import { $ as $23 } from "zx/core";
|
|
16304
16332
|
|
|
16305
16333
|
// src/cmd/restore-local.ts
|
|
16306
|
-
import * as
|
|
16334
|
+
import * as p20 from "@clack/prompts";
|
|
16307
16335
|
import fse6 from "fs-extra";
|
|
16308
16336
|
import { $ as $21 } from "zx/core";
|
|
16309
|
-
var spinner6 =
|
|
16337
|
+
var spinner6 = p20.spinner();
|
|
16310
16338
|
async function restoreLocal() {
|
|
16311
16339
|
const backupDir = "./docker/database/backups";
|
|
16312
16340
|
const backups = await fse6.readdir(backupDir);
|
|
16313
16341
|
const tarGzBackups = backups.filter((b) => b.endsWith(".tar.gz"));
|
|
16314
16342
|
if (tarGzBackups.length === 0) {
|
|
16315
|
-
|
|
16316
|
-
|
|
16343
|
+
p20.log.warn("No backup files found to restore.");
|
|
16344
|
+
p20.log.warn(
|
|
16317
16345
|
`Database backup files should be placed in the '${backupDir}' folder.`
|
|
16318
16346
|
);
|
|
16319
16347
|
process.exit(0);
|
|
@@ -16330,9 +16358,9 @@ async function restoreLocal() {
|
|
|
16330
16358
|
};
|
|
16331
16359
|
})
|
|
16332
16360
|
);
|
|
16333
|
-
const userChoices = await
|
|
16361
|
+
const userChoices = await p20.group(
|
|
16334
16362
|
{
|
|
16335
|
-
selectedBackup: () =>
|
|
16363
|
+
selectedBackup: () => p20.select({
|
|
16336
16364
|
message: "Select a backup to restore:",
|
|
16337
16365
|
options: backupDetails,
|
|
16338
16366
|
initialValue: backupDetails[0]?.value
|
|
@@ -16340,7 +16368,7 @@ async function restoreLocal() {
|
|
|
16340
16368
|
},
|
|
16341
16369
|
{
|
|
16342
16370
|
onCancel: () => {
|
|
16343
|
-
|
|
16371
|
+
p20.cancel("Restore process was canceled.");
|
|
16344
16372
|
process.exit(0);
|
|
16345
16373
|
}
|
|
16346
16374
|
}
|
|
@@ -16362,38 +16390,38 @@ async function restoreLocal() {
|
|
|
16362
16390
|
spinner6.stop(
|
|
16363
16391
|
`\u{1F331} Database restored successfully from ${userChoices.selectedBackup}`
|
|
16364
16392
|
);
|
|
16365
|
-
|
|
16366
|
-
|
|
16367
|
-
|
|
16368
|
-
|
|
16393
|
+
p20.log.info(`Elapsed time: ${elapsedTime} seconds`);
|
|
16394
|
+
p20.log.info(`Restore date: ${formatDate(/* @__PURE__ */ new Date())}`);
|
|
16395
|
+
p20.log.info(`Restored DB size: ${restoreSize} MB`);
|
|
16396
|
+
p20.log.info(`Branch name: ${branchName}`);
|
|
16369
16397
|
}
|
|
16370
16398
|
|
|
16371
16399
|
// src/cmd/restore-remote.ts
|
|
16372
|
-
import * as
|
|
16400
|
+
import * as p21 from "@clack/prompts";
|
|
16373
16401
|
import fse7 from "fs-extra";
|
|
16374
16402
|
import { $ as $22 } from "zx/core";
|
|
16375
16403
|
var STAGING_BACKUP_BUCKET = "staging";
|
|
16376
|
-
var spinner8 =
|
|
16404
|
+
var spinner8 = p21.spinner();
|
|
16377
16405
|
async function restoreRemote() {
|
|
16378
16406
|
await checkCockroach();
|
|
16379
16407
|
await checkGCloud();
|
|
16380
16408
|
const keyFilePath = await $22`gcloud auth application-default login 2>&1`.then((res) => {
|
|
16381
16409
|
if (res.exitCode !== 0) {
|
|
16382
|
-
|
|
16410
|
+
p21.cancel(`\u274C Couldn't authenticate with gcloud, ${res.stdout}`);
|
|
16383
16411
|
process.exit(0);
|
|
16384
16412
|
}
|
|
16385
|
-
|
|
16413
|
+
p21.log.success(`\u{1F513} Successfully authenticated with gcloud.`);
|
|
16386
16414
|
const parsedFilePath = external_exports.string().min(1).safeParse(res.stdout.match(/\[(?<filepath>.*)\]/)?.groups?.filepath);
|
|
16387
16415
|
if (parsedFilePath.success) {
|
|
16388
16416
|
return parsedFilePath.data;
|
|
16389
16417
|
} else {
|
|
16390
|
-
|
|
16418
|
+
p21.cancel(
|
|
16391
16419
|
`\u274C Couldn't find the key's file path from the gcloud response, err: ${parsedFilePath.error}`
|
|
16392
16420
|
);
|
|
16393
16421
|
process.exit(0);
|
|
16394
16422
|
}
|
|
16395
16423
|
});
|
|
16396
|
-
|
|
16424
|
+
p21.log.success(`\u2705 Successfully parsed the backup file path: ${keyFilePath}`);
|
|
16397
16425
|
const base64Key = await fse7.readJson(keyFilePath, "utf-8").then((keyJson) => {
|
|
16398
16426
|
const parsedKey = external_exports.object({
|
|
16399
16427
|
account: external_exports.string(),
|
|
@@ -16405,7 +16433,7 @@ async function restoreRemote() {
|
|
|
16405
16433
|
universe_domain: external_exports.string()
|
|
16406
16434
|
}).safeParse(keyJson);
|
|
16407
16435
|
if (!parsedKey.success) {
|
|
16408
|
-
|
|
16436
|
+
p21.log.error(
|
|
16409
16437
|
`\u274C Couldn't parse the key file: ${keyFilePath}: ${parsedKey.error}`
|
|
16410
16438
|
);
|
|
16411
16439
|
process.exit(0);
|
|
@@ -16413,31 +16441,31 @@ async function restoreRemote() {
|
|
|
16413
16441
|
return btoa(JSON.stringify(parsedKey.data));
|
|
16414
16442
|
}
|
|
16415
16443
|
}).catch((err) => {
|
|
16416
|
-
|
|
16444
|
+
p21.log.error(`\u274C Couldn't read the key file: ${keyFilePath}: ${err}`);
|
|
16417
16445
|
process.exit(0);
|
|
16418
16446
|
});
|
|
16419
|
-
|
|
16447
|
+
p21.log.success(`\u2705 Successfully parsed the key file.`);
|
|
16420
16448
|
spinner8.start(
|
|
16421
16449
|
"\u{1F504} Restoring database from latest staging backup in GCP bucket."
|
|
16422
16450
|
);
|
|
16423
16451
|
spinner8.message(`\u{1F52B} Dropping the current "dev" database`);
|
|
16424
16452
|
await $22`cockroach sql --url="postgresql://root@127.0.0.1:26257?sslmode=disable" -e "DROP DATABASE IF EXISTS dev;"`;
|
|
16425
|
-
|
|
16453
|
+
p21.log.success(`\u2705 Successfully reset the current database.`);
|
|
16426
16454
|
spinner8.message(`\u{1F6B0} Restoring`);
|
|
16427
16455
|
const restoreFeedBack = await $22`cockroach sql --url="postgresql://root@localhost:26257?sslmode=disable" -e "RESTORE DATABASE \\"pragma\-api\\" FROM LATEST IN 'gs://pragma-cockroach-backup/${STAGING_BACKUP_BUCKET}?AUTH=specified&CREDENTIALS=${base64Key}' WITH new_db_name = 'dev';"`.then((res) => {
|
|
16428
16456
|
if (res.stderr) {
|
|
16429
16457
|
spinner8.stop("\u274C Failed to restore the database.");
|
|
16430
|
-
|
|
16458
|
+
p21.log.error(`\u274C Couldn't restore the database: ${res.stderr}`);
|
|
16431
16459
|
process.exit(0);
|
|
16432
16460
|
}
|
|
16433
16461
|
return res.stdout;
|
|
16434
16462
|
}).catch((err) => {
|
|
16435
16463
|
spinner8.stop("\u274C Failed to restore the database.");
|
|
16436
|
-
|
|
16464
|
+
p21.log.error(`\u274C Couldn't restore the database: ${err}`);
|
|
16437
16465
|
process.exit(0);
|
|
16438
16466
|
});
|
|
16439
16467
|
spinner8.stop("\u{1F331} Database restored successfully from GCP Bucket.");
|
|
16440
|
-
|
|
16468
|
+
p21.log.success(String(restoreFeedBack));
|
|
16441
16469
|
}
|
|
16442
16470
|
|
|
16443
16471
|
// src/cmd/restore.ts
|
|
@@ -16451,29 +16479,29 @@ var restore = new Command16().name("restore").description("Restore the database
|
|
|
16451
16479
|
new Argument("[source]", "Source to restore the DB from").choices(["local", "remote"]).argParser((source) => sourceSchema.optional().parse(source))
|
|
16452
16480
|
).action(async (source, option) => {
|
|
16453
16481
|
console.clear();
|
|
16454
|
-
|
|
16455
|
-
|
|
16482
|
+
p22.intro(`${color9.bgCyan(color9.black(" Popina CLI - DB Restore "))}`);
|
|
16483
|
+
p22.log.step("Restoring database from backup...");
|
|
16456
16484
|
await checkDocker();
|
|
16457
16485
|
if (!await isContainerUp("pragma-project-cockroach-dev")) {
|
|
16458
|
-
|
|
16486
|
+
p22.log.error(
|
|
16459
16487
|
"Cockroach container is not running. Please start it and try again."
|
|
16460
16488
|
);
|
|
16461
16489
|
process.exit(1);
|
|
16462
16490
|
}
|
|
16463
|
-
const spinner10 =
|
|
16491
|
+
const spinner10 = p22.spinner();
|
|
16464
16492
|
if (option.skipArchive) {
|
|
16465
|
-
|
|
16493
|
+
p22.log.info("Skipping archiving of the current database");
|
|
16466
16494
|
} else {
|
|
16467
|
-
await
|
|
16495
|
+
await p22.confirm({
|
|
16468
16496
|
message: "\u{1F4BE} Do you want to archive the current database before restoring?",
|
|
16469
16497
|
initialValue: true
|
|
16470
16498
|
}).then(async (archive) => {
|
|
16471
16499
|
if (String(archive) === "Symbol(clack:cancel)") {
|
|
16472
|
-
|
|
16500
|
+
p22.log.info("Cancelled... \u{1F44B}.");
|
|
16473
16501
|
process.exit(0);
|
|
16474
16502
|
}
|
|
16475
16503
|
if (archive === false) {
|
|
16476
|
-
|
|
16504
|
+
p22.log.info("Current database will not be archived");
|
|
16477
16505
|
} else {
|
|
16478
16506
|
spinner10.start(`\u{1F4E6} Archiving current database...`);
|
|
16479
16507
|
const timestamp = getTimestamp();
|
|
@@ -16491,7 +16519,7 @@ var restore = new Command16().name("restore").description("Restore the database
|
|
|
16491
16519
|
case "remote":
|
|
16492
16520
|
return await restoreRemote();
|
|
16493
16521
|
case void 0:
|
|
16494
|
-
await
|
|
16522
|
+
await p22.select({
|
|
16495
16523
|
message: "Choose the source to restore the database from:",
|
|
16496
16524
|
options: [
|
|
16497
16525
|
{ label: "\u{1F4BD} Local backup", value: "local" },
|
|
@@ -16500,7 +16528,7 @@ var restore = new Command16().name("restore").description("Restore the database
|
|
|
16500
16528
|
initialValue: "local"
|
|
16501
16529
|
}).then(async (s) => {
|
|
16502
16530
|
if (typeof s === "symbol" || String(s) === "Symbol(clack:cancel)") {
|
|
16503
|
-
|
|
16531
|
+
p22.log.info("Canceled... \u{1F44B}");
|
|
16504
16532
|
process.exit(0);
|
|
16505
16533
|
} else {
|
|
16506
16534
|
const parsedSource = sourceSchema.parse(s);
|
|
@@ -16512,7 +16540,7 @@ var restore = new Command16().name("restore").description("Restore the database
|
|
|
16512
16540
|
}
|
|
16513
16541
|
});
|
|
16514
16542
|
}
|
|
16515
|
-
|
|
16543
|
+
p22.outro(
|
|
16516
16544
|
`\u{1F9DA}\u2728${color9.bgCyan(color9.black(" Database restore complete! "))}\u2728\u{1F9DA}`
|
|
16517
16545
|
);
|
|
16518
16546
|
});
|