@slim-lang/core 1.2.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.
Files changed (52) hide show
  1. package/README.md +666 -0
  2. package/package.json +55 -0
  3. package/packages/slim/.spm +7 -0
  4. package/packages/slim/converters/main.slim +106 -0
  5. package/packages/slim/helpers/array.slim +25 -0
  6. package/packages/slim/helpers/path.slim +3 -0
  7. package/packages/slim/helpers/request.slim +102 -0
  8. package/packages/slim/helpers/string.slim +27 -0
  9. package/packages/slim/main.slim +42 -0
  10. package/packages/slim/parse/main.slim +25 -0
  11. package/packages/slim/server/main.slim +423 -0
  12. package/packages/slim/time/main.slim +66 -0
  13. package/packages/slim/types/common.slim +6 -0
  14. package/packages/slim/types/formats.slim +23 -0
  15. package/packages/slim/types/hash.slim +6 -0
  16. package/packages/slim/types/mails.slim +3 -0
  17. package/packages/slim/types/numerical.slim +9 -0
  18. package/packages/slim/types/time.slim +3 -0
  19. package/run-dev-slim.js +133 -0
  20. package/run-slim.js +20 -0
  21. package/src/bin/api/github_auth.js +89 -0
  22. package/src/bin/api/github_get.js +139 -0
  23. package/src/bin/api/github_req.js +455 -0
  24. package/src/bin/api/lock.js +37 -0
  25. package/src/bin/api/spm.js +103 -0
  26. package/src/bin/api/storage.js +30 -0
  27. package/src/bin/cli.js +404 -0
  28. package/src/bin/config.default.json +5 -0
  29. package/src/bin/helpers.js +147 -0
  30. package/src/bin/parsers/spm.js +174 -0
  31. package/src/bin/spm.js +519 -0
  32. package/src/checker.js +926 -0
  33. package/src/compile.js +230 -0
  34. package/src/external/classErrors.js +202 -0
  35. package/src/external/client.js +38 -0
  36. package/src/external/core.js +861 -0
  37. package/src/external/defaults.js +25 -0
  38. package/src/external/helpers.js +541 -0
  39. package/src/external/slim-globals.d.ts +65 -0
  40. package/src/external/types.js +38 -0
  41. package/src/format.js +81 -0
  42. package/src/handlers/errorHandler.js +43 -0
  43. package/src/handlers/parser/components.js +250 -0
  44. package/src/handlers/parserHandler.js +793 -0
  45. package/src/jsdoc.js +273 -0
  46. package/src/lexer.js +174 -0
  47. package/src/modulePaths.js +74 -0
  48. package/src/parser.js +818 -0
  49. package/src/repl.js +32 -0
  50. package/src/sourcemap.js +0 -0
  51. package/src/test-runner.js +62 -0
  52. package/src/transform.js +765 -0
