etranzact-fe-cli 0.0.3 → 0.0.5

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/README.md CHANGED
@@ -3,13 +3,12 @@
3
3
 
4
4
  ```bash
5
5
  pnpm add etranzact-fe-cli -g
6
+ npm add etranzact-fe-cli -g
6
7
  ```
7
8
 
8
9
  ## Usage
9
10
 
10
11
  ```bash
11
- npx etz-cli new [project-name]
12
+ npx etranzact new [project-name]
12
13
  ```
13
14
 
14
- <!-- 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 -->
15
- <!-- git remote set-url origin https://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@github.com/olayinkaa/etz-cli.git -->
package/dist/index.cjs CHANGED
@@ -1,109 +1,105 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
25
-
26
- // src/index.ts
27
- var import_commander2 = require("commander");
28
-
29
- // src/commands/scaffold.ts
30
- var import_commander = require("commander");
31
- var import_chalk = __toESM(require("chalk"), 1);
32
- var import_fs_extra = __toESM(require("fs-extra"), 1);
33
- var import_path = __toESM(require("path"), 1);
34
- var import_simple_git = require("simple-git");
35
- var import_ora = __toESM(require("ora"), 1);
36
- var import_inquirer = __toESM(require("inquirer"), 1);
37
- var import_execa = require("execa");
2
+ "use strict";var O=Object.create;var g=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var _=Object.getPrototypeOf,U=Object.prototype.hasOwnProperty;var R=(e,t,s,d)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of D(t))!U.call(e,n)&&n!==s&&g(e,n,{get:()=>t[n],enumerable:!(d=L(t,n))||d.enumerable});return e};var r=(e,t,s)=>(s=e!=null?O(_(e)):{},R(t||!e||!e.__esModule?g(s,"default",{value:e,enumerable:!0}):s,e));var A=require("commander");var k=require("commander"),o=r(require("chalk"),1),l=r(require("fs-extra"),1),E=r(require("path"),1),b=require("simple-git"),S=r(require("ora"),1),j=r(require("inquirer"),1),c=require("execa");var m="https://github.com/olayinkaa/nextjs-starter-template-etz.git",h="https://github.com/MUKE-coder/nodejs-typescript-starter-template.git";function x(e){switch(e){case"next":return{repoUrl:m,label:"Next.js"};case"ts-start":return{repoUrl:m,label:"Tanstack Start"};case"express":return{repoUrl:h,label:"Express"};default:throw new Error("Invalid template selected.")}}var i=r(require("fs-extra"),1),a=r(require("path"),1);var w=`
3
+ import type { SessionOptions } from "iron-session";
4
+ export interface IronSessionData {
5
+ user?:
6
+ | {
7
+ id: number;
8
+ email: string;
9
+ name: string;
10
+ merchant: string;
11
+ roleName: string;
12
+ lastLogin: string;
13
+ permissions: string[];
14
+ image: string;
15
+ }
16
+ | undefined;
17
+ accessToken?: string | undefined;
18
+ refreshToken?: string | undefined;
19
+ expiresAt?: number | undefined;
20
+ }
38
21
 
39
- // src/utils/constants.ts
40
- var NEXT_TEMPLATE = "https://github.com/olayinkaa/nextjs-starter-template-etz.git";
41
- var EXPRESS_TEMPLATE = "https://github.com/MUKE-coder/nodejs-typescript-starter-template.git";
22
+ export const defaultSession: IronSessionData = {
23
+ user: undefined,
24
+ accessToken: undefined,
25
+ refreshToken: undefined,
26
+ expiresAt: undefined,
27
+ };
42
28
 
43
- // src/utils/resolve-templates.ts
44
- function resolveTemplate(template) {
45
- switch (template) {
46
- case "next":
47
- return { repoUrl: NEXT_TEMPLATE, label: "Next.js" };
48
- case "express":
49
- return { repoUrl: EXPRESS_TEMPLATE, label: "Express" };
50
- default:
51
- throw new Error("Invalid template selected.");
52
- }
29
+ export const sessionOptions: SessionOptions = {
30
+ password: process.env.AUTH_SECRET!,
31
+ cookieName: "e-firs-session",
32
+ cookieOptions: {
33
+ secure: process.env.COOKIE_SECURE === "true",
34
+ httpOnly: true,
35
+ sameSite: "lax",
36
+ maxAge: 7 * 24 * 60 * 60, // 7 days
37
+ },
38
+ };
39
+ `,T=`
40
+ import { jwtDecode } from "jwt-decode";
41
+ export interface IDecodedToken {
42
+ id: number;
43
+ name: string;
44
+ roleName: string;
45
+ lastLogin: string;
46
+ permissions: string[];
47
+ merchant: string;
48
+ image: string;
49
+ sub: string;
50
+ iat: number;
51
+ exp: number;
53
52
  }
54
53
 
55
- // src/commands/scaffold.ts
56
- var scaffoldCommand = new import_commander.Command("new");
57
- scaffoldCommand.argument("<project-name>", "name of the project").action(async (projectName) => {
58
- const projectPath = import_path.default.join(process.cwd(), projectName);
59
- if (import_fs_extra.default.existsSync(projectPath)) {
60
- console.error(
61
- import_chalk.default.red(`Error: Directory ${projectName} already exists.`)
62
- );
63
- process.exit(1);
64
- }
65
- const answers = await import_inquirer.default.prompt([
66
- {
67
- type: "rawlist",
68
- name: "template",
69
- message: "Which template would you like to use?",
70
- choices: [
71
- { name: "Nextjs", value: "next" },
72
- { name: "Tanstack Start", value: "ts-start" },
73
- { name: "Nodejs Express", value: "express" }
74
- ],
75
- default: "next"
76
- }
77
- ]);
78
- const { repoUrl, label } = resolveTemplate(answers.template);
79
- import_fs_extra.default.mkdirSync(projectPath);
80
- const spinner = (0, import_ora.default)().start();
81
- const git = (0, import_simple_git.simpleGit)();
54
+ /**
55
+ * Decode JWT token without verification
56
+ */
57
+ export function decodeToken(token: string): IDecodedToken | null {
82
58
  try {
83
- spinner.text = `Downloading ${label} template...`;
84
- await git.clone(repoUrl, projectPath);
85
- spinner.succeed("Template downloaded successfully!");
86
- process.chdir(projectPath);
87
- spinner.start("Installing dependencies...");
88
- await (0, import_execa.execa)("pnpm", ["install"], {
89
- stdio: "inherit"
90
- // shows install logs
91
- });
92
- spinner.succeed("Dependencies installed successfully!");
93
- console.log();
94
- console.log(import_chalk.default.green(`Project ${projectName} is ready! \u{1F680}`));
95
- console.log(import_chalk.default.cyan(`cd ${projectName}`));
96
- console.log(import_chalk.default.cyan(`pnpm dev`));
59
+ return jwtDecode<IDecodedToken>(token);
97
60
  } catch (error) {
98
- spinner.fail("Failed to set up the project.");
99
- console.error(import_chalk.default.red(error.message));
100
- process.exit(1);
61
+ console.error("Failed to decode token:", error);
62
+ return null;
101
63
  }
102
- });
103
- var scaffold_default = scaffoldCommand;
64
+ }
65
+
66
+ /**
67
+ * Check if token is expired
68
+ */
69
+ export function isTokenExpired(token: string): boolean {
70
+ const decoded = decodeToken(token);
71
+ if (!decoded || !decoded.exp) return true;
72
+ return Date.now() >= decoded.exp * 1000;
73
+ }
74
+
75
+ /**
76
+ * Get time until token expiry in milliseconds
77
+ */
78
+ export function getTimeUntilExpiry(expiresAt: number): number {
79
+ return expiresAt - Date.now();
80
+ }
104
81
 
105
- // src/index.ts
106
- var program = new import_commander2.Command();
107
- program.name("etranzact").description("A powerful cli to scaffold new etranzact project").version("1.0.0");
108
- program.addCommand(scaffold_default);
109
- program.parse(process.argv);
82
+ /**
83
+ * Check if token needs refresh (refresh if less than 2 minutes remaining)
84
+ */
85
+ export function shouldRefreshToken(expiresAt: number): boolean {
86
+ const timeLeft = getTimeUntilExpiry(expiresAt);
87
+ return timeLeft > 0 && timeLeft < 2 * 60 * 1000;
88
+ }
89
+
90
+ export function formatLastLoginISO(lastLogin: string | undefined) {
91
+ if (!lastLogin) return "N/A";
92
+
93
+ const date = new Date(lastLogin);
94
+ return date.toLocaleString("en-US", {
95
+ year: "numeric",
96
+ month: "2-digit",
97
+ day: "2-digit",
98
+ hour: "2-digit",
99
+ minute: "2-digit",
100
+ hour12: false,
101
+ });
102
+ }
103
+ `;async function y(e,t){let s=a.default.join(e,"src","lib");switch(await i.default.ensureDir(s),t){case"iron-session":await i.default.writeFile(a.default.join(s,"session.ts"),w,"utf-8"),await i.default.writeFile(a.default.join(s,"auth-util.ts"),T,"utf-8");break;case"jose":await i.default.writeFile(a.default.join(s,"auth.ts"),"","utf-8");break;case"next-auth":await i.default.writeFile(a.default.join(s,"auth.ts"),"","utf-8");break;default:throw new Error("Unsupported auth library")}}var N=new k.Command("new");N.argument("<project-name>","name of the project").action(async e=>{let t=E.default.join(process.cwd(),e);try{l.default.existsSync(t)&&(console.error(o.default.red(`Directory ${e} already exists.`)),process.exit(1));let s=await j.default.prompt([{type:"rawlist",name:"template",message:"Which template would you like to use?",choices:[{name:"Next.js",value:"next"},{name:"Tanstack Start",value:"ts-start"},{name:"Node.js Express",value:"express"}],default:"next"},{type:"rawlist",name:"auth",message:"Select an authentication library:",choices:[{name:"iron-session",value:"iron-session"},{name:"jose",value:"jose"},{name:"next-auth",value:"next-auth"},{name:"none",value:"none"}],when:I=>!["express"].includes(I.template),default:"iron-session"}]),{template:d,auth:n}=s,{repoUrl:C,label:f}=x(d);l.default.mkdirSync(t);let p=(0,S.default)(`Downloading ${f} template...`).start();await(0,b.simpleGit)().clone(C,t),p.succeed(`${f} template downloaded!`),process.chdir(t),n&&n!=="none"&&(p.start(`Configuring ${n}...`),await y(t,n),p.succeed(`${n} configured!`)),p.start("Installing dependencies..."),n==="iron-session"?await(0,c.execa)("pnpm",["add","iron-session"],{stdio:"inherit"}):n==="jose"?await(0,c.execa)("pnpm",["add","jose"],{stdio:"inherit"}):n==="next-auth"&&await(0,c.execa)("pnpm",["add","next-auth"],{stdio:"inherit"}),await(0,c.execa)("pnpm",["add","jwt-decode"],{stdio:"inherit"}),await(0,c.execa)("pnpm",["install"],{stdio:"inherit"}),p.succeed("Dependencies installed!"),console.log(o.default.green(`
104
+ Project ${e} is ready! \u{1F680}`)),console.log(o.default.cyan(`cd ${e}`)),console.log(o.default.cyan("pnpm dev"))}catch(s){console.error(o.default.red(`
105
+ An error occurred during project setup:`)),console.error(o.default.red(s.message||s)),process.exit(1)}});var v=N;var u=new A.Command;u.name("etranzact").description("A powerful cli to scaffold new etranzact project").version("1.0.0");u.addCommand(v);u.parse(process.argv);
package/dist/index.js CHANGED
@@ -1,86 +1,105 @@
1
1
  #!/usr/bin/env node
