Skip to content

Commit

Permalink
Merge pull request #3 from nomo-app/init-nomo_cli.config.js
Browse files Browse the repository at this point in the history
Init nomo cli.config.js
  • Loading branch information
dev2-nomo authored Nov 20, 2023
2 parents 7b0c354 + 14b0cfa commit f72f43b
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 88 deletions.
27 changes: 0 additions & 27 deletions nomo_cli.config.js

This file was deleted.

8 changes: 0 additions & 8 deletions out/nomo_manifest.json

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nomo-webon-cli",
"version": "0.1.1",
"version": "0.1.0",
"description": "A CLI for building and deploying Nomo WebOns",
"repository": {
"type": "git",
Expand Down
102 changes: 87 additions & 15 deletions src/init/init.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as fs from "fs";
import * as path from "path";
import { NomoManifest } from "./interface";
import { NomoManifest, NomoCliConfig, GeneratedFile } from "./interface";
import { isValidWebOnId } from "../util/validate-manifest";

async function getUserInput(prompt: string): Promise<string> {
// Import inquirer dynamically
const inquirer = require("inquirer");

const { userInput } = await (inquirer as any).prompt([
Expand All @@ -17,28 +17,100 @@ async function getUserInput(prompt: string): Promise<string> {
return userInput;
}

async function generateNomoManifestContent(
webonId: string,
webonName: string
): Promise<NomoManifest> {
return {
nomo_manifest_version: "1.1.0",
webon_id: webonId,
webon_name: webonName,
webon_version: "0.1.0",
permissions: [],
};
}

function generateNomoCliConfigContent(webonId: string): NomoCliConfig {
return {
deployTargets: {
production: {
rawSSH: {
sshHost: "root@<IP-address>",
sshBaseDir: `/var/www/production_webons/${webonId}/`,
publicBaseUrl: `https://w.nomo.app/${webonId}`,
},
},
staging: {
rawSSH: {
sshHost:
process.env.SSH_TARGET ||
"Set your env SSH_TARGET like: export SSH_TARGET= <value> ",
sshBaseDir: `/var/www/html/webons/${webonId}/`,
publicBaseUrl: `https://staging.nomo.app/${webonId}`,
sshPort: 51110,
},
},
},
};
}

function writeFile(file: GeneratedFile): void {
fs.writeFileSync(file.filePath, file.content);
console.log(`${path.basename(file.filePath)} created successfully.`);
}

export async function init(args: { assetDir: string }): Promise<void> {
const assetDir = args.assetDir;
const manifestFilePath = path.join(assetDir, "nomo_manifest.json");
const cliConfigFilePath = path.join(process.cwd(), "nomo_cli.config.js");

// Check if nomo_manifest.json already exists
if (fs.existsSync(manifestFilePath)) {
console.log("nomo_manifest.json already exists.");
} else {
// Prompt user for input
const webonId = await getUserInput("Enter webon_id: ");
const webonName = await getUserInput("Enter webon_name: ");
const webonId = await getValidWebOnId("Enter unique webon_id: ");

const nomoManifest = await generateNomoManifestContent(webonId, webonName);

writeFile({
filePath: manifestFilePath,
content: JSON.stringify(nomoManifest, null, 2),
});
}

// Check if nomo_cli.config.js already exists
if (fs.existsSync(cliConfigFilePath)) {
console.log("nomo_cli.config.js already exists.");
} else {
const nomoManifestContent = fs.readFileSync(manifestFilePath, "utf-8");
const nomoManifest: NomoManifest = JSON.parse(nomoManifestContent);

const webonId = nomoManifest.webon_id;
const nomoCliConfig = generateNomoCliConfigContent(webonId);

writeFile({
filePath: cliConfigFilePath,
content: `/**
* This is a sample configuration that can be adapted to your needs.
*/
const nomoCliConfig = ${JSON.stringify(nomoCliConfig, null, 2)};
module.exports = {
nomoCliConfig,
};`,
});
}
}

// Create nomo_manifest.json with user input
const nomoManifest: NomoManifest = {
nomo_manifest_version: "1.1.0",
webon_id: webonId,
webon_name: webonName,
webon_version: "0.1.0",
permissions: [],
};

fs.writeFileSync(manifestFilePath, JSON.stringify(nomoManifest, null, 2));
console.log("nomo_manifest.json created successfully.");
async function getValidWebOnId(prompt: string): Promise<string> {
let webonId = await getUserInput(prompt);
while (!isValidWebOnId(webonId)) {
console.error(`Invalid webon_id: ${webonId}`);
webonId = await getUserInput(
"Enter an unique valid webon_id like demo.web.app for example:"
);
}
return webonId;
}
97 changes: 60 additions & 37 deletions src/init/interface.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,61 @@
export interface NomoManifest {
/**
* If min_nomo_version is set, then outdated versions of the Nomo App will refuse to install the WebOn.
*/
min_nomo_version?: string | null;
/**
* nomo_manifest_version should be 1.1.0.
*/
nomo_manifest_version: string;
/**
* A list of permissions for security-critical features.
*/
permissions: string[];
/**
* webon_id should be the reverse-domain of a domain that is owned by the WebOn-author.
* See https://en.wikipedia.org/wiki/Reverse_domain_name_notation for more details about the reverse domain name notation.
*/
webon_id: string;
/**
* webon_name is the user-visible name of the WebOn.
*/
webon_name: string;
/**
* webon_version should comply with the semantic versioning standard.
* See https://semver.org/ for details.
*/
webon_version: string;
/**
* If true, then the WebOn could be displayed in both card-mode and fullscreen-mode.
* If false, then the WebOn will only be displayed in fullscreen-mode.
*/
card_mode?: boolean;
/**
* If defined, then the WebOn can decide whether a navigation bar should be shown or not.
*/
show_navbar?: boolean;
}

/**
* If min_nomo_version is set, then outdated versions of the Nomo App will refuse to install the WebOn.
*/
min_nomo_version?: string | null;
/**
* nomo_manifest_version should be 1.1.0.
*/
nomo_manifest_version: string;
/**
* A list of permissions for security-critical features.
*/
permissions: string[];
/**
* webon_id should be the reverse-domain of a domain that is owned by the WebOn-author.
* See https://en.wikipedia.org/wiki/Reverse_domain_name_notation for more details about the reverse domain name notation.
*/
webon_id: string;
/**
* webon_name is the user-visible name of the WebOn.
*/
webon_name: string;
/**
* webon_version should comply with the semantic versioning standard.
* See https://semver.org/ for details.
*/
webon_version: string;
/**
* If true, then the WebOn could be displayed in both card-mode and fullscreen-mode.
* If false, then the WebOn will only be displayed in fullscreen-mode.
*/
card_mode?: boolean;
/**
* If defined, then the WebOn can decide whether a navigation bar should be shown or not.
*/
show_navbar?: boolean;
}

export interface NomoCliConfig {
deployTargets: {
production: {
rawSSH: {
sshHost: string;
sshBaseDir: string;
publicBaseUrl: string;
};
};
staging: {
rawSSH: {
sshHost: string;
sshBaseDir: string;
publicBaseUrl: string;
sshPort: number;
};
};
};
}
export interface GeneratedFile {
filePath: string;
content: string;
}
75 changes: 75 additions & 0 deletions src/util/validate-manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { NomoManifest } from "../init/interface";

class WebOnError extends Error {
constructor(message: string) {
super(message);
this.name = "WebOnError";
}
}

async function validateManifest(
manifest: NomoManifest,
webonUrl: string,
{ devMode }: { devMode: boolean }
): Promise<void> {
const webonVersion = manifest.webon_version;
if (!_isValidSemanticVersion(webonVersion)) {
throw new WebOnError(
`webon_version ${webonVersion} does not comply with semantic versioning regexp`
);
}

const webonId = manifest.webon_id;
if (!isValidWebOnId(webonId)) {
throw new WebOnError(`webon_id ${webonId} does not comply with regexp`);
}

const manifestVersion = manifest.nomo_manifest_version;
if (!_isValidSemanticVersion(manifestVersion)) {
throw new WebOnError(
`nomo_manifest_version ${manifestVersion} does not comply with semantic versioning regexp`
);
}

if (manifest.webon_name.trim() == null) {
throw new WebOnError("webon_name is empty");
}

const minNomoVersion = manifest.min_nomo_version;
if (minNomoVersion != null) {
if (!_isValidSemanticVersion(minNomoVersion)) {
throw new WebOnError(
`min_nomo_version ${minNomoVersion} does not comply with semantic versioning regexp`
);
}
// Assume you have a function similar to versionTwoGreaterThanVersionOne
const currentVersion = "1.2.0"; // You need to replace this with the actual version
if (versionTwoGreaterThanVersionOne(currentVersion, minNomoVersion)) {
throw new WebOnError(
`Nomo App outdated! This WebOn requires ${minNomoVersion}, but the current version is ${currentVersion}`
);
}
}
}


function _isValidSemanticVersion(version: string): boolean {
const pattern = /^(\d+)\.(\d+)\.(\d+)$/;
const regex = new RegExp(pattern);
return regex.test(version);
}

// Assuming versionTwoGreaterThanVersionOne is a function you have implemented
function versionTwoGreaterThanVersionOne(
versionTwo: string,
versionOne: string
): boolean {
// Implement the comparison logic here
return false;
}

export function isValidWebOnId(webon_id: string): boolean {
const webonIdRegExp =
/^(?:[a-zA-Z0-9_-]+\.)*[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+$/;
return webonIdRegExp.test(webon_id);
}

0 comments on commit f72f43b

Please sign in to comment.