@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.
- package/README.md +666 -0
- package/package.json +55 -0
- package/packages/slim/.spm +7 -0
- package/packages/slim/converters/main.slim +106 -0
- package/packages/slim/helpers/array.slim +25 -0
- package/packages/slim/helpers/path.slim +3 -0
- package/packages/slim/helpers/request.slim +102 -0
- package/packages/slim/helpers/string.slim +27 -0
- package/packages/slim/main.slim +42 -0
- package/packages/slim/parse/main.slim +25 -0
- package/packages/slim/server/main.slim +423 -0
- package/packages/slim/time/main.slim +66 -0
- package/packages/slim/types/common.slim +6 -0
- package/packages/slim/types/formats.slim +23 -0
- package/packages/slim/types/hash.slim +6 -0
- package/packages/slim/types/mails.slim +3 -0
- package/packages/slim/types/numerical.slim +9 -0
- package/packages/slim/types/time.slim +3 -0
- package/run-dev-slim.js +133 -0
- package/run-slim.js +20 -0
- package/src/bin/api/github_auth.js +89 -0
- package/src/bin/api/github_get.js +139 -0
- package/src/bin/api/github_req.js +455 -0
- package/src/bin/api/lock.js +37 -0
- package/src/bin/api/spm.js +103 -0
- package/src/bin/api/storage.js +30 -0
- package/src/bin/cli.js +404 -0
- package/src/bin/config.default.json +5 -0
- package/src/bin/helpers.js +147 -0
- package/src/bin/parsers/spm.js +174 -0
- package/src/bin/spm.js +519 -0
- package/src/checker.js +926 -0
- package/src/compile.js +230 -0
- package/src/external/classErrors.js +202 -0
- package/src/external/client.js +38 -0
- package/src/external/core.js +861 -0
- package/src/external/defaults.js +25 -0
- package/src/external/helpers.js +541 -0
- package/src/external/slim-globals.d.ts +65 -0
- package/src/external/types.js +38 -0
- package/src/format.js +81 -0
- package/src/handlers/errorHandler.js +43 -0
- package/src/handlers/parser/components.js +250 -0
- package/src/handlers/parserHandler.js +793 -0
- package/src/jsdoc.js +273 -0
- package/src/lexer.js +174 -0
- package/src/modulePaths.js +74 -0
- package/src/parser.js +818 -0
- package/src/repl.js +32 -0
- package/src/sourcemap.js +0 -0
- package/src/test-runner.js +62 -0
- package/src/transform.js +765 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import { formatItalic, getPackagePath, isPackageExists } from "../helpers.js"
|
|
3
|
+
import { existsSync } from "node:fs"
|
|
4
|
+
import { readFile } from "node:fs/promises"
|
|
5
|
+
|
|
6
|
+
export function validateGitHub(value) {
|
|
7
|
+
const regex = /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\/[a-zA-Z0-9._-]+$/;
|
|
8
|
+
|
|
9
|
+
if (regex.test(value)) {
|
|
10
|
+
return {
|
|
11
|
+
success: true,
|
|
12
|
+
value
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const url = new URL(value);
|
|
18
|
+
|
|
19
|
+
if (url.hostname === "github.com") {
|
|
20
|
+
const parts = url.pathname.split("/").filter(Boolean);
|
|
21
|
+
|
|
22
|
+
if (parts.length >= 2) {
|
|
23
|
+
const github = `${parts[0]}/${parts[1]}`;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
value: github,
|
|
28
|
+
msg: `Use "${github}" instead of "${value}"`
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} catch {}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
success: false,
|
|
36
|
+
msg: `Invalid GitHub repository. Expected "user/repo".`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function getSPM(pkgName) {
|
|
41
|
+
if (isPackageExists(pkgName)) {
|
|
42
|
+
const pkgPath = getPackagePath(pkgName)
|
|
43
|
+
const dotSpmPath = path.join(pkgPath, ".spm")
|
|
44
|
+
|
|
45
|
+
if (existsSync(dotSpmPath)) {
|
|
46
|
+
try {
|
|
47
|
+
const data = await readFile(dotSpmPath, 'utf8');
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
content: parseSPM(data)
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
content: String(err)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
content: ".spm file doest not exists inside the package"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else return {
|
|
67
|
+
success: false,
|
|
68
|
+
content: "Package does not exists"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function parseSPM(content) {
|
|
73
|
+
const result = {};
|
|
74
|
+
const required = ["name", "version"]
|
|
75
|
+
const allowedRoot = new Set(["name", "version", "description"]);
|
|
76
|
+
|
|
77
|
+
const githubSectionAllowed = new Set(["repo", "organization"]);
|
|
78
|
+
|
|
79
|
+
let currentSection = null;
|
|
80
|
+
|
|
81
|
+
for (const line of content.split(/\r?\n/)) {
|
|
82
|
+
const trimmed = line.trim();
|
|
83
|
+
|
|
84
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (trimmed.startsWith("@")) {
|
|
89
|
+
const section = trimmed.slice(1).trim();
|
|
90
|
+
|
|
91
|
+
if (!section) {
|
|
92
|
+
throw new Error("empty section name");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
currentSection = section.split("/");
|
|
96
|
+
|
|
97
|
+
let target = result;
|
|
98
|
+
|
|
99
|
+
for (const part of currentSection) {
|
|
100
|
+
if (!target[part]) {
|
|
101
|
+
target[part] = {};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
target = target[part];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const match = trimmed.match(/^([a-zA-Z_][\w-]*)\s*=\s*"([^"]*)"$/);
|
|
111
|
+
|
|
112
|
+
if (!match) {
|
|
113
|
+
throw new Error(`invalid line: ${trimmed}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const [, key, value] = match;
|
|
117
|
+
|
|
118
|
+
if (!currentSection) {
|
|
119
|
+
if (!allowedRoot.has(key)) {
|
|
120
|
+
throw new Error(`unknown property "${key}"`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (result[key] !== undefined) {
|
|
124
|
+
throw new Error(`duplicate property "${key}"`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
result[key] = value;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const sectionName = currentSection.join("/");
|
|
132
|
+
|
|
133
|
+
if (sectionName === "github") {
|
|
134
|
+
if (!githubSectionAllowed.has(key)) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`unknown property "${key}" in @${sectionName} section`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (key == "repo") {
|
|
141
|
+
const repoTest = validateGitHub(value)
|
|
142
|
+
if (!repoTest.success) {
|
|
143
|
+
throw new Error(`@${sectionName}/${key}: ${repoTest.msg}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (key === "organization" && value !== "true" && value !== "false") {
|
|
148
|
+
throw new Error(`@${sectionName}/${key} must be "true" or "false"`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let target = result;
|
|
153
|
+
|
|
154
|
+
for (const part of currentSection) {
|
|
155
|
+
target = target[part];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (target[key] !== undefined) {
|
|
159
|
+
throw new Error(`duplicate property "${key}"`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
target[key] = (sectionName === "github" && key === "organization")
|
|
163
|
+
? value === "true"
|
|
164
|
+
: value;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const key of required) {
|
|
168
|
+
if (!result[key]) {
|
|
169
|
+
throw new Error(`missing required property "${key}"`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return result;
|
|
174
|
+
}
|
package/src/bin/spm.js
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { formatError, formatBold, formatItalic, formatSuccess, createFolder, createFile } from "./helpers.js"
|
|
5
|
+
import pkg from "../../package.json" with { type: "json" };
|
|
6
|
+
import { log, isPackageExists, rootPath, deleteDirectory, loading, delay } from "./helpers.js";
|
|
7
|
+
|
|
8
|
+
import fs from "node:fs"
|
|
9
|
+
import path from "node:path"
|
|
10
|
+
import { getSPM } from "./parsers/spm.js";
|
|
11
|
+
import { loginGitHub } from "./api/github_auth.js";
|
|
12
|
+
import { deleteGitHubToken, getGitHubToken, saveGitHubToken } from "./api/storage.js";
|
|
13
|
+
import { downloadGitHubRepo, getGitHubUser } from "./api/github_get.js";
|
|
14
|
+
|
|
15
|
+
import { getPackage, publishPackage, removePackage, updatePackage } from "./api/spm.js"
|
|
16
|
+
import { readLock, setLockEntry, removeLockEntry } from "./api/lock.js"
|
|
17
|
+
import { createGitHubRepo, deleteGitHubRepo, githubHeaders, publishToGitHub, updateGitHubRepo } from "./api/github_req.js";
|
|
18
|
+
|
|
19
|
+
import open from "open";
|
|
20
|
+
|
|
21
|
+
export const spm = new Command();
|
|
22
|
+
|
|
23
|
+
function spmlog(...args) {
|
|
24
|
+
console.log("[SPM]", ...args)
|
|
25
|
+
}
|
|
26
|
+
function errlog(...args) {
|
|
27
|
+
console.log(formatError(...args))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const packagesPath = path.join(rootPath, "packages")
|
|
31
|
+
|
|
32
|
+
function renderObject(obj, indent = 0) {
|
|
33
|
+
let output = "";
|
|
34
|
+
const prefix = " ".repeat(indent);
|
|
35
|
+
|
|
36
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
37
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
38
|
+
output += `\n${formatItalic(prefix)}${formatBold(key)}:`;
|
|
39
|
+
output += renderObject(value, indent + 2);
|
|
40
|
+
} else {
|
|
41
|
+
output += `\n${formatItalic(prefix)}${formatBold(key)}: ${value}`;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return output;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function renderBlock({ name, content }) {
|
|
49
|
+
function generateSepLines(len) {
|
|
50
|
+
let line = `-------------------------------------`
|
|
51
|
+
|
|
52
|
+
if (len) {
|
|
53
|
+
for (let i = 0; i < len; i++) {
|
|
54
|
+
line += "-"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return line
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const nameLen = name.length
|
|
62
|
+
|
|
63
|
+
return `${formatSuccess(name)} ${generateSepLines()}` +
|
|
64
|
+
content +
|
|
65
|
+
`\n${generateSepLines(nameLen + 1)}`
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
spm
|
|
69
|
+
.name("spm")
|
|
70
|
+
.description(`Slim Package Manager (SPM ${pkg.version})`)
|
|
71
|
+
.version(pkg.version);
|
|
72
|
+
|
|
73
|
+
spm
|
|
74
|
+
.command("list")
|
|
75
|
+
.action(() => {
|
|
76
|
+
const targetDir = path.join(rootPath, "packages")
|
|
77
|
+
if (!fs.existsSync(targetDir)) {
|
|
78
|
+
spmlog("No packages installed (the packages/ directory does not exist)")
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const relativePaths = fs.readdirSync(targetDir);
|
|
83
|
+
|
|
84
|
+
if (relativePaths.length === 0) {
|
|
85
|
+
spmlog("No packages installed")
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getPkgPath(pkg) {
|
|
90
|
+
const relative = path.relative(process.cwd(), path.join(targetDir, pkg))
|
|
91
|
+
return relative
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
spmlog(`List of all installed packages:\n${relativePaths.map(item => "- @" + item + ` (${getPkgPath(item)})`).join(",\n")}`)
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
spm
|
|
98
|
+
.command("lock")
|
|
99
|
+
.description("Show resolved package versions from spm.lock.json")
|
|
100
|
+
.action(() => {
|
|
101
|
+
const { packages } = readLock()
|
|
102
|
+
const names = Object.keys(packages)
|
|
103
|
+
|
|
104
|
+
if (names.length === 0) {
|
|
105
|
+
spmlog("No locked packages (spm.lock.json is empty or missing)")
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
spmlog(`Locked packages:\n${names.map(name => `- @${name}:${packages[name].version} (${packages[name].repo})`).join("\n")}`)
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
spm
|
|
113
|
+
.command("get")
|
|
114
|
+
.argument("<name>")
|
|
115
|
+
.action(async (name) => {
|
|
116
|
+
let msg = null;
|
|
117
|
+
|
|
118
|
+
if (isPackageExists(name)) {
|
|
119
|
+
const spmFileContent = await getSPM(name);
|
|
120
|
+
|
|
121
|
+
if (!spmFileContent.success) {
|
|
122
|
+
errlog(spmFileContent.content);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const SPMContent = spmFileContent.content;
|
|
127
|
+
let packageName = "@" + name
|
|
128
|
+
|
|
129
|
+
const infoFromRegistryReq = await getPackage({ name: name })
|
|
130
|
+
|
|
131
|
+
if(infoFromRegistryReq.success) {
|
|
132
|
+
packageName = `${packageName} (${infoFromRegistryReq.content.latest})`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
msg = renderBlock({
|
|
136
|
+
name: packageName,
|
|
137
|
+
content: renderObject(SPMContent)
|
|
138
|
+
})
|
|
139
|
+
} else {
|
|
140
|
+
msg =
|
|
141
|
+
formatError(`@${name} not installed\n`) +
|
|
142
|
+
`Want to install? Try ${formatItalic(`${spm.name()} i ${name}`)}`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
spmlog(msg);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
spm
|
|
149
|
+
.command("rm")
|
|
150
|
+
.argument('<name>')
|
|
151
|
+
.option("--g", "Removes the project from the project registry and GitHub")
|
|
152
|
+
.action(async (name, opt) => {
|
|
153
|
+
await loading({
|
|
154
|
+
startMsg: `Removing @${name}...`,
|
|
155
|
+
callback: async ({ fail, ok }) => {
|
|
156
|
+
const isGlobally = opt.g == undefined ? false : true
|
|
157
|
+
|
|
158
|
+
if (isGlobally) {
|
|
159
|
+
const spmFileContent = await getSPM(name);
|
|
160
|
+
|
|
161
|
+
if (!spmFileContent.success) {
|
|
162
|
+
return fail("SPM Check:", spmFileContent.content);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const SPMContent = spmFileContent.content;
|
|
166
|
+
const githubRepo = SPMContent.github.repo
|
|
167
|
+
|
|
168
|
+
const githubToken = await getGitHubToken()
|
|
169
|
+
|
|
170
|
+
const removePackageRegReq = await removePackage({
|
|
171
|
+
token: githubToken,
|
|
172
|
+
name: name
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
if (!removePackageRegReq.success) {
|
|
176
|
+
return fail("SPM Registry remove:", removePackageRegReq.content)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const removeFromGithubReq = await deleteGitHubRepo(githubToken, githubRepo)
|
|
180
|
+
|
|
181
|
+
if (!removeFromGithubReq.success) {
|
|
182
|
+
return fail(`${githubRepo} failed to remove from Github`)
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return ok(`${githubRepo} removed from Github and registry`)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const res = await deleteDirectory(path.join(rootPath, "packages", name))
|
|
190
|
+
|
|
191
|
+
if (res) {
|
|
192
|
+
removeLockEntry(name)
|
|
193
|
+
return ok(`package @${name} successfully removed locally`)
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return fail(`Failed to remove the @${name} package`)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
spm
|
|
203
|
+
.command("i")
|
|
204
|
+
.argument('<name>')
|
|
205
|
+
.option("--ver <version>", "Download a specific version")
|
|
206
|
+
.action(async (name, opt) => {
|
|
207
|
+
await loading({
|
|
208
|
+
startMsg: `Installing @${name}...`,
|
|
209
|
+
callback: async ({ fail, ok }) => {
|
|
210
|
+
const getPackageReq = await getPackage({ name: name })
|
|
211
|
+
|
|
212
|
+
if (!getPackageReq.success) {
|
|
213
|
+
return fail("SPM Install:", getPackageReq.content)
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
const githubToken = await getGitHubToken()
|
|
217
|
+
const data = getPackageReq.content
|
|
218
|
+
|
|
219
|
+
const repo = data.repo
|
|
220
|
+
const version = opt.ver == undefined ? data.latest : opt.ver
|
|
221
|
+
|
|
222
|
+
console.log(`\nDownloading ${repo}...`)
|
|
223
|
+
|
|
224
|
+
const downloadRepoReq = await downloadGitHubRepo(githubToken, repo, path.join(packagesPath, name), opt.ver)
|
|
225
|
+
|
|
226
|
+
if (!downloadRepoReq.success) {
|
|
227
|
+
return fail(downloadRepoReq.msg)
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
setLockEntry(name, { version, repo })
|
|
231
|
+
return ok(`Package @${name}:${version} installed`)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
spm
|
|
239
|
+
.command("create")
|
|
240
|
+
.argument("<name>")
|
|
241
|
+
|
|
242
|
+
.option("--github", "Create repository on Github")
|
|
243
|
+
.option("--local", "Create minimum package template in packages")
|
|
244
|
+
|
|
245
|
+
.option("--github-repo <repoName>", "Fill in '@github/repo' in the configuration")
|
|
246
|
+
.option("--description <description>", "Fill in 'description' in the configuration")
|
|
247
|
+
.option("--ver <version>", "Fill in 'version' in the configuration")
|
|
248
|
+
|
|
249
|
+
.action(async (name, opt) => {
|
|
250
|
+
const defaultGithubRepo = opt.githubRepo == undefined ? "username/repo" : opt.githubRepo
|
|
251
|
+
const defaultDescription = opt.description == undefined ? "My first Slim package" : opt.description
|
|
252
|
+
const defaultVersion = opt.ver == undefined ? "1.0.0" : opt.ver
|
|
253
|
+
|
|
254
|
+
if (opt.local) {
|
|
255
|
+
const isExists = isPackageExists(name)
|
|
256
|
+
|
|
257
|
+
await loading({
|
|
258
|
+
startMsg: `Creating path for ${name}`,
|
|
259
|
+
callback: async ({ fail, ok }) => {
|
|
260
|
+
const packagePath = path.join(rootPath, "packages", name)
|
|
261
|
+
|
|
262
|
+
if (isExists) return fail("Package is already exists")
|
|
263
|
+
else {
|
|
264
|
+
const createFolderReq = await createFolder(packagePath)
|
|
265
|
+
|
|
266
|
+
if (!createFolderReq.success) {
|
|
267
|
+
return fail(createFolderReq.content)
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
const createSPMReq = createFile(path.join(packagePath, ".spm"), `
|
|
271
|
+
name = "${name}"
|
|
272
|
+
description = "${defaultDescription}"
|
|
273
|
+
version = "${defaultVersion}"
|
|
274
|
+
|
|
275
|
+
@ github
|
|
276
|
+
repo = "${defaultGithubRepo}"
|
|
277
|
+
`.trim())
|
|
278
|
+
|
|
279
|
+
if (!createSPMReq.success) {
|
|
280
|
+
return fail(createSPMReq.content)
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
return ok("Local package created")
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
else if (opt.github || opt.githubRepo) {
|
|
291
|
+
const spmFileContent = await getSPM(name);
|
|
292
|
+
|
|
293
|
+
if (!spmFileContent.success) {
|
|
294
|
+
spmlog(formatError(spmFileContent.content));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const SPMContent = spmFileContent.content;
|
|
299
|
+
const packageName = "@" + name;
|
|
300
|
+
const githubRepo = SPMContent.github.repo
|
|
301
|
+
const organization = SPMContent.github.organization === true
|
|
302
|
+
|
|
303
|
+
await loading({
|
|
304
|
+
startMsg: `Creating repository for ${packageName}`,
|
|
305
|
+
callback: async ({ fail, ok }) => {
|
|
306
|
+
const githubToken = await getGitHubToken();
|
|
307
|
+
|
|
308
|
+
const createRepoReq = await createGitHubRepo(githubToken, githubRepo, organization)
|
|
309
|
+
|
|
310
|
+
if (!createRepoReq.success) {
|
|
311
|
+
return fail(createRepoReq.msg)
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
return ok(createRepoReq.msg)
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
spm
|
|
322
|
+
.command("publish")
|
|
323
|
+
.argument('<name>')
|
|
324
|
+
.action(async (name) => {
|
|
325
|
+
if (isPackageExists(name)) {
|
|
326
|
+
const spmFileContent = await getSPM(name);
|
|
327
|
+
|
|
328
|
+
if (!spmFileContent.success) {
|
|
329
|
+
spmlog(formatError(spmFileContent.content));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const SPMContent = spmFileContent.content;
|
|
334
|
+
const packageName = "@" + name;
|
|
335
|
+
|
|
336
|
+
const githubRepo = SPMContent.github.repo
|
|
337
|
+
const version = SPMContent.version
|
|
338
|
+
const description = SPMContent.description
|
|
339
|
+
const packagePath = path.join("packages", name)
|
|
340
|
+
|
|
341
|
+
if ("github" in SPMContent && "repo" in SPMContent.github) {
|
|
342
|
+
await loading({
|
|
343
|
+
startMsg: `Publishing ${packageName}`,
|
|
344
|
+
callback: async ({ fail, ok }) => {
|
|
345
|
+
const githubToken = await getGitHubToken()
|
|
346
|
+
|
|
347
|
+
const installationsReq = await fetch(
|
|
348
|
+
"https://api.github.com/user/installations",
|
|
349
|
+
{
|
|
350
|
+
headers: githubHeaders(githubToken),
|
|
351
|
+
},
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
const installations = await installationsReq.json()
|
|
355
|
+
|
|
356
|
+
if ("total_count" in installations) {
|
|
357
|
+
if (installations.total_count == 0) {
|
|
358
|
+
await open(
|
|
359
|
+
"https://github.com/apps/slim-package-manager/installations/new",
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
console.log("\n")
|
|
363
|
+
spmlog(formatError(`No application has been installed on the "${githubRepo}" repository\n`))
|
|
364
|
+
spmlog("Open:", formatBold.underline("https://github.com/apps/slim-package-manager/installations/new"))
|
|
365
|
+
spmlog("Press Enter after installation...\n")
|
|
366
|
+
|
|
367
|
+
return fail(`No application has been installed on the "${githubRepo}" repository`)
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const githubPublishReq = await publishToGitHub({
|
|
371
|
+
token: githubToken,
|
|
372
|
+
repo: githubRepo,
|
|
373
|
+
contentPath: packagePath
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
const packageInfoReq = await getPackage({
|
|
377
|
+
name: name
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
if (!githubPublishReq.success) {
|
|
381
|
+
return fail("Github publish:", githubPublishReq.msg)
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
const isPackagesExists = packageInfoReq.success
|
|
385
|
+
|
|
386
|
+
if (isPackagesExists) {
|
|
387
|
+
console.log("\nPackage is already exists... updating")
|
|
388
|
+
|
|
389
|
+
const updatePackageReq = await updatePackage({
|
|
390
|
+
token: githubToken,
|
|
391
|
+
name: name,
|
|
392
|
+
description: description,
|
|
393
|
+
version: version,
|
|
394
|
+
github: githubRepo
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
if (!updatePackageReq.success) {
|
|
398
|
+
return fail("Something went wrong while requesting a package update. Please try again later")
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
console.log("\nUpdating package on Github...")
|
|
402
|
+
|
|
403
|
+
const updateReq = await updateGitHubRepo({
|
|
404
|
+
token: githubToken,
|
|
405
|
+
repo: githubRepo,
|
|
406
|
+
packagePath: packagePath,
|
|
407
|
+
version: updatePackageReq.content.latest
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
if (!updateReq.success) {
|
|
411
|
+
return fail("Failed to push the new version to GitHub")
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
const publishedVer = updateReq.version
|
|
415
|
+
return ok(`@${name} ${publishedVer} published on Github`)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
const publishReq = await publishPackage({
|
|
421
|
+
token: githubToken,
|
|
422
|
+
name: name,
|
|
423
|
+
version: version,
|
|
424
|
+
github: githubRepo,
|
|
425
|
+
description: description
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
if (!publishReq.success) {
|
|
429
|
+
return fail("SPM Registry publishing:", publishReq.content)
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
return ok(`${packageName} published and registred: ${name} v${version}`)
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
return fail("Installations:", installations.message)
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
})
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
spmlog(formatError("No GitHub repository specified"));
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
spmlog(formatError(`No package founded: /packages/${name}`));
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
spm
|
|
453
|
+
.command("login")
|
|
454
|
+
.description("Connect your GitHub account")
|
|
455
|
+
.option("--check", "Check if you logged in")
|
|
456
|
+
.action(async (opt) => {
|
|
457
|
+
if (opt.check) {
|
|
458
|
+
const token = await getGitHubToken()
|
|
459
|
+
|
|
460
|
+
if (token) {
|
|
461
|
+
try {
|
|
462
|
+
const user = await getGitHubUser(token)
|
|
463
|
+
|
|
464
|
+
spmlog(formatSuccess("Github connected"))
|
|
465
|
+
spmlog(`${formatBold("Account")}: ${user.name} (${user.html_url})`)
|
|
466
|
+
}
|
|
467
|
+
catch (e) {
|
|
468
|
+
spmlog(formatError(String(e)))
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
spmlog(formatError(`Github NOT connected. Use ${formatItalic.underline(spm.name() + " login")} to login via Github`))
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
await loading({
|
|
477
|
+
startMsg: `Waiting for GitHub authorization...`,
|
|
478
|
+
callback: async () => {
|
|
479
|
+
try {
|
|
480
|
+
const token = await loginGitHub();
|
|
481
|
+
await saveGitHubToken(token)
|
|
482
|
+
|
|
483
|
+
return {
|
|
484
|
+
success: true,
|
|
485
|
+
msg: "Github account connected"
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
return {
|
|
490
|
+
success: false,
|
|
491
|
+
msg:`${error.message}`
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
})
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
spm
|
|
500
|
+
.command("logout")
|
|
501
|
+
.description("Disconnect GitHub account")
|
|
502
|
+
.action(async () => {
|
|
503
|
+
try {
|
|
504
|
+
await deleteGitHubToken();
|
|
505
|
+
|
|
506
|
+
spmlog(formatSuccess("GitHub account disconnected"));
|
|
507
|
+
} catch (error) {
|
|
508
|
+
spmlog(formatError(`✗ ${error.message}`));
|
|
509
|
+
process.exitCode = 1;
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
spm.parse();
|
|
515
|
+
}
|
|
516
|
+
catch (err) {
|
|
517
|
+
spmlog(formatError(err?.message ?? String(err)))
|
|
518
|
+
process.exitCode = 1
|
|
519
|
+
}
|