2
+ import{Command as A}from"commander";import{Command as b}from"commander";import r from"chalk";import x from"fs-extra";import S from"path";import{simpleGit as j}from"simple-git";import N from"ora";import v from"inquirer";import{execa as c}from"execa";var p="https://github.com/olayinkaa/nextjs-starter-template-etz.git",l="https://github.com/MUKE-coder/nodejs-typescript-starter-template.git";function u(t){switch(t){case"next":return{repoUrl:p,label:"Next.js"};case"ts-start":return{repoUrl:p,label:"Tanstack Start"};case"express":return{repoUrl:l,label:"Express"};default:throw new Error("Invalid template selected.")}}import i from"fs-extra";import a from"path";var f=`
3
+ import type { SessionOptions } from "iron-session";
4
+ export interface IronSessionData {
5
+ user?:
6
+ | {
7
+ id: number;
8
+ email: string;
9
+ name: string;
10
+ merchant: string;
11
+ roleName: string;
12
+ lastLogin: string;
13
+ permissions: string[];
14
+ image: string;
15
+ }
16
+ | undefined;
17
+ accessToken?: string | undefined;
18
+ refreshToken?: string | undefined;
19
+ expiresAt?: number | undefined;
20
+ }
2
21
 
3
- // src/index.ts
4
- import { Command as Command2 } from "commander";
5
-
6
- // src/commands/scaffold.ts
7
- import { Command } from "commander";
8
- import chalk from "chalk";
9
- import fs from "fs-extra";
10
- import path from "path";
11
- import { simpleGit } from "simple-git";
12
- import ora from "ora";
13
- import inquirer from "inquirer";
14
- import { execa } from "execa";
15
-
16
- // src/utils/constants.ts
17
- var NEXT_TEMPLATE = "https://github.com/olayinkaa/nextjs-starter-template-etz.git";
18
- var EXPRESS_TEMPLATE = "https://github.com/MUKE-coder/nodejs-typescript-starter-template.git";
22
+ export const defaultSession: IronSessionData = {
23
+ user: undefined,
24
+ accessToken: undefined,
25
+ refreshToken: undefined,
26
+ expiresAt: undefined,
27
+ };
19
28
 
20
- // src/utils/resolve-templates.ts
21
- function resolveTemplate(template) {
22
- switch (template) {
23
- case "next":
24
- return { repoUrl: NEXT_TEMPLATE, label: "Next.js" };
25
- case "express":
26
- return { repoUrl: EXPRESS_TEMPLATE, label: "Express" };
27
- default:
28
- throw new Error("Invalid template selected.");
29
- }
29
+ export const sessionOptions: SessionOptions = {
30
+ password: process.env.AUTH_SECRET!,
31
+ cookieName: "e-firs-session",
32
+ cookieOptions: {
33
+ secure: process.env.COOKIE_SECURE === "true",
34
+ httpOnly: true,
35
+ sameSite: "lax",
36
+ maxAge: 7 * 24 * 60 * 60, // 7 days
37
+ },
38
+ };
39
+ `,g=`
40
+ import { jwtDecode } from "jwt-decode";
41
+ export interface IDecodedToken {
42
+ id: number;
43
+ name: string;
44
+ roleName: string;
45
+ lastLogin: string;
46
+ permissions: string[];
47
+ merchant: string;
48
+ image: string;
49
+ sub: string;
50
+ iat: number;
51
+ exp: number;
30
52
  }
31
53
 
32
- // src/commands/scaffold.ts
33
- var scaffoldCommand = new Command("new");
34
- scaffoldCommand.argument("<project-name>", "name of the project").action(async (projectName) => {
35
- const projectPath = path.join(process.cwd(), projectName);
36
- if (fs.existsSync(projectPath)) {
37
- console.error(
38
- chalk.red(`Error: Directory ${projectName} already exists.`)
39
- );
40
- process.exit(1);
41
- }
42
- const answers = await inquirer.prompt([
43
- {
44
- type: "rawlist",
45
- name: "template",
46
- message: "Which template would you like to use?",
47
- choices: [
48
- { name: "Nextjs", value: "next" },
49
- { name: "Tanstack Start", value: "ts-start" },
50
- { name: "Nodejs Express", value: "express" }
51
- ],
52
- default: "next"
53
- }
54
- ]);
55
- const { repoUrl, label } = resolveTemplate(answers.template);
56
- fs.mkdirSync(projectPath);
57
- const spinner = ora().start();
58
- const git = simpleGit();
54
+ /**
55
+ * Decode JWT token without verification
56
+ */
57
+ export function decodeToken(token: string): IDecodedToken | null {
59
58
  try {
60
- spinner.text = `Downloading ${label} template...`;
61
- await git.clone(repoUrl, projectPath);
62
- spinner.succeed("Template downloaded successfully!");
63
- process.chdir(projectPath);
64
- spinner.start("Installing dependencies...");
65
- await execa("pnpm", ["install"], {
66
- stdio: "inherit"
67
- // shows install logs
68
- });
69
- spinner.succeed("Dependencies installed successfully!");
70
- console.log();
71
- console.log(chalk.green(`Project ${projectName} is ready! \u{1F680}`));
72
- console.log(chalk.cyan(`cd ${projectName}`));
73
- console.log(chalk.cyan(`pnpm dev`));
59
+ return jwtDecode<IDecodedToken>(token);
74
60
  } catch (error) {
75
- spinner.fail("Failed to set up the project.");
76
- console.error(chalk.red(error.message));
77
- process.exit(1);
61
+ console.error("Failed to decode token:", error);
62
+ return null;
78
63
  }
79
- });
80
- var scaffold_default = scaffoldCommand;
64
+ }
65
+
66
+ /**
67
+ * Check if token is expired
68
+ */
69
+ export function isTokenExpired(token: string): boolean {
70
+ const decoded = decodeToken(token);
71
+ if (!decoded || !decoded.exp) return true;
72
+ return Date.now() >= decoded.exp * 1000;
73
+ }
74
+
75
+ /**
76
+ * Get time until token expiry in milliseconds
77
+ */
78
+ export function getTimeUntilExpiry(expiresAt: number): number {
79
+ return expiresAt - Date.now();
80
+ }
81
81
 
82
- // src/index.ts
83
- var program = new Command2();
84
- program.name("etranzact").description("A powerful cli to scaffold new etranzact project").version("1.0.0");
85
- program.addCommand(scaffold_default);
86
- program.parse(process.argv);
82
+ /**
83
+ * Check if token needs refresh (refresh if less than 2 minutes remaining)
84
+ */
85
+ export function shouldRefreshToken(expiresAt: number): boolean {
86
+ const timeLeft = getTimeUntilExpiry(expiresAt);
87
+ return timeLeft > 0 && timeLeft < 2 * 60 * 1000;
88
+ }
89
+
90
+ export function formatLastLoginISO(lastLogin: string | undefined) {
91
+ if (!lastLogin) return "N/A";
92
+
93
+ const date = new Date(lastLogin);
94
+ return date.toLocaleString("en-US", {
95
+ year: "numeric",
96
+ month: "2-digit",
97
+ day: "2-digit",
98
+ hour: "2-digit",
99
+ minute: "2-digit",
100
+ hour12: false,
101
+ });
102
+ }
103
+ `;async function h(t,n){let e=a.join(t,"src","lib");switch(await i.ensureDir(e),n){case"iron-session":await i.writeFile(a.join(e,"session.ts"),f,"utf-8"),await i.writeFile(a.join(e,"auth-util.ts"),g,"utf-8");break;case"jose":await i.writeFile(a.join(e,"auth.ts"),"","utf-8");break;case"next-auth":await i.writeFile(a.join(e,"auth.ts"),"","utf-8");break;default:throw new Error("Unsupported auth library")}}var w=new b("new");w.argument("<project-name>","name of the project").action(async t=>{let n=S.join(process.cwd(),t);try{x.existsSync(n)&&(console.error(r.red(`Directory ${t} already exists.`)),process.exit(1));let e=await v.prompt([{type:"rawlist",name:"template",message:"Which template would you like to use?",choices:[{name:"Next.js",value:"next"},{name:"Tanstack Start",value:"ts-start"},{name:"Node.js Express",value:"express"}],default:"next"},{type:"rawlist",name:"auth",message:"Select an authentication library:",choices:[{name:"iron-session",value:"iron-session"},{name:"jose",value:"jose"},{name:"next-auth",value:"next-auth"},{name:"none",value:"none"}],when:E=>!["express"].includes(E.template),default:"iron-session"}]),{template:y,auth:s}=e,{repoUrl:k,label:m}=u(y);x.mkdirSync(n);let o=N(`Downloading ${m} template...`).start();await j().clone(k,n),o.succeed(`${m} template downloaded!`),process.chdir(n),s&&s!=="none"&&(o.start(`Configuring ${s}...`),await h(n,s),o.succeed(`${s} configured!`)),o.start("Installing dependencies..."),s==="iron-session"?await c("pnpm",["add","iron-session"],{stdio:"inherit"}):s==="jose"?await c("pnpm",["add","jose"],{stdio:"inherit"}):s==="next-auth"&&await c("pnpm",["add","next-auth"],{stdio:"inherit"}),await c("pnpm",["add","jwt-decode"],{stdio:"inherit"}),await c("pnpm",["install"],{stdio:"inherit"}),o.succeed("Dependencies installed!"),console.log(r.green(`
104
+ Project ${t} is ready! \u{1F680}`)),console.log(r.cyan(`cd ${t}`)),console.log(r.cyan("pnpm dev"))}catch(e){console.error(r.red(`
105
+ An error occurred during project setup:`)),console.error(r.red(e.message||e)),process.exit(1)}});var T=w;var d=new A;d.name("etranzact").description("A powerful cli to scaffold new etranzact project").version("1.0.0");d.addCommand(T);d.parse(process.argv);
package/package.json CHANGED
@@ -1,19 +1,24 @@
1
1
  {
2
2
  "name": "etranzact-fe-cli",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "private": false,
5
5
  "description": "Etranzact Cli for scaffolding new frontend project",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.mjs",
9
9
  "bin": {
10
- "etz-cli": "./dist/index.js"
10
+ "etranzact": "./dist/index.js"
11
11
  },
12
12
  "files": [
13
13
  "dist",
14
14
  "README.md"
15
15
  ],
16
- "keywords": [],
16
+ "keywords": [
17
+ "cli",
18
+ "scaffolding",
19
+ "frontend",
20
+ "project"
21
+ ],
17
22
  "author": "Olayinka Ibrahim",
18
23
  "license": "ISC",
19
24
  "devDependencies": {
@@ -34,7 +39,7 @@
34
39
  "simple-git": "^3.32.2"
35
40
  },
36
41
  "scripts": {
37
- "dev": "tsc --watch",
42
+ "dev": "pnpm run clean && tsup --watch",
38
43
  "build:tsc": "pnpm run clean && tsc",
39
44
  "build:esb": "node esbuild.config.mjs",
40
45
  "build:tsup": "tsup",