@rindo/core 2.16.0 → 2.17.0
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/cli/index.cjs +122 -16
- package/cli/index.js +122 -16
- package/cli/package.json +1 -1
- package/compiler/package.json +1 -1
- package/compiler/rindo.js +728 -263
- package/compiler/rindo.min.js +2 -2
- package/dependencies.json +1 -1
- package/dev-server/client/index.js +1 -1
- package/dev-server/client/package.json +1 -1
- package/dev-server/connector.html +3 -3
- package/dev-server/index.js +1 -1
- package/dev-server/package.json +1 -1
- package/dev-server/server-process.js +4 -2
- package/internal/app-data/package.json +1 -1
- package/internal/client/css-shim.js +1 -1
- package/internal/client/dom.js +1 -1
- package/internal/client/index.js +1 -1
- package/internal/client/package.json +1 -1
- package/internal/client/patch-browser.js +1 -1
- package/internal/client/patch-esm.js +1 -1
- package/internal/client/shadow-css.js +1 -1
- package/internal/hydrate/index.js +3 -3
- package/internal/hydrate/package.json +1 -1
- package/internal/package.json +1 -1
- package/internal/rindo-private.d.ts +4 -0
- package/internal/rindo-public-compiler.d.ts +3 -2
- package/internal/testing/index.js +1 -1
- package/internal/testing/package.json +1 -1
- package/mock-doc/index.cjs +142 -5
- package/mock-doc/index.d.ts +77 -1
- package/mock-doc/index.js +142 -5
- package/mock-doc/package.json +1 -1
- package/package.json +3 -1
- package/screenshot/index.js +2 -0
- package/screenshot/package.json +1 -1
- package/sys/node/index.js +325 -314
- package/sys/node/package.json +1 -1
- package/sys/node/worker.js +1 -1
- package/testing/index.d.ts +1 -1
- package/testing/index.js +105 -62
- package/testing/mocks.d.ts +22 -2
- package/testing/package.json +1 -1
package/cli/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Rindo CLI (CommonJS) v2.
|
|
2
|
+
Rindo CLI (CommonJS) v2.17.0 | MIT Licensed | https://rindojs.web.app
|
|
3
3
|
*/
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
@@ -118,6 +118,8 @@ const TASK_CANCELED_MSG = `task canceled`;
|
|
|
118
118
|
* Forward-slash paths can be used in Windows as long as they're not
|
|
119
119
|
* extended-length paths and don't contain any non-ascii characters.
|
|
120
120
|
* This was created since the path methods in Node.js outputs \\ paths on Windows.
|
|
121
|
+
* @param path the Windows-based path to convert
|
|
122
|
+
* @returns the converted path
|
|
121
123
|
*/
|
|
122
124
|
const normalizePath = (path) => {
|
|
123
125
|
if (typeof path !== 'string') {
|
|
@@ -530,7 +532,7 @@ const getNpmConfigEnvArgs = (sys) => {
|
|
|
530
532
|
const dependencies = [
|
|
531
533
|
{
|
|
532
534
|
name: "@rindo/core",
|
|
533
|
-
version: "2.
|
|
535
|
+
version: "2.17.0",
|
|
534
536
|
main: "compiler/rindo.js",
|
|
535
537
|
resources: [
|
|
536
538
|
"package.json",
|
|
@@ -964,7 +966,9 @@ async function updateConfig(sys, newOptions) {
|
|
|
964
966
|
return await writeConfig(sys, Object.assign(config, newOptions));
|
|
965
967
|
}
|
|
966
968
|
|
|
969
|
+
const isOutputTargetHydrate = (o) => o.type === DIST_HYDRATE_SCRIPT;
|
|
967
970
|
const isOutputTargetDocs = (o) => o.type === DOCS_README || o.type === DOCS_JSON || o.type === DOCS_CUSTOM || o.type === DOCS_VSCODE;
|
|
971
|
+
const DIST_HYDRATE_SCRIPT = 'dist-hydrate-script';
|
|
968
972
|
const DOCS_CUSTOM = 'docs-custom';
|
|
969
973
|
const DOCS_JSON = 'docs-json';
|
|
970
974
|
const DOCS_README = 'docs-readme';
|
|
@@ -992,6 +996,7 @@ async function telemetryBuildFinishedAction(sys, config, logger, coreCompiler, r
|
|
|
992
996
|
}
|
|
993
997
|
/**
|
|
994
998
|
* A function to wrap a compiler task function around. Will send telemetry if, and only if, the machine allows.
|
|
999
|
+
*
|
|
995
1000
|
* @param sys The system where the command is invoked
|
|
996
1001
|
* @param config The config passed into the Rindo command
|
|
997
1002
|
* @param logger The tool used to do logging
|
|
@@ -1037,6 +1042,16 @@ async function getActiveTargets(config) {
|
|
|
1037
1042
|
const result = config.outputTargets.map((t) => t.type);
|
|
1038
1043
|
return Array.from(new Set(result));
|
|
1039
1044
|
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Prepare data for telemetry
|
|
1047
|
+
*
|
|
1048
|
+
* @param coreCompiler the core compiler
|
|
1049
|
+
* @param config the current Rindo config
|
|
1050
|
+
* @param sys the compiler system instance in use
|
|
1051
|
+
* @param duration_ms the duration of the action being tracked
|
|
1052
|
+
* @param component_count the number of components being built (optional)
|
|
1053
|
+
* @returns a Promise wrapping data for the telemetry endpoint
|
|
1054
|
+
*/
|
|
1040
1055
|
const prepareData = async (coreCompiler, config, sys, duration_ms, component_count = undefined) => {
|
|
1041
1056
|
const { typescript, rollup } = coreCompiler.versions || { typescript: 'unknown', rollup: 'unknown' };
|
|
1042
1057
|
const { packages, packagesNoVersions } = await getInstalledPackages(sys, config);
|
|
@@ -1049,6 +1064,7 @@ const prepareData = async (coreCompiler, config, sys, duration_ms, component_cou
|
|
|
1049
1064
|
const cpu_model = sys.details.cpuModel;
|
|
1050
1065
|
const build = coreCompiler.buildId || 'unknown';
|
|
1051
1066
|
const has_app_pwa_config = hasAppTarget(config);
|
|
1067
|
+
const anonymizedConfig = anonymizeConfigForTelemetry(config);
|
|
1052
1068
|
return {
|
|
1053
1069
|
yarn,
|
|
1054
1070
|
duration_ms,
|
|
@@ -1068,13 +1084,86 @@ const prepareData = async (coreCompiler, config, sys, duration_ms, component_cou
|
|
|
1068
1084
|
typescript,
|
|
1069
1085
|
rollup,
|
|
1070
1086
|
has_app_pwa_config,
|
|
1087
|
+
config: anonymizedConfig,
|
|
1071
1088
|
};
|
|
1072
1089
|
};
|
|
1090
|
+
// props in output targets for which we retain their original values when
|
|
1091
|
+
// preparing a config for telemetry
|
|
1092
|
+
//
|
|
1093
|
+
// we omit the values of all other fields on output targets.
|
|
1094
|
+
const OUTPUT_TARGET_KEYS_TO_KEEP = ['type'];
|
|
1095
|
+
// top-level config props that we anonymize for telemetry
|
|
1096
|
+
const CONFIG_PROPS_TO_ANONYMIZE = [
|
|
1097
|
+
'rootDir',
|
|
1098
|
+
'fsNamespace',
|
|
1099
|
+
'packageJsonFilePath',
|
|
1100
|
+
'namespace',
|
|
1101
|
+
'srcDir',
|
|
1102
|
+
'srcIndexHtml',
|
|
1103
|
+
'buildLogFilePath',
|
|
1104
|
+
'cacheDir',
|
|
1105
|
+
'configPath',
|
|
1106
|
+
'tsconfig',
|
|
1107
|
+
];
|
|
1108
|
+
// Props we delete entirely from the config for telemetry
|
|
1109
|
+
//
|
|
1110
|
+
// TODO: Investigate improving anonymization for tsCompilerOptions and devServer
|
|
1111
|
+
const CONFIG_PROPS_TO_DELETE = ['sys', 'logger', 'tsCompilerOptions', 'devServer'];
|
|
1073
1112
|
/**
|
|
1074
|
-
*
|
|
1113
|
+
* Anonymize the config for telemetry, replacing potentially revealing config props
|
|
1114
|
+
* with a placeholder string if they are present (this lets us still track how frequently
|
|
1115
|
+
* these config options are being used)
|
|
1116
|
+
*
|
|
1117
|
+
* @param config the config to anonymize
|
|
1118
|
+
* @returns an anonymized copy of the same config
|
|
1119
|
+
*/
|
|
1120
|
+
const anonymizeConfigForTelemetry = (config) => {
|
|
1121
|
+
var _a;
|
|
1122
|
+
const anonymizedConfig = { ...config };
|
|
1123
|
+
for (const prop of CONFIG_PROPS_TO_ANONYMIZE) {
|
|
1124
|
+
if (anonymizedConfig[prop] !== undefined) {
|
|
1125
|
+
anonymizedConfig[prop] = 'omitted';
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
anonymizedConfig.outputTargets = ((_a = config.outputTargets) !== null && _a !== void 0 ? _a : []).map((target) => {
|
|
1129
|
+
// Anonymize the outputTargets on our configuration, taking advantage of the
|
|
1130
|
+
// optional 2nd argument to `JSON.stringify`. If anything is not a string
|
|
1131
|
+
// we retain it so that any nested properties are handled, else we check
|
|
1132
|
+
// whether it's in our 'keep' list to decide whether to keep it or replace it
|
|
1133
|
+
// with `"omitted"`.
|
|
1134
|
+
const anonymizedOT = JSON.parse(JSON.stringify(target, (key, value) => {
|
|
1135
|
+
if (!(typeof value === 'string')) {
|
|
1136
|
+
return value;
|
|
1137
|
+
}
|
|
1138
|
+
if (OUTPUT_TARGET_KEYS_TO_KEEP.includes(key)) {
|
|
1139
|
+
return value;
|
|
1140
|
+
}
|
|
1141
|
+
return 'omitted';
|
|
1142
|
+
}));
|
|
1143
|
+
// this prop has to be handled separately because it is an array
|
|
1144
|
+
// so the replace function above will be called with all of its
|
|
1145
|
+
// members, giving us `["omitted", "omitted", ...]`.
|
|
1146
|
+
//
|
|
1147
|
+
// Instead, we check for its presence and manually copy over.
|
|
1148
|
+
if (isOutputTargetHydrate(target) && target.external) {
|
|
1149
|
+
anonymizedOT['external'] = target.external.concat();
|
|
1150
|
+
}
|
|
1151
|
+
return anonymizedOT;
|
|
1152
|
+
});
|
|
1153
|
+
// TODO: Investigate improving anonymization for tsCompilerOptions and devServer
|
|
1154
|
+
for (const prop of CONFIG_PROPS_TO_DELETE) {
|
|
1155
|
+
delete anonymizedConfig[prop];
|
|
1156
|
+
}
|
|
1157
|
+
return anonymizedConfig;
|
|
1158
|
+
};
|
|
1159
|
+
/**
|
|
1160
|
+
* Reads package-lock.json, yarn.lock, and package.json files in order to cross-reference
|
|
1075
1161
|
* the dependencies and devDependencies properties. Pulls up the current installed version
|
|
1076
1162
|
* of each package under the @rindo, @navify, and @jigra scopes.
|
|
1077
|
-
*
|
|
1163
|
+
*
|
|
1164
|
+
* @param sys the system instance where telemetry is invoked
|
|
1165
|
+
* @param config the Rindo configuration associated with the current task that triggered telemetry
|
|
1166
|
+
* @returns an object listing all dev and production dependencies under the aforementioned scopes
|
|
1078
1167
|
*/
|
|
1079
1168
|
async function getInstalledPackages(sys, config) {
|
|
1080
1169
|
let packages = [];
|
|
@@ -1153,7 +1242,13 @@ function sanitizeDeclaredVersion(version) {
|
|
|
1153
1242
|
return version.replace(/[*^~]/g, '');
|
|
1154
1243
|
}
|
|
1155
1244
|
/**
|
|
1156
|
-
* If telemetry is enabled, send a metric
|
|
1245
|
+
* If telemetry is enabled, send a metric to an external data store
|
|
1246
|
+
*
|
|
1247
|
+
* @param sys the system instance where telemetry is invoked
|
|
1248
|
+
* @param config the Rindo configuration associated with the current task that triggered telemetry
|
|
1249
|
+
* @param name the name of a trackable metric. Note this name is not necessarily a scalar value to track, like
|
|
1250
|
+
* "Rindo Version". For example, "rindo_cli_command" is a name that is used to track all CLI command information.
|
|
1251
|
+
* @param value the data to send to the external data store under the provided name argument
|
|
1157
1252
|
*/
|
|
1158
1253
|
async function sendMetric(sys, config, name, value) {
|
|
1159
1254
|
const session_id = await getTelemetryToken(sys);
|
|
@@ -1164,10 +1259,11 @@ async function sendMetric(sys, config, name, value) {
|
|
|
1164
1259
|
value,
|
|
1165
1260
|
session_id,
|
|
1166
1261
|
};
|
|
1167
|
-
await sendTelemetry(sys, config,
|
|
1262
|
+
await sendTelemetry(sys, config, message);
|
|
1168
1263
|
}
|
|
1169
1264
|
/**
|
|
1170
1265
|
* Used to read the config file's tokens.telemetry property.
|
|
1266
|
+
*
|
|
1171
1267
|
* @param sys The system where the command is invoked
|
|
1172
1268
|
* @returns string
|
|
1173
1269
|
*/
|
|
@@ -1189,7 +1285,7 @@ async function sendTelemetry(sys, config, data) {
|
|
|
1189
1285
|
try {
|
|
1190
1286
|
const now = new Date().toISOString();
|
|
1191
1287
|
const body = {
|
|
1192
|
-
metrics: [data
|
|
1288
|
+
metrics: [data],
|
|
1193
1289
|
sent_at: now,
|
|
1194
1290
|
};
|
|
1195
1291
|
// This request is only made if telemetry is on.
|
|
@@ -1201,7 +1297,7 @@ async function sendTelemetry(sys, config, data) {
|
|
|
1201
1297
|
body: JSON.stringify(body),
|
|
1202
1298
|
});
|
|
1203
1299
|
hasVerbose(config) &&
|
|
1204
|
-
console.debug('\nSent %O metric to events service (status: %O)', data.
|
|
1300
|
+
console.debug('\nSent %O metric to events service (status: %O)', data.name, response.status, '\n');
|
|
1205
1301
|
if (response.status !== 204) {
|
|
1206
1302
|
hasVerbose(config) &&
|
|
1207
1303
|
console.debug('\nBad response from events service. Request body: %O', response.body.toString(), '\n');
|
|
@@ -1352,7 +1448,8 @@ const taskGenerate = async (coreCompiler, config) => {
|
|
|
1352
1448
|
if (!writtenFiles) {
|
|
1353
1449
|
return config.sys.exit(1);
|
|
1354
1450
|
}
|
|
1355
|
-
//
|
|
1451
|
+
// We use `console.log` here rather than our `config.logger` because we don't want
|
|
1452
|
+
// our TUI messages to be prefixed with timestamps and so on.
|
|
1356
1453
|
console.log();
|
|
1357
1454
|
console.log(`${config.logger.gray('$')} rindo generate ${input}`);
|
|
1358
1455
|
console.log();
|
|
@@ -1466,7 +1563,10 @@ const getBoilerplateByExtension = (tagName, extension, withCss) => {
|
|
|
1466
1563
|
}
|
|
1467
1564
|
};
|
|
1468
1565
|
/**
|
|
1469
|
-
* Get the boilerplate for a component
|
|
1566
|
+
* Get the boilerplate for a file containing the definition of a component
|
|
1567
|
+
* @param tagName the name of the tag to give the component
|
|
1568
|
+
* @param hasStyle designates if the component has an external stylesheet or not
|
|
1569
|
+
* @returns the contents of a file that defines a component
|
|
1470
1570
|
*/
|
|
1471
1571
|
const getComponentBoilerplate = (tagName, hasStyle) => {
|
|
1472
1572
|
const decorator = [`{`];
|
|
@@ -1500,7 +1600,9 @@ const getStyleUrlBoilerplate = () => `:host {
|
|
|
1500
1600
|
}
|
|
1501
1601
|
`;
|
|
1502
1602
|
/**
|
|
1503
|
-
* Get the boilerplate for a spec test
|
|
1603
|
+
* Get the boilerplate for a file containing a spec (unit) test for a component
|
|
1604
|
+
* @param tagName the name of the tag associated with the component under test
|
|
1605
|
+
* @returns the contents of a file that unit tests a component
|
|
1504
1606
|
*/
|
|
1505
1607
|
const getSpecTestBoilerplate = (tagName) => `import { newSpecPage } from '@rindo/core/testing';
|
|
1506
1608
|
import { ${toPascalCase(tagName)} } from '../${tagName}';
|
|
@@ -1522,22 +1624,26 @@ describe('${tagName}', () => {
|
|
|
1522
1624
|
});
|
|
1523
1625
|
`;
|
|
1524
1626
|
/**
|
|
1525
|
-
* Get the boilerplate for an E2E test
|
|
1627
|
+
* Get the boilerplate for a file containing an end-to-end (E2E) test for a component
|
|
1628
|
+
* @param tagName the name of the tag associated with the component under test
|
|
1629
|
+
* @returns the contents of a file that E2E tests a component
|
|
1526
1630
|
*/
|
|
1527
|
-
const getE2eTestBoilerplate = (
|
|
1631
|
+
const getE2eTestBoilerplate = (tagName) => `import { newE2EPage } from '@rindo/core/testing';
|
|
1528
1632
|
|
|
1529
|
-
describe('${
|
|
1633
|
+
describe('${tagName}', () => {
|
|
1530
1634
|
it('renders', async () => {
|
|
1531
1635
|
const page = await newE2EPage();
|
|
1532
|
-
await page.setContent('<${
|
|
1636
|
+
await page.setContent('<${tagName}></${tagName}>');
|
|
1533
1637
|
|
|
1534
|
-
const element = await page.find('${
|
|
1638
|
+
const element = await page.find('${tagName}');
|
|
1535
1639
|
expect(element).toHaveClass('hydrated');
|
|
1536
1640
|
});
|
|
1537
1641
|
});
|
|
1538
1642
|
`;
|
|
1539
1643
|
/**
|
|
1540
1644
|
* Convert a dash case string to pascal case.
|
|
1645
|
+
* @param str the string to convert
|
|
1646
|
+
* @returns the converted input as pascal case
|
|
1541
1647
|
*/
|
|
1542
1648
|
const toPascalCase = (str) => str.split('-').reduce((res, part) => res + part[0].toUpperCase() + part.slice(1), '');
|
|
1543
1649
|
|
package/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Rindo CLI v2.
|
|
2
|
+
Rindo CLI v2.17.0 | MIT Licensed | https://rindojs.web.app
|
|
3
3
|
*/
|
|
4
4
|
const toLowerCase = (str) => str.toLowerCase();
|
|
5
5
|
const dashToPascalCase = (str) => toLowerCase(str)
|
|
@@ -94,6 +94,8 @@ const TASK_CANCELED_MSG = `task canceled`;
|
|
|
94
94
|
* Forward-slash paths can be used in Windows as long as they're not
|
|
95
95
|
* extended-length paths and don't contain any non-ascii characters.
|
|
96
96
|
* This was created since the path methods in Node.js outputs \\ paths on Windows.
|
|
97
|
+
* @param path the Windows-based path to convert
|
|
98
|
+
* @returns the converted path
|
|
97
99
|
*/
|
|
98
100
|
const normalizePath = (path) => {
|
|
99
101
|
if (typeof path !== 'string') {
|
|
@@ -506,7 +508,7 @@ const getNpmConfigEnvArgs = (sys) => {
|
|
|
506
508
|
const dependencies = [
|
|
507
509
|
{
|
|
508
510
|
name: "@rindo/core",
|
|
509
|
-
version: "2.
|
|
511
|
+
version: "2.17.0",
|
|
510
512
|
main: "compiler/rindo.js",
|
|
511
513
|
resources: [
|
|
512
514
|
"package.json",
|
|
@@ -940,7 +942,9 @@ async function updateConfig(sys, newOptions) {
|
|
|
940
942
|
return await writeConfig(sys, Object.assign(config, newOptions));
|
|
941
943
|
}
|
|
942
944
|
|
|
945
|
+
const isOutputTargetHydrate = (o) => o.type === DIST_HYDRATE_SCRIPT;
|
|
943
946
|
const isOutputTargetDocs = (o) => o.type === DOCS_README || o.type === DOCS_JSON || o.type === DOCS_CUSTOM || o.type === DOCS_VSCODE;
|
|
947
|
+
const DIST_HYDRATE_SCRIPT = 'dist-hydrate-script';
|
|
944
948
|
const DOCS_CUSTOM = 'docs-custom';
|
|
945
949
|
const DOCS_JSON = 'docs-json';
|
|
946
950
|
const DOCS_README = 'docs-readme';
|
|
@@ -968,6 +972,7 @@ async function telemetryBuildFinishedAction(sys, config, logger, coreCompiler, r
|
|
|
968
972
|
}
|
|
969
973
|
/**
|
|
970
974
|
* A function to wrap a compiler task function around. Will send telemetry if, and only if, the machine allows.
|
|
975
|
+
*
|
|
971
976
|
* @param sys The system where the command is invoked
|
|
972
977
|
* @param config The config passed into the Rindo command
|
|
973
978
|
* @param logger The tool used to do logging
|
|
@@ -1013,6 +1018,16 @@ async function getActiveTargets(config) {
|
|
|
1013
1018
|
const result = config.outputTargets.map((t) => t.type);
|
|
1014
1019
|
return Array.from(new Set(result));
|
|
1015
1020
|
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Prepare data for telemetry
|
|
1023
|
+
*
|
|
1024
|
+
* @param coreCompiler the core compiler
|
|
1025
|
+
* @param config the current Rindo config
|
|
1026
|
+
* @param sys the compiler system instance in use
|
|
1027
|
+
* @param duration_ms the duration of the action being tracked
|
|
1028
|
+
* @param component_count the number of components being built (optional)
|
|
1029
|
+
* @returns a Promise wrapping data for the telemetry endpoint
|
|
1030
|
+
*/
|
|
1016
1031
|
const prepareData = async (coreCompiler, config, sys, duration_ms, component_count = undefined) => {
|
|
1017
1032
|
const { typescript, rollup } = coreCompiler.versions || { typescript: 'unknown', rollup: 'unknown' };
|
|
1018
1033
|
const { packages, packagesNoVersions } = await getInstalledPackages(sys, config);
|
|
@@ -1025,6 +1040,7 @@ const prepareData = async (coreCompiler, config, sys, duration_ms, component_cou
|
|
|
1025
1040
|
const cpu_model = sys.details.cpuModel;
|
|
1026
1041
|
const build = coreCompiler.buildId || 'unknown';
|
|
1027
1042
|
const has_app_pwa_config = hasAppTarget(config);
|
|
1043
|
+
const anonymizedConfig = anonymizeConfigForTelemetry(config);
|
|
1028
1044
|
return {
|
|
1029
1045
|
yarn,
|
|
1030
1046
|
duration_ms,
|
|
@@ -1044,13 +1060,86 @@ const prepareData = async (coreCompiler, config, sys, duration_ms, component_cou
|
|
|
1044
1060
|
typescript,
|
|
1045
1061
|
rollup,
|
|
1046
1062
|
has_app_pwa_config,
|
|
1063
|
+
config: anonymizedConfig,
|
|
1047
1064
|
};
|
|
1048
1065
|
};
|
|
1066
|
+
// props in output targets for which we retain their original values when
|
|
1067
|
+
// preparing a config for telemetry
|
|
1068
|
+
//
|
|
1069
|
+
// we omit the values of all other fields on output targets.
|
|
1070
|
+
const OUTPUT_TARGET_KEYS_TO_KEEP = ['type'];
|
|
1071
|
+
// top-level config props that we anonymize for telemetry
|
|
1072
|
+
const CONFIG_PROPS_TO_ANONYMIZE = [
|
|
1073
|
+
'rootDir',
|
|
1074
|
+
'fsNamespace',
|
|
1075
|
+
'packageJsonFilePath',
|
|
1076
|
+
'namespace',
|
|
1077
|
+
'srcDir',
|
|
1078
|
+
'srcIndexHtml',
|
|
1079
|
+
'buildLogFilePath',
|
|
1080
|
+
'cacheDir',
|
|
1081
|
+
'configPath',
|
|
1082
|
+
'tsconfig',
|
|
1083
|
+
];
|
|
1084
|
+
// Props we delete entirely from the config for telemetry
|
|
1085
|
+
//
|
|
1086
|
+
// TODO: Investigate improving anonymization for tsCompilerOptions and devServer
|
|
1087
|
+
const CONFIG_PROPS_TO_DELETE = ['sys', 'logger', 'tsCompilerOptions', 'devServer'];
|
|
1049
1088
|
/**
|
|
1050
|
-
*
|
|
1089
|
+
* Anonymize the config for telemetry, replacing potentially revealing config props
|
|
1090
|
+
* with a placeholder string if they are present (this lets us still track how frequently
|
|
1091
|
+
* these config options are being used)
|
|
1092
|
+
*
|
|
1093
|
+
* @param config the config to anonymize
|
|
1094
|
+
* @returns an anonymized copy of the same config
|
|
1095
|
+
*/
|
|
1096
|
+
const anonymizeConfigForTelemetry = (config) => {
|
|
1097
|
+
var _a;
|
|
1098
|
+
const anonymizedConfig = { ...config };
|
|
1099
|
+
for (const prop of CONFIG_PROPS_TO_ANONYMIZE) {
|
|
1100
|
+
if (anonymizedConfig[prop] !== undefined) {
|
|
1101
|
+
anonymizedConfig[prop] = 'omitted';
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
anonymizedConfig.outputTargets = ((_a = config.outputTargets) !== null && _a !== void 0 ? _a : []).map((target) => {
|
|
1105
|
+
// Anonymize the outputTargets on our configuration, taking advantage of the
|
|
1106
|
+
// optional 2nd argument to `JSON.stringify`. If anything is not a string
|
|
1107
|
+
// we retain it so that any nested properties are handled, else we check
|
|
1108
|
+
// whether it's in our 'keep' list to decide whether to keep it or replace it
|
|
1109
|
+
// with `"omitted"`.
|
|
1110
|
+
const anonymizedOT = JSON.parse(JSON.stringify(target, (key, value) => {
|
|
1111
|
+
if (!(typeof value === 'string')) {
|
|
1112
|
+
return value;
|
|
1113
|
+
}
|
|
1114
|
+
if (OUTPUT_TARGET_KEYS_TO_KEEP.includes(key)) {
|
|
1115
|
+
return value;
|
|
1116
|
+
}
|
|
1117
|
+
return 'omitted';
|
|
1118
|
+
}));
|
|
1119
|
+
// this prop has to be handled separately because it is an array
|
|
1120
|
+
// so the replace function above will be called with all of its
|
|
1121
|
+
// members, giving us `["omitted", "omitted", ...]`.
|
|
1122
|
+
//
|
|
1123
|
+
// Instead, we check for its presence and manually copy over.
|
|
1124
|
+
if (isOutputTargetHydrate(target) && target.external) {
|
|
1125
|
+
anonymizedOT['external'] = target.external.concat();
|
|
1126
|
+
}
|
|
1127
|
+
return anonymizedOT;
|
|
1128
|
+
});
|
|
1129
|
+
// TODO: Investigate improving anonymization for tsCompilerOptions and devServer
|
|
1130
|
+
for (const prop of CONFIG_PROPS_TO_DELETE) {
|
|
1131
|
+
delete anonymizedConfig[prop];
|
|
1132
|
+
}
|
|
1133
|
+
return anonymizedConfig;
|
|
1134
|
+
};
|
|
1135
|
+
/**
|
|
1136
|
+
* Reads package-lock.json, yarn.lock, and package.json files in order to cross-reference
|
|
1051
1137
|
* the dependencies and devDependencies properties. Pulls up the current installed version
|
|
1052
1138
|
* of each package under the @rindo, @navify, and @jigra scopes.
|
|
1053
|
-
*
|
|
1139
|
+
*
|
|
1140
|
+
* @param sys the system instance where telemetry is invoked
|
|
1141
|
+
* @param config the Rindo configuration associated with the current task that triggered telemetry
|
|
1142
|
+
* @returns an object listing all dev and production dependencies under the aforementioned scopes
|
|
1054
1143
|
*/
|
|
1055
1144
|
async function getInstalledPackages(sys, config) {
|
|
1056
1145
|
let packages = [];
|
|
@@ -1129,7 +1218,13 @@ function sanitizeDeclaredVersion(version) {
|
|
|
1129
1218
|
return version.replace(/[*^~]/g, '');
|
|
1130
1219
|
}
|
|
1131
1220
|
/**
|
|
1132
|
-
* If telemetry is enabled, send a metric
|
|
1221
|
+
* If telemetry is enabled, send a metric to an external data store
|
|
1222
|
+
*
|
|
1223
|
+
* @param sys the system instance where telemetry is invoked
|
|
1224
|
+
* @param config the Rindo configuration associated with the current task that triggered telemetry
|
|
1225
|
+
* @param name the name of a trackable metric. Note this name is not necessarily a scalar value to track, like
|
|
1226
|
+
* "Rindo Version". For example, "rindo_cli_command" is a name that is used to track all CLI command information.
|
|
1227
|
+
* @param value the data to send to the external data store under the provided name argument
|
|
1133
1228
|
*/
|
|
1134
1229
|
async function sendMetric(sys, config, name, value) {
|
|
1135
1230
|
const session_id = await getTelemetryToken(sys);
|
|
@@ -1140,10 +1235,11 @@ async function sendMetric(sys, config, name, value) {
|
|
|
1140
1235
|
value,
|
|
1141
1236
|
session_id,
|
|
1142
1237
|
};
|
|
1143
|
-
await sendTelemetry(sys, config,
|
|
1238
|
+
await sendTelemetry(sys, config, message);
|
|
1144
1239
|
}
|
|
1145
1240
|
/**
|
|
1146
1241
|
* Used to read the config file's tokens.telemetry property.
|
|
1242
|
+
*
|
|
1147
1243
|
* @param sys The system where the command is invoked
|
|
1148
1244
|
* @returns string
|
|
1149
1245
|
*/
|
|
@@ -1165,7 +1261,7 @@ async function sendTelemetry(sys, config, data) {
|
|
|
1165
1261
|
try {
|
|
1166
1262
|
const now = new Date().toISOString();
|
|
1167
1263
|
const body = {
|
|
1168
|
-
metrics: [data
|
|
1264
|
+
metrics: [data],
|
|
1169
1265
|
sent_at: now,
|
|
1170
1266
|
};
|
|
1171
1267
|
// This request is only made if telemetry is on.
|
|
@@ -1177,7 +1273,7 @@ async function sendTelemetry(sys, config, data) {
|
|
|
1177
1273
|
body: JSON.stringify(body),
|
|
1178
1274
|
});
|
|
1179
1275
|
hasVerbose(config) &&
|
|
1180
|
-
console.debug('\nSent %O metric to events service (status: %O)', data.
|
|
1276
|
+
console.debug('\nSent %O metric to events service (status: %O)', data.name, response.status, '\n');
|
|
1181
1277
|
if (response.status !== 204) {
|
|
1182
1278
|
hasVerbose(config) &&
|
|
1183
1279
|
console.debug('\nBad response from events service. Request body: %O', response.body.toString(), '\n');
|
|
@@ -1328,7 +1424,8 @@ const taskGenerate = async (coreCompiler, config) => {
|
|
|
1328
1424
|
if (!writtenFiles) {
|
|
1329
1425
|
return config.sys.exit(1);
|
|
1330
1426
|
}
|
|
1331
|
-
//
|
|
1427
|
+
// We use `console.log` here rather than our `config.logger` because we don't want
|
|
1428
|
+
// our TUI messages to be prefixed with timestamps and so on.
|
|
1332
1429
|
console.log();
|
|
1333
1430
|
console.log(`${config.logger.gray('$')} rindo generate ${input}`);
|
|
1334
1431
|
console.log();
|
|
@@ -1442,7 +1539,10 @@ const getBoilerplateByExtension = (tagName, extension, withCss) => {
|
|
|
1442
1539
|
}
|
|
1443
1540
|
};
|
|
1444
1541
|
/**
|
|
1445
|
-
* Get the boilerplate for a component
|
|
1542
|
+
* Get the boilerplate for a file containing the definition of a component
|
|
1543
|
+
* @param tagName the name of the tag to give the component
|
|
1544
|
+
* @param hasStyle designates if the component has an external stylesheet or not
|
|
1545
|
+
* @returns the contents of a file that defines a component
|
|
1446
1546
|
*/
|
|
1447
1547
|
const getComponentBoilerplate = (tagName, hasStyle) => {
|
|
1448
1548
|
const decorator = [`{`];
|
|
@@ -1476,7 +1576,9 @@ const getStyleUrlBoilerplate = () => `:host {
|
|
|
1476
1576
|
}
|
|
1477
1577
|
`;
|
|
1478
1578
|
/**
|
|
1479
|
-
* Get the boilerplate for a spec test
|
|
1579
|
+
* Get the boilerplate for a file containing a spec (unit) test for a component
|
|
1580
|
+
* @param tagName the name of the tag associated with the component under test
|
|
1581
|
+
* @returns the contents of a file that unit tests a component
|
|
1480
1582
|
*/
|
|
1481
1583
|
const getSpecTestBoilerplate = (tagName) => `import { newSpecPage } from '@rindo/core/testing';
|
|
1482
1584
|
import { ${toPascalCase(tagName)} } from '../${tagName}';
|
|
@@ -1498,22 +1600,26 @@ describe('${tagName}', () => {
|
|
|
1498
1600
|
});
|
|
1499
1601
|
`;
|
|
1500
1602
|
/**
|
|
1501
|
-
* Get the boilerplate for an E2E test
|
|
1603
|
+
* Get the boilerplate for a file containing an end-to-end (E2E) test for a component
|
|
1604
|
+
* @param tagName the name of the tag associated with the component under test
|
|
1605
|
+
* @returns the contents of a file that E2E tests a component
|
|
1502
1606
|
*/
|
|
1503
|
-
const getE2eTestBoilerplate = (
|
|
1607
|
+
const getE2eTestBoilerplate = (tagName) => `import { newE2EPage } from '@rindo/core/testing';
|
|
1504
1608
|
|
|
1505
|
-
describe('${
|
|
1609
|
+
describe('${tagName}', () => {
|
|
1506
1610
|
it('renders', async () => {
|
|
1507
1611
|
const page = await newE2EPage();
|
|
1508
|
-
await page.setContent('<${
|
|
1612
|
+
await page.setContent('<${tagName}></${tagName}>');
|
|
1509
1613
|
|
|
1510
|
-
const element = await page.find('${
|
|
1614
|
+
const element = await page.find('${tagName}');
|
|
1511
1615
|
expect(element).toHaveClass('hydrated');
|
|
1512
1616
|
});
|
|
1513
1617
|
});
|
|
1514
1618
|
`;
|
|
1515
1619
|
/**
|
|
1516
1620
|
* Convert a dash case string to pascal case.
|
|
1621
|
+
* @param str the string to convert
|
|
1622
|
+
* @returns the converted input as pascal case
|
|
1517
1623
|
*/
|
|
1518
1624
|
const toPascalCase = (str) => str.split('-').reduce((res, part) => res + part[0].toUpperCase() + part.slice(1), '');
|
|
1519
1625
|
|
package/cli/package.json
CHANGED