Skip to content

Commit a9317f4

Browse files
committed
type safety! part 1
1 parent 3d78bf2 commit a9317f4

27 files changed

+454
-244
lines changed

.prettierrc

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
{
2-
"tabWidth": 4,
3-
"useTabs": false,
4-
"printWidth": 150,
5-
"arrowParens": "avoid",
6-
"trailingComma": "none",
7-
"embeddedLanguageFormatting": "off"
8-
9-
}
2+
"tabWidth": 4,
3+
"useTabs": false,
4+
"printWidth": 112,
5+
"arrowParens": "avoid",
6+
"trailingComma": "none",
7+
"embeddedLanguageFormatting": "off",
8+
"overrides": [
9+
{
10+
"files": [
11+
"package-lock.json",
12+
"package.json"
13+
],
14+
"options": {
15+
"requirePragma": true,
16+
"parser": "json"
17+
}
18+
}
19+
]
20+
}

.vscode/launch.json

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
11
{
22
"configurations": [
33
{
4-
"command": "npm run test-watch",
4+
"command": "npm run test-local-watch",
55
"name": "local tests",
66
"request": "launch",
77
"type": "node-terminal"
88
},
9+
{
10+
"command": "npm run build-types-watch",
11+
"name": "build types",
12+
"request": "launch",
13+
"type": "node-terminal"
14+
},
15+
{
16+
"command": "npm run push-watch",
17+
"name": "auto push",
18+
"request": "launch",
19+
"type": "node-terminal"
20+
}
921
{
1022
"command": "npm run test-server",
1123
"name": "server tests",
1224
"request": "launch",
1325
"type": "node-terminal"
1426
}
27+
],
28+
"compounds": [
29+
{
30+
"name": "all watchers",
31+
"configurations": [
32+
"local tests",
33+
"build types",
34+
"auto push"
35+
],
36+
"stopAll": true
37+
}
1538
]
1639
}

.vscode/tasks.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
"tasks": [
44
{
55
"type": "npm",
6-
"script": "debug",
6+
"script": "debug-watch",
77
"problemMatcher": [],
88
"label": "REPL",
99
"detail": "runs one-off functions in GAS"
1010
},
1111
{
1212
"type": "npm",
13-
"script": "test-watch",
13+
"script": "test-local-watch",
1414
"problemMatcher": [],
1515
"label": "LOCAL TEST",
1616
"detail": "runs local tests"
@@ -28,6 +28,14 @@
2828
"problemMatcher": [],
2929
"label": "OPEN LOGGER",
3030
"detail": "show GCP console"
31+
},
32+
{
33+
"type": "npm",
34+
"script": "push-watch",
35+
"group": "build",
36+
"problemMatcher": [],
37+
"label": "npm: push-watch",
38+
"detail": "clasp push --watch --force"
3139
}
3240
]
3341
}

Code.js

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ TODOs
2626
----
2727
*/
2828

29-
// todo: ui for export
30-
// todo: hourly syncs, sync display, & sync logs
29+
// todo: syncs + sync logs
3130
// todo: docs
3231

