Skip to content

Commit

Permalink
Finishing verbose mode and error messaging with CLI moduleg
Browse files Browse the repository at this point in the history
  • Loading branch information
vzhang03 committed Aug 1, 2024
1 parent 0b10725 commit d8a35f6
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 44 deletions.
79 changes: 79 additions & 0 deletions dev/v8-data/dataset_description.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,85 @@
"levels": [
"y"
]
},
{
"@type": "PropertyValue",
"name": "slider_start",
"description": "The starting value of the slider.",
"value": "number",
"minValue": 50,
"maxValue": 50
},
{
"@type": "PropertyValue",
"name": "correct",
"description": "`true` if the participant got the correct answer, `false` otherwise.",
"value": "boolean",
"levels": [
false
]
},
{
"@type": "PropertyValue",
"name": "device_id",
"description": "The [device ID](https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/deviceId) of the selected camera.",
"value": "string",
"levels": [
"224904af1fc7ec895c764b361a04a167504d8af498a36c576e...",
"ed812fc33d145bfb870d47b64ec9702b3456f6640af448d78b..."
]
},
{
"@type": "PropertyValue",
"name": "extension_type",
"description": "The name(s) of the extension(s) used in the trial.",
"value": "string"
},
{
"@type": "PropertyValue",
"name": "extension_version",
"description": "The version(s) of the extension(s) used in the trial.",
"value": "numeric"
},
{
"@type": "PropertyValue",
"name": "record_video_data",
"description": "[Base 64 encoded](https://developer.mozilla.org/en-US/docs/Glossary/Base64) representation of the video data.",
"value": "string",
"levels": [
"GkXfo6NChoEBQveBAULygQRC84EIQoKIbWF0cm9za2FCh4EEQo...",
"GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQRChYECGF..."
]
},
{
"@type": "PropertyValue",
"name": "task",
"description": "unknown",
"value": "string",
"levels": [
"draw",
"replay"
]
},
{
"@type": "PropertyValue",
"name": "mouse_tracking_data",
"description": "* An array of objects containing mouse movement data for the trial. Each object has an `x`, a `y`, a `t`, and an * `event` property. The `x` and `y` properties specify the mouse coordinates in pixels relative to the top left * corner of the viewport and `t` specifies the time in milliseconds since the start of the trial. The `event` * will be either 'mousemove', 'mousedown', or 'mouseup' depending on which event was generated.",
"value": "object"
},
{
"@type": "PropertyValue",
"name": "mouse_tracking_targets",
"description": "* An object contain the pixel coordinates of elements on the screen specified by the `.targets` parameter. Each key * in this object will be a `selector` property, containing the CSS selector string used to find the element. The object * corresponding to each key will contain `x` and `y` properties specifying the top-left corner of the object, `width` * and `height` values, plus `top`, `bottom`, `left`, and `right` parameters which specify the * [bounding rectangle](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) of the element.",
"value": "object"
},
{
"@type": "PropertyValue",
"name": "index",
"description": "The index of the current trial across the whole experiment.",
"value": "numeric",
"minValue": 0,
"maxValue": 16
}
]
}
18 changes: 4 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"metadata",
"cli"
],
"repository": {
"repository": {
"url": "https://github.com/jspsych/metadata"
},
"bin": {
Expand All @@ -25,9 +25,7 @@
"data:abs": "node dist/esm/cli.js ~/Documents/work/ursi2024/metadata/dev/data ~/Documents/work/ursi2024/metadata/dev/options/metadata-options.json",
"data:rec": "node dist/esm/cli.js ../../dev/data-rec",
"options": "node dist/esm/cli.js ../../dev/data ../../dev/options/metadata-options.json",

"build": "npm run build:esm && npm run build:cjs",

"build:esm": "npm run build:no-prompt:esm && npm run build:data:esm && npm run build:validate:esm && npm run build:files:esm && npm run build:utils:esm && npm run build:cli:esm",
"build:no-prompt:esm": "esbuild src/cli.ts --bundle --format=esm --platform=node --outfile=dist/esm/cli.js",
"build:data:esm": "esbuild src/data.ts --packages=external --format=esm --platform=node --outfile=dist/esm/data.js",
Expand All @@ -36,7 +34,6 @@
"build:utils:esm": "esbuild src/utils.ts --packages=external --format=esm --platform=node --outfile=dist/esm/utils.js",
"build:cli:esm": "esbuild src/index.ts --packages=external --format=esm --platform=node --outfile=dist/esm/index.js",
"cli": "node dist/esm/index.js",

"build:cjs": "npm run build:no-prompt:cjs && npm run build:data:cjs && npm run build:validate:cjs && npm run build:files:cjs && npm run build:utils:cjs && npm run build:cli:cjs",
"build:no-prompt:cjs": "esbuild src/cli.ts --bundle --format=cjs --platform=node --outfile=dist/cjs/cli.js",
"build:data:cjs": "esbuild src/data.ts --packages=external --format=cjs --platform=node --outfile=dist/cjs/data.js",
Expand All @@ -50,6 +47,7 @@
"fuzzy": "^0.1.3",
"inquirer": "^10.0.1",
"inquirer-autocomplete-prompt": "^3.0.1",
"metadata": "file:../metadata/"
"metadata": "file:../metadata/",
"yargs": "^17.7.2"
}
}
18 changes: 9 additions & 9 deletions packages/cli/src/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const generatePath = (inputPath) => {
}
};

