@shipdit/cli 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/index.mjs +432 -121
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -12,3 +12,24 @@ shipd types gen
|
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
`shipd login` stores a scoped management API key. Use `SHIPD_API_KEY` for CI — keys carry org/project/environment metadata.
|
|
15
|
+
|
|
16
|
+
## Go projects
|
|
17
|
+
|
|
18
|
+
The CLI reads `shipd.config.go` directly. Declare an exported
|
|
19
|
+
`var Config = config.ShipdConfig{...}` using
|
|
20
|
+
`github.com/alasti-company/useshipd.com/sdks/go/config`. Go 1.23+ and Node.js 22.12+
|
|
21
|
+
are needed for CLI commands; the application runtime only needs Go.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
shipd diff
|
|
25
|
+
shipd push
|
|
26
|
+
shipd types gen
|
|
27
|
+
shipd pull
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Go input automatically selects Go output in `internal/flags/flags_gen.go`.
|
|
31
|
+
Generation emits per-flag accessors, key and variant constants, and `Defaults()`.
|
|
32
|
+
Pull writes Go definitions back to `shipd.config.go`. No JSON flag file is needed.
|
|
33
|
+
The definition file is evaluated on its own inside the Go module: imports and
|
|
34
|
+
helpers declared in that file work; sibling files are not loaded. Do not define
|
|
35
|
+
`main` in it. See `examples/go-examples` for a complete example.
|
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,27 @@ import os from "node:os";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { createJiti } from "jiti";
|
|
8
|
+
import { spawn } from "node:child_process";
|
|
8
9
|
|
|
10
|
+
//#region src/lib/errors.ts
|
|
11
|
+
var CliError = class extends Error {
|
|
12
|
+
code;
|
|
13
|
+
exitCode;
|
|
14
|
+
details;
|
|
15
|
+
constructor(code, message, options) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "CliError";
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.exitCode = options?.exitCode ?? 1;
|
|
20
|
+
this.details = options?.details;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function exitCodeForError(error) {
|
|
24
|
+
if (error instanceof CliError) return error.exitCode;
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
9
29
|
//#region src/lib/config.ts
|
|
10
30
|
/** Hosted control plane. Used when no flag, env, project, global, or credential URL is set. */
|
|
11
31
|
const DEFAULT_API_URL = "https://api.useshipd.com";
|
|
@@ -44,7 +64,7 @@ function clearCredentials() {
|
|
|
44
64
|
function findProjectRoot(start = process.cwd()) {
|
|
45
65
|
let current = path.resolve(start);
|
|
46
66
|
while (true) {
|
|
47
|
-
if (fs.existsSync(path.join(current, "shipd.config.ts")) || fs.existsSync(path.join(current, ".shipd", "config.json"))) return current;
|
|
67
|
+
if (fs.existsSync(path.join(current, "shipd.config.ts")) || fs.existsSync(path.join(current, "shipd.config.go")) || fs.existsSync(path.join(current, "shipd.config.json")) || fs.existsSync(path.join(current, ".shipd", "config.json"))) return current;
|
|
48
68
|
const parent = path.dirname(current);
|
|
49
69
|
if (parent === current) return process.cwd();
|
|
50
70
|
current = parent;
|
|
@@ -60,7 +80,14 @@ function resolveRuntimeConfig(flags, options) {
|
|
|
60
80
|
const globalConfig = loadGlobalConfig();
|
|
61
81
|
const credentials = loadCredentials();
|
|
62
82
|
const ci = flags.ci === true || flags.yes === true || process.env.CI === "1" || process.env.CI === "true" || process.env.SHIPD_CI === "1";
|
|
63
|
-
const defaultConfigFile =
|
|
83
|
+
const defaultConfigFile = path.join(projectRoot, [
|
|
84
|
+
"shipd.config.ts",
|
|
85
|
+
"shipd.config.go",
|
|
86
|
+
"shipd.config.json"
|
|
87
|
+
].find((file) => fs.existsSync(path.join(projectRoot, file))) ?? "shipd.config.ts");
|
|
88
|
+
const configFile = flags.flagsConfig ? path.resolve(flags.flagsConfig) : projectConfig.configFile ?? defaultConfigFile;
|
|
89
|
+
const typesLanguage = projectConfig.typesLanguage ?? (path.extname(configFile) === ".go" ? "go" : "typescript");
|
|
90
|
+
if (typesLanguage !== "typescript" && typesLanguage !== "go") throw new CliError("validation_error", "typesLanguage must be typescript or go");
|
|
64
91
|
return {
|
|
65
92
|
apiUrl: flags.apiUrl ?? process.env.SHIPD_API_URL ?? projectConfig.apiUrl ?? globalConfig.apiUrl ?? credentials.apiUrl ?? options?.defaultApiUrl ?? "https://api.useshipd.com",
|
|
66
93
|
appUrl: process.env.SHIPD_APP_URL ?? projectConfig.appUrl ?? globalConfig.appUrl ?? "http://localhost:5173",
|
|
@@ -68,8 +95,10 @@ function resolveRuntimeConfig(flags, options) {
|
|
|
68
95
|
org: flags.org ?? process.env.SHIPD_ORG ?? projectConfig.org ?? globalConfig.org,
|
|
69
96
|
project: flags.project ?? process.env.SHIPD_PROJECT ?? projectConfig.project ?? globalConfig.project,
|
|
70
97
|
env: flags.env ?? process.env.SHIPD_ENV ?? projectConfig.env ?? globalConfig.env,
|
|
71
|
-
configFile
|
|
72
|
-
typesOut: projectConfig.typesOut ?? "src/generated/flags.ts",
|
|
98
|
+
configFile,
|
|
99
|
+
typesOut: projectConfig.typesOut ?? (typesLanguage === "go" ? "internal/flags/flags_gen.go" : "src/generated/flags.ts"),
|
|
100
|
+
typesLanguage,
|
|
101
|
+
typesPackage: projectConfig.typesPackage ?? "flags",
|
|
73
102
|
yes: ci,
|
|
74
103
|
json: flags.json === true,
|
|
75
104
|
cwd,
|
|
@@ -440,6 +469,9 @@ function A$1(e) {
|
|
|
440
469
|
feedback: (e) => O$1(r.me.feedback.$post, e)
|
|
441
470
|
},
|
|
442
471
|
project: {
|
|
472
|
+
listTransfers: (e = {}) => O$1(i.project.listTransfers.$post, e),
|
|
473
|
+
requestTransfer: (e) => O$1(i.project.requestTransfer.$post, e),
|
|
474
|
+
decideTransfer: (e) => O$1(i.project.decideTransfer.$post, e),
|
|
443
475
|
list: (e = {}) => O$1(i.project.list.$post, e),
|
|
444
476
|
create: (e) => O$1(i.project.create.$post, e),
|
|
445
477
|
update: (e) => O$1(i.project.update.$post, e),
|
|
@@ -466,6 +498,7 @@ function A$1(e) {
|
|
|
466
498
|
archive: (e) => O$1(A.flag.archive.$post, e),
|
|
467
499
|
listArchived: (e) => O$1(A.flag.listArchived.$post, e),
|
|
468
500
|
restore: (e) => O$1(A.flag.restore.$post, e),
|
|
501
|
+
publishEnvironments: (e) => O$1(A.flag.publishEnvironments.$post, e),
|
|
469
502
|
updateEnvironment: (e) => O$1(A.flag.updateEnvironment.$post, e),
|
|
470
503
|
toggleEnvironment: (e) => O$1(A.flag.toggleEnvironment.$post, e),
|
|
471
504
|
listEnvironmentStates: (e) => O$1(A.flag.listEnvironmentStates.$post, e),
|
|
@@ -608,7 +641,7 @@ function A$1(e) {
|
|
|
608
641
|
}
|
|
609
642
|
|
|
610
643
|
//#endregion
|
|
611
|
-
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@
|
|
644
|
+
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@opentelemet_0d5083f53bdf976e0320d8b98ec7aa98/node_modules/@better-auth/core/dist/utils/error-codes.mjs
|
|
612
645
|
function defineErrorCodes(codes) {
|
|
613
646
|
return Object.fromEntries(Object.entries(codes).map(([key, value]) => [key, {
|
|
614
647
|
code: key,
|
|
@@ -618,7 +651,7 @@ function defineErrorCodes(codes) {
|
|
|
618
651
|
}
|
|
619
652
|
|
|
620
653
|
//#endregion
|
|
621
|
-
//#region ../../node_modules/.pnpm/better-call@1.4.0_zod@4.6.
|
|
654
|
+
//#region ../../node_modules/.pnpm/better-call@1.4.0_zod@4.6.7/node_modules/better-call/dist/error.mjs
|
|
622
655
|
function isErrorStackTraceLimitWritable() {
|
|
623
656
|
const desc = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit");
|
|
624
657
|
if (desc === void 0) return Object.isExtensible(Error);
|
|
@@ -735,7 +768,7 @@ var InternalAPIError = class extends Error {
|
|
|
735
768
|
const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);
|
|
736
769
|
|
|
737
770
|
//#endregion
|
|
738
|
-
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@
|
|
771
|
+
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@opentelemet_0d5083f53bdf976e0320d8b98ec7aa98/node_modules/@better-auth/core/dist/error/index.mjs
|
|
739
772
|
var BetterAuthError = class extends Error {
|
|
740
773
|
constructor(message, options) {
|
|
741
774
|
super(message, options);
|
|
@@ -746,7 +779,7 @@ var BetterAuthError = class extends Error {
|
|
|
746
779
|
};
|
|
747
780
|
|
|
748
781
|
//#endregion
|
|
749
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
782
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/access/access.mjs
|
|
750
783
|
function unknownResourceResponse(requestedResource) {
|
|
751
784
|
return {
|
|
752
785
|
success: false,
|
|
@@ -823,7 +856,7 @@ function createAccessControl(s) {
|
|
|
823
856
|
}
|
|
824
857
|
|
|
825
858
|
//#endregion
|
|
826
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
859
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/two-factor/error-code.mjs
|
|
827
860
|
const TWO_FACTOR_ERROR_CODES = defineErrorCodes({
|
|
828
861
|
OTP_NOT_ENABLED: "OTP not enabled",
|
|
829
862
|
OTP_NOT_CONFIGURED: "OTP is not available",
|
|
@@ -841,15 +874,15 @@ const TWO_FACTOR_ERROR_CODES = defineErrorCodes({
|
|
|
841
874
|
});
|
|
842
875
|
|
|
843
876
|
//#endregion
|
|
844
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
877
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/package.mjs
|
|
845
878
|
var version = "1.7.7";
|
|
846
879
|
|
|
847
880
|
//#endregion
|
|
848
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
881
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/version.mjs
|
|
849
882
|
const PACKAGE_VERSION$3 = version;
|
|
850
883
|
|
|
851
884
|
//#endregion
|
|
852
|
-
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@
|
|
885
|
+
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@opentelemet_0d5083f53bdf976e0320d8b98ec7aa98/node_modules/@better-auth/core/dist/utils/url.mjs
|
|
853
886
|
/**
|
|
854
887
|
* Schemes that execute or embed code when navigated to or accepted as a
|
|
855
888
|
* redirect target. These are never safe as an OAuth `redirect_uri` or as a
|
|
@@ -881,7 +914,7 @@ function isSafeUrlScheme(value) {
|
|
|
881
914
|
}
|
|
882
915
|
|
|
883
916
|
//#endregion
|
|
884
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
917
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/two-factor/client.mjs
|
|
885
918
|
const twoFactorClient = (options) => {
|
|
886
919
|
return {
|
|
887
920
|
id: "two-factor",
|
|
@@ -919,7 +952,7 @@ const twoFactorClient = (options) => {
|
|
|
919
952
|
};
|
|
920
953
|
|
|
921
954
|
//#endregion
|
|
922
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
955
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/admin/access/statement.mjs
|
|
923
956
|
const defaultStatements$1 = {
|
|
924
957
|
user: [
|
|
925
958
|
"create",
|
|
@@ -970,7 +1003,7 @@ const defaultRoles$1 = {
|
|
|
970
1003
|
};
|
|
971
1004
|
|
|
972
1005
|
//#endregion
|
|
973
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1006
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/admin/error-codes.mjs
|
|
974
1007
|
const ADMIN_ERROR_CODES = defineErrorCodes({
|
|
975
1008
|
FAILED_TO_CREATE_USER: "Failed to create user",
|
|
976
1009
|
USER_ALREADY_EXISTS: "User already exists.",
|
|
@@ -998,7 +1031,7 @@ const ADMIN_ERROR_CODES = defineErrorCodes({
|
|
|
998
1031
|
});
|
|
999
1032
|
|
|
1000
1033
|
//#endregion
|
|
1001
|
-
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@
|
|
1034
|
+
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@opentelemet_0d5083f53bdf976e0320d8b98ec7aa98/node_modules/@better-auth/core/dist/env/env-impl.mjs
|
|
1002
1035
|
const _envShim = Object.create(null);
|
|
1003
1036
|
const _getEnv = (useShim) => globalThis.process?.env || globalThis.Deno?.env.toObject() || globalThis.__env__ || (useShim ? _envShim : globalThis);
|
|
1004
1037
|
const env = new Proxy(_envShim, {
|
|
@@ -1062,7 +1095,7 @@ const ENV = Object.freeze({
|
|
|
1062
1095
|
});
|
|
1063
1096
|
|
|
1064
1097
|
//#endregion
|
|
1065
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1098
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/utils/url.mjs
|
|
1066
1099
|
const SLASH_CHAR_CODE = "/".charCodeAt(0);
|
|
1067
1100
|
function trimTrailingSlashes(value) {
|
|
1068
1101
|
let end = value.length;
|
|
@@ -1141,7 +1174,7 @@ function getOrigin(url) {
|
|
|
1141
1174
|
}
|
|
1142
1175
|
|
|
1143
1176
|
//#endregion
|
|
1144
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1177
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/admin/has-permission.mjs
|
|
1145
1178
|
const hasPermission = (input) => {
|
|
1146
1179
|
if (input.userId && input.options?.adminUserIds?.includes(input.userId)) return true;
|
|
1147
1180
|
if (!input.permissions) return false;
|
|
@@ -1743,7 +1776,7 @@ const createFetch = (config) => {
|
|
|
1743
1776
|
};
|
|
1744
1777
|
|
|
1745
1778
|
//#endregion
|
|
1746
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1779
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/parser.mjs
|
|
1747
1780
|
const PROTO_POLLUTION_PATTERNS = {
|
|
1748
1781
|
proto: /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,
|
|
1749
1782
|
constructor: /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,
|
|
@@ -1813,7 +1846,7 @@ function parseJSON(value, options = { strict: true }) {
|
|
|
1813
1846
|
}
|
|
1814
1847
|
|
|
1815
1848
|
//#endregion
|
|
1816
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1849
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/organization/access/statement.mjs
|
|
1817
1850
|
const defaultStatements = {
|
|
1818
1851
|
organization: ["update", "delete"],
|
|
1819
1852
|
member: [
|
|
@@ -1889,7 +1922,7 @@ const defaultRoles = {
|
|
|
1889
1922
|
};
|
|
1890
1923
|
|
|
1891
1924
|
//#endregion
|
|
1892
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1925
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/organization/permission.mjs
|
|
1893
1926
|
const hasPermissionFn = (input, acRoles) => {
|
|
1894
1927
|
if (!input.permissions) return false;
|
|
1895
1928
|
const roles = input.role.split(",");
|
|
@@ -1902,7 +1935,7 @@ const hasPermissionFn = (input, acRoles) => {
|
|
|
1902
1935
|
};
|
|
1903
1936
|
|
|
1904
1937
|
//#endregion
|
|
1905
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
1938
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/organization/error-codes.mjs
|
|
1906
1939
|
const ORGANIZATION_ERROR_CODES = defineErrorCodes({
|
|
1907
1940
|
YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION: "You are not allowed to create a new organization",
|
|
1908
1941
|
YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS: "You have reached the maximum number of organizations",
|
|
@@ -2240,7 +2273,7 @@ const n$1 = {
|
|
|
2240
2273
|
};
|
|
2241
2274
|
|
|
2242
2275
|
//#endregion
|
|
2243
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2276
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/broadcast-channel.mjs
|
|
2244
2277
|
const kBroadcastChannel = Symbol.for("better-auth:broadcast-channel");
|
|
2245
2278
|
const now$1 = () => Math.floor(Date.now() / 1e3);
|
|
2246
2279
|
var WindowBroadcastChannel = class {
|
|
@@ -2464,7 +2497,7 @@ let onMount = ($store, initialize) => {
|
|
|
2464
2497
|
};
|
|
2465
2498
|
|
|
2466
2499
|
//#endregion
|
|
2467
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2500
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/equality.mjs
|
|
2468
2501
|
function isPlainObject(value) {
|
|
2469
2502
|
if (typeof value !== "object" || value === null) return false;
|
|
2470
2503
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -2505,7 +2538,7 @@ function withEquality(store, isEqual) {
|
|
|
2505
2538
|
}
|
|
2506
2539
|
|
|
2507
2540
|
//#endregion
|
|
2508
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2541
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/focus-manager.mjs
|
|
2509
2542
|
const kFocusManager = Symbol.for("better-auth:focus-manager");
|
|
2510
2543
|
var WindowFocusManager = class {
|
|
2511
2544
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -2535,7 +2568,7 @@ function getGlobalFocusManager() {
|
|
|
2535
2568
|
}
|
|
2536
2569
|
|
|
2537
2570
|
//#endregion
|
|
2538
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2571
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/online-manager.mjs
|
|
2539
2572
|
const kOnlineManager = Symbol.for("better-auth:online-manager");
|
|
2540
2573
|
var WindowOnlineManager = class {
|
|
2541
2574
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -2568,7 +2601,7 @@ function getGlobalOnlineManager() {
|
|
|
2568
2601
|
}
|
|
2569
2602
|
|
|
2570
2603
|
//#endregion
|
|
2571
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2604
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/query-atom.mjs
|
|
2572
2605
|
const kAuthQuery = Symbol.for("better-auth:auth-query");
|
|
2573
2606
|
function createAuthQueryAtom(initialValue) {
|
|
2574
2607
|
const queryAtom = /* @__PURE__ */ atom(initialValue);
|
|
@@ -2577,7 +2610,7 @@ function createAuthQueryAtom(initialValue) {
|
|
|
2577
2610
|
}
|
|
2578
2611
|
|
|
2579
2612
|
//#endregion
|
|
2580
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2613
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/query.mjs
|
|
2581
2614
|
const isServer$1 = () => typeof window === "undefined";
|
|
2582
2615
|
function isAuthQueryStateEqual(a, b) {
|
|
2583
2616
|
return isJsonEqual(a.data, b.data) && a.error === b.error && a.isPending === b.isPending && a.isRefetching === b.isRefetching && a.refetch === b.refetch;
|
|
@@ -2708,7 +2741,7 @@ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
|
|
|
2708
2741
|
};
|
|
2709
2742
|
|
|
2710
2743
|
//#endregion
|
|
2711
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2744
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/session-refresh.mjs
|
|
2712
2745
|
const now = () => Math.floor(Date.now() / 1e3);
|
|
2713
2746
|
/**
|
|
2714
2747
|
* Rate limit: don't refetch on focus if a session request was made within this many seconds
|
|
@@ -2836,7 +2869,7 @@ function createSessionRefreshManager(opts) {
|
|
|
2836
2869
|
}
|
|
2837
2870
|
|
|
2838
2871
|
//#endregion
|
|
2839
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2872
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/fetch-plugins.mjs
|
|
2840
2873
|
const redirectPlugin = {
|
|
2841
2874
|
id: "redirect",
|
|
2842
2875
|
name: "Redirect",
|
|
@@ -2852,7 +2885,7 @@ const redirectPlugin = {
|
|
|
2852
2885
|
};
|
|
2853
2886
|
|
|
2854
2887
|
//#endregion
|
|
2855
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
2888
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/session-atom.mjs
|
|
2856
2889
|
const isServer = () => typeof window === "undefined";
|
|
2857
2890
|
const SESSION_MOUNT_DEDUPE_INTERVAL = STORE_UNMOUNT_DELAY;
|
|
2858
2891
|
function hydrateSessionAtom(sessionAtom, session) {
|
|
@@ -3027,7 +3060,7 @@ function getSessionAtom($fetch, options) {
|
|
|
3027
3060
|
}
|
|
3028
3061
|
|
|
3029
3062
|
//#endregion
|
|
3030
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3063
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/config.mjs
|
|
3031
3064
|
const resolvePublicAuthUrl = (basePath) => {
|
|
3032
3065
|
if (typeof process === "undefined") return void 0;
|
|
3033
3066
|
const path = basePath ?? "/api/auth";
|
|
@@ -3133,13 +3166,13 @@ const getClientConfig = (options, loadEnv) => {
|
|
|
3133
3166
|
};
|
|
3134
3167
|
|
|
3135
3168
|
//#endregion
|
|
3136
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3169
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/utils/is-atom.mjs
|
|
3137
3170
|
function isAtom(value) {
|
|
3138
3171
|
return typeof value === "object" && value !== null && "get" in value && typeof value.get === "function" && "lc" in value && typeof value.lc === "number";
|
|
3139
3172
|
}
|
|
3140
3173
|
|
|
3141
3174
|
//#endregion
|
|
3142
|
-
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@
|
|
3175
|
+
//#region ../../node_modules/.pnpm/@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.2_@opentelemet_0d5083f53bdf976e0320d8b98ec7aa98/node_modules/@better-auth/core/dist/utils/string.mjs
|
|
3143
3176
|
function capitalizeFirstLetter(str) {
|
|
3144
3177
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3145
3178
|
}
|
|
@@ -3153,7 +3186,7 @@ function toKebabCase(input) {
|
|
|
3153
3186
|
}
|
|
3154
3187
|
|
|
3155
3188
|
//#endregion
|
|
3156
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3189
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/proxy.mjs
|
|
3157
3190
|
function getMethod(path, knownPathMethods, args) {
|
|
3158
3191
|
const method = knownPathMethods[path];
|
|
3159
3192
|
const { fetchOptions, query: _query, ...body } = args || {};
|
|
@@ -3229,7 +3262,7 @@ function createDynamicPathProxy(routes, client, knownPathMethods, atoms, atomLis
|
|
|
3229
3262
|
}
|
|
3230
3263
|
|
|
3231
3264
|
//#endregion
|
|
3232
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3265
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/client/vanilla.mjs
|
|
3233
3266
|
function createAuthClient(options) {
|
|
3234
3267
|
const { pluginPathMethods, pluginsActions, pluginsAtoms, hydrateSession, $fetch, atomListeners, $store } = getClientConfig(options);
|
|
3235
3268
|
const resolvedHooks = {};
|
|
@@ -3244,7 +3277,7 @@ function createAuthClient(options) {
|
|
|
3244
3277
|
}
|
|
3245
3278
|
|
|
3246
3279
|
//#endregion
|
|
3247
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3280
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/additional-fields/client.mjs
|
|
3248
3281
|
const inferAdditionalFields = (schema) => {
|
|
3249
3282
|
return {
|
|
3250
3283
|
id: "additional-fields-client",
|
|
@@ -3254,7 +3287,7 @@ const inferAdditionalFields = (schema) => {
|
|
|
3254
3287
|
};
|
|
3255
3288
|
|
|
3256
3289
|
//#endregion
|
|
3257
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3290
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/admin/client.mjs
|
|
3258
3291
|
const adminClient = (options) => {
|
|
3259
3292
|
const roles = {
|
|
3260
3293
|
admin: adminAc$1,
|
|
@@ -3289,7 +3322,7 @@ const adminClient = (options) => {
|
|
|
3289
3322
|
};
|
|
3290
3323
|
|
|
3291
3324
|
//#endregion
|
|
3292
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3325
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/device-authorization/client.mjs
|
|
3293
3326
|
const deviceAuthorizationClient = () => {
|
|
3294
3327
|
return {
|
|
3295
3328
|
id: "device-authorization",
|
|
@@ -3306,7 +3339,7 @@ const deviceAuthorizationClient = () => {
|
|
|
3306
3339
|
};
|
|
3307
3340
|
|
|
3308
3341
|
//#endregion
|
|
3309
|
-
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc.
|
|
3342
|
+
//#region ../../node_modules/.pnpm/better-auth@1.7.7_@opentelemetry+api@1.9.1_drizzle-kit@1.0.0-rc.4_drizzle-orm@1.0.0-rc._7c90dee8a2acd893f91862de908c6808/node_modules/better-auth/dist/plugins/organization/client.mjs
|
|
3310
3343
|
/**
|
|
3311
3344
|
* Using the same `hasPermissionFn` function, but without the need for a `ctx` parameter or the `organizationId` parameter.
|
|
3312
3345
|
*/
|
|
@@ -3401,7 +3434,7 @@ const organizationClient = (options) => {
|
|
|
3401
3434
|
};
|
|
3402
3435
|
|
|
3403
3436
|
//#endregion
|
|
3404
|
-
//#region ../../node_modules/.pnpm/@better-auth+api-key@1.7.7_@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-
|
|
3437
|
+
//#region ../../node_modules/.pnpm/@better-auth+api-key@1.7.7_@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fet_3f872e6aea52bc61f9c5dfb40b2109fb/node_modules/@better-auth/api-key/dist/version-CUtTQbZf.mjs
|
|
3405
3438
|
const API_KEY_ERROR_CODES = defineErrorCodes({
|
|
3406
3439
|
INVALID_METADATA_TYPE: "metadata must be an object or undefined",
|
|
3407
3440
|
REFILL_AMOUNT_AND_INTERVAL_REQUIRED: "refillAmount is required when refillInterval is provided",
|
|
@@ -3438,7 +3471,7 @@ const API_KEY_ERROR_CODES = defineErrorCodes({
|
|
|
3438
3471
|
const PACKAGE_VERSION$2 = "1.7.7";
|
|
3439
3472
|
|
|
3440
3473
|
//#endregion
|
|
3441
|
-
//#region ../../node_modules/.pnpm/@better-auth+api-key@1.7.7_@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-
|
|
3474
|
+
//#region ../../node_modules/.pnpm/@better-auth+api-key@1.7.7_@better-auth+core@1.7.7_@better-auth+utils@0.4.2_@better-fet_3f872e6aea52bc61f9c5dfb40b2109fb/node_modules/@better-auth/api-key/dist/client.mjs
|
|
3442
3475
|
const apiKeyClient = () => {
|
|
3443
3476
|
return {
|
|
3444
3477
|
id: "api-key",
|
|
@@ -3454,7 +3487,7 @@ const apiKeyClient = () => {
|
|
|
3454
3487
|
};
|
|
3455
3488
|
|
|
3456
3489
|
//#endregion
|
|
3457
|
-
//#region ../../node_modules/.pnpm/@better-auth+passkey@1.7.
|
|
3490
|
+
//#region ../../node_modules/.pnpm/@better-auth+passkey@1.7.7_59c4b159f325028b6aeb6ca5fe859369/node_modules/@better-auth/passkey/dist/version-Bx477_EO.mjs
|
|
3458
3491
|
const PASSKEY_ERROR_CODES = defineErrorCodes({
|
|
3459
3492
|
CHALLENGE_NOT_FOUND: "Challenge not found",
|
|
3460
3493
|
YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: "You are not allowed to register this passkey",
|
|
@@ -3944,7 +3977,7 @@ async function startAuthentication(options) {
|
|
|
3944
3977
|
}
|
|
3945
3978
|
|
|
3946
3979
|
//#endregion
|
|
3947
|
-
//#region ../../node_modules/.pnpm/@better-auth+passkey@1.7.
|
|
3980
|
+
//#region ../../node_modules/.pnpm/@better-auth+passkey@1.7.7_59c4b159f325028b6aeb6ca5fe859369/node_modules/@better-auth/passkey/dist/client.mjs
|
|
3948
3981
|
const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
|
|
3949
3982
|
const signInPasskey = async (opts, options) => {
|
|
3950
3983
|
const response = await $fetch("/passkey/generate-authenticate-options", {
|
|
@@ -4146,11 +4179,11 @@ const passkeyClient = () => {
|
|
|
4146
4179
|
};
|
|
4147
4180
|
|
|
4148
4181
|
//#endregion
|
|
4149
|
-
//#region ../../node_modules/.pnpm/@better-auth+sso@1.7.
|
|
4182
|
+
//#region ../../node_modules/.pnpm/@better-auth+sso@1.7.7_f840261b078ff9b2a25d6de6ccbfccc0/node_modules/@better-auth/sso/dist/version-DFla2W8i.mjs
|
|
4150
4183
|
const PACKAGE_VERSION = "1.7.7";
|
|
4151
4184
|
|
|
4152
4185
|
//#endregion
|
|
4153
|
-
//#region ../../node_modules/.pnpm/@better-auth+sso@1.7.
|
|
4186
|
+
//#region ../../node_modules/.pnpm/@better-auth+sso@1.7.7_f840261b078ff9b2a25d6de6ccbfccc0/node_modules/@better-auth/sso/dist/client.mjs
|
|
4154
4187
|
const ssoClient = (options) => {
|
|
4155
4188
|
return {
|
|
4156
4189
|
id: "sso-client",
|
|
@@ -4200,25 +4233,6 @@ const f$1 = (e) => createAuthClient({
|
|
|
4200
4233
|
plugins: d$1(e)
|
|
4201
4234
|
});
|
|
4202
4235
|
|
|
4203
|
-
//#endregion
|
|
4204
|
-
//#region src/lib/errors.ts
|
|
4205
|
-
var CliError = class extends Error {
|
|
4206
|
-
code;
|
|
4207
|
-
exitCode;
|
|
4208
|
-
details;
|
|
4209
|
-
constructor(code, message, options) {
|
|
4210
|
-
super(message);
|
|
4211
|
-
this.name = "CliError";
|
|
4212
|
-
this.code = code;
|
|
4213
|
-
this.exitCode = options?.exitCode ?? 1;
|
|
4214
|
-
this.details = options?.details;
|
|
4215
|
-
}
|
|
4216
|
-
};
|
|
4217
|
-
function exitCodeForError(error) {
|
|
4218
|
-
if (error instanceof CliError) return error.exitCode;
|
|
4219
|
-
return 1;
|
|
4220
|
-
}
|
|
4221
|
-
|
|
4222
4236
|
//#endregion
|
|
4223
4237
|
//#region src/lib/client.ts
|
|
4224
4238
|
const AUTH_BASE_PATH = "/api/v1/auth";
|
|
@@ -4621,6 +4635,7 @@ const w = z.object({
|
|
|
4621
4635
|
});
|
|
4622
4636
|
});
|
|
4623
4637
|
const T = z.object({
|
|
4638
|
+
expectedVersion: z.number().int().positive().optional(),
|
|
4624
4639
|
flagId: z.string().min(1),
|
|
4625
4640
|
key: o.optional(),
|
|
4626
4641
|
name: z.string().min(1).optional(),
|
|
@@ -4633,6 +4648,7 @@ const E = z.object({ flagId: z.string().min(1) });
|
|
|
4633
4648
|
const D = z.object({ projectId: z.string().min(1) });
|
|
4634
4649
|
const O = z.object({ flagId: z.string().min(1) });
|
|
4635
4650
|
const k = z.object({
|
|
4651
|
+
expectedVersion: z.number().int().positive().optional(),
|
|
4636
4652
|
flagId: z.string().min(1),
|
|
4637
4653
|
environmentId: z.string().min(1),
|
|
4638
4654
|
enabled: z.boolean().optional(),
|
|
@@ -4640,17 +4656,25 @@ const k = z.object({
|
|
|
4640
4656
|
fallthrough: u.optional()
|
|
4641
4657
|
});
|
|
4642
4658
|
const A = z.object({
|
|
4659
|
+
flagId: z.string().min(1),
|
|
4660
|
+
environments: z.array(z.object({
|
|
4661
|
+
environmentId: z.string().min(1),
|
|
4662
|
+
expectedVersion: z.number().int().positive()
|
|
4663
|
+
})).min(1).refine((e) => new Set(e.map((e) => e.environmentId)).size === e.length, `Duplicate environments`)
|
|
4664
|
+
});
|
|
4665
|
+
const j = z.object({
|
|
4666
|
+
expectedVersion: z.number().int().positive().optional(),
|
|
4643
4667
|
flagId: z.string().min(1),
|
|
4644
4668
|
environmentId: z.string().min(1),
|
|
4645
4669
|
enabled: z.boolean()
|
|
4646
4670
|
});
|
|
4647
|
-
const
|
|
4648
|
-
const
|
|
4649
|
-
function
|
|
4671
|
+
const M = z.object({ flagId: z.string().min(1) });
|
|
4672
|
+
const N = z.enum([`active`, `deprecated`]);
|
|
4673
|
+
function P(e) {
|
|
4650
4674
|
let t = Object.getPrototypeOf(e);
|
|
4651
4675
|
return t === Object.prototype || t === null;
|
|
4652
4676
|
}
|
|
4653
|
-
function
|
|
4677
|
+
function F(e, t) {
|
|
4654
4678
|
if (e === null) return !0;
|
|
4655
4679
|
switch (typeof e) {
|
|
4656
4680
|
case `boolean`:
|
|
@@ -4658,13 +4682,13 @@ function P(e, t) {
|
|
|
4658
4682
|
case `number`: return Number.isFinite(e);
|
|
4659
4683
|
case `object`: {
|
|
4660
4684
|
let n = t ?? /* @__PURE__ */ new WeakSet();
|
|
4661
|
-
return !n.has(e) && (n.add(e), Array.isArray(e) ? e.every((e) =>
|
|
4685
|
+
return !n.has(e) && (n.add(e), Array.isArray(e) ? e.every((e) => F(e, n)) : !P(e) || Object.getOwnPropertySymbols(e).length > 0 ? !1 : Object.keys(e).every((t) => F(e[t], n)));
|
|
4662
4686
|
}
|
|
4663
4687
|
default: return !1;
|
|
4664
4688
|
}
|
|
4665
4689
|
}
|
|
4666
|
-
const
|
|
4667
|
-
function
|
|
4690
|
+
const I = z.custom(F, { message: `default must be JSON-serializable` });
|
|
4691
|
+
function L(e, t) {
|
|
4668
4692
|
switch (e.type) {
|
|
4669
4693
|
case `boolean`:
|
|
4670
4694
|
typeof e.default != `boolean` && t.addIssue({
|
|
@@ -4693,43 +4717,43 @@ function I(e, t) {
|
|
|
4693
4717
|
});
|
|
4694
4718
|
break;
|
|
4695
4719
|
}
|
|
4696
|
-
case `json`:
|
|
4720
|
+
case `json`: I.safeParse(e.default).success || t.addIssue({
|
|
4697
4721
|
code: `custom`,
|
|
4698
4722
|
path: [`default`],
|
|
4699
4723
|
message: `json flag default must be JSON-serializable`
|
|
4700
4724
|
});
|
|
4701
4725
|
}
|
|
4702
4726
|
}
|
|
4703
|
-
const
|
|
4727
|
+
const R = z.object({
|
|
4704
4728
|
key: o,
|
|
4705
4729
|
type: t,
|
|
4706
4730
|
default: z.unknown(),
|
|
4707
4731
|
description: z.string().optional(),
|
|
4708
4732
|
tags: z.array(z.string()).default([]),
|
|
4709
|
-
lifecycle:
|
|
4733
|
+
lifecycle: N.default(`active`),
|
|
4710
4734
|
variants: z.array(z.string()).optional(),
|
|
4711
4735
|
disabled: z.boolean().optional()
|
|
4712
4736
|
});
|
|
4713
|
-
const
|
|
4714
|
-
const
|
|
4737
|
+
const z$1 = R.superRefine(L);
|
|
4738
|
+
const B = R.extend({
|
|
4715
4739
|
version: z.number().int().positive(),
|
|
4716
4740
|
environmentVersion: z.number().int().positive().optional(),
|
|
4717
4741
|
managedBy: n
|
|
4718
|
-
}).superRefine(
|
|
4719
|
-
const
|
|
4742
|
+
}).superRefine(L);
|
|
4743
|
+
const V = z.object({
|
|
4720
4744
|
version: z.number().int().positive(),
|
|
4721
4745
|
environmentVersion: z.number().int().positive().optional()
|
|
4722
4746
|
});
|
|
4723
|
-
const
|
|
4747
|
+
const H = z.object({
|
|
4724
4748
|
projectId: z.string().min(1),
|
|
4725
4749
|
environmentId: z.string().min(1)
|
|
4726
4750
|
});
|
|
4727
|
-
const
|
|
4751
|
+
const U = z.object({
|
|
4728
4752
|
projectId: z.string(),
|
|
4729
4753
|
environmentId: z.string(),
|
|
4730
|
-
flags: z.array(
|
|
4754
|
+
flags: z.array(B)
|
|
4731
4755
|
});
|
|
4732
|
-
function
|
|
4756
|
+
function W(e, t) {
|
|
4733
4757
|
let n = /* @__PURE__ */ new Set();
|
|
4734
4758
|
for (let [r, i] of e.entries()) n.has(i.key) && t.addIssue({
|
|
4735
4759
|
code: `custom`,
|
|
@@ -4741,12 +4765,12 @@ function U(e, t) {
|
|
|
4741
4765
|
message: `duplicate flag key "${i.key}"`
|
|
4742
4766
|
}), n.add(i.key);
|
|
4743
4767
|
}
|
|
4744
|
-
const
|
|
4768
|
+
const G = z.object({
|
|
4745
4769
|
projectId: z.string().min(1),
|
|
4746
4770
|
environmentId: z.string().min(1),
|
|
4747
|
-
flags: z.array(
|
|
4748
|
-
}).superRefine((e, t) =>
|
|
4749
|
-
const
|
|
4771
|
+
flags: z.array(z$1).max(500)
|
|
4772
|
+
}).superRefine((e, t) => W(e.flags, t));
|
|
4773
|
+
const K = z.object({
|
|
4750
4774
|
key: z.string(),
|
|
4751
4775
|
op: z.enum([
|
|
4752
4776
|
`add`,
|
|
@@ -4754,40 +4778,223 @@ const G = z.object({
|
|
|
4754
4778
|
`remove`,
|
|
4755
4779
|
`unlinked`
|
|
4756
4780
|
]),
|
|
4757
|
-
before:
|
|
4758
|
-
after:
|
|
4781
|
+
before: B.optional(),
|
|
4782
|
+
after: z$1.optional(),
|
|
4759
4783
|
message: z.string().optional()
|
|
4760
4784
|
});
|
|
4761
|
-
const
|
|
4785
|
+
const q = z.object({
|
|
4762
4786
|
projectId: z.string(),
|
|
4763
4787
|
environmentId: z.string(),
|
|
4764
|
-
changes: z.array(
|
|
4765
|
-
remoteOnly: z.array(
|
|
4788
|
+
changes: z.array(K),
|
|
4789
|
+
remoteOnly: z.array(B).default([])
|
|
4766
4790
|
});
|
|
4767
|
-
const
|
|
4791
|
+
const J = z.object({
|
|
4768
4792
|
projectId: z.string().min(1),
|
|
4769
4793
|
environmentId: z.string().min(1),
|
|
4770
|
-
flags: z.array(
|
|
4794
|
+
flags: z.array(z$1).max(500),
|
|
4771
4795
|
apply: z.boolean().default(!1),
|
|
4772
4796
|
prune: z.boolean().default(!1),
|
|
4773
4797
|
force: z.boolean().default(!1),
|
|
4774
4798
|
adopt: z.boolean().default(!1),
|
|
4775
|
-
expectedVersions: z.record(z.string(),
|
|
4776
|
-
}).superRefine((e, t) =>
|
|
4777
|
-
const
|
|
4799
|
+
expectedVersions: z.record(z.string(), V).optional()
|
|
4800
|
+
}).superRefine((e, t) => W(e.flags, t));
|
|
4801
|
+
const Y = z.object({
|
|
4778
4802
|
projectId: z.string(),
|
|
4779
4803
|
environmentId: z.string(),
|
|
4780
4804
|
applied: z.boolean(),
|
|
4781
|
-
changes: z.array(
|
|
4782
|
-
remoteOnly: z.array(
|
|
4805
|
+
changes: z.array(K),
|
|
4806
|
+
remoteOnly: z.array(B).default([]),
|
|
4783
4807
|
forced: z.boolean().default(!1),
|
|
4784
4808
|
adopted: z.boolean().default(!1),
|
|
4785
|
-
approvalRequests: z.array(z.string()).default([])
|
|
4809
|
+
approvalRequests: z.array(z.string()).default([]),
|
|
4810
|
+
drafts: z.array(z.string()).default([])
|
|
4786
4811
|
});
|
|
4787
4812
|
|
|
4813
|
+
//#endregion
|
|
4814
|
+
//#region src/lib/go-string.ts
|
|
4815
|
+
/** Go strings cannot represent JavaScript's unpaired UTF-16 surrogates. */
|
|
4816
|
+
function goString(value) {
|
|
4817
|
+
for (const character of value) {
|
|
4818
|
+
const code = character.charCodeAt(0);
|
|
4819
|
+
if (character.length === 1 && code >= 55296 && code <= 57343) throw new CliError("validation_error", `Cannot generate Go for a string containing an unpaired Unicode surrogate: ${JSON.stringify(value)}`);
|
|
4820
|
+
}
|
|
4821
|
+
return JSON.stringify(value);
|
|
4822
|
+
}
|
|
4823
|
+
|
|
4824
|
+
//#endregion
|
|
4825
|
+
//#region src/lib/go-config.ts
|
|
4826
|
+
/** Read the package clause after leading whitespace and comments, not comment text. */
|
|
4827
|
+
function goPackageClause(source) {
|
|
4828
|
+
let offset = 0;
|
|
4829
|
+
const skipTrivia = () => {
|
|
4830
|
+
while (offset < source.length) {
|
|
4831
|
+
const trivia = /^(?:\s+|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)/u.exec(source.slice(offset));
|
|
4832
|
+
if (!trivia) break;
|
|
4833
|
+
offset += trivia[0].length;
|
|
4834
|
+
}
|
|
4835
|
+
};
|
|
4836
|
+
skipTrivia();
|
|
4837
|
+
if (!/^package\b/u.test(source.slice(offset))) throw new Error("Go config must have a package declaration");
|
|
4838
|
+
offset += 7;
|
|
4839
|
+
skipTrivia();
|
|
4840
|
+
const name = /^[_\p{L}][_\p{L}\p{Nd}]*/u.exec(source.slice(offset))?.[0];
|
|
4841
|
+
if (!name) throw new Error("Go config must have a package name");
|
|
4842
|
+
return {
|
|
4843
|
+
name,
|
|
4844
|
+
start: offset,
|
|
4845
|
+
end: offset + name.length
|
|
4846
|
+
};
|
|
4847
|
+
}
|
|
4848
|
+
/** Evaluate a self-contained Go definition file within its own module. */
|
|
4849
|
+
async function loadGoConfig(file) {
|
|
4850
|
+
const source = fs.readFileSync(file, "utf8");
|
|
4851
|
+
const clause = goPackageClause(source);
|
|
4852
|
+
const directory = fs.mkdtempSync(path.join(path.dirname(file), ".shipd-go-"));
|
|
4853
|
+
const cleanup = () => fs.rmSync(directory, {
|
|
4854
|
+
recursive: true,
|
|
4855
|
+
force: true
|
|
4856
|
+
});
|
|
4857
|
+
process.once("exit", cleanup);
|
|
4858
|
+
let interrupted;
|
|
4859
|
+
let terminate;
|
|
4860
|
+
const interrupt = () => {
|
|
4861
|
+
interrupted = 130;
|
|
4862
|
+
terminate?.();
|
|
4863
|
+
};
|
|
4864
|
+
const shutdown = () => {
|
|
4865
|
+
interrupted = 143;
|
|
4866
|
+
terminate?.();
|
|
4867
|
+
};
|
|
4868
|
+
process.once("SIGINT", interrupt);
|
|
4869
|
+
process.once("SIGTERM", shutdown);
|
|
4870
|
+
try {
|
|
4871
|
+
fs.writeFileSync(path.join(directory, ".gitignore"), "*\n");
|
|
4872
|
+
fs.writeFileSync(path.join(directory, "definitions.go"), source.slice(0, clause.start) + "main" + source.slice(clause.end));
|
|
4873
|
+
fs.writeFileSync(path.join(directory, "main.go"), `package main
|
|
4874
|
+
import (
|
|
4875
|
+
"encoding/json"
|
|
4876
|
+
"fmt"
|
|
4877
|
+
"os"
|
|
4878
|
+
)
|
|
4879
|
+
func main() {
|
|
4880
|
+
file, err := os.Create(os.Args[1])
|
|
4881
|
+
if err == nil {
|
|
4882
|
+
err = json.NewEncoder(file).Encode(Config)
|
|
4883
|
+
if closeErr := file.Close(); err == nil { err = closeErr }
|
|
4884
|
+
}
|
|
4885
|
+
if err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
|
|
4886
|
+
}
|
|
4887
|
+
`);
|
|
4888
|
+
const output = path.join(directory, "config.json");
|
|
4889
|
+
try {
|
|
4890
|
+
await new Promise((resolve, reject) => {
|
|
4891
|
+
const grouped = process.platform !== "win32";
|
|
4892
|
+
const child = spawn("go", [
|
|
4893
|
+
"run",
|
|
4894
|
+
".",
|
|
4895
|
+
output
|
|
4896
|
+
], {
|
|
4897
|
+
cwd: directory,
|
|
4898
|
+
detached: grouped,
|
|
4899
|
+
stdio: [
|
|
4900
|
+
"ignore",
|
|
4901
|
+
"ignore",
|
|
4902
|
+
"pipe"
|
|
4903
|
+
]
|
|
4904
|
+
});
|
|
4905
|
+
let stderr = "";
|
|
4906
|
+
let failure;
|
|
4907
|
+
const kill = (signal) => {
|
|
4908
|
+
if (!child.pid) return;
|
|
4909
|
+
try {
|
|
4910
|
+
if (grouped) process.kill(-child.pid, signal);
|
|
4911
|
+
else child.kill(signal);
|
|
4912
|
+
} catch (error) {
|
|
4913
|
+
if (error.code !== "ESRCH") throw error;
|
|
4914
|
+
}
|
|
4915
|
+
};
|
|
4916
|
+
let killTimer;
|
|
4917
|
+
terminate = () => {
|
|
4918
|
+
kill("SIGTERM");
|
|
4919
|
+
killTimer = setTimeout(() => kill("SIGKILL"), 1e3);
|
|
4920
|
+
};
|
|
4921
|
+
const timer = setTimeout(() => {
|
|
4922
|
+
failure = /* @__PURE__ */ new Error("Go config evaluation timed out");
|
|
4923
|
+
kill("SIGKILL");
|
|
4924
|
+
}, 12e4);
|
|
4925
|
+
child.stderr.on("data", (chunk) => {
|
|
4926
|
+
stderr += chunk.toString();
|
|
4927
|
+
if (stderr.length > 8388608) {
|
|
4928
|
+
failure = /* @__PURE__ */ new Error("Go compiler output exceeds 8 MiB");
|
|
4929
|
+
kill("SIGKILL");
|
|
4930
|
+
}
|
|
4931
|
+
});
|
|
4932
|
+
child.once("error", (error) => {
|
|
4933
|
+
failure = error;
|
|
4934
|
+
});
|
|
4935
|
+
child.once("close", (code) => {
|
|
4936
|
+
clearTimeout(timer);
|
|
4937
|
+
clearTimeout(killTimer);
|
|
4938
|
+
terminate = void 0;
|
|
4939
|
+
if (failure || code !== 0) reject(Object.assign(failure ?? /* @__PURE__ */ new Error(`go run exited with code ${code}`), { stderr }));
|
|
4940
|
+
else resolve();
|
|
4941
|
+
});
|
|
4942
|
+
});
|
|
4943
|
+
} catch (error) {
|
|
4944
|
+
throw goRunError(error, path.basename(file));
|
|
4945
|
+
}
|
|
4946
|
+
return JSON.parse(fs.readFileSync(output, "utf8"));
|
|
4947
|
+
} finally {
|
|
4948
|
+
process.removeListener("SIGINT", interrupt);
|
|
4949
|
+
process.removeListener("SIGTERM", shutdown);
|
|
4950
|
+
process.removeListener("exit", cleanup);
|
|
4951
|
+
cleanup();
|
|
4952
|
+
if (interrupted !== void 0) process.exit(interrupted);
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
function goRunError(error, configName) {
|
|
4956
|
+
if (error.code === "ENOENT") return /* @__PURE__ */ new Error("Go 1.23+ is required to load Go flag definitions, but `go` was not found on PATH. Install Go from https://go.dev/dl and try again.");
|
|
4957
|
+
const stderr = String(error.stderr ?? "").replace(/(?:\.\/)?definitions\.go/g, configName).trim();
|
|
4958
|
+
const hint = /\bundefined:/.test(stderr) ? `\n${configName} must be self-contained: the CLI compiles only this file, not sibling Go files. Move helper declarations into it or import them from another package.` : "";
|
|
4959
|
+
return new Error(stderr ? `go run failed:\n${stderr}${hint}` : String(error));
|
|
4960
|
+
}
|
|
4961
|
+
function goNumber(value) {
|
|
4962
|
+
const literal = JSON.stringify(value);
|
|
4963
|
+
return Number.isSafeInteger(value) || /[.eE]/.test(literal) ? literal : `${literal}.0`;
|
|
4964
|
+
}
|
|
4965
|
+
function goValue(value) {
|
|
4966
|
+
if (value === null) return "nil";
|
|
4967
|
+
if (typeof value === "number") return goNumber(value);
|
|
4968
|
+
if (typeof value === "string") return goString(value);
|
|
4969
|
+
if (Array.isArray(value)) return `[]any{${value.map(goValue).join(", ")}}`;
|
|
4970
|
+
if (typeof value === "object") return `map[string]any{${Object.entries(value).map(([key, entry]) => `${goString(key)}: ${goValue(entry)}`).join(", ")}}`;
|
|
4971
|
+
return JSON.stringify(value);
|
|
4972
|
+
}
|
|
4973
|
+
/** Emits gofmt-clean Go: one block per flag, field values aligned as gofmt does. */
|
|
4974
|
+
function generateGoConfigSource(flags, packageName = "main") {
|
|
4975
|
+
const entries = flags.map((flag) => {
|
|
4976
|
+
const fields = [["Type", goString(flag.type)], ["Default", goValue(flag.default)]];
|
|
4977
|
+
if (flag.variants) fields.push(["Variants", `[]string{${flag.variants.map((v) => goString(v)).join(", ")}}`]);
|
|
4978
|
+
if (flag.description !== void 0) fields.push(["Description", goString(flag.description)]);
|
|
4979
|
+
if (flag.tags.length) fields.push(["Tags", `[]string{${flag.tags.map((v) => goString(v)).join(", ")}}`]);
|
|
4980
|
+
if (flag.lifecycle === "deprecated") fields.push(["Deprecated", "true"]);
|
|
4981
|
+
if (flag.disabled) fields.push(["Disabled", "true"]);
|
|
4982
|
+
const width = Math.max(...fields.map(([name]) => name.length)) + 1;
|
|
4983
|
+
const lines = fields.map(([name, value]) => `\t\t${`${name}:`.padEnd(width)} ${value},`);
|
|
4984
|
+
return `\t${goString(flag.key)}: {\n${lines.join("\n")}\n\t},`;
|
|
4985
|
+
});
|
|
4986
|
+
return `// Generated by shipd pull. Pull replaces this file; review changes before committing.
|
|
4987
|
+
package ${packageName}
|
|
4988
|
+
|
|
4989
|
+
import "github.com/alasti-company/useshipd.com/sdks/go/config"
|
|
4990
|
+
|
|
4991
|
+
var Config = config.ShipdConfig${entries.length ? `{\n${entries.join("\n")}\n}` : "{}"}
|
|
4992
|
+
`;
|
|
4993
|
+
}
|
|
4994
|
+
|
|
4788
4995
|
//#endregion
|
|
4789
4996
|
//#region src/lib/local-config.ts
|
|
4790
|
-
const localFlagsArraySchema = z.array(
|
|
4997
|
+
const localFlagsArraySchema = z.array(z$1).superRefine((flags, ctx) => {
|
|
4791
4998
|
const seen = /* @__PURE__ */ new Set();
|
|
4792
4999
|
for (const [index, flag] of flags.entries()) {
|
|
4793
5000
|
if (seen.has(flag.key)) ctx.addIssue({
|
|
@@ -4801,23 +5008,32 @@ const localFlagsArraySchema = z.array(R).superRefine((flags, ctx) => {
|
|
|
4801
5008
|
async function loadLocalFlags(configFile) {
|
|
4802
5009
|
const absolute = path.resolve(configFile);
|
|
4803
5010
|
if (!fs.existsSync(absolute)) throw new CliError("not_found", `Config file not found: ${absolute}`);
|
|
4804
|
-
|
|
4805
|
-
let loaded;
|
|
5011
|
+
let config;
|
|
4806
5012
|
try {
|
|
4807
|
-
|
|
5013
|
+
if (path.extname(absolute) === ".json") {
|
|
5014
|
+
config = JSON.parse(fs.readFileSync(absolute, "utf8"));
|
|
5015
|
+
if (config?.version !== 1) throw new Error("JSON flag config must have version: 1");
|
|
5016
|
+
} else if (path.extname(absolute) === ".go") config = await loadGoConfig(absolute);
|
|
5017
|
+
else {
|
|
5018
|
+
const loaded = await createJiti(import.meta.url, { interopDefault: true }).import(absolute);
|
|
5019
|
+
config = loaded.default ?? loaded;
|
|
5020
|
+
}
|
|
4808
5021
|
} catch (error) {
|
|
4809
5022
|
const message = error instanceof Error ? error.message : String(error);
|
|
4810
5023
|
throw new CliError("validation_error", `Failed to load config ${absolute}: ${message}`);
|
|
4811
5024
|
}
|
|
4812
|
-
|
|
4813
|
-
|
|
5025
|
+
if (!config?.flags || typeof config.flags !== "object" || Array.isArray(config.flags)) throw new CliError("validation_error", "Flag config must contain a flags object (defineFlags result or version-1 JSON)");
|
|
5026
|
+
for (const [key, flag] of Object.entries(config.flags)) {
|
|
5027
|
+
if (!flag || typeof flag !== "object" || Array.isArray(flag)) throw new CliError("validation_error", `Invalid definition for flag ${JSON.stringify(key)}`);
|
|
5028
|
+
if ("deprecated" in flag && typeof flag.deprecated !== "boolean") throw new CliError("validation_error", `Flag ${JSON.stringify(key)} deprecated must be a boolean`);
|
|
5029
|
+
}
|
|
4814
5030
|
const candidates = Object.entries(config.flags).map(([key, flag]) => ({
|
|
4815
5031
|
key,
|
|
4816
5032
|
type: flag.type,
|
|
4817
5033
|
default: flag.default,
|
|
4818
5034
|
description: flag.description,
|
|
4819
5035
|
tags: flag.tags ?? [],
|
|
4820
|
-
lifecycle: flag.lifecycle ?? "active",
|
|
5036
|
+
lifecycle: flag.lifecycle ?? (flag.deprecated === true ? "deprecated" : "active"),
|
|
4821
5037
|
variants: flag.variants,
|
|
4822
5038
|
disabled: flag.disabled
|
|
4823
5039
|
}));
|
|
@@ -4904,6 +5120,14 @@ function serializeTypeLiteral(value) {
|
|
|
4904
5120
|
if (value === null) return "null";
|
|
4905
5121
|
return JSON.stringify(value);
|
|
4906
5122
|
}
|
|
5123
|
+
/** Pull preserves JSON config workflows rather than introducing a TS dependency. */
|
|
5124
|
+
function generateJSONConfigSource(flags) {
|
|
5125
|
+
const entries = flags.map(({ key, ...definition }) => [key, definition]);
|
|
5126
|
+
return `${JSON.stringify({
|
|
5127
|
+
version: 1,
|
|
5128
|
+
flags: Object.fromEntries(entries)
|
|
5129
|
+
}, null, 2)}\n`;
|
|
5130
|
+
}
|
|
4907
5131
|
|
|
4908
5132
|
//#endregion
|
|
4909
5133
|
//#region src/lib/plan.ts
|
|
@@ -5166,24 +5390,100 @@ function registerProjectsCommands(program) {
|
|
|
5166
5390
|
});
|
|
5167
5391
|
}
|
|
5168
5392
|
|
|
5393
|
+
//#endregion
|
|
5394
|
+
//#region src/lib/go-typegen.ts
|
|
5395
|
+
const GO_KEYWORDS = new Set("break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var".split(" "));
|
|
5396
|
+
function goName(value) {
|
|
5397
|
+
let name = (value.normalize("NFC").match(/[\p{L}\p{Nd}]+/gu) ?? []).map((word) => word[0].toUpperCase() + word.slice(1)).join("");
|
|
5398
|
+
if (!/^\p{Lu}/u.test(name)) name = `Flag${name}`;
|
|
5399
|
+
return name;
|
|
5400
|
+
}
|
|
5401
|
+
function generateGoTypesSource(flags, packageName = "flags") {
|
|
5402
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(packageName) || packageName === "_" || GO_KEYWORDS.has(packageName)) throw new CliError("validation_error", `Invalid Go package name ${JSON.stringify(packageName)}`);
|
|
5403
|
+
const used = /* @__PURE__ */ new Set(["Defaults"]);
|
|
5404
|
+
const claim = (name, key) => {
|
|
5405
|
+
if (used.has(name)) throw new CliError("validation_error", `Go identifier ${name} collides for flag ${JSON.stringify(key)}; rename the flag or variant`);
|
|
5406
|
+
used.add(name);
|
|
5407
|
+
return name;
|
|
5408
|
+
};
|
|
5409
|
+
const declarations = flags.map((flag) => {
|
|
5410
|
+
const name = claim(goName(flag.key), flag.key);
|
|
5411
|
+
const keyName = claim(`${name}Key`, flag.key);
|
|
5412
|
+
const lines = [`const ${keyName} = ${goString(flag.key)}`];
|
|
5413
|
+
let returnType;
|
|
5414
|
+
let expression;
|
|
5415
|
+
switch (flag.type) {
|
|
5416
|
+
case "boolean":
|
|
5417
|
+
returnType = "bool";
|
|
5418
|
+
expression = `client.IsEnabled(${keyName}, context)`;
|
|
5419
|
+
break;
|
|
5420
|
+
case "number":
|
|
5421
|
+
returnType = "float64";
|
|
5422
|
+
expression = `client.GetNumber(${keyName}, context)`;
|
|
5423
|
+
break;
|
|
5424
|
+
case "json":
|
|
5425
|
+
returnType = "any";
|
|
5426
|
+
expression = `client.GetJSON(${keyName}, context)`;
|
|
5427
|
+
break;
|
|
5428
|
+
case "variant":
|
|
5429
|
+
returnType = claim(`${name}Variant`, flag.key);
|
|
5430
|
+
lines.push(`type ${returnType} string`);
|
|
5431
|
+
for (const variant of flag.variants ?? []) {
|
|
5432
|
+
const constant = claim(`${name}${goName(variant)}`, flag.key);
|
|
5433
|
+
lines.push(`const ${constant} ${returnType} = ${goString(variant)}`);
|
|
5434
|
+
}
|
|
5435
|
+
expression = `${returnType}(client.GetVariant(${keyName}, context))`;
|
|
5436
|
+
}
|
|
5437
|
+
lines.push(`func ${name}(client *shipd.Client, context shipd.EvaluationContext) ${returnType} {\n\treturn ${expression}\n}`);
|
|
5438
|
+
return lines.join("\n\n");
|
|
5439
|
+
}).join("\n\n");
|
|
5440
|
+
const defaults = Object.fromEntries(flags.map((flag) => [flag.key, flag.default]));
|
|
5441
|
+
return `// Code generated by shipd types gen --language go; DO NOT EDIT.
|
|
5442
|
+
package ${packageName}
|
|
5443
|
+
|
|
5444
|
+
import (
|
|
5445
|
+
\t"encoding/json"
|
|
5446
|
+
${flags.length ? " shipd \"github.com/alasti-company/useshipd.com/sdks/go\"\n" : ""})
|
|
5447
|
+
|
|
5448
|
+
// Defaults returns a fresh map of the config's defaults for shipd.Options.
|
|
5449
|
+
func Defaults() map[string]any {
|
|
5450
|
+
\tvar defaults map[string]any
|
|
5451
|
+
\t_ = json.Unmarshal([]byte(${JSON.stringify(JSON.stringify(defaults))}), &defaults)
|
|
5452
|
+
\treturn defaults
|
|
5453
|
+
}
|
|
5454
|
+
|
|
5455
|
+
${declarations}
|
|
5456
|
+
`.trimEnd() + "\n";
|
|
5457
|
+
}
|
|
5458
|
+
|
|
5169
5459
|
//#endregion
|
|
5170
5460
|
//#region src/lib/typegen.ts
|
|
5171
|
-
async function runTypegen(runtime, outPath = runtime.typesOut) {
|
|
5172
|
-
|
|
5461
|
+
async function runTypegen(runtime, outPath = runtime.typesOut, options = {}) {
|
|
5462
|
+
return writeTypegen(prepareTypegen(runtime, await loadLocalFlags(runtime.configFile), outPath, options));
|
|
5463
|
+
}
|
|
5464
|
+
function prepareTypegen(runtime, flags, outPath = runtime.typesOut, options = {}) {
|
|
5173
5465
|
const absolute = path.resolve(outPath);
|
|
5174
|
-
const
|
|
5175
|
-
|
|
5176
|
-
fs.writeFileSync(absolute, source);
|
|
5466
|
+
const language = options.language ?? runtime.typesLanguage ?? "typescript";
|
|
5467
|
+
if (language !== "go" && language !== "typescript") throw new CliError("validation_error", "Type generation language must be typescript or go");
|
|
5177
5468
|
return {
|
|
5469
|
+
source: language === "go" ? generateGoTypesSource(flags, options.packageName ?? runtime.typesPackage ?? "flags") : generateTypesSource(flags),
|
|
5178
5470
|
written: absolute,
|
|
5179
5471
|
flagCount: flags.length
|
|
5180
5472
|
};
|
|
5181
5473
|
}
|
|
5474
|
+
function writeTypegen(prepared) {
|
|
5475
|
+
fs.mkdirSync(path.dirname(prepared.written), { recursive: true });
|
|
5476
|
+
fs.writeFileSync(prepared.written, prepared.source);
|
|
5477
|
+
return {
|
|
5478
|
+
written: prepared.written,
|
|
5479
|
+
flagCount: prepared.flagCount
|
|
5480
|
+
};
|
|
5481
|
+
}
|
|
5182
5482
|
|
|
5183
5483
|
//#endregion
|
|
5184
5484
|
//#region src/commands/pull.ts
|
|
5185
5485
|
function registerPullCommand(program) {
|
|
5186
|
-
program.command("pull").description("Regenerate
|
|
5486
|
+
program.command("pull").description("Regenerate the flag config from the server and run typegen").action(async (_opts, command) => {
|
|
5187
5487
|
const runtime = getRuntime(command);
|
|
5188
5488
|
const client = await createCliApiClient(runtime);
|
|
5189
5489
|
const { projectId, environmentId } = await resolveIds(client, runtime);
|
|
@@ -5200,11 +5500,13 @@ function registerPullCommand(program) {
|
|
|
5200
5500
|
variants: flag.variants,
|
|
5201
5501
|
disabled: flag.disabled
|
|
5202
5502
|
}));
|
|
5203
|
-
const
|
|
5503
|
+
const packageName = path.extname(runtime.configFile) === ".go" && fs.existsSync(runtime.configFile) ? goPackageClause(fs.readFileSync(runtime.configFile, "utf8")).name : "main";
|
|
5504
|
+
const source = path.extname(runtime.configFile) === ".json" ? generateJSONConfigSource(localFlags) : path.extname(runtime.configFile) === ".go" ? generateGoConfigSource(localFlags, packageName) : generateShipdConfigSource(localFlags);
|
|
5505
|
+
const preparedTypes = prepareTypegen(runtime, localFlags);
|
|
5204
5506
|
const outPath = path.resolve(runtime.configFile);
|
|
5205
5507
|
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
5206
5508
|
fs.writeFileSync(outPath, source);
|
|
5207
|
-
const types =
|
|
5509
|
+
const types = writeTypegen(preparedTypes);
|
|
5208
5510
|
printResult(runtime, {
|
|
5209
5511
|
written: outPath,
|
|
5210
5512
|
flagCount: localFlags.length,
|
|
@@ -5259,6 +5561,7 @@ function registerPushCommand(program) {
|
|
|
5259
5561
|
}
|
|
5260
5562
|
if (planHasDefinitionChanges(plan) && !runtime.json) console.error("Note: definition/ownership changes apply to all environments (requires production permission).");
|
|
5261
5563
|
if (!await confirm(runtime, "Apply this plan?")) throw new CliError("validation_error", "Push cancelled (pass --yes or --ci to apply non-interactively)");
|
|
5564
|
+
const preparedTypes = prepareTypegen(runtime, localFlags);
|
|
5262
5565
|
const expectedVersions = expectedVersionsFromChanges(planned.changes);
|
|
5263
5566
|
const applied = await client.flag.push({
|
|
5264
5567
|
projectId,
|
|
@@ -5271,18 +5574,21 @@ function registerPushCommand(program) {
|
|
|
5271
5574
|
expectedVersions
|
|
5272
5575
|
}).catch(mapApiError);
|
|
5273
5576
|
const appliedPlan = buildSyncPlan(applied.changes);
|
|
5274
|
-
const types =
|
|
5577
|
+
const types = writeTypegen(preparedTypes);
|
|
5275
5578
|
const approvalRequests = applied.approvalRequests ?? [];
|
|
5579
|
+
const drafts = applied.drafts ?? [];
|
|
5276
5580
|
printResult(runtime, {
|
|
5277
5581
|
plan: appliedPlan,
|
|
5278
5582
|
remoteOnly,
|
|
5279
5583
|
forced: applied.forced === true,
|
|
5280
5584
|
approvalRequests,
|
|
5281
|
-
|
|
5585
|
+
drafts,
|
|
5586
|
+
outcome: approvalRequests.length > 0 ? "pending_approval" : drafts.length > 0 ? "draft" : "applied",
|
|
5282
5587
|
types
|
|
5283
5588
|
}, [
|
|
5284
|
-
applied.changes.length > 0 ? `
|
|
5589
|
+
applied.changes.length > 0 ? `Saved ${applied.changes.length} change(s).` : null,
|
|
5285
5590
|
approvalRequests.length > 0 ? `${approvalRequests.length} environment change(s) queued for approval.` : null,
|
|
5591
|
+
drafts.length > 0 ? `${drafts.length} targeting draft(s) ready to publish from the dashboard environment plan.` : null,
|
|
5286
5592
|
applied.forced ? "Forced through version conflicts (audited)." : null,
|
|
5287
5593
|
`Wrote types for ${types.flagCount} flag(s) to ${types.written}`
|
|
5288
5594
|
].filter(Boolean).join("\n"));
|
|
@@ -5366,9 +5672,14 @@ function registerSnapshotsCommands(program) {
|
|
|
5366
5672
|
//#endregion
|
|
5367
5673
|
//#region src/commands/types.ts
|
|
5368
5674
|
function registerTypesCommands(program) {
|
|
5369
|
-
program.command("types").description("Type generation helpers").command("gen").description("Generate TypeScript types from
|
|
5675
|
+
program.command("types").description("Type generation helpers").command("gen").description("Generate TypeScript types or Go accessors from the local flag config").addOption(new Option("--language <language>", "Output language").choices(["typescript", "go"])).option("--package <name>", "Go package name (default: flags)").option("-o, --out <path>", "Output file path").action(async (opts, command) => {
|
|
5370
5676
|
const runtime = getRuntime(command);
|
|
5371
|
-
const
|
|
5677
|
+
const language = opts.language ?? runtime.typesLanguage ?? "typescript";
|
|
5678
|
+
const defaultOutput = language === (runtime.typesLanguage ?? "typescript") ? runtime.typesOut : language === "go" ? "internal/flags/flags_gen.go" : "src/generated/flags.ts";
|
|
5679
|
+
const result = await runTypegen(runtime, opts.out ?? defaultOutput, {
|
|
5680
|
+
language,
|
|
5681
|
+
packageName: opts.package
|
|
5682
|
+
});
|
|
5372
5683
|
printResult(runtime, result, `Wrote types for ${result.flagCount} flag(s) to ${result.written}`);
|
|
5373
5684
|
});
|
|
5374
5685
|
}
|
|
@@ -5377,7 +5688,7 @@ function registerTypesCommands(program) {
|
|
|
5377
5688
|
//#region src/index.ts
|
|
5378
5689
|
/** Detected before parse so usage errors can suppress Commander text under `--json`. */
|
|
5379
5690
|
const jsonRequested = process.argv.includes("--json");
|
|
5380
|
-
const program = new Command().name("shipd").description("shipd CLI — flags as code").option("--json", "Machine-readable JSON output", false).option("--yes", "Skip confirmation prompts", false).option("--ci", "Non-interactive mode (same as --yes / CI=1)", false).option("--api-url <url>", `API origin (default: ${DEFAULT_API_URL})`).option("--org <slug>", "Organization slug (session: select; API key: must match)").option("--project <slug>", "Project slug").option("--env <slug>", "Environment slug").option("--config <path>", "Project settings JSON (.shipd/config.json shape)").option("--flags-config <path>", "Path to shipd.config.ts").exitOverride().showHelpAfterError(!jsonRequested);
|
|
5691
|
+
const program = new Command().name("shipd").description("shipd CLI — flags as code").option("--json", "Machine-readable JSON output", false).option("--yes", "Skip confirmation prompts", false).option("--ci", "Non-interactive mode (same as --yes / CI=1)", false).option("--api-url <url>", `API origin (default: ${DEFAULT_API_URL})`).option("--org <slug>", "Organization slug (session: select; API key: must match)").option("--project <slug>", "Project slug").option("--env <slug>", "Environment slug").option("--config <path>", "Project settings JSON (.shipd/config.json shape)").option("--flags-config <path>", "Path to shipd.config.ts, shipd.config.go, or shipd.config.json").exitOverride().showHelpAfterError(!jsonRequested);
|
|
5381
5692
|
if (jsonRequested) program.configureOutput({
|
|
5382
5693
|
writeErr: () => {},
|
|
5383
5694
|
writeOut: () => {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipdit/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "shipd's command-line interface",
|
|
5
5
|
"homepage": "https://docs.useshipd.com",
|
|
6
6
|
"bugs": {
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"commander": "^15.0.0",
|
|
20
20
|
"jiti": "^2.5.1",
|
|
21
|
-
"shipdit": "0.
|
|
22
|
-
"zod": "^4.6.
|
|
21
|
+
"shipdit": "0.4.0",
|
|
22
|
+
"zod": "^4.6.7"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@shipd/api-client": "0.0.1",
|