1 | 'use strict'
|
2 | Object.defineProperty(exports, '__esModule', { value: true })
|
3 | const tslib_1 = require('tslib')
|
4 | const lex_1 = require('./lex')
|
5 | class Element {
|
6 | constructor({ pre = '\n', post = ' ' } = {}) {
|
7 | this.pre = pre
|
8 | this.post = post
|
9 | }
|
10 | get content() {
|
11 | return `${this.pre}${this._content}${this.post}`
|
12 | }
|
13 | }
|
14 | exports.Element = Element
|
15 | class Prop extends Element {
|
16 | constructor(opts) {
|
17 | super(opts)
|
18 | this.name = opts.name
|
19 | this.value = opts.value
|
20 | }
|
21 | get _content() {
|
22 | return `${this.name} ${this.value}`
|
23 | }
|
24 | }
|
25 | exports.Prop = Prop
|
26 | class MachineBase extends Element {
|
27 | constructor(_a) {
|
28 | var { props = [] } = _a,
|
29 | opts = tslib_1.__rest(_a, ['props'])
|
30 | super(opts)
|
31 | this.props = props
|
32 | }
|
33 | get login() {
|
34 | return this.getProp('login')
|
35 | }
|
36 | get password() {
|
37 | return this.getProp('password')
|
38 | }
|
39 | get account() {
|
40 | return this.getProp('account')
|
41 | }
|
42 | set login(v) {
|
43 | this.setProp('login', v)
|
44 | }
|
45 | set password(v) {
|
46 | this.setProp('password', v)
|
47 | }
|
48 | set account(v) {
|
49 | this.setProp('account', v)
|
50 | }
|
51 | get content() {
|
52 | return `${this.pre}${this._content}${this.props.map(p => p.content).join('')}${this.post}`
|
53 | }
|
54 | getProp(name) {
|
55 | const p = this.props.find(p => p.name === name)
|
56 | return p && p.value
|
57 | }
|
58 | setProp(name, value) {
|
59 | if (!value) {
|
60 | this.props = this.props.filter(p => p.name === name)
|
61 | return
|
62 | }
|
63 | let p = this.props.find(p => p.name === name)
|
64 | if (p) {
|
65 | p.value = value
|
66 | } else {
|
67 | p = new Prop({ name, value })
|
68 | this.props.push(p)
|
69 | }
|
70 | }
|
71 | }
|
72 | exports.MachineBase = MachineBase
|
73 | class Machine extends MachineBase {
|
74 | constructor(_a) {
|
75 | var { host } = _a,
|
76 | opts = tslib_1.__rest(_a, ['host'])
|
77 | super(opts)
|
78 | this.type = 'machine'
|
79 | this.host = host
|
80 | }
|
81 | get _content() {
|
82 | return `machine ${this.host}`
|
83 | }
|
84 | }
|
85 | exports.Machine = Machine
|
86 | class DefaultMachine extends MachineBase {
|
87 | constructor() {
|
88 | super(...arguments)
|
89 | this.type = 'default'
|
90 | }
|
91 | get _content() {
|
92 | return 'default'
|
93 | }
|
94 | }
|
95 | exports.DefaultMachine = DefaultMachine
|
96 | function parse(body) {
|
97 | const file = {
|
98 | machines: {},
|
99 | _tokens: [],
|
100 | }
|
101 | const tokens = lex_1.default(body)
|
102 | const getMachineTokens = () => {
|
103 | let machineTokens = []
|
104 | while (tokens.length && !['machine', 'default', 'macdef'].includes(tokens[0].type)) {
|
105 | machineTokens.push(tokens.shift())
|
106 | }
|
107 | return machineTokens
|
108 | }
|
109 | while (tokens.length) {
|
110 | const cur = tokens.shift()
|
111 | switch (cur.type) {
|
112 | case 'macdef':
|
113 | file._tokens.push(cur, ...getMachineTokens())
|
114 | break
|
115 | case 'default':
|
116 | file.default = machineProxy({ type: 'default', _tokens: getMachineTokens() })
|
117 | file._tokens.push(file.default)
|
118 | break
|
119 | case 'machine':
|
120 | let host = cur.host
|
121 | file.machines[host]._tokens = getMachineTokens()
|
122 | break
|
123 | default:
|
124 | file._tokens.push(cur)
|
125 | }
|
126 | }
|
127 | return file
|
128 | }
|
129 | exports.default = parse
|
130 | function machinesProxy(content) {
|
131 | function addNewMachine(host) {
|
132 | let machine = machineProxy({
|
133 | type: 'machine',
|
134 | host,
|
135 | _tokens: [{ type: 'machine', value: host, content: `machine ${host}` }, { type: 'whitespace', content: '\n' }],
|
136 | })
|
137 | content.push(machine)
|
138 | return machine
|
139 | }
|
140 | return new Proxy(
|
141 | {},
|
142 | {
|
143 | get: (machines, host) => {
|
144 | if (typeof host !== 'string') return machines[host]
|
145 | if (!machines[host]) machines[host] = addNewMachine(host)
|
146 | return machines[host]
|
147 | },
|
148 | set: (machines, host, value) => {
|
149 | if (!machines[host]) machines[host] = addNewMachine(host)
|
150 | machines[host] = machineProxy(value)
|
151 | return true
|
152 | },
|
153 | deleteProperty: (machines, host) => {
|
154 | if (!machines[host]) return false
|
155 | delete machines[host]
|
156 | for (let i = 0; i < content.length; i++) {
|
157 | if (content[i].type === 'machine' && content[i].value === host) {
|
158 | content.splice(i, 1)
|
159 | }
|
160 | }
|
161 | return true
|
162 | },
|
163 | },
|
164 | )
|
165 | }
|
166 | function machineProxy(machine) {
|
167 | const props = () => machine._tokens.filter(t => t.type === 'prop')
|
168 | const loadProps = () =>
|
169 | props().forEach(prop => {
|
170 | machine[prop.name] = prop.value
|
171 | })
|
172 | loadProps()
|
173 | return new Proxy(machine, {
|
174 | set: (machine, name, value) => {
|
175 | machine[name] = value
|
176 | let prop = props().find(p => p.name === name)
|
177 | if (prop) prop.value = value
|
178 | else {
|
179 | let lastPropIdx = findIndex(machine._tokens, t => t.type === 'prop')
|
180 | let whitespace = lastPropIdx === -1 ? { type: 'whitespace', content: '\n ' } : machine._tokens[lastPropIdx - 1]
|
181 | machine._tokens.splice(lastPropIdx, 0, whitespace)
|
182 | machine._tokens.splice(lastPropIdx, 0, { type: 'prop', name, value })
|
183 | }
|
184 | return true
|
185 | },
|
186 | })
|
187 | }
|
188 | function findIndex(arr, fn) {
|
189 | for (let i = 0; i < arr.length; i++) {
|
190 | if (fn(arr[i])) return i
|
191 | }
|
192 | return -1
|
193 | }
|