const copyFileWithStructure = async (sourceFilePath, targetDirectoryPath) => {
const copyFileWithStructure = async (sourceFilePath, verbose, targetDirectoryPath) => {
try {
sourceFilePath = expandHomeDir(sourceFilePath);
targetDirectoryPath = expandHomeDir(targetDirectoryPath);
Expand All @@ -25,16 +25,16 @@ const copyFileWithStructure = async (sourceFilePath, targetDirectoryPath) => {

// Copy the file
await fs.promises.copyFile(sourceFilePath, targetFilePath);
// console.log(`File copied from ${sourceFilePath} to ${targetFilePath}`); can delete
if (verbose) console.log(`File copied from ${sourceFilePath} to ${targetFilePath}`);
} catch (error) {
console.error(`Failed to copy file from ${sourceFilePath} to ${targetDirectoryPath}:`, error);
}
};

// processing single file, need to refactor this into a seperate call
const processFile = async (metadata, directoryPath, file, targetDirectoryPath?) => {
const processFile = async (metadata, directoryPath, file, verbose, targetDirectoryPath?) => {
const filePath = path.join(directoryPath, file);
// console.log("Reading file:", filePath); -> does not need to count the number of files that read
if (verbose) console.log("Reading file:", filePath);

try {
const content = await fs.promises.readFile(filePath, "utf8");
Expand All @@ -53,7 +53,7 @@ const processFile = async (metadata, directoryPath, file, targetDirectoryPath?)
return false;
}

if (targetDirectoryPath) await copyFileWithStructure(filePath, targetDirectoryPath); // error catching to create backwards compability with CLI and old cli prompting
if (targetDirectoryPath) await copyFileWithStructure(filePath, verbose, targetDirectoryPath); // error catching to create backwards compability with CLI and old cli prompting
} catch (err) {
console.error(`Error reading file ${file}: ${err} Please ensure this is data generated by JsPsych.`);
return false;
Expand All @@ -63,7 +63,7 @@ const processFile = async (metadata, directoryPath, file, targetDirectoryPath?)
}

// Processing directory recursively up to one level
export const processDirectory = async (metadata, directoryPath, targetDirectoryPath?) => {
export const processDirectory = async (metadata, directoryPath, verbose, targetDirectoryPath?) => {
let total = 0;
let failed = 0;

Expand All @@ -89,7 +89,7 @@ export const processDirectory = async (metadata, directoryPath, targetDirectoryP
await processDirectoryRecursive(itemPath, level + 1);
} else {
total += 1;
if (!await processFile(metadata, currentPath, item.name, targetDirectoryPath)) failed += 1; // returns false if failed
if (!await processFile(metadata, currentPath, item.name, verbose, targetDirectoryPath)) failed += 1; // returns false if failed
}
}

Expand All @@ -105,12 +105,12 @@ export const processDirectory = async (metadata, directoryPath, targetDirectoryP
};

// Processing metadata options json
export const processOptions = async (metadata, filePath) => {
export const processOptions = async (metadata, filePath, verbose) => {
try {
const metadata_options_path = generatePath(filePath);
const data = fs.readFileSync(metadata_options_path, "utf8"); // synchronous read

console.log("\nmetadata options:", data, "\n"); // log the raw data
if (verbose) console.log("\nmetadata options:", data, "\n"); // log the raw data
var metadata_options = JSON.parse(data); // parse the JSON data

metadata.updateMetadata(metadata_options);
Expand Down
31 changes: 23 additions & 8 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
#!/usr/bin/env node

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { input, select } from '@inquirer/prompts';
import JsPsychMetadata from "metadata";
import { processDirectory, processOptions, saveTextToPath, loadMetadata } from "./data.js";
import { validateDirectory, validateJson } from './validateFunctions.js';
import { createDirectoryWithStructure } from './handleFiles.js';

async function metadataOptionsPrompt(metadata){
// Define a type for the parsed arguments
interface Args {
verbose?: boolean;
[x: string]: unknown;
}

// Parse the arguments and cast them to the defined type
const argv = yargs(hideBin(process.argv)).argv as Args;

async function metadataOptionsPrompt(metadata, verbose){
const answer = await select({
message: 'Would you like to customize the metadata by providing a .json specifying changes?',
choices: [
Expand Down Expand Up @@ -34,7 +45,7 @@ async function metadataOptionsPrompt(metadata){
}
});

await processOptions(metadata, optionsPath);
await processOptions(metadata, optionsPath, verbose);
}

return optionsPath;
Expand Down Expand Up @@ -108,7 +119,7 @@ const promptName = async () => {
return project_name;
}

const promptData = async (metadata, targetDirectoryPath) => {
const promptData = async (metadata, verbose, targetDirectoryPath) => {
// can prompt an additional reading data -> keeps reading data until it is done and then writes it to the data_directory of the folder
var data_path;

Expand All @@ -122,23 +133,27 @@ const promptData = async (metadata, targetDirectoryPath) => {
}
});

await processDirectory(metadata, data_path, targetDirectoryPath); // will check if already existing metadata and won't need to prompt
await processDirectory(metadata, data_path, verbose, targetDirectoryPath); // will check if already existing metadata and won't need to prompt
}

const main = async () => {
const metadata = new JsPsychMetadata();
var [project_path, new_project] = await promptProjectStructure(metadata); // -> if reading from existing will want to look for if dataset_description file exists
const verbose = argv.verbose ? argv.verbose : false;

const metadata = new JsPsychMetadata(verbose);
var [ project_path, new_project ] = await promptProjectStructure(metadata); // -> if reading from existing will want to look for if dataset_description file exists

if (new_project) {
const project_name = await promptName();
project_path = `${project_path}/${project_name}`;
createDirectoryWithStructure(project_path); // change the message
}
await promptData(metadata, `${project_path}/data`);
await promptData(metadata, verbose, `${project_path}/data`);

await metadataOptionsPrompt(metadata); // passing in options file to overwite existing file
await metadataOptionsPrompt(metadata, verbose); // passing in options file to overwite existing file

const metadataString = JSON.stringify(metadata.getMetadata(), null, 2); // Assuming getMetadata() is the function that retrieves your metadata

if (argv.verbose) console.log("Final metadata string:\n\n", metadataString);
saveTextToPath(metadataString,`${project_path}/dataset_description.json`);
};

Expand Down
Loading

0 comments on commit d8a35f6

Please sign in to comment.