Skip to content

Commit

Permalink
staxfile updates
Browse files Browse the repository at this point in the history
  • Loading branch information
kla committed Aug 5, 2024
1 parent 90d3673 commit 176644f
Showing 1 changed file with 91 additions and 7 deletions.
98 changes: 91 additions & 7 deletions src/staxfile/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,113 @@
import path from 'path'
import { readFileSync } from 'fs'
import { load } from 'js-yaml'
import path from 'path'
import { exit, fileExists } from '~/utils'

export default class Compiler {
public staxfile: string
private data: any

constructor(staxfile: string) {
this.staxfile = staxfile
}

get baseDir(): string {
return path.dirname(path.resolve(this.staxfile))
}

public compile() {
const data = load(readFileSync(this.staxfile, 'utf-8'))
this.data = load(readFileSync(this.staxfile, 'utf-8'))
const cwd = process.cwd()
const base = path.dirname(path.resolve(this.staxfile))

try {
process.chdir(base)
this.createDockerfile(data.build)
process.chdir(this.baseDir)
this.createDockerfile()
} finally {
process.chdir(cwd)
}
}

private createDockerfile(build: any) {
const base = readFileSync(build.base, 'utf-8')
private createDockerfile() {
const includes = this.loadIncludes()
const base = this.parseBase(this.data.build.base, includes)
console.log(base)
}

private loadIncludes(): Record<string, string> {
if (!this.data.build.includes)
return {}

const dir = path.resolve(path.dirname(this.data.build.base))
const includes: Record<string, string> = {}
this.data.build.includes.forEach(item => this.parseIncludeFile(`${dir}/${item}`, includes))
return includes
}

private parseIncludeFile(file: string, includes: Record<string, string>) {
if (!fileExists(file))
exit(1, `Include file not found: ${file}`)

const contents = readFileSync(file, 'utf-8')
let sectionName: string

this.verifyVariables(file, contents)

if (!contents.includes('# $stax.append_to'))
exit(1, `Must specify at least one "# $stax.append_to" directive in include file: ${file}`)

contents.split("\n").forEach((line) => {
let matches = line.match(/# \$stax\.append_to (.*?)$/)

if (matches && matches[1]) {
sectionName = matches[1]
includes[sectionName] ||= ''
if (includes[sectionName] != '') includes[sectionName] += '\n'
includes[sectionName] += `# ${sectionName}: ${file}`
} else if (sectionName)
includes[sectionName] += `\n${line}`
})
return includes
}

private verifyVariables(file: string, contents: string) {
const matches = contents.match(/#{(.*?)}/g)

if (!matches)
return

matches.forEach((match) => {
const name = match.slice(2, -1)

if (!this.data.build.args[name])
exit(1, `Variable ${name} must be defined for ${file}`)
})
}

private envVarComments(): string {
return Object.entries(this.data.build.args).map(([name, value]) => `# ${name}=${value}\n`).join('')
}

private parseBase(file: string, includes: Record<string, string>) {
let text = this.envVarComments()

if (!fileExists(file))
exit(1, `File not found: ${file}`)

readFileSync(this.data.build.base, 'utf-8').split("\n").forEach((line) => {
const matches = line.trim().match(/# \$stax\.section +(.*?)$/)

if (matches && matches[1] && includes[matches[1]])
text += includes[matches[1]]
else
text += line + "\n"
})
return this.substituteVariables(text)
}

private substituteVariables(dockerfile: string): string {
for (const [name, value] of Object.entries(this.data.build.args)) {
dockerfile = dockerfile.replaceAll(`#{${name}}`, value)
}
return dockerfile
}
}

0 comments on commit 176644f

Please sign in to comment.