@@ -0,0 +1,103 @@
1
+ const API_URL = "https://codemotion.yurba.one/api/spm"
2
+
3
+ export async function publishPackage({ token, name, version, github, description = "" }) {
4
+ const res = await fetch(`${API_URL}/publish`, {
5
+ method: "POST",
6
+ headers: { "Content-Type": "application/json" },
7
+ body: JSON.stringify({
8
+ github_token: token,
9
+ name,
10
+ description,
11
+ version,
12
+ github,
13
+ }),
14
+ });
15
+
16
+ const data = await res.json();
17
+
18
+ if (!data.success) {
19
+ return {
20
+ success: false,
21
+ content: data.result
22
+ }
23
+ }
24
+
25
+ return {
26
+ success: true,
27
+ content: data.result
28
+ }
29
+ }
30
+
31
+ export async function getPackage({ name }) {
32
+ const res = await fetch(`${API_URL}/install?name=${name}`, {
33
+ method: "GET",
34
+ headers: { "Content-Type": "application/json" }
35
+ });
36
+
37
+ const data = await res.json();
38
+
39
+ if (!data.success) {
40
+ return {
41
+ success: false,
42
+ content: data.result
43
+ }
44
+ }
45
+
46
+ return {
47
+ success: true,
48
+ content: data.result
49
+ }
50
+ }
51
+
52
+ export async function updatePackage({ token, name, description, version, github }) {
53
+ const res = await fetch(`${API_URL}/update`, {
54
+ method: "POST",
55
+ headers: { "Content-Type": "application/json" },
56
+ body: JSON.stringify({
57
+ github_token: token,
58
+ name,
59
+ description,
60
+ version,
61
+ github,
62
+ }),
63
+ });
64
+
65
+ const data = await res.json();
66
+
67
+ if (!data.success) {
68
+ return {
69
+ success: false,
70
+ content: data.result
71
+ }
72
+ }
73
+
74
+ return {
75
+ success: true,
76
+ content: data.result
77
+ }
78
+ }
79
+
80
+ export async function removePackage({ token, name }) {
81
+ const res = await fetch(`${API_URL}/remove`, {
82
+ method: "POST",
83
+ headers: { "Content-Type": "application/json" },
84
+ body: JSON.stringify({
85
+ github_token: token,
86
+ name
87
+ }),
88
+ });
89
+
90
+ const data = await res.json();
91
+
92
+ if (!data.success) {
93
+ return {
94
+ success: false,
95
+ content: data.result
96
+ }
97
+ }
98
+
99
+ return {
100
+ success: true,
101
+ content: data.result
102
+ }
103
+ }
@@ -0,0 +1,30 @@
1
+ import keytar from "keytar";
2
+
3
+ const SERVICE = "slim-package-manager";
4
+ const ACCOUNT = "github";
5
+
6
+ export async function saveGitHubToken(token) {
7
+ if (!token) {
8
+ throw new Error("GitHub token is empty");
9
+ }
10
+
11
+ await keytar.setPassword(
12
+ SERVICE,
13
+ ACCOUNT,
14
+ token
15
+ );
16
+ }
17
+
18
+ export async function getGitHubToken() {
19
+ return await keytar.getPassword(
20
+ SERVICE,
21
+ ACCOUNT
22
+ );
23
+ }
24
+
25
+ export async function deleteGitHubToken() {
26
+ return await keytar.deletePassword(
27
+ SERVICE,
28
+ ACCOUNT
29
+ );
30
+ }
package/src/bin/cli.js ADDED
@@ -0,0 +1,404 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import { execSync } from "child_process";
5
+ import { readFile } from 'node:fs/promises';
6
+ import path from "node:path"
7
+ import fs from "node:fs"
8
+
9
+ import { log, error, parseValue } from "./helpers.js"
10
+ import { runTests } from "../test-runner.js"
11
+ import { formatFile } from "../format.js"
12
+
13
+ import pkg from "../../package.json" with { type: "json" };
14
+ import defaultConfig from "./config.default.json" with { type: "json" };
15
+
16
+ const root = process.cwd()
17
+ const program = new Command();
18
+ const slimConfigPath = path.join(root, "slimconfig.json")
19
+ const packagePath = path.join(root, "package.json")
20
+ const spaceRegex = /\s/gm
21
+
22
+ function slimConfigCheck() {
23
+ packageCheck()
24
+
25
+ if (!fs.existsSync(slimConfigPath)) {
26
+ error(`The configuration file does not exist, or it is not in the root directory. You can create the configuration file:
27
+ ${program.name()} create --config`)
28
+ process.exit(1)
29
+ }
30
+
31
+ return true
32
+ }
33
+ function slimConfigRead() {
34
+ slimConfigCheck()
35
+
36
+ return JSON.parse(fs.readFileSync(slimConfigPath, "utf8"));
37
+ }
38
+ // slimserver.json lives next to the entry file named by slimconfig's "main".
39
+ function serverConfigRead() {
40
+ try {
41
+ const config = JSON.parse(fs.readFileSync(slimConfigPath, "utf8"))
42
+ if (!config.main) return {}
43
+
44
+ const dir = path.dirname(path.resolve(config.main))
45
+ return JSON.parse(fs.readFileSync(path.join(dir, "slimserver.json"), "utf8"))
46
+ } catch {
47
+ return {}
48
+ }
49
+ }
50
+ function packageCheck() {
51
+ if (!fs.existsSync(packagePath)) {
52
+ error(`package.json was not found in the root folder of the directory`)
53
+ process.exit(1)
54
+ }
55
+
56
+ return true
57
+ }
58
+
59
+ program
60
+ .name("slmc")
61
+ .description(`Slim Language CLI (SLMC ${pkg.version})`)
62
+ .version(pkg.version);
63
+
64
+ program
65
+ .command("build")
66
+ .description("Build a Slim project")
67
+ .option("-S, --silent", "Build without log")
68
+ .option("--no-check", "Build without static type checking")
69
+ .action((params) => {
70
+ slimConfigCheck()
71
+
72
+ if(!params.check) process.env.SLIM_NO_CHECK = "1"
73
+
74
+ if(!params.silent) log("Building...")
75
+ execSync("node src/compile.js", { stdio: "inherit" });
76
+ if(!params.silent) log("Ready!")
77
+ });
78
+
79
+ program
80
+ .command("run")
81
+ .description("Build and run a Slim project")
82
+ .option("-S, --silent", "Run without log")
83
+ .option("-D, --dev", "Run with dev features enabled (SLIM_DEV)")
84
+ .option("-R, --release", "Run without runtime type checks")
85
+ .option("--no-check", "Run without static type checking")
86
+ .action((params) => {
87
+ slimConfigCheck()
88
+
89
+ if(params.release) process.env.SLIM_RELEASE = "1"
90
+ if(params.dev) process.env.SLIM_DEV = "1"
91
+ if(!params.check) process.env.SLIM_NO_CHECK = "1"
92
+ if(!params.silent) log(params.dev ? "Building and running (dev)..." : "Building and running...")
93
+ execSync("node src/compile.js && node run-slim.js", { stdio: "inherit" });
94
+ });
95
+
96
+ program
97
+ .command("view")
98
+ .description("View the current file to be compiled")
99
+ .option("-L, --line <line>", "View on line")
100
+ .action((params) => {
101
+ const config = slimConfigRead()
102
+
103
+ if("main" in config) {
104
+ const mainContent = fs.readFileSync(config.main + ".slim", "utf8")
105
+
106
+ if(params["line"]) {
107
+ try {
108
+ let line = parseInt(params.line) - 1
109
+ const lines = mainContent.split("\n")
110
+ const lineContent = lines[line]
111
+
112
+ if(lineContent != undefined) {
113
+ console.log(mainContent.split("\n")[line])
114
+ }
115
+ else {
116
+ error(`Line ${line + 1} does not exist. The file contains between 1 and ${lines.length} line(-s)`)
117
+ }
118
+ }
119
+ catch(e) {
120
+ error(e)
121
+ return
122
+ }
123
+ }
124
+ else {
125
+ console.log(mainContent)
126
+ }
127
+ }
128
+ });
129
+
130
+ program
131
+ .command("server")
132
+ .description("Run a Slim server (prod by default; --dev for watch + live reload)")
133
+ .option("-D, --dev", "Dev mode: watch, rebuild, live reload, request logs")
134
+ .option("-H, --hot", "Dev mode with hot reload")
135
+ .option("-R, --release", "Run without runtime type checks")
136
+ .action((params) => {
137
+ slimConfigCheck()
138
+
139
+ // Dev is on when requested on the CLI or set in slimserver.json ("dev": true).
140
+ const dev = Boolean(params.dev || params.hot || serverConfigRead().dev === true)
141
+
142
+ if(params.release) process.env.SLIM_RELEASE = "1"
143
+
144
+ if(dev) {
145
+ log("Starting Slim dev server (watch + live reload)...")
146
+ execSync(`node run-dev-slim.js${params.hot ? " --hot" : ""}`, { stdio: "inherit" });
147
+ }
148
+ else {
149
+ log("Starting Slim server...")
150
+ execSync("node src/compile.js && node run-slim.js", { stdio: "inherit" });
151
+ }
152
+ });
153
+
154
+ program
155
+ .command("config")
156
+ .description("View current Slim config")
157
+ .option("-K, --keys <keys>", "Show only specific keys")
158
+ .option("-S, --set <key>=<value>", "Set key value")
159
+ .option("-R, --remove <key>", "Remove key")
160
+ .action(async (params) => {
161
+ slimConfigCheck()
162
+
163
+ try {
164
+ let data = await readFile(path.join(root, "slimconfig.json"), 'utf8');
165
+ const res = JSON.parse(data);
166
+
167
+ if(params["keys"]) {
168
+ const args = params["keys"].split(spaceRegex).map(item => item.trim())
169
+
170
+ if(args.length > 0) {
171
+ args.forEach(a => {
172
+ a = a.replaceAll("--", "")
173
+ if(a in res) {
174
+ console.log(res[a])
175
+ }
176
+ })
177
+ }
178
+ else {
179
+ console.log(res)
180
+ }
181
+ }
182
+ else if(params["set"]) {
183
+ const config = JSON.parse(fs.readFileSync(slimConfigPath, "utf8"));
184
+ const args = params["set"].split(spaceRegex).map(item => item.trim());
185
+
186
+ args.forEach(arg => {
187
+ if (!arg.includes("=")) return;
188
+
189
+ const [key, ...valueParts] = arg.split("=");
190
+
191
+ const value = valueParts.join("=").trim();
192
+
193
+ config[key.trim()] = parseValue(value);
194
+ });
195
+
196
+ fs.writeFileSync(
197
+ slimConfigPath,
198
+ JSON.stringify(config, null, 4),
199
+ "utf8"
200
+ );
201
+ }
202
+ else if (params["remove"]) {
203
+ const config = JSON.parse(fs.readFileSync(slimConfigPath, "utf8"));
204
+ const keys = params["remove"]
205
+ .split(spaceRegex)
206
+ .map(item => item.trim())
207
+ .filter(Boolean);
208
+
209
+ keys.forEach(key => {
210
+ delete config[key];
211
+ });
212
+
213
+ fs.writeFileSync(
214
+ slimConfigPath,
215
+ JSON.stringify(config, null, 4),
216
+ "utf8"
217
+ );
218
+ }
219
+ else {
220
+ const config = JSON.parse(fs.readFileSync(slimConfigPath, "utf8"));
221
+ console.log(config)
222
+ }
223
+ } catch (err) {
224
+ console.error(err);
225
+ }
226
+ });
227
+
228
+ program
229
+ .command("create")
230
+ .description("Workspace creating")
231
+ .option("--cfg, --config", "Create config")
232
+ .option("--srv, --server", "Create a slimserver.json next to the entry file")
233
+ .option("--file <name>", "Create file")
234
+ .action((params) => {
235
+ if(params.config) {
236
+ try {
237
+ fs.writeFileSync(slimConfigPath, JSON.stringify(defaultConfig, null, 4), 'utf8');
238
+ log('Slim config create in root dir');
239
+ } catch (err) {
240
+ error('An error occurred while creating config:', err);
241
+ }
242
+ }
243
+ if(params.server) {
244
+ try {
245
+ const config = slimConfigRead()
246
+ const dir = config.main ? path.dirname(path.resolve(config.main)) : root
247
+ const serverConfigPath = path.join(dir, "slimserver.json")
248
+
249
+ if(fs.existsSync(serverConfigPath)) {
250
+ log(`slimserver.json already exists at ${path.relative(root, serverConfigPath)}, leaving it untouched`)
251
+ }
252
+ else {
253
+ const template = {
254
+ port: 3000,
255
+ dev: false,
256
+ statics: [{ from: "/public", to: "./public" }],
257
+ redirects: [{ from: "/github", to: "https://example.com" }]
258
+ }
259
+ fs.writeFileSync(serverConfigPath, JSON.stringify(template, null, 4) + "\n", 'utf8')
260
+ log(`Created ${path.relative(root, serverConfigPath)}`)
261
+ }
262
+ } catch (err) {
263
+ error('An error occurred while creating slimserver.json:', err);
264
+ }
265
+ }
266
+ if(params.file) {
267
+ try {
268
+ fs.writeFileSync(params.file + ".slim", "", 'utf8');
269
+ log(`File ${params.file}.slim created`);
270
+ } catch (err) {
271
+ error('An error occurred while creating file:', err);
272
+ }
273
+ }
274
+ if(!params.config && !params.server && !params.file) {
275
+ log(
276
+ `Please use the following arguments to create files:
277
+ ${program.name()} help create
278
+ `)
279
+ }
280
+ });
281
+
282
+ program
283
+ .command("version")
284
+ .option("--check", "Check actual version")
285
+ .action(async (params) => {
286
+ packageCheck()
287
+
288
+ if(params.check) {
289
+ const githubRepo = pkg.repository.url.split("git+https://github.com/")[1].trim().split(".git")[0]
290
+ const res = await fetch("https://raw.githubusercontent.com/" + githubRepo + "/main/package.json")
291
+ const githubPkg = await res.json()
292
+
293
+ if(githubPkg.version != pkg.version) {
294
+ log(`Your version is not compatible with the latest version of Slim:
295
+ Current: ${githubPkg.version}
296
+ Your's: ${pkg.version}`)
297
+ }
298
+ else {
299
+ log(`You on the latest Slim version`)
300
+ }
301
+ return
302
+ }
303
+ console.log(program.version())
304
+ });
305
+
306
+ program
307
+ .command("log")
308
+ .argument('<string>')
309
+ .action((str) => {
310
+ log(str)
311
+ });
312
+
313
+ program
314
+ .command("check")
315
+ .action(() => {
316
+ if(slimConfigCheck() != false) {
317
+ log("Everything is OK")
318
+ }
319
+ });
320
+
321
+ program
322
+ .command("init")
323
+ .description("Scaffold a new Slim project")
324
+ .action(() => {
325
+ packageCheck()
326
+
327
+ if (!fs.existsSync(slimConfigPath)) {
328
+ fs.writeFileSync(slimConfigPath, JSON.stringify({ main: "index", usePackages: true }, null, 4), "utf8")
329
+ log("Created slimconfig.json")
330
+ } else {
331
+ log("slimconfig.json already exists, leaving it untouched")
332
+ }
333
+
334
+ const entryFile = path.join(root, "index.slim")
335
+ if (!fs.existsSync(entryFile)) {
336
+ fs.writeFileSync(entryFile,
337
+ `struct User {
338
+ name: string
339
+ id: int
340
+ }
341
+
342
+ const user: User = { name: "Slim", id: 1 }
343
+ log(\`Hello, \${user.name}!\`)
344
+ `, "utf8")
345
+ log("Created index.slim")
346
+ } else {
347
+ log("index.slim already exists, leaving it untouched")
348
+ }
349
+
350
+ log("Done. Run your project with: slmc run")
351
+ });
352
+
353
+ program
354
+ .command("repl")
355
+ .description("Start an interactive Slim REPL")
356
+ .action(async () => {
357
+ const { startRepl } = await import("../repl.js")
358
+ startRepl()
359
+ });
360
+
361
+ program
362
+ .command("test")
363
+ .description("Run Slim test files (*.test.slim)")
364
+ .argument("[file]", "Run a specific test file")
365
+ .action((file) => {
366
+ process.exitCode = runTests(file)
367
+ });
368
+
369
+ program
370
+ .command("fmt")
371
+ .description("Format Slim source")
372
+ .argument("[file]", "File to format (defaults to the config main)")
373
+ .action((file) => {
374
+ let target = file
375
+ if (!target) {
376
+ const config = slimConfigRead()
377
+ if (!("main" in config)) {
378
+ error(`No file given and no "main" in slimconfig.json`)
379
+ process.exitCode = 1
380
+ return
381
+ }
382
+ target = config.main
383
+ }
384
+ if (!target.endsWith(".slim")) target += ".slim"
385
+ target = path.resolve(target)
386
+
387
+ if (!fs.existsSync(target)) {
388
+ error(`File not found: ${target}`)
389
+ process.exitCode = 1
390
+ return
391
+ }
392
+
393
+ const changed = formatFile(target)
394
+ log(changed ? `Formatted ${path.relative(root, target)}` : `${path.relative(root, target)} already formatted`)
395
+ });
396
+
397
+
398
+ try {
399
+ program.parse();
400
+ }
401
+ catch (err) {
402
+ error(err?.message ?? err)
403
+ process.exitCode = 1
404
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "main": "path/to/your/files",
3
+ "usePackages": true,
4
+ "uses": "import"
5
+ }
@@ -0,0 +1,147 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { rm, mkdir } from 'node:fs/promises';
4
+ import chalk from "chalk";
5
+
6
+ export const formatError = chalk.red.bold
7
+ export const formatSuccess = chalk.green.bold
8
+ export const formatBgWhite = chalk.bgWhiteBright
9
+ export const formatItalic = chalk.italic
10
+ export const formatBold = chalk.bold
11
+ export const rootPath = process.cwd()
12
+ export const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
13
+
14
+ export function parseValue(value) {
15
+ if(value == "true" || value == "false") {
16
+ return value == "true"
17
+ }
18
+ if(/^-?\d*\.?\d*$/.test(value)) {
19
+ return parseFloat(value)
20
+ }
21
+
22
+ return value
23
+ }
24
+
25
+ export function log(...text) {
26
+ console.log(`[SLIM CLI]`, ...text)
27
+ }
28
+ export function error(...text) {
29
+ console.error(`[SLIM CLI]`, ...text)
30
+ }
31
+
32
+ export function isPackageExists(name) {
33
+ return fs.existsSync(path.join(rootPath, "packages", name))
34
+ }
35
+ export function getPackagePath(name) {
36
+ return path.join(rootPath, "packages", name)
37
+ }
38
+
39
+ export async function deleteDirectory(dirPath) {
40
+ try {
41
+ await rm(dirPath, { recursive: true, force: true });
42
+ return true
43
+ } catch (err) {
44
+ return false
45
+ }
46
+ }
47
+
48
+ export async function loading({ startMsg, callback }) {
49
+ function fail(...args) {
50
+ return {
51
+ success: false,
52
+ msg: args.join(" ")
53
+ }
54
+ }
55
+ function ok(...args) {
56
+ return {
57
+ success: true,
58
+ msg: args.join(" ")
59
+ }
60
+ }
61
+
62
+ const spinChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
63
+ let i = 0;
64
+
65
+ const render = (char, msg) => {
66
+ process.stdout.write(
67
+ `\r\x1b[2K${chalk.green.bold(`[SPM] ${char} ${msg}`)}`
68
+ );
69
+ };
70
+
71
+ const spinnerInterval = setInterval(() => {
72
+ render(spinChars[i++ % spinChars.length], startMsg);
73
+ }, 100);
74
+
75
+ try {
76
+ const result = await callback({ fail, ok });
77
+
78
+ clearInterval(spinnerInterval);
79
+
80
+ process.stdout.write('\r\x1b[2K');
81
+
82
+ if (!result || typeof result.success !== 'boolean') {
83
+ return {
84
+ success: false,
85
+ msg: 'Invalid callback result'
86
+ };
87
+ }
88
+
89
+ const icon = result.success ? '✓' : '✗';
90
+
91
+ process.stdout.write(
92
+ `${chalk.green.bold(`[SPM] ${icon} ${result.msg}`)}\n`
93
+ );
94
+
95
+ return result;
96
+ } catch (error) {
97
+ clearInterval(spinnerInterval);
98
+
99
+ process.stdout.write('\r\x1b[2K');
100
+
101
+ const result = {
102
+ success: false,
103
+ msg: error instanceof Error ? error.message : String(error)
104
+ };
105
+
106
+ process.stdout.write(
107
+ `${chalk.red.bold(`[SPM] ✗ ${result.msg}`)}\n`
108
+ );
109
+
110
+ return result;
111
+ }
112
+ }
113
+
114
+ export async function createFolder(path) {
115
+ try {
116
+ await mkdir(path, { recursive: true });
117
+ return { success: true }
118
+ } catch (err) {
119
+ return {
120
+ success: false,
121
+ content: err.message
122
+ }
123
+ }
124
+ }
125
+
126
+ export function createFile(filePath, content) {
127
+ try {
128
+ const normalized = content
129
+ .replace(/^\s*\n/, "")
130
+ .replace(/\n\s*$/, "")
131
+ .replace(/^[ \t]+/gm, line => {
132
+ return line.replace(/^[ \t]{0,7}/, "");
133
+ });
134
+
135
+ fs.writeFileSync(filePath, normalized);
136
+
137
+ return {
138
+ success: true
139
+ }
140
+ }
141
+ catch (err) {
142
+ return {
143
+ success: false,
144
+ content: err.message
145
+ };
146
+ }
147
+ }