@solana-mobile/dapp-store-cli 0.2.0 → 0.4.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/lib/esm/commands/create/app.js +7 -5
- package/lib/esm/commands/create/app.js.map +1 -1
- package/lib/esm/commands/create/publisher.js +7 -5
- package/lib/esm/commands/create/publisher.js.map +1 -1
- package/lib/esm/commands/create/release.js +7 -5
- package/lib/esm/commands/create/release.js.map +1 -1
- package/lib/esm/commands/publish/remove.js +2 -2
- package/lib/esm/commands/publish/remove.js.map +1 -1
- package/lib/esm/commands/publish/submit.js +2 -2
- package/lib/esm/commands/publish/submit.js.map +1 -1
- package/lib/esm/commands/publish/support.js +2 -2
- package/lib/esm/commands/publish/support.js.map +1 -1
- package/lib/esm/commands/publish/update.js +2 -2
- package/lib/esm/commands/publish/update.js.map +1 -1
- package/lib/esm/commands/validate.js +2 -2
- package/lib/esm/commands/validate.js.map +1 -1
- package/lib/esm/generated/config_obj.json +1 -1
- package/lib/esm/generated/config_schema.json +1 -1
- package/lib/esm/index.js +18 -8
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/package.json +2 -2
- package/lib/esm/utils.js +55 -16
- package/lib/esm/utils.js.map +1 -1
- package/lib/types/commands/create/app.d.ts.map +1 -1
- package/lib/types/commands/create/publisher.d.ts.map +1 -1
- package/lib/types/commands/create/release.d.ts.map +1 -1
- package/lib/types/utils.d.ts +2 -2
- package/lib/types/utils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/commands/create/app.ts +7 -5
- package/src/commands/create/publisher.ts +7 -5
- package/src/commands/create/release.ts +7 -5
- package/src/commands/publish/remove.ts +2 -2
- package/src/commands/publish/submit.ts +2 -2
- package/src/commands/publish/support.ts +2 -2
- package/src/commands/publish/update.ts +2 -2
- package/src/commands/validate.ts +2 -2
- package/src/index.ts +25 -10
- package/src/prebuild_schema/publishing_source.yaml +7 -5
- package/src/prebuild_schema/schemagen.js +7 -0
- package/src/utils.ts +77 -23
- package/src/config/schema.json +0 -195
- package/src/generated/config_obj.json +0 -1
- package/src/generated/config_schema.json +0 -1
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
-
import type { AndroidDetails, App, Publisher, Release } from "@solana-mobile/dapp-store-publishing-tools";
|
|
2
|
+
import type { AndroidDetails, App, Publisher, Release, ReleaseJsonMetadata } from "@solana-mobile/dapp-store-publishing-tools";
|
|
3
3
|
import type { Connection } from "@solana/web3.js";
|
|
4
4
|
import { Keypair, PublicKey } from "@solana/web3.js";
|
|
5
5
|
import type { CLIConfig } from "./config/index.js";
|
|
@@ -22,7 +22,7 @@ const runImgSize = util.promisify(imageSize);
|
|
|
22
22
|
const runExec = util.promisify(exec);
|
|
23
23
|
|
|
24
24
|
export class Constants {
|
|
25
|
-
static CLI_VERSION = "0.
|
|
25
|
+
static CLI_VERSION = "0.4.0";
|
|
26
26
|
static CONFIG_FILE_NAME = "config.yaml";
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -58,9 +58,12 @@ export const parseKeypair = (pathToKeypairFile: string) => {
|
|
|
58
58
|
const keypairFile = fs.readFileSync(pathToKeypairFile, "utf-8");
|
|
59
59
|
return Keypair.fromSecretKey(Buffer.from(JSON.parse(keypairFile)));
|
|
60
60
|
} catch (e) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
showMessage
|
|
62
|
+
(
|
|
63
|
+
"KeyPair Error",
|
|
64
|
+
"Something went wrong when attempting to retrieve the keypair at " + pathToKeypairFile,
|
|
65
|
+
"error"
|
|
66
|
+
)
|
|
64
67
|
}
|
|
65
68
|
};
|
|
66
69
|
|
|
@@ -71,11 +74,10 @@ const AaptPrefixes = {
|
|
|
71
74
|
verCodePrefix: "versionCode=",
|
|
72
75
|
verNamePrefix: "versionName=",
|
|
73
76
|
sdkPrefix: "sdkVersion:",
|
|
74
|
-
permissionPrefix: "uses-permission: name=",
|
|
75
77
|
localePrefix: "locales: ",
|
|
76
78
|
};
|
|
77
79
|
|
|
78
|
-
export const
|
|
80
|
+
export const getConfigWithChecks = async (
|
|
79
81
|
buildToolsDir: string | null = null
|
|
80
82
|
): Promise<CLIConfig> => {
|
|
81
83
|
const configFilePath = `${process.cwd()}/${Constants.CONFIG_FILE_NAME}`;
|
|
@@ -142,6 +144,17 @@ export const getConfigFile = async (
|
|
|
142
144
|
}
|
|
143
145
|
});
|
|
144
146
|
|
|
147
|
+
validateLocalizableResources(config);
|
|
148
|
+
|
|
149
|
+
const googlePkg = config.solana_mobile_dapp_publisher_portal.google_store_package;
|
|
150
|
+
if (googlePkg?.length) {
|
|
151
|
+
const pkgCompare = new RegExp("[a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+)+").exec(googlePkg);
|
|
152
|
+
|
|
153
|
+
if (!pkgCompare?.length) {
|
|
154
|
+
throw new Error("Please provide a valid Google store package name in the Publisher Portal section of your configuration file.");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
145
158
|
return config;
|
|
146
159
|
};
|
|
147
160
|
|
|
@@ -165,6 +178,33 @@ const checkImageExtension = (uri: string): boolean => {
|
|
|
165
178
|
);
|
|
166
179
|
};
|
|
167
180
|
|
|
181
|
+
/**
|
|
182
|
+
* We need to pre-check some things in the localized resources before we move forward
|
|
183
|
+
*/
|
|
184
|
+
const validateLocalizableResources = (config: CLIConfig) => {
|
|
185
|
+
if (!config.release.catalog["en-US"]) {
|
|
186
|
+
throw new Error("Please ensure you have the en-US locale strings in your configuration file.");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const baselineSize = Object.keys(config.release.catalog["en-US"]).length;
|
|
190
|
+
Object.keys(config.release.catalog).forEach((locale) => {
|
|
191
|
+
const size = Object.keys(config.release.catalog[locale]).length;
|
|
192
|
+
|
|
193
|
+
if (size != baselineSize) {
|
|
194
|
+
throw new Error("Please ensure you have included all localized strings for all locales in your configuration file.");
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const descsWrongLength = Object.values(config.release.catalog)
|
|
199
|
+
.map((x) => x.short_description)
|
|
200
|
+
.filter((desc) => !desc?.length || desc.length > 50);
|
|
201
|
+
|
|
202
|
+
if (descsWrongLength.length > 0) {
|
|
203
|
+
throw new Error("Please ensure all translations of short_description are between 0 and 50 characters");
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
|
|
168
208
|
export const isDevnet = (rpcUrl: string): boolean => {
|
|
169
209
|
return rpcUrl.indexOf("devnet") != -1;
|
|
170
210
|
};
|
|
@@ -196,17 +236,27 @@ export const generateNetworkSuffix = (rpcUrl: string): string => {
|
|
|
196
236
|
export const showMessage = (
|
|
197
237
|
titleMessage = "",
|
|
198
238
|
contentMessage = "",
|
|
199
|
-
|
|
200
|
-
) => {
|
|
201
|
-
|
|
239
|
+
type: "standard" | "error" | "warning" = "standard",
|
|
240
|
+
): string => {
|
|
241
|
+
let color = "cyan";
|
|
242
|
+
if (type == "error") {
|
|
243
|
+
color = "redBright";
|
|
244
|
+
} else if (type == "warning") {
|
|
245
|
+
color = "yellow";
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const msg = boxen(contentMessage, {
|
|
202
249
|
title: titleMessage,
|
|
203
250
|
padding: 1,
|
|
204
251
|
margin: 1,
|
|
205
252
|
borderStyle: 'single',
|
|
206
|
-
borderColor:
|
|
253
|
+
borderColor: color,
|
|
207
254
|
textAlignment: "left",
|
|
208
|
-
titleAlignment: "center"
|
|
209
|
-
})
|
|
255
|
+
titleAlignment: "center",
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
console.log(msg);
|
|
259
|
+
return msg;
|
|
210
260
|
};
|
|
211
261
|
|
|
212
262
|
const checkIconDimensions = async (iconPath: string): Promise<boolean> => {
|
|
@@ -233,30 +283,34 @@ const getAndroidDetails = async (
|
|
|
233
283
|
const minSdk = new RegExp(
|
|
234
284
|
AaptPrefixes.sdkPrefix + AaptPrefixes.quoteRegex
|
|
235
285
|
).exec(stdout);
|
|
236
|
-
const permissions =
|
|
237
|
-
AaptPrefixes.permissionPrefix + AaptPrefixes.quoteNonLazyRegex
|
|
238
|
-
).exec(stdout);
|
|
286
|
+
const permissions = [...stdout.matchAll(/uses-permission: name='(.*)'/g)];
|
|
239
287
|
const locales = new RegExp(
|
|
240
288
|
AaptPrefixes.localePrefix + AaptPrefixes.quoteNonLazyRegex
|
|
241
289
|
).exec(stdout);
|
|
242
290
|
|
|
243
|
-
let permissionArray = Array.from(permissions?.values() ?? []);
|
|
244
|
-
if (permissionArray.length >= 2) {
|
|
245
|
-
permissionArray = permissionArray.slice(1);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
291
|
let localeArray = Array.from(locales?.values() ?? []);
|
|
249
292
|
if (localeArray.length == 2) {
|
|
250
293
|
const localesSrc = localeArray[1];
|
|
251
294
|
localeArray = ["en-US"].concat(localesSrc.split("' '").slice(1));
|
|
252
295
|
}
|
|
253
296
|
|
|
297
|
+
if (localeArray.length >= 60) {
|
|
298
|
+
showMessage(
|
|
299
|
+
"The bundle apk claims supports for following locales",
|
|
300
|
+
"Claim for supported locales::\n" +
|
|
301
|
+
localeArray +
|
|
302
|
+
"\nIf this release does not support all these locales the release may be rejected" +
|
|
303
|
+
"\nSee details at https://developer.android.com/guide/topics/resources/multilingual-support#design for configuring the supported locales",
|
|
304
|
+
"warning"
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
|
|
254
308
|
return {
|
|
255
309
|
android_package: appPackage?.[1] ?? "",
|
|
256
310
|
min_sdk: parseInt(minSdk?.[1] ?? "0", 10),
|
|
257
311
|
version_code: parseInt(versionCode?.[1] ?? "0", 10),
|
|
258
312
|
version: versionName?.[1] ?? "0",
|
|
259
|
-
permissions:
|
|
313
|
+
permissions: permissions.flatMap(permission => permission[1]),
|
|
260
314
|
locales: localeArray,
|
|
261
315
|
};
|
|
262
316
|
};
|
|
@@ -272,7 +326,7 @@ export const saveToConfig = async ({
|
|
|
272
326
|
app,
|
|
273
327
|
release,
|
|
274
328
|
}: SaveToConfigArgs) => {
|
|
275
|
-
const currentConfig = await
|
|
329
|
+
const currentConfig = await getConfigWithChecks();
|
|
276
330
|
|
|
277
331
|
delete currentConfig.publisher.icon;
|
|
278
332
|
delete currentConfig.app.icon;
|
package/src/config/schema.json
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"type": "object",
|
|
3
|
-
"properties": {
|
|
4
|
-
"publisher": {
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"name": {
|
|
8
|
-
"type": "string"
|
|
9
|
-
},
|
|
10
|
-
"address": {
|
|
11
|
-
"type": "string"
|
|
12
|
-
},
|
|
13
|
-
"website": {
|
|
14
|
-
"type": "string"
|
|
15
|
-
},
|
|
16
|
-
"email": {
|
|
17
|
-
"type": "string"
|
|
18
|
-
},
|
|
19
|
-
"media": {
|
|
20
|
-
"type": "array",
|
|
21
|
-
"items": [
|
|
22
|
-
{
|
|
23
|
-
"type": "object",
|
|
24
|
-
"properties": {
|
|
25
|
-
"purpose": {
|
|
26
|
-
"type": "string"
|
|
27
|
-
},
|
|
28
|
-
"uri": {
|
|
29
|
-
"type": "string"
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"required": ["purpose", "uri"]
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
"required": ["name", "website", "email", "media"]
|
|
38
|
-
},
|
|
39
|
-
"app": {
|
|
40
|
-
"type": "object",
|
|
41
|
-
"properties": {
|
|
42
|
-
"name": {
|
|
43
|
-
"type": "string"
|
|
44
|
-
},
|
|
45
|
-
"address": {
|
|
46
|
-
"type": "string"
|
|
47
|
-
},
|
|
48
|
-
"android_package": {
|
|
49
|
-
"type": "string"
|
|
50
|
-
},
|
|
51
|
-
"urls": {
|
|
52
|
-
"type": "object",
|
|
53
|
-
"properties": {
|
|
54
|
-
"license_url": {
|
|
55
|
-
"type": "string"
|
|
56
|
-
},
|
|
57
|
-
"copyright_url": {
|
|
58
|
-
"type": "string"
|
|
59
|
-
},
|
|
60
|
-
"privacy_policy_url": {
|
|
61
|
-
"type": "string"
|
|
62
|
-
},
|
|
63
|
-
"website": {
|
|
64
|
-
"type": "string"
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
"required": [
|
|
68
|
-
"license_url",
|
|
69
|
-
"copyright_url",
|
|
70
|
-
"privacy_policy_url",
|
|
71
|
-
"website"
|
|
72
|
-
]
|
|
73
|
-
},
|
|
74
|
-
"media": {
|
|
75
|
-
"type": "array",
|
|
76
|
-
"items": [
|
|
77
|
-
{
|
|
78
|
-
"type": "object",
|
|
79
|
-
"properties": {
|
|
80
|
-
"purpose": {
|
|
81
|
-
"type": "string"
|
|
82
|
-
},
|
|
83
|
-
"uri": {
|
|
84
|
-
"type": "string"
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
"required": ["purpose", "uri"]
|
|
88
|
-
}
|
|
89
|
-
]
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
"required": ["name", "android_package", "urls", "media"]
|
|
93
|
-
},
|
|
94
|
-
"release": {
|
|
95
|
-
"type": "object",
|
|
96
|
-
"properties": {
|
|
97
|
-
"address": {
|
|
98
|
-
"type": "string"
|
|
99
|
-
},
|
|
100
|
-
"media": {
|
|
101
|
-
"type": "array",
|
|
102
|
-
"items": [
|
|
103
|
-
{
|
|
104
|
-
"type": "object",
|
|
105
|
-
"properties": {
|
|
106
|
-
"purpose": {
|
|
107
|
-
"type": "string"
|
|
108
|
-
},
|
|
109
|
-
"uri": {
|
|
110
|
-
"type": "string"
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
"required": ["purpose", "uri"]
|
|
114
|
-
}
|
|
115
|
-
]
|
|
116
|
-
},
|
|
117
|
-
"files": {
|
|
118
|
-
"type": "array",
|
|
119
|
-
"minItems": 1,
|
|
120
|
-
"contains": {
|
|
121
|
-
"type": "object",
|
|
122
|
-
"properties": {
|
|
123
|
-
"purpose": {
|
|
124
|
-
"type": "string",
|
|
125
|
-
"const": "install"
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
"items": [
|
|
130
|
-
{
|
|
131
|
-
"type": "object",
|
|
132
|
-
"properties": {
|
|
133
|
-
"purpose": {
|
|
134
|
-
"type": "string"
|
|
135
|
-
},
|
|
136
|
-
"uri": {
|
|
137
|
-
"type": "string"
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
"required": ["purpose", "uri"]
|
|
141
|
-
}
|
|
142
|
-
]
|
|
143
|
-
},
|
|
144
|
-
"catalog": {
|
|
145
|
-
"type": "object",
|
|
146
|
-
"patternProperties": {
|
|
147
|
-
"^[a-zA-Z]{2,8}(-[a-zA-Z0-9]{2,8})*$": {
|
|
148
|
-
"type": "object",
|
|
149
|
-
"properties": {
|
|
150
|
-
"name": {
|
|
151
|
-
"type": "string"
|
|
152
|
-
},
|
|
153
|
-
"long_description": {
|
|
154
|
-
"type": "string"
|
|
155
|
-
},
|
|
156
|
-
"new_in_version": {
|
|
157
|
-
"type": "string"
|
|
158
|
-
},
|
|
159
|
-
"saga_features": {
|
|
160
|
-
"type": "string"
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
"required": [
|
|
164
|
-
"name",
|
|
165
|
-
"long_description",
|
|
166
|
-
"new_in_version",
|
|
167
|
-
"saga_features"
|
|
168
|
-
]
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
"additionalProperties": false
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
"required": ["media", "files", "catalog"]
|
|
175
|
-
},
|
|
176
|
-
"solana_mobile_dapp_publisher_portal": {
|
|
177
|
-
"type": "object",
|
|
178
|
-
"properties": {
|
|
179
|
-
"google_store_package": {
|
|
180
|
-
"type": "string"
|
|
181
|
-
},
|
|
182
|
-
"testing_instructions": {
|
|
183
|
-
"type": "string"
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
"required": ["testing_instructions"]
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
"required": [
|
|
190
|
-
"publisher",
|
|
191
|
-
"app",
|
|
192
|
-
"release",
|
|
193
|
-
"solana_mobile_dapp_publisher_portal"
|
|
194
|
-
]
|
|
195
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"publisher":{"name":"<<YOUR_PUBLISHER_NAME>>","address":"","website":"<<URL_OF_PUBLISHER_WEBSITE>>","email":"<<EMAIL_ADDRESS_TO_CONTACT_PUBLISHER>>","media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_PUBLISHER_ICON>>"}]},"app":{"name":"<<APP_NAME>>","address":"","android_package":"<<ANDROID_PACKAGE_NAME>>","urls":{"license_url":"<<URL_OF_APP_LICENSE_OR_TERMS_OF_SERVICE>>","copyright_url":"<<URL_OF_COPYRIGHT_DETAILS_FOR_APP>>","privacy_policy_url":"<<URL_OF_APP_PRIVACY_POLICY>>","website":"<<URL_OF_APP_WEBSITE>>"},"media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_APP_ICON>>"}]},"release":{"address":"","media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_RELEASE_ICON>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT>>"}],"files":[{"purpose":"install","uri":"<<RELATIVE_PATH_TO_APK>>"}],"catalog":{"en-US":{"name":"<<APP_NAME>>\n","long_description":"<<LONG_APP_DESCRIPTION>>\n","new_in_version":"<<WHATS_NEW_IN_THIS_VERSION>>\n","saga_features":"<<ANY_FEATURES_ONLY_AVAILBLE_WHEN_RUNNING_ON_SAGA>>\n"}}},"solana_mobile_dapp_publisher_portal":{"google_store_package":"<<ANDROID_PACKAGE_NAME_OF_GOOGLE_PLAY_STORE_VERSION_IF_DIFFERENT>>","testing_instructions":"<<TESTING_INSTRUCTIONS>>\n"}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type":"object","properties":{"publisher":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"website":{"type":"string"},"email":{"type":"string"},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}}}},"app":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"android_package":{"type":"string"},"urls":{"type":"object","properties":{"license_url":{"type":"string"},"copyright_url":{"type":"string"},"privacy_policy_url":{"type":"string"},"website":{"type":"string"}}},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}}}},"release":{"type":"object","properties":{"address":{"type":"string"},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}},"required":["purpose","uri"]}},"files":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}},"catalog":{"type":"object","properties":{"en-US":{"type":"object","properties":{"name":{"type":"string"},"long_description":{"type":"string"},"new_in_version":{"type":"string"},"saga_features":{"type":"string"}}}}}}},"solana_mobile_dapp_publisher_portal":{"type":"object","properties":{"google_store_package":{"type":"string"},"testing_instructions":{"type":"string"}}}}}
|