3332
/*
@@ -97,11 +96,16 @@ function SheetToMixpanelView() {
9796
*
9897
* @param {SheetMpConfig} config if not supplied, last known will be used
9998
* @param {SheetInfo} sheetInfo the source sheet which contains the data
100-
* @returns {[ImportResponse[], Summary]}
99+
* @returns {[ImportResponse[], ImportResults, string]}
101100
*/
102-
function testSyncSheetsToMp(config = {}, sheetInfo = SpreadsheetApp.getActiveSheet()) {
101+
function testSyncSheetsToMp(config, sheetInfo = getSheetInfo(SpreadsheetApp.getActiveSheet())) {
103102
const testId = Math.random();
104-
const t = tracker({ testId, record_type: config.record_type, project_id: config.project_id, view: "sheet → mixpanel" });
103+
const t = tracker({
104+
testId,
105+
record_type: config?.record_type,
106+
project_id: config?.project_id,
107+
view: "sheet → mixpanel"
108+
});
105109
try {
106110
const auth = validateCreds(config);
107111
config.auth = auth;
@@ -113,19 +117,24 @@ function testSyncSheetsToMp(config = {}, sheetInfo = SpreadsheetApp.getActiveShe
113117

114118
t("test start"); //something happening here... what it is ain't exactly clear
115119
const [responses, summary] = importData(config, sheet);
116-
const { total, success, failed, seconds } = summary.results;
120+
const { total, success, failed, seconds } = summary;
117121
t("test end", { total, success, failed, seconds });
118122

123+
//store config for future syncs
124+
setConfig({ ...config, ...sheetInfo });
125+
119126
return [responses, summary, `https://mixpanel.com/project/${config.project_id}`];
120127
}
121128

122129
/**
123130
* called when a user clicks the 'sync' button in the Sheet → Mixpanel UI
124131
*
125132
* @param {SheetMpConfig} config
126-
* @returns {[ImportResponse[], Summary] | SheetMpConfig}
133+
// * @returns {[ImportResponse[], ImportResults[], string]}
127134
*/
128-
function syncSheetsToMp(config) {}
135+
function syncSheetsToMp(config) {
136+
return;
137+
}
129138

130139
/*
131140
----------------
@@ -159,9 +168,9 @@ function MixpanelToSheetView() {
159168
*
160169
* @param {MpSheetConfig} config if not supplied, last known will be used
161170
*/
162-
function testSyncMpToSheets(config = {}) {
171+
function testSyncMpToSheets(config) {
163172
const testId = Math.random();
164-
const t = tracker({ testId, record_type: config.record_type, project_id: config.project_id, view: "mixpanel → sheet" });
173+
const t = tracker({ testId, project_id: config.project_id, view: "mixpanel → sheet" });
165174

166175
try {
167176
const auth = validateCreds(config);
@@ -188,7 +197,7 @@ function testSyncMpToSheets(config = {}) {
188197
}
189198

190199
const destSheet = createSheet(sheetName);
191-
const updatedSheet = updateSheet(csvData, destSheet);
200+
const updatedSheet = overwriteSheet(csvData, destSheet);
192201

193202
t("test end");
194203

@@ -219,3 +228,15 @@ REF DOCS
219228
// ? delete triggers: https://stackoverflow.com/a/47217237
220229
// ? tests: https://github.com/WildH0g/UnitTestingApp
221230
//? bundling npm modules: https://12ft.io/proxy?q=https%3A%2F%2Fmedium.com%2Fgeekculture%2Fthe-ultimate-guide-to-npm-modules-in-google-apps-script-a84545c3f57c
231+
232+
if (typeof module !== "undefined") {
233+
const { tracker } = require("./utilities/tracker.js");
234+
const {
235+
getSheetHeaders,
236+
getSheetById,
237+
getSheetInfo,
238+
createSheet,
239+
overwriteSheet
240+
} = require("./utilities/sheet");
241+
const { validateCreds } = require("./utilities/validate.js");
242+
}

components/dataExport.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ DATA OUT OF MP
88
* export data; if not called with a config, uses last known
99
*
1010
* @param {MpSheetConfig} [config={}]
11-
* @returns {[string, ReportMeta | CohortMeta]} string + metadata `[csv, {}]`
11+
* @returns {[string, ReportMeta & CohortMeta]} string + metadata `[csv, {}]`
1212
*/
1313
function exportData(config = {}) {
1414
const startTime = Date.now();

components/dataImport.js

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ DATA INTO MP
99
*
1010
* @param {SheetMpConfig} [config={}]
1111
* @param {GoogleAppsScript.Spreadsheet.Sheet} sheet
12-
* @returns {[ImportResponse[], Summary]}
12+
* @returns {[ImportResponse[], Results]}
1313
*/
1414
function importData(config = {}, sheet) {
1515
const runId = Math.random();
@@ -28,23 +28,23 @@ function importData(config = {}, sheet) {
2828
const sourceData = getJSON(sheet);
2929

3030
// console.log(`TRANSFORM: ${comma(sourceData.length)} ${config.record_type}s`);
31-
const targetData = sourceData.slice().map((row) => transform(row, mappings, cleanConfig));
31+
const targetData = sourceData.slice().map(row => transform(row, mappings, cleanConfig));
3232

3333
// console.log(`FLUSH: ${comma(targetData.length)} ${config.record_type}s`);
3434
const imported = flushToMixpanel(targetData, cleanConfig);
3535
const endTime = Date.now();
36-
const runTime = Math.floor(endTime - startTime) / 1000;
36+
3737
// track('FLUSH', { runId, record_type });
3838

3939
// console.log(`FINISHED: ${runTime} seconds`);
40-
updateConfig(cleanConfig, imported, runTime, targetData);
40+
const summary = summarizeImport(cleanConfig, imported, startTime, endTime, targetData);
4141

4242
if (cleanConfig.results.errors.length > 0) {
4343
Logger.log("FAILED REQUESTS");
4444
Logger.log(cleanConfig.results.errors);
4545
}
4646

47-
return [imported, cleanConfig];
47+
return [imported, summary];
4848
}
4949

5050
/**
@@ -54,25 +54,15 @@ function importData(config = {}, sheet) {
5454
* @returns {EventMappings | UserMappings | GroupMappings | TableMappings}
5555
*/
5656
function getMappings(config) {
57-
const {
58-
record_type,
59-
event_name_col,
60-
distinct_id_col,
61-
time_col,
62-
insert_id_col,
63-
name_col,
64-
email_col,
65-
avatar_col,
66-
created_col,
67-
profile_operation,
68-
} = config;
57+
const { record_type, event_name_col, distinct_id_col, time_col, insert_id_col, name_col, email_col, avatar_col, created_col, profile_operation } =
58+
config;
6959

7060
if (record_type === "event") {
7161
return {
7262
distinct_id_col,
7363
event_name_col,
7464
time_col,
75-
insert_id_col,
65+
insert_id_col
7666
};
7767
}
7868

@@ -83,7 +73,7 @@ function getMappings(config) {
8373
email_col,
8474
avatar_col,
8575
created_col,
86-
profile_operation,
76+
profile_operation
8777
};
8878
}
8979

@@ -94,7 +84,7 @@ function getMappings(config) {
9484
email_col,
9585
avatar_col,
9686
created_col,
97-
profile_operation,
87+
profile_operation
9888
};
9989
}
10090

@@ -125,8 +115,8 @@ function getMixpanelConfig(config) {
125115
failed: 0,
126116
batches: 0,
127117
seconds: 0,
128-
errors: [],
129-
},
118+
errors: []
119+
}
130120
};
131121

132122
if (record_type === "group") mixpanel.batchSize = 200;
@@ -151,14 +141,19 @@ function getTransformType(config) {
151141
}
152142

153143
/**
154-
* uses the responses to update the config; warning SIDE EFFECTS!!!
155-
* @param {MpSheetConfig} config
144+
* uses the responses to update the config
145+
* @param {MpSheetConfig} cleanConfig
156146
* @param {Responses} responses
157-
* @param {number} runTime
147+
* @param {number} startTime
148+
* @param {number} endTime
158149
* @param {mpEvent[] | mpUser[] | mpGroup[] | Object[]} targetData
150+
* @returns {Results}
159151
*/
160-
function updateConfig(config, responses, runTime, targetData) {
161-
config.results.seconds = runTime;
152+
function summarizeImport(cleanConfig, responses, startTime, endTime, targetData) {
153+
config = clone(cleanConfig);
154+
config.results.startTime = startTime;
155+
config.results.endTime = endTime;
156+
config.results.seconds = Math.floor(endTime - startTime) / 1000;
162157
config.results.total = targetData.length;
163158
config.results.batches = responses.length;
164159

@@ -186,4 +181,7 @@ function updateConfig(config, responses, runTime, targetData) {
186181
if (config.results.success > config.results.total) config.results.success = config.results.total;
187182
if (config.results.failed > config.results.total) config.results.failed = config.results.total;
188183
}
184+
185+
config.results.record_type = config.record_type;
186+
return config.results;
189187
}

jsconfig.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
{
22
"compilerOptions": {
33
"module": "None",
4-
"checkJs": false,
5-
"typeRoots" : ["./node_modules/@types", "./types"]
4+
"checkJs": true,
5+
"typeRoots": [
6+
"./node_modules/@types",
7+
"./types"
8+
]
69
},
7-
"exclude": ["node_modules"]
10+
"exclude": [
11+
"node_modules"
12+
],
13+
"typeAcquisition": {
14+
"enable": false
15+
}
816
}

models/modelEvents.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,8 @@ function modelMpEvents(row, mappings) {
5757

5858
return mpEvent;
5959
}
60+
61+
if (typeof module !== "undefined") {
62+
const { MD5 } = require("../utilities/md5.js");
63+
module.exports = { modelMpEvents };
64+
}

0 commit comments

Comments
 (0)