Begin work on new structure resolvers.
This commit is contained in:
64
package-lock.json
generated
64
package-lock.json
generated
@@ -24,16 +24,25 @@
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@types/fs-extra": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz",
|
||||
"integrity": "sha512-bCtL5v9zdbQW86yexOlXWTEGvLNqWxMFyi7gQA7Gcthbezr2cPSOb8SkESVKA937QD5cIwOFLDFt0MQoXOEr9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.6.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz",
|
||||
"integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==",
|
||||
"version": "12.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.2.tgz",
|
||||
"integrity": "sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.0.tgz",
|
||||
"integrity": "sha512-hY0o+kcz9M6kH32NUeb6VURghqMuCVkiUx+8Btsqhj4Hhov/hVGUx9DmBJeIkzlp1uAQK4wngQBCjqWdUUkFyA==",
|
||||
"version": "13.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.2.tgz",
|
||||
"integrity": "sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/yargs-parser": "*"
|
||||
@@ -174,9 +183,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
@@ -321,9 +330,9 @@
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
|
||||
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
|
||||
"integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
@@ -369,27 +378,27 @@
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
|
||||
"integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
|
||||
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz",
|
||||
"integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
|
||||
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"set-blocking": {
|
||||
@@ -437,9 +446,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.18.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz",
|
||||
"integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==",
|
||||
"version": "5.19.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.19.0.tgz",
|
||||
"integrity": "sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
@@ -504,11 +513,12 @@
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "13.3.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
|
||||
"integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz",
|
||||
"integrity": "sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow==",
|
||||
"requires": {
|
||||
"cliui": "^5.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^3.0.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
|
||||
11
package.json
11
package.json
@@ -26,15 +26,16 @@
|
||||
},
|
||||
"homepage": "https://github.com/dscalzi/Nebula#readme",
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.6.8",
|
||||
"@types/yargs": "^13.0.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"tslint": "^5.18.0",
|
||||
"@types/fs-extra": "^8.0.0",
|
||||
"@types/node": "^12.7.2",
|
||||
"@types/yargs": "^13.0.2",
|
||||
"rimraf": "^3.0.0",
|
||||
"tslint": "^5.19.0",
|
||||
"typescript": "^3.5.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"adm-zip": "^0.4.13",
|
||||
"fs-extra": "^8.1.0",
|
||||
"yargs": "^13.3.0"
|
||||
"yargs": "^14.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
62
src/index.ts
62
src/index.ts
@@ -1,6 +1,8 @@
|
||||
/* tslint:disable:no-shadowed-variable */
|
||||
import { resolve } from 'path'
|
||||
import { writeFile } from 'fs-extra'
|
||||
import { resolve as resolvePath } from 'path'
|
||||
import yargs from 'yargs'
|
||||
import { DistributionStructure } from './model/struct/distribution.struct'
|
||||
|
||||
function rootOption(yargs: yargs.Argv) {
|
||||
return yargs.option('root', {
|
||||
@@ -10,7 +12,29 @@ function rootOption(yargs: yargs.Argv) {
|
||||
global: true
|
||||
})
|
||||
.coerce({
|
||||
root: resolve
|
||||
root: resolvePath
|
||||
})
|
||||
}
|
||||
|
||||
function baseUrlOption(yargs: yargs.Argv) {
|
||||
return yargs.option('baseUrl', {
|
||||
describe: 'Base url of your file host.',
|
||||
type: 'string',
|
||||
demandOption: true,
|
||||
global: true
|
||||
})
|
||||
.coerce({
|
||||
baseUrl: (arg: string) => {
|
||||
// Users must provide protocol in all other instances.
|
||||
if (arg.indexOf('//') === -1) {
|
||||
if (arg.toLowerCase().startsWith('localhost')) {
|
||||
arg = 'http://' + arg
|
||||
} else {
|
||||
throw new TypeError('Please provide a URL protocol (ex. http:// or https://)')
|
||||
}
|
||||
}
|
||||
return (new URL(arg)).toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,9 +56,15 @@ const initRootCommand: yargs.CommandModule = {
|
||||
yargs = rootOption(yargs)
|
||||
return yargs
|
||||
},
|
||||
handler: (argv) => {
|
||||
console.log(`Root set to ${argv.root}`)
|
||||
console.log('Invoked init root.')
|
||||
handler: async (argv) => {
|
||||
console.debug(`Root set to ${argv.root}`)
|
||||
console.debug('Invoked init root.')
|
||||
try {
|
||||
await new DistributionStructure(argv.root as string, '').init()
|
||||
console.log(`Successfully created new root at ${argv.root}`)
|
||||
} catch (error) {
|
||||
console.error(`Failed to init new root at ${argv.root}`, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +110,8 @@ const generateServerCommand: yargs.CommandModule = {
|
||||
})
|
||||
},
|
||||
handler: (argv) => {
|
||||
console.log(`Root set to ${argv.root}`)
|
||||
console.log(`Generating server ${argv.id} for Minecraft ${argv.version}.`,
|
||||
console.debug(`Root set to ${argv.root}`)
|
||||
console.debug(`Generating server ${argv.id} for Minecraft ${argv.version}.`,
|
||||
`\n\t├ Include forge: ${argv.forge}`,
|
||||
`\n\t└ Include liteloader: ${argv.liteloader}`)
|
||||
}
|
||||
@@ -92,12 +122,22 @@ const generateDistroCommand: yargs.CommandModule = {
|
||||
describe: 'Generate a distribution index from the root file structure.',
|
||||
builder: (yargs) => {
|
||||
yargs = rootOption(yargs)
|
||||
yargs = baseUrlOption(yargs)
|
||||
yargs = namePositional(yargs)
|
||||
return yargs
|
||||
},
|
||||
handler: (argv) => {
|
||||
console.log(`Root set to ${argv.root}`)
|
||||
console.log(`Invoked generate distro name ${argv.name}.json.`)
|
||||
handler: async (argv) => {
|
||||
console.debug(`Root set to ${argv.root}`)
|
||||
console.debug(`Base Url set to ${argv.baseUrl}`)
|
||||
console.debug(`Invoked generate distro name ${argv.name}.json.`)
|
||||
try {
|
||||
const distributionStruct = new DistributionStructure(argv.root as string, argv.baseUrl as string)
|
||||
const distro = await distributionStruct.getSpecModel()
|
||||
writeFile(resolvePath(argv.root as string, `${argv.name}.json`), JSON.stringify(distro, null, 2))
|
||||
console.log(distro)
|
||||
} catch (error) {
|
||||
console.error(`Failed to generate distribution with root ${argv.root}.`, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +162,7 @@ const validateCommand: yargs.CommandModule = {
|
||||
return namePositional(yargs)
|
||||
},
|
||||
handler: (argv) => {
|
||||
console.log(`Invoked validate with name ${argv.name}.json`)
|
||||
console.debug(`Invoked validate with name ${argv.name}.json`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +1,58 @@
|
||||
export const Types: {[property: string]: Type} = {
|
||||
export enum Type {
|
||||
|
||||
Library = 'Library',
|
||||
ForgeHosted = 'ForgeHosted',
|
||||
Forge = 'Forge',
|
||||
LiteLoader = 'LiteLoader',
|
||||
ForgeMod = 'ForgeMod',
|
||||
LiteMod = 'LiteMod',
|
||||
File = 'File',
|
||||
VersionManifest = 'VersionManifest'
|
||||
|
||||
}
|
||||
|
||||
export interface TypeMetadata {
|
||||
|
||||
id: string
|
||||
defaultExtension?: string
|
||||
|
||||
}
|
||||
|
||||
export const TypeMetadata: {[property: string]: TypeMetadata} = {
|
||||
|
||||
Library: {
|
||||
id: 'Library',
|
||||
id: Type.Library,
|
||||
defaultExtension: 'jar'
|
||||
},
|
||||
/**
|
||||
* @deprecated Will be replaced by Types.Forge.
|
||||
*/
|
||||
ForgeHosted: {
|
||||
id: 'ForgeHosted',
|
||||
id: Type.ForgeHosted,
|
||||
defaultExtension: 'jar'
|
||||
},
|
||||
Forge: {
|
||||
id: 'Forge',
|
||||
id: Type.Forge,
|
||||
defaultExtension: 'jar'
|
||||
},
|
||||
LiteLoader: {
|
||||
id: 'LiteLoader',
|
||||
id: Type.LiteLoader,
|
||||
defaultExtension: 'jar'
|
||||
},
|
||||
ForgeMod: {
|
||||
id: 'ForgeMod',
|
||||
id: Type.ForgeMod,
|
||||
defaultExtension: 'jar'
|
||||
},
|
||||
LiteMod: {
|
||||
id: 'LiteMod',
|
||||
id: Type.LiteMod,
|
||||
defaultExtension: 'litemod'
|
||||
},
|
||||
File: {
|
||||
id: 'File'
|
||||
id: Type.File
|
||||
},
|
||||
VersionManifest: {
|
||||
id: 'VersionManifest',
|
||||
id: Type.VersionManifest,
|
||||
defaultExtension: 'json'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface Type {
|
||||
|
||||
id: string
|
||||
defaultExtension?: string
|
||||
|
||||
}
|
||||
|
||||
26
src/model/struct/basemodel.struct.ts
Normal file
26
src/model/struct/basemodel.struct.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { mkdirs } from 'fs-extra'
|
||||
import { join, resolve } from 'path'
|
||||
import { ModelStructure } from './model.struct'
|
||||
|
||||
export abstract class BaseModelStructure<T> implements ModelStructure<T[]> {
|
||||
|
||||
protected resolvedModels: T[] | undefined
|
||||
protected containerDirectory: string
|
||||
|
||||
constructor(
|
||||
protected absoluteRoot: string,
|
||||
protected relativeRoot: string,
|
||||
protected structRoot: string,
|
||||
protected baseUrl: string
|
||||
) {
|
||||
this.relativeRoot = join(relativeRoot, structRoot)
|
||||
this.containerDirectory = resolve(absoluteRoot, structRoot)
|
||||
}
|
||||
|
||||
public async init() {
|
||||
mkdirs(this.containerDirectory)
|
||||
}
|
||||
|
||||
public abstract async getSpecModel(): Promise<T[]>
|
||||
|
||||
}
|
||||
@@ -1,25 +1,32 @@
|
||||
import { mkdirs } from 'fs-extra'
|
||||
import { Distribution } from '../spec/distribution'
|
||||
import { ModelStructure } from './model.struct'
|
||||
import { ServerStructure } from './server.struct'
|
||||
|
||||
export class DistributionStructure implements ModelStructure<Distribution> {
|
||||
|
||||
private servers: ServerStructure[] | undefined
|
||||
private serverStruct: ServerStructure
|
||||
|
||||
constructor(
|
||||
private root: string
|
||||
) {}
|
||||
|
||||
public getServers() {
|
||||
return new ServerStructure(this.root).getSpecModel()
|
||||
private absoluteRoot: string,
|
||||
private baseUrl: string
|
||||
) {
|
||||
this.serverStruct = new ServerStructure(this.absoluteRoot, this.baseUrl)
|
||||
}
|
||||
|
||||
public getSpecModel(): Distribution {
|
||||
return {
|
||||
public async init() {
|
||||
await mkdirs(this.absoluteRoot)
|
||||
await this.serverStruct.init()
|
||||
}
|
||||
|
||||
public async getSpecModel() {
|
||||
return new Promise(async (resolve) => {
|
||||
resolve({
|
||||
version: '1.0.0',
|
||||
rss: 'TODO',
|
||||
servers: this.getServers()
|
||||
}
|
||||
rss: '<FILL IN MANUALLY>',
|
||||
servers: await this.serverStruct.getSpecModel()
|
||||
})
|
||||
}) as Promise<Distribution>
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export interface ModelStructure<T> {
|
||||
|
||||
getSpecModel(): T
|
||||
init(): void
|
||||
|
||||
getSpecModel(): Promise<T>
|
||||
|
||||
}
|
||||
|
||||
28
src/model/struct/module/file.struct.ts
Normal file
28
src/model/struct/module/file.struct.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Stats } from 'fs'
|
||||
import { Type } from '../../spec/type'
|
||||
import { ModuleStructure } from './module.struct'
|
||||
|
||||
export class FileStructure extends ModuleStructure {
|
||||
|
||||
constructor(
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
baseUrl: string
|
||||
) {
|
||||
super(absoluteRoot, relativeRoot, 'files', baseUrl, Type.File)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleUrl(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return 'TODO'
|
||||
}
|
||||
protected async getModulePath(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return 'TODO'
|
||||
}
|
||||
|
||||
}
|
||||
28
src/model/struct/module/forgemod.struct.ts
Normal file
28
src/model/struct/module/forgemod.struct.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Stats } from 'fs-extra'
|
||||
import { Type } from '../../spec/type'
|
||||
import { ModuleStructure } from './module.struct'
|
||||
|
||||
export class ForgeModStructure extends ModuleStructure {
|
||||
|
||||
constructor(
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
baseUrl: string
|
||||
) {
|
||||
super(absoluteRoot, relativeRoot, 'forgemods', baseUrl, Type.ForgeMod)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleUrl(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return 'TODO'
|
||||
}
|
||||
protected async getModulePath(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return 'TODO'
|
||||
}
|
||||
|
||||
}
|
||||
29
src/model/struct/module/litemod.struct.ts
Normal file
29
src/model/struct/module/litemod.struct.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Stats } from 'fs-extra'
|
||||
import { join } from 'path'
|
||||
import { Type } from '../../spec/type'
|
||||
import { ModuleStructure } from './module.struct'
|
||||
|
||||
export class LiteModStructure extends ModuleStructure {
|
||||
|
||||
constructor(
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
baseUrl: string
|
||||
) {
|
||||
super(absoluteRoot, relativeRoot, 'litemods', baseUrl, Type.LiteMod)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleUrl(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return 'TODO'
|
||||
}
|
||||
protected async getModulePath(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return 'TODO'
|
||||
}
|
||||
|
||||
}
|
||||
67
src/model/struct/module/module.struct.ts
Normal file
67
src/model/struct/module/module.struct.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { createHash } from 'crypto'
|
||||
import { lstat, pathExists, readdir, readFile, Stats } from 'fs-extra'
|
||||
import { resolve } from 'path'
|
||||
import { Module } from '../../spec/module'
|
||||
import { Type } from '../../spec/type'
|
||||
import { BaseModelStructure } from '../basemodel.struct'
|
||||
|
||||
export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
||||
|
||||
constructor(
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
structRoot: string,
|
||||
baseUrl: string,
|
||||
protected type: Type
|
||||
) {
|
||||
super(absoluteRoot, relativeRoot, structRoot, baseUrl)
|
||||
}
|
||||
|
||||
public async getSpecModel(): Promise<Module[]> {
|
||||
if (this.resolvedModels == null) {
|
||||
this.resolvedModels = await this._doModuleRetrieval()
|
||||
}
|
||||
|
||||
return this.resolvedModels
|
||||
}
|
||||
|
||||
protected async abstract getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string>
|
||||
protected async abstract getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string>
|
||||
protected async abstract getModuleUrl(name: string, path: string, stats: Stats, buf: Buffer): Promise<string>
|
||||
protected async abstract getModulePath(name: string, path: string, stats: Stats, buf: Buffer): Promise<string>
|
||||
|
||||
private async _doModuleRetrieval(): Promise<Module[]> {
|
||||
|
||||
const accumulator: Module[] = []
|
||||
|
||||
if (await pathExists(this.containerDirectory)) {
|
||||
const files = await readdir(this.containerDirectory)
|
||||
for (const file of files) {
|
||||
const filePath = resolve(this.containerDirectory, file)
|
||||
const stats = await lstat(filePath)
|
||||
const buf = await readFile(filePath)
|
||||
if (stats.isFile()) {
|
||||
accumulator.push({
|
||||
id: await this.getModuleId(file, filePath, stats, buf),
|
||||
name: await this.getModuleName(file, filePath, stats, buf),
|
||||
type: this.type,
|
||||
required: {
|
||||
value: false,
|
||||
def: false
|
||||
},
|
||||
artifact: {
|
||||
size: stats.size,
|
||||
MD5: createHash('md5').update(buf).digest('hex'),
|
||||
url: await this.getModuleUrl(file, filePath, stats, buf),
|
||||
path: await this.getModulePath(file, filePath, stats, buf)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +1,100 @@
|
||||
import { resolve } from 'path'
|
||||
import { lstat, readdir } from 'fs-extra'
|
||||
import { join, resolve as resolvePath } from 'path'
|
||||
import { resolve as resolveUrl } from 'url'
|
||||
import { Server } from '../spec/server'
|
||||
import { ModelStructure } from './model.struct'
|
||||
import { BaseModelStructure } from './basemodel.struct'
|
||||
import { FileStructure } from './module/file.struct'
|
||||
import { ForgeModStructure } from './module/forgemod.struct'
|
||||
import { LiteModStructure } from './module/litemod.struct'
|
||||
|
||||
export class ServerStructure implements ModelStructure<Server[]> {
|
||||
export class ServerStructure extends BaseModelStructure<Server> {
|
||||
|
||||
private servers: Server[] | undefined
|
||||
private readonly ID_REGEX = /(.+-(.+)$)/
|
||||
|
||||
constructor(
|
||||
private root: string
|
||||
) {}
|
||||
|
||||
public getSpecModel(): Server[] {
|
||||
if (this.servers == null) {
|
||||
this.servers = this._doSeverRetrieval()
|
||||
}
|
||||
return this.servers
|
||||
absoluteRoot: string,
|
||||
baseUrl: string
|
||||
) {
|
||||
super(absoluteRoot, '', 'servers', baseUrl)
|
||||
}
|
||||
|
||||
private _doSeverRetrieval(): Server[] {
|
||||
const base = resolve(this.root, 'servers')
|
||||
return [] // TODO
|
||||
public async getSpecModel() {
|
||||
if (this.resolvedModels == null) {
|
||||
this.resolvedModels = await this._doSeverRetrieval()
|
||||
}
|
||||
return this.resolvedModels
|
||||
}
|
||||
|
||||
private async _doSeverRetrieval(): Promise<Server[]> {
|
||||
|
||||
const accumulator: Server[] = []
|
||||
const files = await readdir(this.containerDirectory)
|
||||
for (const file of files) {
|
||||
const absoluteServerRoot = resolvePath(this.containerDirectory, file)
|
||||
const relativeServerRoot = join(this.relativeRoot, file)
|
||||
if ((await lstat(absoluteServerRoot)).isDirectory()) {
|
||||
|
||||
const match = this.ID_REGEX.exec(file)
|
||||
if (match == null) {
|
||||
console.warn(`Server directory ${file} does not match the defined standard.`)
|
||||
console.warn(`All server ids must end with -<minecraft version> (ex. -1.12.2)`)
|
||||
continue
|
||||
}
|
||||
|
||||
let iconUrl
|
||||
|
||||
// Resolve server icon
|
||||
const subFiles = await readdir(absoluteServerRoot)
|
||||
for (const subFile of subFiles) {
|
||||
const caseInsensitive = subFile.toLowerCase()
|
||||
if (caseInsensitive.endsWith('.jpg') || caseInsensitive.endsWith('.png')) {
|
||||
iconUrl = resolveUrl(this.baseUrl, join(relativeServerRoot, subFile))
|
||||
}
|
||||
}
|
||||
|
||||
if (!iconUrl) {
|
||||
console.warn(`No icon file found for server ${file}.`)
|
||||
iconUrl = '<FILL IN MANUALLY>'
|
||||
}
|
||||
|
||||
const forgeModStruct = new ForgeModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
||||
const forgeModModules = await forgeModStruct.getSpecModel()
|
||||
|
||||
const liteModStruct = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
||||
const liteModModules = await liteModStruct.getSpecModel()
|
||||
|
||||
const fileStruct = new FileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl)
|
||||
const fileModules = await fileStruct.getSpecModel()
|
||||
|
||||
const modules = [
|
||||
...forgeModModules,
|
||||
...liteModModules,
|
||||
...fileModules
|
||||
]
|
||||
|
||||
accumulator.push({
|
||||
id: match[1],
|
||||
name: '<FILL IN MANUALLY>',
|
||||
description: '<FILL IN MANUALLY>',
|
||||
icon: iconUrl,
|
||||
version: '1.0.0',
|
||||
address: '<FILL IN MANUALLY>',
|
||||
minecraftVersion: match[2],
|
||||
discord: {
|
||||
shortId: '<FILL IN MANUALLY OR REMOVE>',
|
||||
largeImageText: '<FILL IN MANUALLY OR REMOVE>',
|
||||
largeImageKey: '<FILL IN MANUALLY OR REMOVE>'
|
||||
},
|
||||
mainServer: false,
|
||||
autoconnect: false,
|
||||
modules
|
||||
})
|
||||
|
||||
} else {
|
||||
console.warn(`Path ${file} in server directory is not a directory!`)
|
||||
}
|
||||
}
|
||||
return accumulator
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user