@player-cli/cli 0.0.2--canary.6.49

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.
Files changed (56) hide show
  1. package/README.md +82 -0
  2. package/bin/dev +17 -0
  3. package/bin/run +11 -0
  4. package/dist/commands/dependency-versions/check.d.ts +19 -0
  5. package/dist/commands/dependency-versions/check.js +270 -0
  6. package/dist/commands/dsl/compile.d.ts +20 -0
  7. package/dist/commands/dsl/compile.js +173 -0
  8. package/dist/commands/dsl/validate.d.ts +15 -0
  9. package/dist/commands/dsl/validate.js +142 -0
  10. package/dist/commands/json/validate.d.ts +18 -0
  11. package/dist/commands/json/validate.js +91 -0
  12. package/dist/commands/xlr/compile.d.ts +24 -0
  13. package/dist/commands/xlr/compile.js +153 -0
  14. package/dist/commands/xlr/convert.d.ts +20 -0
  15. package/dist/commands/xlr/convert.js +77 -0
  16. package/dist/config.d.ts +39 -0
  17. package/dist/config.js +3 -0
  18. package/dist/index.d.ts +7 -0
  19. package/dist/index.js +12 -0
  20. package/dist/plugins/LSPAssetsPlugin.d.ts +50 -0
  21. package/dist/plugins/LSPAssetsPlugin.js +47 -0
  22. package/dist/plugins/LSPPluginPlugin.d.ts +11 -0
  23. package/dist/plugins/LSPPluginPlugin.js +22 -0
  24. package/dist/plugins/LSPTransformsPlugin.d.ts +12 -0
  25. package/dist/plugins/LSPTransformsPlugin.js +17 -0
  26. package/dist/plugins/index.d.ts +33 -0
  27. package/dist/plugins/index.js +7 -0
  28. package/dist/utils/babel-register.d.ts +3 -0
  29. package/dist/utils/babel-register.js +19 -0
  30. package/dist/utils/base-command.d.ts +26 -0
  31. package/dist/utils/base-command.js +155 -0
  32. package/dist/utils/compilation-context.d.ts +53 -0
  33. package/dist/utils/compilation-context.js +57 -0
  34. package/dist/utils/compile-renderer.d.ts +13 -0
  35. package/dist/utils/compile-renderer.js +42 -0
  36. package/dist/utils/compiler-options.d.ts +3 -0
  37. package/dist/utils/compiler-options.js +16 -0
  38. package/dist/utils/diag-renderer.d.ts +31 -0
  39. package/dist/utils/diag-renderer.js +224 -0
  40. package/dist/utils/fs.d.ts +9 -0
  41. package/dist/utils/fs.js +39 -0
  42. package/dist/utils/log-levels.d.ts +11 -0
  43. package/dist/utils/log-levels.js +21 -0
  44. package/dist/utils/task-runner.d.ts +59 -0
  45. package/dist/utils/task-runner.js +59 -0
  46. package/dist/utils/xlr/consts.d.ts +7 -0
  47. package/dist/utils/xlr/consts.js +18 -0
  48. package/dist/utils/xlr/visitors/file.d.ts +5 -0
  49. package/dist/utils/xlr/visitors/file.js +25 -0
  50. package/dist/utils/xlr/visitors/index.d.ts +4 -0
  51. package/dist/utils/xlr/visitors/index.js +7 -0
  52. package/dist/utils/xlr/visitors/plugin.d.ts +5 -0
  53. package/dist/utils/xlr/visitors/plugin.js +167 -0
  54. package/dist/utils/xlr/visitors/types.d.ts +13 -0
  55. package/dist/utils/xlr/visitors/types.js +3 -0
  56. package/package.json +58 -0
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validationRenderer = exports.getTaskSymbol = void 0;
4
+ exports.getSummary = getSummary;
5
+ exports.formatDiagnosticResults = formatDiagnosticResults;
6
+ const tslib_1 = require("tslib");
7
+ const vscode_languageserver_types_1 = require("vscode-languageserver-types");
8
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
9
+ const log_symbols_1 = tslib_1.__importDefault(require("log-symbols"));
10
+ const elegant_spinner_1 = tslib_1.__importDefault(require("elegant-spinner"));
11
+ const fs_1 = require("./fs");
12
+ const source_map_js_1 = tslib_1.__importDefault(require("source-map-js"));
13
+ /** Compare the ranges and return the one that starts of finishes first */
14
+ function rangeComparator(first, second) {
15
+ if (first.start.line < second.start.line) {
16
+ return -1;
17
+ }
18
+ if (first.start.line > second.start.line) {
19
+ return 1;
20
+ }
21
+ if (first.start.character < second.start.character) {
22
+ return -1;
23
+ }
24
+ if (first.start.character > second.start.character) {
25
+ return 1;
26
+ }
27
+ return 0;
28
+ }
29
+ /** Sort a list of digs by position */
30
+ const sortDiagnostics = (validations) => {
31
+ // Sort the validations by line/char number
32
+ return validations.sort((a, b) => {
33
+ return rangeComparator(a.range, b.range);
34
+ });
35
+ };
36
+ /** Get the text representing the line range */
37
+ function getLineRange(range) {
38
+ return `${range.start.line + 1}:${range.start.character + 1}`;
39
+ }
40
+ /** Fix the plurality of a word */
41
+ function maybePlural(word, count) {
42
+ return count > 1 ? `${word}s` : word;
43
+ }
44
+ /** Get the lines representing the summary of the results */
45
+ function getSummary({ errors, warnings, skipped, fileCount, duration, }) {
46
+ return [
47
+ "\n",
48
+ (errors > 0 || warnings === 0) &&
49
+ chalk_1.default.red(`${errors} ${maybePlural("error", errors)}`),
50
+ warnings > 0 &&
51
+ chalk_1.default.yellow(`${warnings} ${maybePlural("warning", warnings)}`),
52
+ skipped !== undefined &&
53
+ skipped > 0 &&
54
+ chalk_1.default.gray(`${skipped} ${maybePlural("skipped", skipped)}`),
55
+ chalk_1.default.gray(`in ${fileCount} ${maybePlural("file", fileCount)}`),
56
+ chalk_1.default.gray(`took ${duration}ms`),
57
+ ]
58
+ .filter(Boolean)
59
+ .join(" ");
60
+ }
61
+ /** Format a diag for printing on the console */
62
+ function formatDiagnostic(diag, longestLine, fName) {
63
+ let type;
64
+ if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Error) {
65
+ type = chalk_1.default.red(`${log_symbols_1.default.error} `);
66
+ }
67
+ else if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Warning) {
68
+ type = chalk_1.default.yellow(`${log_symbols_1.default.warning} `);
69
+ }
70
+ else if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Information) {
71
+ type = chalk_1.default.blue(`${log_symbols_1.default.info} `);
72
+ }
73
+ else if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Hint) {
74
+ type = chalk_1.default.gray(`${log_symbols_1.default.info} `);
75
+ }
76
+ else {
77
+ type = chalk_1.default.green(`${log_symbols_1.default.info} `);
78
+ }
79
+ const msg = chalk_1.default.bold(diag.message);
80
+ const range = getLineRange(diag.range);
81
+ return [
82
+ `${type}`,
83
+ range.padEnd(longestLine),
84
+ msg,
85
+ `${fName}:${range.padEnd(longestLine)}`,
86
+ ].join(" ");
87
+ }
88
+ function mapDiagnosticBackToSourceLine(diag, mapper) {
89
+ const { line, character } = diag.range.start;
90
+ if (mapper && line && character >= 1) {
91
+ const sourceNode = mapper.originalPositionFor({
92
+ line,
93
+ column: character,
94
+ });
95
+ if (sourceNode.source) {
96
+ return {
97
+ diagnostic: {
98
+ ...diag,
99
+ range: {
100
+ ...diag.range,
101
+ start: {
102
+ line: sourceNode.line,
103
+ character: sourceNode.column,
104
+ },
105
+ },
106
+ },
107
+ sourceFile: sourceNode.source,
108
+ };
109
+ }
110
+ }
111
+ }
112
+ /** Format the results for printing on the console */
113
+ function formatDiagnosticResults(filePath, results, loglevel) {
114
+ const count = {
115
+ errors: 0,
116
+ warnings: 0,
117
+ info: 0,
118
+ trace: 0,
119
+ };
120
+ const linePrefix = " ";
121
+ const longestLine = Math.max(...results.map((r) => getLineRange(r.range).length));
122
+ //try and load map file
123
+ const mapFile = (0, fs_1.tryAndLoadSourceMap)(filePath);
124
+ let sourceMapper;
125
+ if (mapFile) {
126
+ sourceMapper = new source_map_js_1.default.SourceMapConsumer(JSON.parse(mapFile));
127
+ }
128
+ let lines = results
129
+ .map((diag) => {
130
+ if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Error) {
131
+ count.errors += 1;
132
+ }
133
+ else if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Warning) {
134
+ count.warnings += 1;
135
+ }
136
+ else if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Information) {
137
+ count.info += 1;
138
+ }
139
+ else if (diag.severity === vscode_languageserver_types_1.DiagnosticSeverity.Hint) {
140
+ count.trace += 1;
141
+ }
142
+ const { diagnostic, sourceFile } = mapDiagnosticBackToSourceLine(diag, sourceMapper) ?? { diagnostic: diag, sourceFile: filePath };
143
+ if (diag.severity && loglevel >= diag.severity) {
144
+ return (linePrefix + formatDiagnostic(diagnostic, longestLine + 1, sourceFile));
145
+ }
146
+ return "";
147
+ })
148
+ .filter((line) => line !== "");
149
+ if (count.errors > 0) {
150
+ lines = ["", `${chalk_1.default.red(log_symbols_1.default.error)} ${filePath}`, ...lines, ""];
151
+ }
152
+ else if (count.warnings > 0 && loglevel >= vscode_languageserver_types_1.DiagnosticSeverity.Warning) {
153
+ lines = [
154
+ "",
155
+ `${chalk_1.default.yellow(log_symbols_1.default.warning)} ${filePath}`,
156
+ ...lines,
157
+ "",
158
+ ];
159
+ }
160
+ else if (count.info > 0 && loglevel >= vscode_languageserver_types_1.DiagnosticSeverity.Information) {
161
+ lines = ["", `${chalk_1.default.blue(log_symbols_1.default.info)} ${filePath}`, ...lines, ""];
162
+ }
163
+ else if (count.trace > 0 && loglevel >= vscode_languageserver_types_1.DiagnosticSeverity.Hint) {
164
+ lines = ["", `${chalk_1.default.gray(log_symbols_1.default.info)} ${filePath}`, ...lines, ""];
165
+ }
166
+ else {
167
+ lines = [`${chalk_1.default.green(log_symbols_1.default.success)} ${filePath}`, ...lines];
168
+ }
169
+ return {
170
+ ...count,
171
+ lines,
172
+ };
173
+ }
174
+ const spinnerState = new WeakMap();
175
+ /** Get the symbol for a given task */
176
+ const getTaskSymbol = (task) => {
177
+ if (task.state === "pending" || task.state === "idle") {
178
+ const spinner = spinnerState.get(task) ?? (0, elegant_spinner_1.default)();
179
+ spinnerState.set(task, spinner);
180
+ return chalk_1.default.yellow(spinner());
181
+ }
182
+ if (task.state === "completed" && task.error) {
183
+ return log_symbols_1.default.error;
184
+ }
185
+ if (task.state === "completed") {
186
+ return chalk_1.default.yellow(log_symbols_1.default.success);
187
+ }
188
+ return " ";
189
+ };
190
+ exports.getTaskSymbol = getTaskSymbol;
191
+ exports.validationRenderer = {
192
+ onUpdate(ctx) {
193
+ const { tasks } = ctx;
194
+ const output = ["Validating content"];
195
+ tasks.forEach((task) => {
196
+ if (task.state === "completed" && task.output) {
197
+ const formattedDiags = formatDiagnosticResults(task.data?.file ? (0, fs_1.normalizePath)(task.data.file) : "", sortDiagnostics(task.output), ctx.loglevel);
198
+ output.push(...formattedDiags.lines);
199
+ }
200
+ else {
201
+ output.push(`${(0, exports.getTaskSymbol)(task)} ${task.data?.file ? (0, fs_1.normalizePath)(task.data.file) : ""}`);
202
+ }
203
+ });
204
+ return output.join("\n");
205
+ },
206
+ onEnd(ctx) {
207
+ const count = {
208
+ errors: 0,
209
+ warnings: 0,
210
+ skipped: 0,
211
+ fileCount: ctx.tasks.length,
212
+ duration: ctx.duration,
213
+ };
214
+ ctx.tasks.forEach((t) => {
215
+ if (t.state === "completed" && t.output) {
216
+ const formattedDiags = formatDiagnosticResults(t.data?.file ?? "", t.output, ctx.loglevel);
217
+ count.errors += formattedDiags.errors;
218
+ count.warnings += formattedDiags.warnings;
219
+ }
220
+ });
221
+ return [exports.validationRenderer.onUpdate(ctx), getSummary(count)].join("\n");
222
+ },
223
+ };
224
+ //# sourceMappingURL=diag-renderer.js.map
@@ -0,0 +1,9 @@
1
+ /** Check if an input is a directory, if it is, then swap it to a globbed path */
2
+ export declare const convertToFileGlob: (input: string[], glob: string) => string[];
3
+ /** Normalize a path for display */
4
+ export declare const normalizePath: (p: string) => string;
5
+ /**
6
+ * Tries to load a source map file
7
+ */
8
+ export declare const tryAndLoadSourceMap: (f: string) => string | undefined;
9
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tryAndLoadSourceMap = exports.normalizePath = exports.convertToFileGlob = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path_1 = tslib_1.__importDefault(require("path"));
6
+ const fs_1 = tslib_1.__importDefault(require("fs"));
7
+ /** To handle globby issue on windows https://github.com/sindresorhus/globby/issues/152 */
8
+ function forcePathSeparatorToPosix(input) {
9
+ return path_1.default.sep === path_1.default.win32.sep
10
+ ? input.split(path_1.default.sep).join(path_1.default.posix.sep)
11
+ : input;
12
+ }
13
+ /** Check if an input is a directory, if it is, then swap it to a globbed path */
14
+ const convertToFileGlob = (input, glob) => {
15
+ return input.map((i) => {
16
+ if (fs_1.default.statSync(i, { throwIfNoEntry: false })?.isDirectory()) {
17
+ return forcePathSeparatorToPosix(path_1.default.join(i, glob));
18
+ }
19
+ return forcePathSeparatorToPosix(i);
20
+ });
21
+ };
22
+ exports.convertToFileGlob = convertToFileGlob;
23
+ /** Normalize a path for display */
24
+ const normalizePath = (p) => {
25
+ return path_1.default.relative(process.cwd(), p);
26
+ };
27
+ exports.normalizePath = normalizePath;
28
+ /**
29
+ * Tries to load a source map file
30
+ */
31
+ const tryAndLoadSourceMap = (f) => {
32
+ const mapFileName = f + ".map";
33
+ if (fs_1.default.existsSync(mapFileName)) {
34
+ return fs_1.default.readFileSync(mapFileName, "utf8");
35
+ }
36
+ return undefined;
37
+ };
38
+ exports.tryAndLoadSourceMap = tryAndLoadSourceMap;
39
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1,11 @@
1
+ import { DiagnosticSeverity } from "vscode-languageserver-types";
2
+ export declare const LogLevelsMap: {
3
+ error: 1;
4
+ warn: 2;
5
+ info: 3;
6
+ trace: 4;
7
+ };
8
+ export type LogLevelsType = keyof typeof LogLevelsMap;
9
+ export declare const LogLevels: string[];
10
+ export declare function stringToLogLevel(level: string): DiagnosticSeverity;
11
+ //# sourceMappingURL=log-levels.d.ts.map
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogLevels = exports.LogLevelsMap = void 0;
4
+ exports.stringToLogLevel = stringToLogLevel;
5
+ const vscode_languageserver_types_1 = require("vscode-languageserver-types");
6
+ exports.LogLevelsMap = {
7
+ error: vscode_languageserver_types_1.DiagnosticSeverity.Error,
8
+ warn: vscode_languageserver_types_1.DiagnosticSeverity.Warning,
9
+ info: vscode_languageserver_types_1.DiagnosticSeverity.Information,
10
+ trace: vscode_languageserver_types_1.DiagnosticSeverity.Hint,
11
+ };
12
+ exports.LogLevels = Object.keys(exports.LogLevelsMap);
13
+ function isValidLogLevel(level) {
14
+ return exports.LogLevels.includes(level);
15
+ }
16
+ function stringToLogLevel(level) {
17
+ return isValidLogLevel(level)
18
+ ? exports.LogLevelsMap[level]
19
+ : vscode_languageserver_types_1.DiagnosticSeverity.Warning;
20
+ }
21
+ //# sourceMappingURL=log-levels.js.map
@@ -0,0 +1,59 @@
1
+ import { DiagnosticSeverity } from "vscode-languageserver-types";
2
+ interface BaseTask<Results, Data> {
3
+ /** The state of the task */
4
+ state: "idle" | "pending";
5
+ /** A function to run */
6
+ run: () => Promise<Results>;
7
+ /** other metadata about the task */
8
+ data?: Data;
9
+ }
10
+ export type CompletedTask<Results, Data> = Omit<BaseTask<Results, Data>, "state"> & {
11
+ /** The state of the task */
12
+ state: "completed";
13
+ } & ({
14
+ /** The results */
15
+ output: Results;
16
+ /** An error if any */
17
+ error?: never;
18
+ } | {
19
+ /** The error if any */
20
+ error: Error;
21
+ /** No output on error */
22
+ output?: never;
23
+ });
24
+ export type Task<ResultsType, Data> = BaseTask<ResultsType, Data> | CompletedTask<ResultsType, Data>;
25
+ export interface TaskProgressRenderer<ResultType, Data = unknown> {
26
+ /** Call back to paint update on the page */
27
+ onUpdate: (ctx: {
28
+ /** The tasks that are running */
29
+ tasks: Array<Task<ResultType, Data>>;
30
+ /** What level of information to log */
31
+ loglevel: DiagnosticSeverity;
32
+ }) => string;
33
+ /** Called for a summary */
34
+ onEnd: (ctx: {
35
+ /** The completed tasks */
36
+ tasks: Array<CompletedTask<ResultType, Data>>;
37
+ /** Number of ms it took to run */
38
+ duration: number;
39
+ /** What level of information to log */
40
+ loglevel: DiagnosticSeverity;
41
+ }) => string;
42
+ }
43
+ interface TaskRunner<R, Data> {
44
+ /** The list of tasks */
45
+ tasks: Array<Task<R, Data>>;
46
+ /** A trigger to start it */
47
+ run: () => Promise<Array<CompletedTask<R, Data>>>;
48
+ }
49
+ /** Create a runner to kick off tasks in parallel */
50
+ export declare const createTaskRunner: <R, D>({ tasks, renderer, loglevel, }: {
51
+ /** A list of tasks to run */
52
+ tasks: Array<Pick<BaseTask<R, D>, "data" | "run">>;
53
+ /** How to report progress */
54
+ renderer: TaskProgressRenderer<R, D>;
55
+ /** What level of logs to write */
56
+ loglevel: DiagnosticSeverity;
57
+ }) => TaskRunner<R, D>;
58
+ export {};
59
+ //# sourceMappingURL=task-runner.d.ts.map
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTaskRunner = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const log_update_1 = tslib_1.__importDefault(require("log-update"));
6
+ /** Create a runner to kick off tasks in parallel */
7
+ const createTaskRunner = ({ tasks, renderer, loglevel, }) => {
8
+ const statefulTasks = tasks.map((t) => {
9
+ return {
10
+ ...t,
11
+ state: "idle",
12
+ };
13
+ });
14
+ /** Kick off the task list */
15
+ const run = async () => {
16
+ const startTime = Date.now();
17
+ let ended = false;
18
+ const paintInterval = setInterval(() => {
19
+ if (ended) {
20
+ return;
21
+ }
22
+ const output = renderer.onUpdate({ tasks: statefulTasks, loglevel });
23
+ if (process.stdout.isTTY) {
24
+ (0, log_update_1.default)(output);
25
+ }
26
+ }, 10);
27
+ await Promise.all(statefulTasks.map(async (t) => {
28
+ t.state = "pending";
29
+ try {
30
+ const r = await t.run();
31
+ t.state = "completed";
32
+ t.output = r;
33
+ }
34
+ catch (e) {
35
+ if (e instanceof Error) {
36
+ t.state = "completed";
37
+ t.error = e;
38
+ }
39
+ }
40
+ }));
41
+ ended = true;
42
+ clearInterval(paintInterval);
43
+ const duration = Date.now() - startTime;
44
+ const output = renderer.onEnd({
45
+ duration,
46
+ tasks: statefulTasks,
47
+ loglevel,
48
+ });
49
+ console.log(output);
50
+ log_update_1.default.done();
51
+ return statefulTasks;
52
+ };
53
+ return {
54
+ tasks: statefulTasks,
55
+ run,
56
+ };
57
+ };
58
+ exports.createTaskRunner = createTaskRunner;
59
+ //# sourceMappingURL=task-runner.js.map
@@ -0,0 +1,7 @@
1
+ export declare const PLAYER_PLUGIN_INTERFACE_NAME = "ExtendedPlayerPlugin";
2
+ export declare const customPrimitives: string[];
3
+ export declare enum Mode {
4
+ PLUGIN = "plugin",
5
+ TYPES = "types"
6
+ }
7
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Mode = exports.customPrimitives = exports.PLAYER_PLUGIN_INTERFACE_NAME = void 0;
4
+ exports.PLAYER_PLUGIN_INTERFACE_NAME = "ExtendedPlayerPlugin";
5
+ exports.customPrimitives = [
6
+ "Expression",
7
+ "Asset",
8
+ "Binding",
9
+ "AssetWrapper",
10
+ "Schema.DataType",
11
+ "ExpressionHandler",
12
+ ];
13
+ var Mode;
14
+ (function (Mode) {
15
+ Mode["PLUGIN"] = "plugin";
16
+ Mode["TYPES"] = "types";
17
+ })(Mode || (exports.Mode = Mode = {}));
18
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1,5 @@
1
+ import type { Manifest } from "@player-tools/xlr";
2
+ import type { VisitorProps } from "./types";
3
+ /** export all exported types in the file */
4
+ export declare function fileVisitor(args: VisitorProps): Manifest | undefined;
5
+ //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fileVisitor = fileVisitor;
4
+ const tslib_1 = require("tslib");
5
+ const path_1 = tslib_1.__importDefault(require("path"));
6
+ const fs_1 = tslib_1.__importDefault(require("fs"));
7
+ /** export all exported types in the file */
8
+ function fileVisitor(args) {
9
+ const { sourceFile, converter, outputDirectory } = args;
10
+ const convertedTypes = converter.convertSourceFile(sourceFile);
11
+ if (convertedTypes.data.types.length === 0) {
12
+ return undefined;
13
+ }
14
+ const capabilities = {
15
+ pluginName: "Types",
16
+ };
17
+ convertedTypes.data.types.forEach((type) => {
18
+ fs_1.default.writeFileSync(path_1.default.join(outputDirectory, `${type.name}.json`), JSON.stringify(type, undefined, 4));
19
+ });
20
+ capabilities.capabilities = new Map([
21
+ ["Types", convertedTypes.convertedTypes],
22
+ ]);
23
+ return capabilities;
24
+ }
25
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1,4 @@
1
+ export * from "./file";
2
+ export * from "./plugin";
3
+ export * from "./types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./file"), exports);
5
+ tslib_1.__exportStar(require("./plugin"), exports);
6
+ tslib_1.__exportStar(require("./types"), exports);
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ import type { Manifest } from "@player-tools/xlr";
2
+ import type { VisitorProps } from "./types";
3
+ /** visit nodes finding exported classes */
4
+ export declare function pluginVisitor(args: VisitorProps): Manifest | undefined;
5
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pluginVisitor = pluginVisitor;
4
+ const tslib_1 = require("tslib");
5
+ const xlr_utils_1 = require("@player-tools/xlr-utils");
6
+ const path_1 = tslib_1.__importDefault(require("path"));
7
+ const typescript_1 = tslib_1.__importDefault(require("typescript"));
8
+ const fs_1 = tslib_1.__importDefault(require("fs"));
9
+ const consts_1 = require("../consts");
10
+ /**
11
+ * Follows references to get the actual underlying declaration
12
+ */
13
+ function getUnderlyingNode(element, checker) {
14
+ let referencedSymbol;
15
+ if (typescript_1.default.isTypeReferenceNode(element)) {
16
+ referencedSymbol = checker.getSymbolAtLocation(element.typeName);
17
+ }
18
+ else {
19
+ referencedSymbol = checker.getSymbolAtLocation(element.exprName);
20
+ }
21
+ const alias = referencedSymbol
22
+ ? checker.getAliasedSymbol(referencedSymbol)
23
+ : undefined;
24
+ let varDecl;
25
+ /**
26
+ * The TypeChecker will return the interface/type declaration or the variable statement
27
+ * so if we are getting a variable, we need to grab the variable declaration
28
+ */
29
+ if (typescript_1.default.isTypeReferenceNode(element)) {
30
+ varDecl = alias?.declarations?.[0];
31
+ }
32
+ else {
33
+ varDecl = alias?.declarations?.[0].parent.parent;
34
+ }
35
+ if (varDecl && (0, xlr_utils_1.isTopLevelNode)(varDecl)) {
36
+ return varDecl;
37
+ }
38
+ }
39
+ /**
40
+ * Fixes ExpressionHandler ref nodes that don't have argument names because some way of writing ExpressionHandler prevent the ts compiler from inferring them
41
+ */
42
+ function fixExpressionArgNames(sourceNode, generatedTypeRef, checker) {
43
+ const typeRefCopy = { ...generatedTypeRef };
44
+ const { initializer } = sourceNode.declarationList.declarations[0];
45
+ let offset;
46
+ let arrowFunction;
47
+ if (initializer &&
48
+ typescript_1.default.isCallExpression(initializer) &&
49
+ typescript_1.default.isArrowFunction(initializer.arguments[0])) {
50
+ // handles the case of `withoutContext` expression where the types are provided by the generic
51
+ offset = 0;
52
+ arrowFunction = initializer.arguments[0];
53
+ }
54
+ else {
55
+ // handles the case of a direct `ExpressionHandler` where the types are provided by the generic
56
+ offset = 1;
57
+ arrowFunction = initializer;
58
+ }
59
+ const paramsNode = typeRefCopy.genericArguments?.[0];
60
+ if (paramsNode && paramsNode.type === "array") {
61
+ const functionArg = arrowFunction.parameters?.[offset];
62
+ if (!paramsNode.name && functionArg) {
63
+ paramsNode.name = functionArg.name.getText();
64
+ }
65
+ }
66
+ else if (paramsNode && paramsNode.type === "tuple") {
67
+ paramsNode.elementTypes?.forEach((gArg, index) => {
68
+ const functionArg = arrowFunction.parameters?.[index + offset];
69
+ if (!gArg.name && functionArg) {
70
+ gArg.name = functionArg.name.getText();
71
+ }
72
+ });
73
+ }
74
+ return typeRefCopy;
75
+ }
76
+ /**
77
+ * Player specific modifications that we need to do to massage generic XLR conversion because of our weird types
78
+ * Most of this is _definitely not_ best practice.
79
+ */
80
+ function runPlayerPostProcessing(node, xlr, checker) {
81
+ if (xlr.type === "ref" &&
82
+ xlr.ref.includes("ExpressionHandler") &&
83
+ typescript_1.default.isVariableStatement(node)) {
84
+ return fixExpressionArgNames(node, xlr, checker);
85
+ }
86
+ return xlr;
87
+ }
88
+ /**
89
+ * Generated the XLR for a Capability, writes it to the specified path, and returns the name
90
+ */
91
+ function generateXLR(node, checker, converter, outputDirectory) {
92
+ if (typescript_1.default.isTypeReferenceNode(node) || typescript_1.default.isTypeQueryNode(node)) {
93
+ const varDecl = getUnderlyingNode(node, checker);
94
+ if (varDecl) {
95
+ let capabilityDescription = converter.convertTopLevelNode(varDecl);
96
+ capabilityDescription = runPlayerPostProcessing(varDecl, capabilityDescription, checker);
97
+ const capabilityName = capabilityDescription?.name ?? "error";
98
+ fs_1.default.writeFileSync(path_1.default.join(outputDirectory, `${capabilityName}.json`), JSON.stringify(capabilityDescription, undefined, 4));
99
+ return capabilityName;
100
+ }
101
+ }
102
+ throw new Error(`Can't export non reference type ${node.getText()}`);
103
+ }
104
+ /** visit nodes finding exported classes */
105
+ function pluginVisitor(args) {
106
+ const { sourceFile, checker, converter, outputDirectory } = args;
107
+ let capabilities;
108
+ typescript_1.default.forEachChild(sourceFile, (node) => {
109
+ // Only consider exported nodes
110
+ if (!(0, xlr_utils_1.isNodeExported)(node)) {
111
+ return;
112
+ }
113
+ // Plugins are classes so filter those
114
+ if (typescript_1.default.isClassDeclaration(node) && node.name) {
115
+ const symbol = checker.getSymbolAtLocation(node.name);
116
+ if (symbol) {
117
+ // look at what they implement
118
+ node.heritageClauses?.forEach((heritage) => {
119
+ heritage.types.forEach((hInterface) => {
120
+ // check if heritage is right one
121
+ if (hInterface.expression.getText() !== consts_1.PLAYER_PLUGIN_INTERFACE_NAME) {
122
+ return;
123
+ }
124
+ capabilities = {
125
+ pluginName: "Unknown Plugin",
126
+ };
127
+ // Get registration name of plugin
128
+ const nameProperty = node.members.find((member) => typescript_1.default.isPropertyDeclaration(member) &&
129
+ member.name?.getText() === "name");
130
+ if (nameProperty && nameProperty.initializer) {
131
+ capabilities.pluginName = nameProperty.initializer
132
+ ?.getText()
133
+ .replace(/[""]+/g, "");
134
+ }
135
+ const provides = new Map();
136
+ const typeArgs = hInterface.typeArguments;
137
+ const pluginDec = checker.getTypeAtLocation(hInterface).symbol
138
+ ?.declarations?.[0];
139
+ // process type parameters to figure out what capabilities are provided
140
+ pluginDec?.typeParameters?.forEach((param, index) => {
141
+ const capabilityType = param.name.getText();
142
+ if (index < (typeArgs?.length ?? 0)) {
143
+ const exportedCapabilities = typeArgs?.[index];
144
+ // if its an array process each type
145
+ if (typescript_1.default.isTupleTypeNode(exportedCapabilities)) {
146
+ const capabilityNames = exportedCapabilities.elements.map((element) => generateXLR(element, checker, converter, outputDirectory));
147
+ provides.set(capabilityType, capabilityNames);
148
+ }
149
+ else if (typescript_1.default.isTypeReferenceNode(exportedCapabilities) ||
150
+ typescript_1.default.isTypeQueryNode(exportedCapabilities)) {
151
+ const capabilityName = generateXLR(exportedCapabilities, checker, converter, outputDirectory);
152
+ provides.set(capabilityType, [capabilityName]);
153
+ }
154
+ else {
155
+ throw new Error(`Can't figure out type ${capabilityType}`);
156
+ }
157
+ }
158
+ });
159
+ capabilities.capabilities = provides;
160
+ });
161
+ });
162
+ }
163
+ }
164
+ });
165
+ return capabilities;
166
+ }
167
+ //# sourceMappingURL=plugin.js.map