@onmyway133/asc-cli 1.0.1 → 1.0.3
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 +12 -80
- package/dist/index.js +164 -156
- package/docs/DEVELOPMENT.md +112 -0
- package/package.json +7 -1
- package/src/commands/app-info.ts +32 -34
- package/src/commands/apps.ts +17 -14
- package/src/commands/availability.ts +17 -16
- package/src/commands/beta-review.ts +51 -61
- package/src/commands/builds.ts +37 -29
- package/src/commands/game-center.ts +56 -55
- package/src/commands/iap.ts +47 -53
- package/src/commands/localizations.ts +83 -0
- package/src/commands/metadata.ts +25 -18
- package/src/commands/phased-release.ts +85 -0
- package/src/commands/pricing.ts +34 -30
- package/src/commands/reports.ts +13 -10
- package/src/commands/review-details.ts +79 -0
- package/src/commands/review-submission.ts +143 -0
- package/src/commands/reviews.ts +36 -30
- package/src/commands/screenshots.ts +40 -51
- package/src/commands/signing.ts +80 -100
- package/src/commands/subscriptions.ts +55 -63
- package/src/commands/testflight.ts +34 -23
- package/src/commands/versions.ts +40 -18
- package/src/commands/xcode-cloud.ts +68 -65
- package/src/index.ts +313 -1
|
@@ -1,60 +1,61 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
appsGameCenterDetailGetToOneRelated,
|
|
3
|
+
gameCenterDetailsGameCenterAchievementsGetToManyRelated,
|
|
4
|
+
gameCenterAchievementsGetInstance,
|
|
5
|
+
gameCenterDetailsGameCenterLeaderboardsGetToManyRelated,
|
|
6
|
+
gameCenterDetailsGameCenterLeaderboardSetsGetToManyRelated,
|
|
7
|
+
appsGameCenterEnabledVersionsGetToManyRelated,
|
|
8
|
+
} from "../api/generated/sdk.gen.ts"
|
|
9
|
+
import { throwOnError } from "../api/client.ts"
|
|
2
10
|
import { detectFormat, printJSON, printSuccess, printTable, truncate } from "../utils/output.ts"
|
|
3
11
|
|
|
12
|
+
async function getGameCenterDetailId(appId: string): Promise<string> {
|
|
13
|
+
const result = await appsGameCenterDetailGetToOneRelated({ path: { id: appId } })
|
|
14
|
+
const data = throwOnError(result)
|
|
15
|
+
return data.data.id
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
// ---- Achievements ----
|
|
5
19
|
|
|
6
20
|
export async function achievementsList(opts: {
|
|
7
21
|
appId: string
|
|
8
22
|
output?: string
|
|
9
23
|
}): Promise<void> {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
points
|
|
15
|
-
|
|
16
|
-
repeatable?: boolean
|
|
17
|
-
archived?: boolean
|
|
18
|
-
}
|
|
19
|
-
}>(`/v1/apps/${opts.appId}/gameCenterAchievements`, {
|
|
20
|
-
params: { "fields[gameCenterAchievements]": "referenceName,points,showBeforeEarned,repeatable,archived" },
|
|
24
|
+
const detailId = await getGameCenterDetailId(opts.appId)
|
|
25
|
+
const result = await gameCenterDetailsGameCenterAchievementsGetToManyRelated({
|
|
26
|
+
path: { id: detailId },
|
|
27
|
+
query: {
|
|
28
|
+
"fields[gameCenterAchievements]": ["referenceName", "points", "showBeforeEarned", "repeatable", "archived"],
|
|
29
|
+
},
|
|
21
30
|
})
|
|
31
|
+
const data = throwOnError(result)
|
|
32
|
+
const items = data.data
|
|
22
33
|
const fmt = detectFormat(opts.output)
|
|
23
34
|
if (fmt === "json") { printJSON(items); return }
|
|
24
35
|
printTable(
|
|
25
36
|
["ID", "Reference Name", "Points", "Repeatable"],
|
|
26
37
|
items.map(a => [
|
|
27
38
|
a.id,
|
|
28
|
-
a.attributes
|
|
29
|
-
String(a.attributes
|
|
30
|
-
String(a.attributes
|
|
39
|
+
a.attributes?.referenceName ?? "-",
|
|
40
|
+
String(a.attributes?.points ?? "-"),
|
|
41
|
+
String(a.attributes?.repeatable ?? "-"),
|
|
31
42
|
]),
|
|
32
43
|
`Game Center Achievements (${items.length})`,
|
|
33
44
|
)
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
export async function achievementGet(achievementId: string, opts: { output?: string } = {}): Promise<void> {
|
|
37
|
-
const result = await
|
|
38
|
-
|
|
39
|
-
id: string
|
|
40
|
-
attributes: {
|
|
41
|
-
referenceName?: string
|
|
42
|
-
points?: number
|
|
43
|
-
showBeforeEarned?: boolean
|
|
44
|
-
repeatable?: boolean
|
|
45
|
-
archived?: boolean
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}>(`/v1/gameCenterAchievements/${achievementId}`)
|
|
48
|
+
const result = await gameCenterAchievementsGetInstance({ path: { id: achievementId } })
|
|
49
|
+
const data = throwOnError(result)
|
|
49
50
|
const fmt = detectFormat(opts.output)
|
|
50
|
-
if (fmt === "json") { printJSON(
|
|
51
|
-
const a =
|
|
52
|
-
console.log(`ID: ${
|
|
53
|
-
console.log(`Reference Name: ${a
|
|
54
|
-
console.log(`Points: ${a
|
|
55
|
-
console.log(`Repeatable: ${a
|
|
56
|
-
console.log(`Show Before Earn:${a
|
|
57
|
-
console.log(`Archived: ${a
|
|
51
|
+
if (fmt === "json") { printJSON(data.data); return }
|
|
52
|
+
const a = data.data.attributes
|
|
53
|
+
console.log(`ID: ${data.data.id}`)
|
|
54
|
+
console.log(`Reference Name: ${a?.referenceName ?? "-"}`)
|
|
55
|
+
console.log(`Points: ${a?.points ?? "-"}`)
|
|
56
|
+
console.log(`Repeatable: ${a?.repeatable ?? false}`)
|
|
57
|
+
console.log(`Show Before Earn:${a?.showBeforeEarned ?? false}`)
|
|
58
|
+
console.log(`Archived: ${a?.archived ?? false}`)
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
// ---- Leaderboards ----
|
|
@@ -63,21 +64,20 @@ export async function leaderboardsList(opts: {
|
|
|
63
64
|
appId: string
|
|
64
65
|
output?: string
|
|
65
66
|
}): Promise<void> {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
defaultFormatter
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
}>(`/v1/apps/${opts.appId}/gameCenterLeaderboards`, {
|
|
74
|
-
params: { "fields[gameCenterLeaderboards]": "referenceName,defaultFormatter,archived" },
|
|
67
|
+
const detailId = await getGameCenterDetailId(opts.appId)
|
|
68
|
+
const result = await gameCenterDetailsGameCenterLeaderboardsGetToManyRelated({
|
|
69
|
+
path: { id: detailId },
|
|
70
|
+
query: {
|
|
71
|
+
"fields[gameCenterLeaderboards]": ["referenceName", "defaultFormatter", "archived"],
|
|
72
|
+
},
|
|
75
73
|
})
|
|
74
|
+
const data = throwOnError(result)
|
|
75
|
+
const items = data.data
|
|
76
76
|
const fmt = detectFormat(opts.output)
|
|
77
77
|
if (fmt === "json") { printJSON(items); return }
|
|
78
78
|
printTable(
|
|
79
79
|
["ID", "Reference Name", "Archived"],
|
|
80
|
-
items.map(l => [l.id, l.attributes
|
|
80
|
+
items.map(l => [l.id, l.attributes?.referenceName ?? "-", String(l.attributes?.archived ?? false)]),
|
|
81
81
|
`Leaderboards (${items.length})`,
|
|
82
82
|
)
|
|
83
83
|
}
|
|
@@ -88,15 +88,17 @@ export async function leaderboardSetsList(opts: {
|
|
|
88
88
|
appId: string
|
|
89
89
|
output?: string
|
|
90
90
|
}): Promise<void> {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
91
|
+
const detailId = await getGameCenterDetailId(opts.appId)
|
|
92
|
+
const result = await gameCenterDetailsGameCenterLeaderboardSetsGetToManyRelated({
|
|
93
|
+
path: { id: detailId },
|
|
94
|
+
})
|
|
95
|
+
const data = throwOnError(result)
|
|
96
|
+
const items = data.data
|
|
95
97
|
const fmt = detectFormat(opts.output)
|
|
96
98
|
if (fmt === "json") { printJSON(items); return }
|
|
97
99
|
printTable(
|
|
98
100
|
["ID", "Reference Name", "Archived"],
|
|
99
|
-
items.map(s => [s.id, s.attributes
|
|
101
|
+
items.map(s => [s.id, s.attributes?.referenceName ?? "-", "-"]),
|
|
100
102
|
`Leaderboard Sets (${items.length})`,
|
|
101
103
|
)
|
|
102
104
|
}
|
|
@@ -104,11 +106,10 @@ export async function leaderboardSetsList(opts: {
|
|
|
104
106
|
// ---- Game Center Enable ----
|
|
105
107
|
|
|
106
108
|
export async function gameCenterEnableCheck(appId: string, opts: { output?: string } = {}): Promise<void> {
|
|
107
|
-
const result = await
|
|
108
|
-
|
|
109
|
-
}>(`/v1/apps/${appId}/gameCenterEnabledVersions`)
|
|
109
|
+
const result = await appsGameCenterEnabledVersionsGetToManyRelated({ path: { id: appId } })
|
|
110
|
+
const data = throwOnError(result)
|
|
110
111
|
const fmt = detectFormat(opts.output)
|
|
111
|
-
if (fmt === "json") { printJSON(
|
|
112
|
+
if (fmt === "json") { printJSON(data); return }
|
|
112
113
|
console.log(`Game Center status for app ${appId}:`)
|
|
113
|
-
console.log(JSON.stringify(
|
|
114
|
+
console.log(JSON.stringify(data.data, null, 2))
|
|
114
115
|
}
|
package/src/commands/iap.ts
CHANGED
|
@@ -1,61 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
appsInAppPurchasesV2GetToManyRelated,
|
|
3
|
+
inAppPurchasesV2GetInstance,
|
|
4
|
+
inAppPurchasesV2CreateInstance,
|
|
5
|
+
inAppPurchasesV2DeleteInstance,
|
|
6
|
+
} from "../api/generated/sdk.gen.ts"
|
|
7
|
+
import { throwOnError } from "../api/client.ts"
|
|
2
8
|
import { detectFormat, printJSON, printSuccess, printTable, truncate } from "../utils/output.ts"
|
|
3
9
|
|
|
4
10
|
// ---- In-App Purchases (non-subscription consumables, non-consumables, non-renewing subscriptions) ----
|
|
5
11
|
|
|
6
12
|
export async function iapList(opts: { appId: string; output?: string }): Promise<void> {
|
|
7
|
-
const
|
|
8
|
-
id:
|
|
9
|
-
|
|
10
|
-
name?: string
|
|
11
|
-
productId?: string
|
|
12
|
-
inAppPurchaseType?: string
|
|
13
|
-
state?: string
|
|
14
|
-
}
|
|
15
|
-
}>(`/v1/apps/${opts.appId}/inAppPurchasesV2`, {
|
|
16
|
-
params: { "fields[inAppPurchasesV2]": "name,productId,inAppPurchaseType,state" },
|
|
13
|
+
const result = await appsInAppPurchasesV2GetToManyRelated({
|
|
14
|
+
path: { id: opts.appId },
|
|
15
|
+
query: { "fields[inAppPurchases]": ["name", "productId", "inAppPurchaseType", "state"] },
|
|
17
16
|
})
|
|
17
|
+
const data = throwOnError(result)
|
|
18
|
+
const items = data.data
|
|
18
19
|
const fmt = detectFormat(opts.output)
|
|
19
20
|
if (fmt === "json") { printJSON(items); return }
|
|
20
21
|
printTable(
|
|
21
22
|
["ID", "Name", "Product ID", "Type", "State"],
|
|
22
23
|
items.map(i => [
|
|
23
24
|
i.id,
|
|
24
|
-
truncate(i.attributes
|
|
25
|
-
i.attributes
|
|
26
|
-
i.attributes
|
|
27
|
-
i.attributes
|
|
25
|
+
truncate(i.attributes?.name ?? "-", 30),
|
|
26
|
+
i.attributes?.productId ?? "-",
|
|
27
|
+
i.attributes?.inAppPurchaseType ?? "-",
|
|
28
|
+
i.attributes?.state ?? "-",
|
|
28
29
|
]),
|
|
29
30
|
`In-App Purchases (${items.length})`,
|
|
30
31
|
)
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export async function iapGet(iapId: string, opts: { output?: string } = {}): Promise<void> {
|
|
34
|
-
const result = await
|
|
35
|
-
|
|
36
|
-
id: string
|
|
37
|
-
attributes: {
|
|
38
|
-
name?: string
|
|
39
|
-
productId?: string
|
|
40
|
-
inAppPurchaseType?: string
|
|
41
|
-
state?: string
|
|
42
|
-
reviewNote?: string
|
|
43
|
-
familySharable?: boolean
|
|
44
|
-
contentHosting?: boolean
|
|
45
|
-
availableInAllTerritories?: boolean
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}>(`/v1/inAppPurchasesV2/${iapId}`)
|
|
35
|
+
const result = await inAppPurchasesV2GetInstance({ path: { id: iapId } })
|
|
36
|
+
const data = throwOnError(result)
|
|
49
37
|
const fmt = detectFormat(opts.output)
|
|
50
|
-
if (fmt === "json") { printJSON(
|
|
51
|
-
const a =
|
|
52
|
-
console.log(`ID: ${
|
|
53
|
-
console.log(`Name: ${a
|
|
54
|
-
console.log(`Product ID: ${a
|
|
55
|
-
console.log(`Type: ${a
|
|
56
|
-
console.log(`State: ${a
|
|
57
|
-
console.log(`Reviewable: ${a
|
|
58
|
-
console.log(`Family Share: ${a
|
|
38
|
+
if (fmt === "json") { printJSON(data.data); return }
|
|
39
|
+
const a = data.data.attributes
|
|
40
|
+
console.log(`ID: ${data.data.id}`)
|
|
41
|
+
console.log(`Name: ${a?.name ?? "-"}`)
|
|
42
|
+
console.log(`Product ID: ${a?.productId ?? "-"}`)
|
|
43
|
+
console.log(`Type: ${a?.inAppPurchaseType ?? "-"}`)
|
|
44
|
+
console.log(`State: ${a?.state ?? "-"}`)
|
|
45
|
+
console.log(`Reviewable: ${a?.reviewNote ?? "(no review note)"}`)
|
|
46
|
+
console.log(`Family Share: ${a?.familySharable ?? false}`)
|
|
59
47
|
}
|
|
60
48
|
|
|
61
49
|
export async function iapCreate(opts: {
|
|
@@ -64,15 +52,14 @@ export async function iapCreate(opts: {
|
|
|
64
52
|
productId: string
|
|
65
53
|
type: string
|
|
66
54
|
}): Promise<void> {
|
|
67
|
-
const result = await
|
|
68
|
-
method: "POST",
|
|
55
|
+
const result = await inAppPurchasesV2CreateInstance({
|
|
69
56
|
body: {
|
|
70
57
|
data: {
|
|
71
|
-
type: "
|
|
58
|
+
type: "inAppPurchases",
|
|
72
59
|
attributes: {
|
|
73
60
|
name: opts.name,
|
|
74
61
|
productId: opts.productId,
|
|
75
|
-
inAppPurchaseType: opts.type,
|
|
62
|
+
inAppPurchaseType: opts.type as never,
|
|
76
63
|
},
|
|
77
64
|
relationships: {
|
|
78
65
|
app: { data: { type: "apps", id: opts.appId } },
|
|
@@ -80,26 +67,33 @@ export async function iapCreate(opts: {
|
|
|
80
67
|
},
|
|
81
68
|
},
|
|
82
69
|
})
|
|
83
|
-
|
|
70
|
+
const data = throwOnError(result)
|
|
71
|
+
printSuccess(`Created IAP: ${data.data.id} (${opts.productId})`)
|
|
84
72
|
}
|
|
85
73
|
|
|
86
74
|
export async function iapDelete(iapId: string): Promise<void> {
|
|
87
|
-
await
|
|
75
|
+
await inAppPurchasesV2DeleteInstance({ path: { id: iapId } })
|
|
88
76
|
printSuccess(`Deleted IAP ${iapId}`)
|
|
89
77
|
}
|
|
90
78
|
|
|
91
79
|
export async function iapLocalesList(iapId: string, opts: { output?: string } = {}): Promise<void> {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
80
|
+
// No direct SDK function for /v1/inAppPurchasesV2/{id}/iapPriceSchedule with localization fields
|
|
81
|
+
// Use the get instance with include
|
|
82
|
+
const result = await inAppPurchasesV2GetInstance({
|
|
83
|
+
path: { id: iapId },
|
|
84
|
+
query: {
|
|
85
|
+
include: ["iapPriceSchedule"],
|
|
86
|
+
"fields[inAppPurchaseLocalizations]": ["locale", "name", "description"],
|
|
87
|
+
},
|
|
97
88
|
})
|
|
89
|
+
const data = throwOnError(result)
|
|
90
|
+
const included = (data as { data: unknown; included?: Array<{ id: string; type: string; attributes?: { locale?: string; name?: string; description?: string } }> }).included ?? []
|
|
91
|
+
const locs = included.filter(r => r.type === "inAppPurchaseLocalizations")
|
|
98
92
|
const fmt = detectFormat(opts.output)
|
|
99
|
-
if (fmt === "json") { printJSON(
|
|
93
|
+
if (fmt === "json") { printJSON(locs); return }
|
|
100
94
|
printTable(
|
|
101
95
|
["Locale", "Name", "Description"],
|
|
102
|
-
|
|
103
|
-
`IAP Localizations (${
|
|
96
|
+
locs.map(l => [l.attributes?.locale ?? l.id, l.attributes?.name ?? "-", truncate(l.attributes?.description ?? "-", 40)]),
|
|
97
|
+
`IAP Localizations (${locs.length})`,
|
|
104
98
|
)
|
|
105
99
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appStoreVersionsAppStoreVersionLocalizationsGetToManyRelated,
|
|
3
|
+
appStoreVersionLocalizationsGetInstance,
|
|
4
|
+
appStoreVersionLocalizationsCreateInstance,
|
|
5
|
+
appStoreVersionLocalizationsDeleteInstance,
|
|
6
|
+
} from "../api/generated/sdk.gen.ts"
|
|
7
|
+
import { throwOnError } from "../api/client.ts"
|
|
8
|
+
import { detectFormat, printJSON, printSuccess, printTable, truncate } from "../utils/output.ts"
|
|
9
|
+
|
|
10
|
+
export async function localizationsList(opts: {
|
|
11
|
+
versionId: string
|
|
12
|
+
output?: string
|
|
13
|
+
}): Promise<void> {
|
|
14
|
+
const result = await appStoreVersionsAppStoreVersionLocalizationsGetToManyRelated({
|
|
15
|
+
path: { id: opts.versionId },
|
|
16
|
+
query: { "fields[appStoreVersionLocalizations]": ["locale", "description", "whatsNew", "keywords"] },
|
|
17
|
+
})
|
|
18
|
+
const data = throwOnError(result)
|
|
19
|
+
const items = data.data
|
|
20
|
+
|
|
21
|
+
const fmt = detectFormat(opts.output)
|
|
22
|
+
if (fmt === "json") { printJSON(items.map(l => ({ id: l.id, ...l.attributes }))); return }
|
|
23
|
+
printTable(
|
|
24
|
+
["ID", "Locale", "What's New", "Description"],
|
|
25
|
+
items.map(l => [
|
|
26
|
+
l.id,
|
|
27
|
+
l.attributes?.locale ?? "-",
|
|
28
|
+
truncate(l.attributes?.whatsNew ?? "-", 40),
|
|
29
|
+
truncate(l.attributes?.description ?? "-", 40),
|
|
30
|
+
]),
|
|
31
|
+
`Localizations (${items.length})`,
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function localizationsGet(localizationId: string, output?: string): Promise<void> {
|
|
36
|
+
const result = await appStoreVersionLocalizationsGetInstance({ path: { id: localizationId } })
|
|
37
|
+
const data = throwOnError(result)
|
|
38
|
+
const l = data.data
|
|
39
|
+
|
|
40
|
+
const fmt = detectFormat(output)
|
|
41
|
+
if (fmt === "json") { printJSON({ id: l.id, ...l.attributes }); return }
|
|
42
|
+
console.log(`ID: ${l.id}`)
|
|
43
|
+
console.log(`Locale: ${l.attributes?.locale ?? "-"}`)
|
|
44
|
+
console.log(`What's New: ${l.attributes?.whatsNew ?? "-"}`)
|
|
45
|
+
console.log(`Description: ${truncate(l.attributes?.description ?? "-", 80)}`)
|
|
46
|
+
console.log(`Keywords: ${l.attributes?.keywords ?? "-"}`)
|
|
47
|
+
console.log(`Promotional Text: ${l.attributes?.promotionalText ?? "-"}`)
|
|
48
|
+
console.log(`Marketing URL: ${l.attributes?.marketingUrl ?? "-"}`)
|
|
49
|
+
console.log(`Support URL: ${l.attributes?.supportUrl ?? "-"}`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function localizationsCreate(opts: {
|
|
53
|
+
versionId: string
|
|
54
|
+
locale: string
|
|
55
|
+
description?: string
|
|
56
|
+
whatsNew?: string
|
|
57
|
+
keywords?: string
|
|
58
|
+
}): Promise<void> {
|
|
59
|
+
const result = await appStoreVersionLocalizationsCreateInstance({
|
|
60
|
+
body: {
|
|
61
|
+
data: {
|
|
62
|
+
type: "appStoreVersionLocalizations",
|
|
63
|
+
attributes: {
|
|
64
|
+
locale: opts.locale,
|
|
65
|
+
description: opts.description,
|
|
66
|
+
whatsNew: opts.whatsNew,
|
|
67
|
+
keywords: opts.keywords,
|
|
68
|
+
},
|
|
69
|
+
relationships: {
|
|
70
|
+
appStoreVersion: { data: { type: "appStoreVersions", id: opts.versionId } },
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
const data = throwOnError(result)
|
|
76
|
+
printSuccess(`Localization created for locale "${opts.locale}" — ID: ${data.data.id}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function localizationsDelete(localizationId: string): Promise<void> {
|
|
80
|
+
const result = await appStoreVersionLocalizationsDeleteInstance({ path: { id: localizationId } })
|
|
81
|
+
throwOnError(result)
|
|
82
|
+
printSuccess(`Localization ${localizationId} deleted`)
|
|
83
|
+
}
|
package/src/commands/metadata.ts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
appStoreVersionsAppStoreVersionLocalizationsGetToManyRelated,
|
|
3
|
+
appStoreVersionLocalizationsUpdateInstance,
|
|
4
|
+
appStoreVersionLocalizationsCreateInstance,
|
|
5
|
+
} from "../api/generated/sdk.gen.ts"
|
|
6
|
+
import { throwOnError } from "../api/client.ts"
|
|
3
7
|
import { detectFormat, printJSON, printSuccess, printTable, truncate } from "../utils/output.ts"
|
|
4
8
|
|
|
5
9
|
export async function metadataList(opts: {
|
|
6
10
|
versionId: string
|
|
7
11
|
output?: string
|
|
8
12
|
}): Promise<void> {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
)
|
|
13
|
+
const result = await appStoreVersionsAppStoreVersionLocalizationsGetToManyRelated({
|
|
14
|
+
path: { id: opts.versionId },
|
|
15
|
+
})
|
|
16
|
+
const data = throwOnError(result)
|
|
17
|
+
const locs = data.data
|
|
12
18
|
|
|
13
19
|
const fmt = detectFormat(opts.output)
|
|
14
20
|
if (fmt === "json") {
|
|
@@ -20,9 +26,9 @@ export async function metadataList(opts: {
|
|
|
20
26
|
["ID", "Locale", "What's New", "Description"],
|
|
21
27
|
locs.map((l) => [
|
|
22
28
|
l.id,
|
|
23
|
-
l.attributes
|
|
24
|
-
truncate(l.attributes
|
|
25
|
-
truncate(l.attributes
|
|
29
|
+
l.attributes?.locale ?? "-",
|
|
30
|
+
truncate(l.attributes?.whatsNew ?? "-", 50),
|
|
31
|
+
truncate(l.attributes?.description ?? "-", 50),
|
|
26
32
|
]),
|
|
27
33
|
`Localizations (${locs.length})`,
|
|
28
34
|
)
|
|
@@ -37,10 +43,12 @@ export async function metadataUpdate(opts: {
|
|
|
37
43
|
promotionalText?: string
|
|
38
44
|
}): Promise<void> {
|
|
39
45
|
// Find existing localization for this locale
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
46
|
+
const result = await appStoreVersionsAppStoreVersionLocalizationsGetToManyRelated({
|
|
47
|
+
path: { id: opts.versionId },
|
|
48
|
+
query: { "filter[locale]": [opts.locale] as never },
|
|
49
|
+
})
|
|
50
|
+
const data = throwOnError(result)
|
|
51
|
+
const locs = data.data
|
|
44
52
|
|
|
45
53
|
const attributes: Record<string, string> = {}
|
|
46
54
|
if (opts.whatsNew !== undefined) attributes["whatsNew"] = opts.whatsNew
|
|
@@ -49,25 +57,24 @@ export async function metadataUpdate(opts: {
|
|
|
49
57
|
if (opts.promotionalText !== undefined) attributes["promotionalText"] = opts.promotionalText
|
|
50
58
|
|
|
51
59
|
if (locs.length > 0 && locs[0]) {
|
|
52
|
-
await
|
|
53
|
-
|
|
60
|
+
await appStoreVersionLocalizationsUpdateInstance({
|
|
61
|
+
path: { id: locs[0].id },
|
|
54
62
|
body: {
|
|
55
63
|
data: {
|
|
56
64
|
type: "appStoreVersionLocalizations",
|
|
57
65
|
id: locs[0].id,
|
|
58
|
-
attributes,
|
|
66
|
+
attributes: attributes as never,
|
|
59
67
|
},
|
|
60
68
|
},
|
|
61
69
|
})
|
|
62
70
|
printSuccess(`Metadata updated for locale "${opts.locale}"`)
|
|
63
71
|
} else {
|
|
64
72
|
// Create new localization
|
|
65
|
-
await
|
|
66
|
-
method: "POST",
|
|
73
|
+
await appStoreVersionLocalizationsCreateInstance({
|
|
67
74
|
body: {
|
|
68
75
|
data: {
|
|
69
76
|
type: "appStoreVersionLocalizations",
|
|
70
|
-
attributes: { locale: opts.locale, ...attributes },
|
|
77
|
+
attributes: { locale: opts.locale, ...attributes } as never,
|
|
71
78
|
relationships: {
|
|
72
79
|
appStoreVersion: {
|
|
73
80
|
data: { type: "appStoreVersions", id: opts.versionId },
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appStoreVersionsAppStoreVersionPhasedReleaseGetToOneRelated,
|
|
3
|
+
appStoreVersionPhasedReleasesCreateInstance,
|
|
4
|
+
appStoreVersionPhasedReleasesUpdateInstance,
|
|
5
|
+
appStoreVersionPhasedReleasesDeleteInstance,
|
|
6
|
+
} from "../api/generated/sdk.gen.ts"
|
|
7
|
+
import type { PhasedReleaseState } from "../api/generated/types.gen.ts"
|
|
8
|
+
import { throwOnError, ASCError } from "../api/client.ts"
|
|
9
|
+
import { detectFormat, printJSON, printSuccess } from "../utils/output.ts"
|
|
10
|
+
|
|
11
|
+
const VALID_STATES: PhasedReleaseState[] = ["INACTIVE", "ACTIVE", "PAUSED", "COMPLETE"]
|
|
12
|
+
|
|
13
|
+
export async function phasedReleaseGet(versionId: string, output?: string): Promise<void> {
|
|
14
|
+
let pr: Awaited<ReturnType<typeof appStoreVersionsAppStoreVersionPhasedReleaseGetToOneRelated>>
|
|
15
|
+
try {
|
|
16
|
+
pr = await appStoreVersionsAppStoreVersionPhasedReleaseGetToOneRelated({ path: { id: versionId } })
|
|
17
|
+
} catch (err) {
|
|
18
|
+
if (err instanceof ASCError && err.status === 404) {
|
|
19
|
+
console.log("No phased release configured for this version.")
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
throw err
|
|
23
|
+
}
|
|
24
|
+
const data = throwOnError(pr)
|
|
25
|
+
const d = data.data
|
|
26
|
+
|
|
27
|
+
const fmt = detectFormat(output)
|
|
28
|
+
if (fmt === "json") { printJSON({ id: d.id, ...d.attributes }); return }
|
|
29
|
+
console.log(`ID: ${d.id}`)
|
|
30
|
+
console.log(`State: ${d.attributes?.phasedReleaseState ?? "-"}`)
|
|
31
|
+
console.log(`Start Date: ${d.attributes?.startDate ?? "-"}`)
|
|
32
|
+
console.log(`Current Day: ${d.attributes?.currentDayNumber ?? "-"} / 7`)
|
|
33
|
+
console.log(`Total Pause Days: ${d.attributes?.totalPauseDuration ?? 0}`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function phasedReleaseCreate(opts: {
|
|
37
|
+
versionId: string
|
|
38
|
+
state?: string
|
|
39
|
+
}): Promise<void> {
|
|
40
|
+
const state = (opts.state ?? "INACTIVE").toUpperCase() as PhasedReleaseState
|
|
41
|
+
if (!VALID_STATES.includes(state)) {
|
|
42
|
+
throw new Error(`Invalid state "${state}". Valid values: ${VALID_STATES.join(", ")}`)
|
|
43
|
+
}
|
|
44
|
+
const result = await appStoreVersionPhasedReleasesCreateInstance({
|
|
45
|
+
body: {
|
|
46
|
+
data: {
|
|
47
|
+
type: "appStoreVersionPhasedReleases",
|
|
48
|
+
attributes: { phasedReleaseState: state },
|
|
49
|
+
relationships: {
|
|
50
|
+
appStoreVersion: { data: { type: "appStoreVersions", id: opts.versionId } },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
const data = throwOnError(result)
|
|
56
|
+
printSuccess(`Phased release created — ID: ${data.data.id} State: ${state}`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function phasedReleaseUpdate(opts: {
|
|
60
|
+
phasedReleaseId: string
|
|
61
|
+
state: string
|
|
62
|
+
}): Promise<void> {
|
|
63
|
+
const state = opts.state.toUpperCase() as PhasedReleaseState
|
|
64
|
+
if (!VALID_STATES.includes(state)) {
|
|
65
|
+
throw new Error(`Invalid state "${state}". Valid values: ${VALID_STATES.join(", ")}`)
|
|
66
|
+
}
|
|
67
|
+
const result = await appStoreVersionPhasedReleasesUpdateInstance({
|
|
68
|
+
path: { id: opts.phasedReleaseId },
|
|
69
|
+
body: {
|
|
70
|
+
data: {
|
|
71
|
+
type: "appStoreVersionPhasedReleases",
|
|
72
|
+
id: opts.phasedReleaseId,
|
|
73
|
+
attributes: { phasedReleaseState: state },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
})
|
|
77
|
+
throwOnError(result)
|
|
78
|
+
printSuccess(`Phased release updated — State: ${state}`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function phasedReleaseDelete(phasedReleaseId: string): Promise<void> {
|
|
82
|
+
const result = await appStoreVersionPhasedReleasesDeleteInstance({ path: { id: phasedReleaseId } })
|
|
83
|
+
throwOnError(result)
|
|
84
|
+
printSuccess(`Phased release ${phasedReleaseId} deleted`)
|
|
85
|
+
}
|