@ldgerrits/rogen 1.4.4 → 2.0.0-beta.2
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/LICENSE.md +6 -6
- package/README.md +109 -33
- package/dist/bundle.cjs +30204 -3895
- package/package.json +103 -66
- package/dist/build.js +0 -256
- package/dist/cli.js +0 -115
- package/dist/config.js +0 -349
- package/dist/constants.js +0 -100
- package/dist/execute.js +0 -128
- package/dist/index.js +0 -115
- package/dist/logger.js +0 -104
- package/dist/route.js +0 -345
- package/dist/tree.js +0 -223
- package/dist/types.js +0 -1
package/dist/logger.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
export var LogLevel;
|
|
2
|
-
(function (LogLevel) {
|
|
3
|
-
LogLevel[LogLevel["Off"] = 0] = "Off";
|
|
4
|
-
LogLevel[LogLevel["Error"] = 1] = "Error";
|
|
5
|
-
LogLevel[LogLevel["Warn"] = 2] = "Warn";
|
|
6
|
-
LogLevel[LogLevel["Success"] = 3] = "Success";
|
|
7
|
-
LogLevel[LogLevel["Info"] = 4] = "Info";
|
|
8
|
-
LogLevel[LogLevel["Debug"] = 5] = "Debug";
|
|
9
|
-
LogLevel[LogLevel["Trace"] = 6] = "Trace";
|
|
10
|
-
})(LogLevel || (LogLevel = {}));
|
|
11
|
-
export class AbstractLogger {
|
|
12
|
-
level = LogLevel.Info;
|
|
13
|
-
setLevel(level) {
|
|
14
|
-
this.level = level;
|
|
15
|
-
}
|
|
16
|
-
getLevel() {
|
|
17
|
-
return this.level;
|
|
18
|
-
}
|
|
19
|
-
canLog(level) {
|
|
20
|
-
return this.level !== LogLevel.Off && this.level >= level;
|
|
21
|
-
}
|
|
22
|
-
format(message, args) {
|
|
23
|
-
let result = message instanceof Error
|
|
24
|
-
? message.stack || message.message
|
|
25
|
-
: message;
|
|
26
|
-
for (const arg of args) {
|
|
27
|
-
if (arg instanceof Error) {
|
|
28
|
-
result += " " + (arg.stack || arg.message);
|
|
29
|
-
}
|
|
30
|
-
else if (typeof arg === "object") {
|
|
31
|
-
try {
|
|
32
|
-
result += " " + JSON.stringify(arg);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
result += " [Unserializable Object]";
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
result += " " + arg;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export function getTimeStamp(wrapInBrackets = true) {
|
|
46
|
-
const now = new Date();
|
|
47
|
-
const h = String(now.getHours()).padStart(2, "0");
|
|
48
|
-
const m = String(now.getMinutes()).padStart(2, "0");
|
|
49
|
-
const s = String(now.getSeconds()).padStart(2, "0");
|
|
50
|
-
const timeStamp = `${h}:${m}:${s}`;
|
|
51
|
-
return wrapInBrackets ? `[${timeStamp}]` : timeStamp;
|
|
52
|
-
}
|
|
53
|
-
export class ConsoleLogger extends AbstractLogger {
|
|
54
|
-
colors = {
|
|
55
|
-
reset: "\x1b[0m",
|
|
56
|
-
red: "\x1b[31m",
|
|
57
|
-
green: "\x1b[32m",
|
|
58
|
-
yellow: "\x1b[33m",
|
|
59
|
-
gray: "\x1b[90m",
|
|
60
|
-
cyan: "\x1b[36m",
|
|
61
|
-
};
|
|
62
|
-
error(message, ...args) {
|
|
63
|
-
if (this.canLog(LogLevel.Error)) {
|
|
64
|
-
console.error(`${this.colors.red}error:${this.colors.reset} ${this.format(message, args)}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
warn(message, ...args) {
|
|
68
|
-
if (this.canLog(LogLevel.Warn)) {
|
|
69
|
-
console.warn(`${this.colors.yellow}warning:${this.colors.reset} ${this.format(message, args)}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
success(message, ...args) {
|
|
73
|
-
if (this.canLog(LogLevel.Info)) {
|
|
74
|
-
console.info(`${getTimeStamp()} ${this.colors.green}success:${this.colors.reset} ${this.format(message, args)}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
info(message, ...args) {
|
|
78
|
-
if (this.canLog(LogLevel.Info)) {
|
|
79
|
-
console.info(this.format(message, args));
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
debug(message, ...args) {
|
|
83
|
-
if (this.canLog(LogLevel.Debug)) {
|
|
84
|
-
console.debug(`${this.colors.gray}[debug] ${this.format(message, args)}${this.colors.reset}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
trace(message, ...args) {
|
|
88
|
-
if (this.canLog(LogLevel.Trace)) {
|
|
89
|
-
console.debug(`${this.colors.cyan}[trace] ${this.format(message, args)}${this.colors.reset}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
export class NullLogger {
|
|
94
|
-
setLevel(_level) { }
|
|
95
|
-
getLevel() {
|
|
96
|
-
return LogLevel.Off;
|
|
97
|
-
}
|
|
98
|
-
error(_message, ..._args) { }
|
|
99
|
-
warn(_message, ..._args) { }
|
|
100
|
-
success(_message, ..._args) { }
|
|
101
|
-
info(_message, ..._args) { }
|
|
102
|
-
debug(_message, ..._args) { }
|
|
103
|
-
trace(_message, ..._args) { }
|
|
104
|
-
}
|
package/dist/route.js
DELETED
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import { serviceAliases, serverContainers, clientContainers, } from "./constants.js";
|
|
3
|
-
import { toPosix } from "./tree.js";
|
|
4
|
-
function resolveFolderRouting(parts, context) {
|
|
5
|
-
const { routingMaps, directoryMarkers, activeTags } = context;
|
|
6
|
-
const { lowerCaseMap } = routingMaps;
|
|
7
|
-
const virtualParts = [];
|
|
8
|
-
let targetService = "ReplicatedStorage";
|
|
9
|
-
let lastRouteKeyword = null;
|
|
10
|
-
let tagKeyword = null;
|
|
11
|
-
const flags = {
|
|
12
|
-
structure: false,
|
|
13
|
-
verbatim: false,
|
|
14
|
-
unwrap: false,
|
|
15
|
-
};
|
|
16
|
-
// Marker routing
|
|
17
|
-
const rootMarkers = directoryMarkers[""];
|
|
18
|
-
if (rootMarkers) {
|
|
19
|
-
if (rootMarkers.includes("structure")) {
|
|
20
|
-
flags.structure = true;
|
|
21
|
-
}
|
|
22
|
-
if (rootMarkers.includes("verbatim")) {
|
|
23
|
-
flags.verbatim = true;
|
|
24
|
-
}
|
|
25
|
-
if (rootMarkers.includes("unwrap")) {
|
|
26
|
-
flags.unwrap = true;
|
|
27
|
-
}
|
|
28
|
-
if (!flags.structure) {
|
|
29
|
-
const routingMarker = rootMarkers.find((m) => lowerCaseMap[m]);
|
|
30
|
-
if (routingMarker) {
|
|
31
|
-
targetService = lowerCaseMap[routingMarker];
|
|
32
|
-
lastRouteKeyword = routingMarker;
|
|
33
|
-
if (serviceAliases.has(routingMarker))
|
|
34
|
-
tagKeyword = routingMarker;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Folder path routing
|
|
39
|
-
let currentPath = "";
|
|
40
|
-
for (const part of parts) {
|
|
41
|
-
currentPath = currentPath ? `${currentPath}/${part}` : part;
|
|
42
|
-
let lowerPart = part.toLowerCase();
|
|
43
|
-
let isInvisible = false;
|
|
44
|
-
if (lowerPart.startsWith("(") && lowerPart.endsWith(")")) {
|
|
45
|
-
isInvisible = true;
|
|
46
|
-
lowerPart = lowerPart.slice(1, -1);
|
|
47
|
-
}
|
|
48
|
-
const markers = directoryMarkers
|
|
49
|
-
? directoryMarkers[currentPath]
|
|
50
|
-
: undefined;
|
|
51
|
-
if (markers) {
|
|
52
|
-
if (markers.includes("structure")) {
|
|
53
|
-
flags.structure = true;
|
|
54
|
-
}
|
|
55
|
-
if (markers.includes("verbatim")) {
|
|
56
|
-
flags.verbatim = true;
|
|
57
|
-
}
|
|
58
|
-
if (markers.includes("unwrap")) {
|
|
59
|
-
flags.unwrap = true;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (flags.structure) {
|
|
63
|
-
if (!activeTags.has(lowerPart)) {
|
|
64
|
-
virtualParts.push(part);
|
|
65
|
-
}
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const matchedService = lowerCaseMap[lowerPart];
|
|
69
|
-
if (markers) {
|
|
70
|
-
const routingMarker = markers.find((m) => lowerCaseMap[m]);
|
|
71
|
-
if (routingMarker) {
|
|
72
|
-
targetService = lowerCaseMap[routingMarker];
|
|
73
|
-
lastRouteKeyword = routingMarker;
|
|
74
|
-
if (serviceAliases.has(routingMarker))
|
|
75
|
-
tagKeyword = routingMarker;
|
|
76
|
-
if (!matchedService &&
|
|
77
|
-
!activeTags.has(lowerPart) &&
|
|
78
|
-
!isInvisible) {
|
|
79
|
-
virtualParts.push(part);
|
|
80
|
-
}
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (matchedService) {
|
|
85
|
-
targetService = matchedService;
|
|
86
|
-
lastRouteKeyword = lowerPart;
|
|
87
|
-
if (serviceAliases.has(lowerPart)) {
|
|
88
|
-
tagKeyword = lowerPart;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
if (!activeTags.has(lowerPart) && !isInvisible) {
|
|
93
|
-
virtualParts.push(part);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
targetService,
|
|
99
|
-
virtualParts,
|
|
100
|
-
lastRouteKeyword,
|
|
101
|
-
tagKeyword,
|
|
102
|
-
flags,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
function resolveAffixes(basename, isInit, routingMaps) {
|
|
106
|
-
const { lowerCaseMap, mergedServices, separatorSuffixRegex, pascalCaseSuffixRegex, separatorPrefixRegex, camelCasePrefixRegex, } = routingMaps;
|
|
107
|
-
let match = basename.match(separatorSuffixRegex);
|
|
108
|
-
if (match && match[0].length < basename.length) {
|
|
109
|
-
const suffix = match[1].toLowerCase();
|
|
110
|
-
return {
|
|
111
|
-
mappedService: lowerCaseMap[suffix],
|
|
112
|
-
matchedLength: match[0].length,
|
|
113
|
-
exactMatch: match[0],
|
|
114
|
-
tagKeyword: !isInit && serviceAliases.has(suffix) ? suffix : undefined,
|
|
115
|
-
isPrefix: false,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
match = basename.match(pascalCaseSuffixRegex);
|
|
119
|
-
if (match && match[0].length < basename.length) {
|
|
120
|
-
const suffix = match[1].toLowerCase();
|
|
121
|
-
return {
|
|
122
|
-
mappedService: mergedServices[match[1]],
|
|
123
|
-
matchedLength: match[0].length,
|
|
124
|
-
exactMatch: match[0],
|
|
125
|
-
tagKeyword: !isInit && serviceAliases.has(suffix) ? suffix : undefined,
|
|
126
|
-
isPrefix: false,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
match = basename.match(separatorPrefixRegex);
|
|
130
|
-
if (match && match[0].length < basename.length) {
|
|
131
|
-
const prefix = match[1].toLowerCase();
|
|
132
|
-
return {
|
|
133
|
-
mappedService: lowerCaseMap[prefix],
|
|
134
|
-
matchedLength: match[0].length,
|
|
135
|
-
exactMatch: match[0],
|
|
136
|
-
tagKeyword: !isInit && serviceAliases.has(prefix) ? prefix : undefined,
|
|
137
|
-
isPrefix: true,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
match = basename.match(camelCasePrefixRegex);
|
|
141
|
-
if (match && match[0].length < basename.length) {
|
|
142
|
-
const prefix = match[1].toLowerCase();
|
|
143
|
-
return {
|
|
144
|
-
mappedService: lowerCaseMap[prefix],
|
|
145
|
-
matchedLength: match[1].length,
|
|
146
|
-
exactMatch: match[0],
|
|
147
|
-
tagKeyword: !isInit && serviceAliases.has(prefix) ? prefix : undefined,
|
|
148
|
-
isPrefix: true,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
function getWrapperFolder(targetService, tagKeyword) {
|
|
154
|
-
if (serverContainers.has(targetService))
|
|
155
|
-
return "server";
|
|
156
|
-
if (clientContainers.has(targetService))
|
|
157
|
-
return "client";
|
|
158
|
-
if (tagKeyword)
|
|
159
|
-
return tagKeyword;
|
|
160
|
-
return "shared";
|
|
161
|
-
}
|
|
162
|
-
export function resolveRoute(relativePath, isInit, context, isSync = false) {
|
|
163
|
-
const { emitLegacyScripts, isTsProject, build, routingMaps, verbatim, knownTags, activeTags, tagRegexes, directoryMarkers, } = context;
|
|
164
|
-
const parts = relativePath ? relativePath.split(/[\\/]/) : [];
|
|
165
|
-
let filename;
|
|
166
|
-
let rawBasename;
|
|
167
|
-
if (isSync) {
|
|
168
|
-
filename = parts.length > 0 ? parts[parts.length - 1] : "";
|
|
169
|
-
rawBasename = filename;
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
filename = parts.length > 0 ? parts.pop() : "";
|
|
173
|
-
rawBasename = filename
|
|
174
|
-
? path.basename(filename, path.extname(filename))
|
|
175
|
-
: "";
|
|
176
|
-
}
|
|
177
|
-
// Detect and strip the hoisting prefix
|
|
178
|
-
let isHoisted = false;
|
|
179
|
-
let cleanBasename = rawBasename;
|
|
180
|
-
if (cleanBasename.startsWith("^")) {
|
|
181
|
-
isHoisted = true;
|
|
182
|
-
cleanBasename = cleanBasename.slice(1);
|
|
183
|
-
}
|
|
184
|
-
let dropped = false;
|
|
185
|
-
// Check folder paths and folder marker files
|
|
186
|
-
let currentRel = "";
|
|
187
|
-
for (const part of parts) {
|
|
188
|
-
currentRel = currentRel ? `${currentRel}/${part}` : part;
|
|
189
|
-
let lowerPart = part.toLowerCase();
|
|
190
|
-
// Strip invisible folder syntax for drop checks
|
|
191
|
-
if (lowerPart.startsWith("(") && lowerPart.endsWith(")")) {
|
|
192
|
-
lowerPart = lowerPart.slice(1, -1);
|
|
193
|
-
}
|
|
194
|
-
// Drop if folder name is an inactive env
|
|
195
|
-
if (knownTags.has(lowerPart) && !activeTags.has(lowerPart)) {
|
|
196
|
-
dropped = true;
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
// Drop if folder contains an inactive env marker file
|
|
200
|
-
const markers = directoryMarkers?.[currentRel];
|
|
201
|
-
if (markers) {
|
|
202
|
-
for (const m of markers) {
|
|
203
|
-
if (knownTags.has(m) && !activeTags.has(m)) {
|
|
204
|
-
dropped = true;
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (dropped)
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
// Check root directory markers for drops
|
|
213
|
-
const rootMarkers = directoryMarkers?.[""];
|
|
214
|
-
if (!dropped && rootMarkers) {
|
|
215
|
-
for (const m of rootMarkers) {
|
|
216
|
-
if (knownTags.has(m) && !activeTags.has(m)) {
|
|
217
|
-
dropped = true;
|
|
218
|
-
break;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
// Check file affixes
|
|
223
|
-
if (!dropped && !isSync && cleanBasename) {
|
|
224
|
-
const delimiterSplit = cleanBasename.split(/[.\-_+]/);
|
|
225
|
-
for (const part of delimiterSplit) {
|
|
226
|
-
const lowerPart = part.toLowerCase();
|
|
227
|
-
if (knownTags.has(lowerPart) && !activeTags.has(lowerPart)) {
|
|
228
|
-
dropped = true;
|
|
229
|
-
break;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
// Stop processing and flag for removal
|
|
234
|
-
if (dropped) {
|
|
235
|
-
return {
|
|
236
|
-
targetService: "",
|
|
237
|
-
wrapperFolder: "",
|
|
238
|
-
virtualParts: [],
|
|
239
|
-
nodeName: "",
|
|
240
|
-
projectPath: "",
|
|
241
|
-
dropped: true,
|
|
242
|
-
unwrap: false,
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
// Strip active environment affixes
|
|
246
|
-
let basename = cleanBasename;
|
|
247
|
-
if (!isSync) {
|
|
248
|
-
for (const regexSet of tagRegexes) {
|
|
249
|
-
while (regexSet.suffix.test(basename)) {
|
|
250
|
-
basename = basename.replace(regexSet.suffix, "");
|
|
251
|
-
}
|
|
252
|
-
while (regexSet.prefix.test(basename)) {
|
|
253
|
-
basename = basename.replace(regexSet.prefix, "");
|
|
254
|
-
}
|
|
255
|
-
while (regexSet.middle.test(basename)) {
|
|
256
|
-
basename = basename.replace(regexSet.middle, "");
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
// Folder and marker routing
|
|
261
|
-
const { targetService: folderTarget, virtualParts, lastRouteKeyword, tagKeyword: folderFlag, flags, } = resolveFolderRouting(parts, context);
|
|
262
|
-
// Apply hoisting
|
|
263
|
-
if (isHoisted) {
|
|
264
|
-
virtualParts.length = 0;
|
|
265
|
-
}
|
|
266
|
-
// Affix routing
|
|
267
|
-
const affix = flags.structure || isSync
|
|
268
|
-
? null
|
|
269
|
-
: resolveAffixes(basename, isInit, routingMaps);
|
|
270
|
-
// Resolve overrides
|
|
271
|
-
let targetService = affix?.mappedService ?? folderTarget;
|
|
272
|
-
const tagKeyword = affix?.tagKeyword ?? folderFlag;
|
|
273
|
-
// Resolve namespace wrapper folder
|
|
274
|
-
const wrapperFolder = getWrapperFolder(targetService, tagKeyword);
|
|
275
|
-
// Determine if the wrapper folder should be skipped
|
|
276
|
-
const unwrap = context.unwrap || flags.unwrap;
|
|
277
|
-
// Edge case: Scripts with non-legacy RunContext run incorrectly in StarterPlayer container,
|
|
278
|
-
// hence they need to be put in ReplicatedStorage.
|
|
279
|
-
const isStarterPlayerContainer = targetService === "StarterPlayerScripts" ||
|
|
280
|
-
targetService === "StarterCharacterScripts";
|
|
281
|
-
if (emitLegacyScripts === false && isStarterPlayerContainer) {
|
|
282
|
-
targetService = "ReplicatedStorage";
|
|
283
|
-
}
|
|
284
|
-
// Node naming and path formatting
|
|
285
|
-
let nodeName = basename;
|
|
286
|
-
let projectPath;
|
|
287
|
-
if (isSync) {
|
|
288
|
-
projectPath = toPosix(path.join(build, relativePath));
|
|
289
|
-
if (virtualParts.length > 0) {
|
|
290
|
-
nodeName = virtualParts.pop();
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
nodeName = lastRouteKeyword
|
|
294
|
-
? lastRouteKeyword
|
|
295
|
-
: filename || "source";
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
else if (isInit) {
|
|
299
|
-
const folderRelativePath = path.dirname(relativePath);
|
|
300
|
-
projectPath = toPosix(path.join(build, folderRelativePath));
|
|
301
|
-
if (virtualParts.length > 0) {
|
|
302
|
-
nodeName = virtualParts.pop();
|
|
303
|
-
}
|
|
304
|
-
else {
|
|
305
|
-
nodeName = lastRouteKeyword ? lastRouteKeyword : "source";
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
let compiledRelativePath = relativePath;
|
|
310
|
-
if (isTsProject) {
|
|
311
|
-
const compiledFilename = filename.replace(/\.tsx?$/i, ".luau");
|
|
312
|
-
compiledRelativePath = path.join(path.dirname(relativePath), compiledFilename);
|
|
313
|
-
}
|
|
314
|
-
projectPath = toPosix(path.join(build, compiledRelativePath));
|
|
315
|
-
if (affix) {
|
|
316
|
-
const keepFullNames = verbatim || flags.verbatim;
|
|
317
|
-
let shouldStrip = !keepFullNames;
|
|
318
|
-
// Rojo relies on '.server' and '.client' explicitly for script types.
|
|
319
|
-
// Even if verbatim is true, we must strip these exact dot-prefixes.
|
|
320
|
-
if (keepFullNames) {
|
|
321
|
-
const exactMatch = affix.exactMatch.toLowerCase();
|
|
322
|
-
if (exactMatch === ".server" || exactMatch === ".client") {
|
|
323
|
-
shouldStrip = true;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
if (shouldStrip) {
|
|
327
|
-
if (affix.isPrefix) {
|
|
328
|
-
nodeName = basename.slice(affix.matchedLength);
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
nodeName = basename.slice(0, -affix.matchedLength);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
targetService,
|
|
338
|
-
wrapperFolder,
|
|
339
|
-
virtualParts,
|
|
340
|
-
nodeName,
|
|
341
|
-
projectPath,
|
|
342
|
-
dropped: false,
|
|
343
|
-
unwrap,
|
|
344
|
-
};
|
|
345
|
-
}
|
package/dist/tree.js
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { combinedServices, dataExtensions } from "./constants.js";
|
|
4
|
-
function hasPathPrefix(p, dir) {
|
|
5
|
-
return p === dir || p.startsWith(dir + "/");
|
|
6
|
-
}
|
|
7
|
-
export const toPosix = (p) => p.split(path.sep).join("/");
|
|
8
|
-
export function applyCasing(value, casing) {
|
|
9
|
-
if (value.length === 0)
|
|
10
|
-
return value;
|
|
11
|
-
const firstCharacter = casing === "PascalCase"
|
|
12
|
-
? value[0].toUpperCase()
|
|
13
|
-
: value[0].toLowerCase();
|
|
14
|
-
return firstCharacter + value.slice(1);
|
|
15
|
-
}
|
|
16
|
-
export function getPathString(node) {
|
|
17
|
-
const p = node.$path;
|
|
18
|
-
if (typeof p === "string")
|
|
19
|
-
return p;
|
|
20
|
-
if (p && typeof p === "object" && typeof p.optional === "string")
|
|
21
|
-
return p.optional;
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
24
|
-
export function getOrCreateNode(parent, key, className) {
|
|
25
|
-
const isRootService = combinedServices.has(key) ||
|
|
26
|
-
(className && combinedServices.has(className));
|
|
27
|
-
if (!parent[key]) {
|
|
28
|
-
parent[key] =
|
|
29
|
-
className == null
|
|
30
|
-
? {}
|
|
31
|
-
: {
|
|
32
|
-
$className: className,
|
|
33
|
-
...(isRootService
|
|
34
|
-
? {}
|
|
35
|
-
: { $ignoreUnknownInstances: false }),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
else if (className != null) {
|
|
39
|
-
const existing = parent[key];
|
|
40
|
-
if (existing.$ignoreUnknownInstances === undefined &&
|
|
41
|
-
existing.$path === undefined) {
|
|
42
|
-
if (!isRootService) {
|
|
43
|
-
existing.$ignoreUnknownInstances = false;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return parent[key];
|
|
48
|
-
}
|
|
49
|
-
export function pruneObject(node, buildDir, outputDir, removed = [], treePath = "") {
|
|
50
|
-
for (const key in node) {
|
|
51
|
-
const val = node[key];
|
|
52
|
-
if (typeof val !== "object" || val === null)
|
|
53
|
-
continue;
|
|
54
|
-
const childTreePath = treePath ? `${treePath}.${key}` : key;
|
|
55
|
-
const childNode = val;
|
|
56
|
-
const childPath = getPathString(childNode);
|
|
57
|
-
if (childPath) {
|
|
58
|
-
if (hasPathPrefix(childPath, buildDir))
|
|
59
|
-
continue;
|
|
60
|
-
// Optional paths are allowed to be absent so only required (string) template
|
|
61
|
-
// paths are pruned when missing.
|
|
62
|
-
const isOptional = typeof childNode.$path === "object";
|
|
63
|
-
if (!isOptional) {
|
|
64
|
-
const absolutePath = path.resolve(outputDir, childPath);
|
|
65
|
-
if (!fs.existsSync(absolutePath)) {
|
|
66
|
-
delete node[key];
|
|
67
|
-
removed.push({
|
|
68
|
-
treePath: childTreePath,
|
|
69
|
-
rojoPath: childPath,
|
|
70
|
-
});
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
pruneObject(childNode, buildDir, outputDir, removed, childTreePath);
|
|
76
|
-
}
|
|
77
|
-
return node;
|
|
78
|
-
}
|
|
79
|
-
export function sortObject(obj) {
|
|
80
|
-
if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
|
|
81
|
-
return obj;
|
|
82
|
-
}
|
|
83
|
-
const record = obj;
|
|
84
|
-
return Object.keys(record)
|
|
85
|
-
.sort()
|
|
86
|
-
.reduce((acc, key) => {
|
|
87
|
-
acc[key] = sortObject(record[key]);
|
|
88
|
-
return acc;
|
|
89
|
-
}, {});
|
|
90
|
-
}
|
|
91
|
-
export function findMissingPaths(node, buildDir, outputDir, missing = [], treePath = "") {
|
|
92
|
-
for (const key in node) {
|
|
93
|
-
const val = node[key];
|
|
94
|
-
if (typeof val !== "object" || val === null)
|
|
95
|
-
continue;
|
|
96
|
-
const childTreePath = treePath ? `${treePath}.${key}` : key;
|
|
97
|
-
const childNode = val;
|
|
98
|
-
const childPath = getPathString(childNode);
|
|
99
|
-
if (childPath && hasPathPrefix(childPath, buildDir)) {
|
|
100
|
-
const absolutePath = path.resolve(outputDir, childPath);
|
|
101
|
-
if (!fs.existsSync(absolutePath)) {
|
|
102
|
-
missing.push({
|
|
103
|
-
parent: node,
|
|
104
|
-
key,
|
|
105
|
-
treePath: childTreePath,
|
|
106
|
-
path: childPath,
|
|
107
|
-
absolutePath,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
findMissingPaths(childNode, buildDir, outputDir, missing, childTreePath);
|
|
112
|
-
}
|
|
113
|
-
return missing;
|
|
114
|
-
}
|
|
115
|
-
const isScript = (filename) => /\.(tsx?|luau|lua)$/i.test(filename) &&
|
|
116
|
-
!filename.toLowerCase().endsWith(".d.ts");
|
|
117
|
-
const isModel = (filename) => /\.(rbxm|rbxmx)$/i.test(filename);
|
|
118
|
-
export function isData(filename) {
|
|
119
|
-
if (isScript(filename) || isModel(filename))
|
|
120
|
-
return false;
|
|
121
|
-
if (filename.toLowerCase().endsWith(".d.ts"))
|
|
122
|
-
return false;
|
|
123
|
-
if (filename.startsWith("."))
|
|
124
|
-
return false;
|
|
125
|
-
const ext = path.extname(filename).toLowerCase();
|
|
126
|
-
return dataExtensions.has(ext);
|
|
127
|
-
}
|
|
128
|
-
export const isValidSource = (filename) => isScript(filename) || isModel(filename) || isData(filename);
|
|
129
|
-
export const isInitFile = (filename) => isScript(filename) && /^(index|init)([.-][a-z0-9_]+)?\./i.test(filename);
|
|
130
|
-
function getRojoBaseName(filename) {
|
|
131
|
-
if (isScript(filename)) {
|
|
132
|
-
return filename
|
|
133
|
-
.replace(/\.(server|client)\.(luau?|lua|tsx?)$/i, "")
|
|
134
|
-
.replace(/\.(luau?|lua|tsx?)$/i, "");
|
|
135
|
-
}
|
|
136
|
-
if (isModel(filename)) {
|
|
137
|
-
return filename.replace(/\.(rbxmx?)$/i, "");
|
|
138
|
-
}
|
|
139
|
-
if (isData(filename)) {
|
|
140
|
-
return filename.replace(/\.[a-z0-9]+$/i, "");
|
|
141
|
-
}
|
|
142
|
-
return filename;
|
|
143
|
-
}
|
|
144
|
-
export function collapseFolders(node, buildDir, outputDir, isIgnored = () => false) {
|
|
145
|
-
let childCount = 0;
|
|
146
|
-
let canCollapse = node.$path === undefined; // Prevent overwriting a folder with an explicit $path
|
|
147
|
-
let commonDir = null;
|
|
148
|
-
for (const key in node) {
|
|
149
|
-
if (key.startsWith("$"))
|
|
150
|
-
continue;
|
|
151
|
-
const val = node[key];
|
|
152
|
-
if (typeof val !== "object" || val === null)
|
|
153
|
-
continue;
|
|
154
|
-
const childNode = val;
|
|
155
|
-
// Process deepest nested children first
|
|
156
|
-
collapseFolders(childNode, buildDir, outputDir, isIgnored);
|
|
157
|
-
childCount++;
|
|
158
|
-
const childPath = getPathString(childNode);
|
|
159
|
-
if (!childPath) {
|
|
160
|
-
canCollapse = false;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
const childAbsPath = path.resolve(outputDir, childPath);
|
|
164
|
-
const parentDir = path.dirname(childAbsPath);
|
|
165
|
-
// All children should share the same directory
|
|
166
|
-
if (commonDir === null) {
|
|
167
|
-
commonDir = parentDir;
|
|
168
|
-
}
|
|
169
|
-
else if (commonDir !== parentDir) {
|
|
170
|
-
canCollapse = false;
|
|
171
|
-
}
|
|
172
|
-
const fileName = path.basename(childAbsPath);
|
|
173
|
-
if (getRojoBaseName(fileName) !== key) {
|
|
174
|
-
canCollapse = false;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (childCount === 0 || !canCollapse || commonDir === null) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
const absoluteBuildDir = path.resolve(outputDir, buildDir);
|
|
182
|
-
if (!hasPathPrefix(toPosix(commonDir), toPosix(absoluteBuildDir))) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
const relativeCommonDir = toPosix(path.relative(outputDir, commonDir));
|
|
186
|
-
try {
|
|
187
|
-
const diskItems = fs.readdirSync(commonDir);
|
|
188
|
-
// filter out marker files and ignored files so they do not prevent folders from collapsing
|
|
189
|
-
const visibleDiskItems = diskItems.filter((item) => !item.startsWith(".") &&
|
|
190
|
-
!isIgnored(toPosix(path.join(relativeCommonDir, item))));
|
|
191
|
-
if (visibleDiskItems.length !== childCount) {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
catch {
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
// Replace all child files with a single folder $path
|
|
199
|
-
for (const key in node) {
|
|
200
|
-
if (!key.startsWith("$")) {
|
|
201
|
-
delete node[key];
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
node.$path = { optional: relativeCommonDir };
|
|
205
|
-
delete node.$className;
|
|
206
|
-
}
|
|
207
|
-
export function findExposedDataFiles(node, exposed = []) {
|
|
208
|
-
for (const key in node) {
|
|
209
|
-
if (key.startsWith("$"))
|
|
210
|
-
continue;
|
|
211
|
-
const val = node[key];
|
|
212
|
-
if (typeof val !== "object" || val === null)
|
|
213
|
-
continue;
|
|
214
|
-
const childNode = val;
|
|
215
|
-
const childPath = getPathString(childNode);
|
|
216
|
-
// Check if the current node exposes a raw data file path
|
|
217
|
-
if (childPath && isData(childPath)) {
|
|
218
|
-
exposed.push({ parent: node, key, path: childPath });
|
|
219
|
-
}
|
|
220
|
-
findExposedDataFiles(childNode, exposed);
|
|
221
|
-
}
|
|
222
|
-
return exposed;
|
|
223
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|