Skip to content

Commit

Permalink
Release 1.6.0 (#111)
Browse files Browse the repository at this point in the history
* chore: .gitignore

* refactor: handle 'close' and 'exit' events w/ interactive mode

* refactor: improve handling of scope in environment variables

* feat: create .vulcan and save initialized preset

* fix: remove hot reload infinite loop
  • Loading branch information
jotanarciso authored Sep 11, 2023
1 parent ec5fff8 commit 0744556
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 71 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ out
.temp
.edge
jsdoc
vulcan.env
vulcan.env
.vulcan
wrangler.toml
4 changes: 2 additions & 2 deletions examples/simple-js-esm/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import messages from './messages.js';

const message = messages[Math.floor(Math.random() * messages.length)];

function main(event) {
const message = messages[Math.floor(Math.random() * messages.length)];

console.log('selected message:', message);
console.log('VERSION_ID =', AZION_VERSION_ID);

Expand Down
90 changes: 50 additions & 40 deletions lib/commands/init.commands.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,70 @@
import { join } from 'path';
import { existsSync } from 'fs';
import { createPromptModule } from 'inquirer';
import { FrameworkInitializer, Messages } from '#constants';
import { feedback } from '#utils';
import { feedback, debug } from '#utils';
import { vulcan } from '#env';

const prompt = createPromptModule();

/**
* A command to Initializes a new project with the selected framework template.
* @memberof commands
* This function prompts the user to select a framework template and enter a project name.
* Then it initializes a new project based on the selected template.
* @param {object} options - An object containing the name for the new project.
* @param {string} options.name - The name of the new project.
* Initializes a new project based on the selected framework template.
* @param {object} options - Configuration options for initialization.
* @param {string} options.name - Name of the new project.
* If not provided, the function will prompt for it.
* @returns {Promise<void>} - A promise that resolves when the new project is initialized.
* @example
*
* initCommand({ name: 'my_new_project' });
*/
async function initComamnd({ name }) {
const AVALIABLE_TEMPLATES = Object.keys(FrameworkInitializer);
let projectName = name;

const { frameworkChoice } = await prompt([
{
type: 'list',
name: 'frameworkChoice',
message: 'Choose a template for your project:',
choices: AVALIABLE_TEMPLATES,
},
]);

while (!projectName) {
// eslint-disable-next-line no-await-in-loop
const { projectName: inputName } = await prompt([
try {
const AVALIABLE_TEMPLATES = Object.keys(FrameworkInitializer);
let projectName = name;

const { frameworkChoice } = await prompt([
{
type: 'input',
name: 'projectName',
message: 'Enter your project name:',
type: 'list',
name: 'frameworkChoice',
message: 'Choose a template for your project:',
choices: AVALIABLE_TEMPLATES,
},
]);

if (inputName) {
projectName = inputName;
}
if (!inputName) {
feedback.pending(Messages.info.name_required);
}
}
while (!projectName) {
const dirExists = (dirName) => existsSync(join(process.cwd(), dirName));

// eslint-disable-next-line no-await-in-loop
const { projectName: inputName } = await prompt([
{
type: 'input',
name: 'projectName',
message: 'Enter your project name:',
},
]);

const createFrameworkTemplate = FrameworkInitializer[frameworkChoice];
if (inputName && !dirExists(inputName)) {
projectName = inputName;
} else if (dirExists(inputName)) {
feedback.pending(
Messages.errors.folder_name_already_exists(inputName),
);
} else {
feedback.pending(Messages.info.name_required);
}
}

if (createFrameworkTemplate) {
process.env.VULCAN_CURRENT_PRESET = projectName; // for Azion CLI in Golang(temp)
await createFrameworkTemplate(projectName);
} else {
feedback.error(Messages.errors.invalid_choice);
const createFrameworkTemplate = FrameworkInitializer[frameworkChoice];
if (createFrameworkTemplate) {
const dest = join(process.cwd(), projectName);
await createFrameworkTemplate(projectName);
await vulcan.createVulcanEnv(
{ preset: frameworkChoice.toLowerCase() },
dest,
);
} else {
feedback.error(Messages.errors.invalid_choice);
}
} catch (error) {
debug.error(error);
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/constants/messages/global.messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const global = {
errors: {
unknown_error: 'An error occurred.',
invalid_choice: 'Invalid choice.',
folder_name_already_exists: (folder) => `The folder ${folder} already exists. Please choose a different name.`,
folder_creation_failed: (folder) => `An error occurred while creating the ${folder} folder.`,
write_file_failed: (file) => `An error occurred while writing the ${file} file.`,
file_doesnt_exist: (file) => `An error occurred while reading the ${file} file.`,
Expand Down
2 changes: 1 addition & 1 deletion lib/env/server.env.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ async function handleFileChange(path, workerPath, port) {

isChangeHandlerRunning = true;

if (path.startsWith('vulcan') || path.startsWith('.edge') || path.startsWith('node_modules/.cache')) {
if (path.startsWith('.vulcan') || path.startsWith('.edge') || path.startsWith('node_modules/.cache')) {
isChangeHandlerRunning = false;
return;
}
Expand Down
51 changes: 32 additions & 19 deletions lib/env/vulcan.env.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,31 @@ import fs from 'fs/promises';
import path from 'path';

/**
* Creates or updates Vulcan environment variables, either at the global or project level.
* Creates or updates Vulcan environment variables.
* @async
* @param {object} variables - An object containing the environment variables to set.
* @param {string} [scope='local'] - Determines the scope of the variable ('global' or 'local').
* @param {string} [scope='local'] - Can be 'global', 'local', or a custom path.
* @throws {Error} Throws an error if the environment file cannot be read or written.
* @example
* // Set multiple global environment variables
* createVulcanEnv({ API_KEY: 'abc123', ANOTHER_KEY: 'xyz' }, 'global')
* .catch(error => console.error(error));
*/
async function createVulcanEnv(variables, scope = 'global') {
const basePath = scope === 'global' ? path.join(process.env.HOME, '.azion') : path.join(process.cwd());
const vulcanEnvPath = path.join(basePath, 'vulcan.env');
let basePath;
switch (scope) {
case 'global':
basePath = path.join(process.env.HOME, '.azion');
break;
case 'local':
basePath = path.join(process.cwd());
break;
default:
basePath = scope;
break;
}
const vulcanEnvPath = path.join(basePath, '.vulcan');

// Create the .azion folder if it doesn't exist
try {
await fs.mkdir(basePath, { recursive: true });
} catch (error) {
Expand All @@ -27,7 +37,6 @@ async function createVulcanEnv(variables, scope = 'global') {
throw error;
}

// Read the existing Vulcan environment file if it exists
let envData = '';
try {
envData = await fs.readFile(vulcanEnvPath, 'utf8');
Expand All @@ -39,7 +48,6 @@ async function createVulcanEnv(variables, scope = 'global') {
}
}

// Update or add each variable to the environment data
Object.entries(variables).forEach(([key, value]) => {
const variableLine = `${key}=${value}`;
const variableRegex = new RegExp(`${key}=.+`);
Expand All @@ -51,7 +59,6 @@ async function createVulcanEnv(variables, scope = 'global') {
}
});

// Write the updated environment data to the file
try {
await fs.writeFile(vulcanEnvPath, envData);
} catch (error) {
Expand All @@ -62,10 +69,8 @@ async function createVulcanEnv(variables, scope = 'global') {
}

/**
* Reads the vulcan.env file, either at the global or project level,
* and returns an object with the variables and their values.
* @param {string} [scope='local'] - Determines the scope of the environment
* file ('global' or 'local').
* Reads the .vulcan file and returns an object with the variables and their values.
* @param {string} [scope='local'] - Can be 'global', 'local', or a custom path.
* @returns {Promise<object|null>} A promise that resolves to an object with
* the variables and their values, or null if the file doesn't exist.
* @throws {Error} Throws an error if the environment file cannot be read.
Expand All @@ -81,16 +86,24 @@ async function createVulcanEnv(variables, scope = 'global') {
* .catch(error => console.error(error));
*/
async function readVulcanEnv(scope = 'global') {
const basePath = scope === 'global' ? path.join(process.env.HOME, '.azion') : path.join(process.cwd());
const vulcanEnvPath = path.join(basePath, 'vulcan.env');
let basePath;
switch (scope) {
case 'global':
basePath = path.join(process.env.HOME, '.azion');
break;
case 'local':
basePath = path.join(process.cwd());
break;
default:
basePath = scope;
break;
}
const vulcanEnvPath = path.join(basePath, '.vulcan');

try {
// Check if the vulcan.env file exists
await fs.access(vulcanEnvPath);

// Read the file contents
const fileContents = await fs.readFile(vulcanEnvPath, 'utf8');
// Parse the variables from the file contents

const variables = {};
const variableRegex = /^([^=]+)=(.*)$/gm;
let match = variableRegex.exec(fileContents);
Expand All @@ -107,7 +120,7 @@ async function readVulcanEnv(scope = 'global') {
return null;
}
debug.error(error);
feedback.error(Messages.errors.write_file_failed(vulcanEnvPath));
feedback.error(Messages.errors.read_file_failed(vulcanEnvPath));
throw error;
}
}
Expand Down
24 changes: 16 additions & 8 deletions lib/utils/exec/exec.utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,23 @@ async function exec(command, scope = 'Process', verbose = false, interactive = f
execProcess.on('error', (error) => {
reject(error);
});

execProcess.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command '${command}' failed with code ${code}`));
}
});
}

execProcess.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command '${command}' failed with code ${code}`));
}
});

execProcess.on('exit', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command '${command}' failed with code ${code}`));
}
});
});
}

Expand Down

0 comments on commit 0744556

Please sign in to comment.