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