fakelab 0.0.7 → 0.0.8
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/lib/cli.js +2 -1
- package/lib/main.d.ts +19 -6
- package/lib/main.js +3 -1
- package/lib/public/css/style.css +39 -9
- package/lib/public/js/fakelab.min.js +42 -22
- package/lib/views/components/code.ejs +1 -1
- package/lib/views/components/sidebar.ejs +3 -2
- package/lib/views/components/toolbar.ejs +60 -0
- package/lib/views/preview.ejs +1 -189
- package/package.json +1 -1
package/lib/cli.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import P from'path';import {fileURLToPath}from'url';import $ from'fs-extra';import l from'zod';import {Command}from'commander';import k from'express';import M from'cors';import K from'express-ejs-layouts';import q from'http';import'ejs';import G from'qs';import {Project}from'ts-morph';import {v4}from'uuid';import u from'picocolors';import Q from'figlet';import {bundleRequire}from'bundle-require';import ee from'joycon';var a=class t{static prefix(e){let r=new Date().toLocaleTimeString();return {info:u.blue,warn:u.yellow,error:u.red,success:u.green,debug:u.magenta}[e](`[${r}] FAKELAB_${e.toUpperCase()}`)}static log(e,r,...n){let o=u.white,s=t.prefix(e);(e==="error"?console.error:e==="warn"?console.warn:console.log)(s,o(r),...n);}static info(e,...r){this.log("info",e,...r);}static warn(e,...r){this.log("warn",e,...r);}static error(e,...r){this.log("error",e,...r);}static success(e,...r){this.log("success",e,...r);}};var d=class{constructor(e){this.faker=e;}JSDOC_FAKER_FIELD="faker";FAKER_TAG_REGEX=/^([a-zA-Z0-9._]+)(?:\((.*)\))?$/;boolMapping={true:true,false:false};string(e){return this.execute(e,this.faker.word.noun)}int(e){return this.execute(e,this.faker.number.int)}bool(e){return this.execute(e,this.faker.datatype.boolean)}bigInt(e){return this.execute(e,this.faker.number.bigInt)}litbool(e){return this.boolMapping[e]}async object(e,r){let n={};return await Promise.all(e.map(async o=>{let s=o.getTypeAtLocation(o.getValueDeclarationOrThrow());n[o.getName()]=await r(s,this,this.readJSDocTags(o));})),n}async union(e){let r=await Promise.all(e);return r[Math.floor(Math.random()*r.length)]}async intersection(e){let r=await Promise.all(e);return r[Math.floor(Math.random()*r.length)]}evalArgs(e){if(!(!e||!e.trim()))return Function(`"use strict"; return (${e});`)()}readJSDocTags(e){let r=e.getJsDocTags().filter(n=>n.getName()===this.JSDOC_FAKER_FIELD);return r.length===0?[]:r.map(n=>{let[o]=n.getText();if(!o)return;let s=o.text.trim().match(this.FAKER_TAG_REGEX);if(!s)return;let[,i,c]=s,p=this.evalArgs(c);return {path:i,args:p}})}execute(e,r){if(!e)return r();let n=e.path.split("."),o=this.faker;for(let s of n)o=o[s],o||(a.error("Invalid faker module path:",e.path),process.exit(1));typeof o!="function"&&(a.error("Unresolvable faker function.",e.path),process.exit(1));try{return e.args?o(e.args):o()}catch{return a.error("Passed invalid arguments to faker function."),o()}}};var y=class{constructor(e){this.files=e;let n=new Project({tsConfigFilePath:"tsconfig.json"}).addSourceFilesAtPaths(e);this.__targets=n.flatMap(o=>o.getInterfaces());}__targets;async run(e){return await e()}normalizePath(e){return e.split(P.sep).join(P.posix.sep)}entities(){let e=this.__targets.map(r=>{let n=r.getName().toLowerCase(),o=r.getType(),s=this.normalizePath(process.cwd()),c=this.normalizePath(r.getSourceFile().getDirectoryPath()).replace(s,""),p=r.getSourceFile().getBaseName(),f=`${c}/${p}`;return [n,{type:o,filepath:f}]});return new Map(e)}async loadFaker(e,r){let{faker:n}=await import(`@faker-js/faker/locale/${r||e.locale}`);return n}};async function m(t,e,r=[],n=0){if(t.isString())return e.string(r[n]);if(t.isNumber())return e.int(r[n]);if(t.isBoolean())return e.bool(r[n]);if(t.isBigInt())return e.bigInt(r[n]);if(t.isBooleanLiteral())return e.litbool(t.getText());if(t.isLiteral())return t.getLiteralValue();if(!t.isUndefined()){if(t.isUnion()){let o=t.getUnionTypes();return await e.union(o.map((s,i)=>m(s,e,r,i)))}if(t.isIntersection()){let o=t.getIntersectionTypes();return await e.intersection(o.map((s,i)=>m(s,e,r,i)))}if(t.isArray()){let o=t.getArrayElementTypeOrThrow();return [await m(o,e,r,n)]}if(t.isObject()){let o=t.getProperties();return await e.object(o,(s,i,c)=>m(s,i,c,n))}return null}}function R({each:t}){return {resolve:async r=>await Promise.all(Array.from({length:r},(n,o)=>t(o)))}}function D(t,e){return t==="uuid"?v4():e+1}function N(t,e,r){return async n=>{let o=await m(t,e);return r.uid&&typeof o=="object"?{[r.uid]:D(r.s,n),...o}:o}}async function L(t,e){let r=await t.files(e.source),n=new y(r),o=await n.loadFaker(t.fakerOpts(e.locale)),s=new d(o),i=n.entities();async function c(p,f){let g=R({each:N(p,s,f)}),h=await(f.count?g.resolve(parseInt(f.count)):m(p,s)),x=JSON.stringify(h,null,2);return {data:h,json:x}}return {entities:i,forge:c}}var B=fileURLToPath(import.meta.url),J=P.dirname(B),F=$.readJSONSync(P.join(J,"../package.json")),v=class{constructor(e,r,n){this.router=e;this.config=r;this.opts=n;let{pathPrefix:o}=this.config.serverOpts(this.opts.pathPrefix);this.prefix=o;}prefix;get querySchema(){return l.object({count:l.string().optional(),uid:l.string().optional(),strategy:l.string().optional()})}async handleQueries(e){let{success:r,data:n,error:o}=await this.querySchema.safeParseAsync(e.query);return r?n:(a.warn(o.message),{})}async register(){let{entities:e,forge:r}=await L(this.config,this.opts);this.router.get("/",(n,o)=>{let s=n.path;o.render("index",{currentPath:s,entities:e,version:F.version});}),this.router.get("/:name",async(n,o)=>{let s=`${n.protocol}://${n.host}/`,i=n.path,c=n.params.name,p=await this.handleQueries(n),f=G.stringify(p,{addQueryPrefix:true}),g=e.get(c.toLowerCase());if(g){let{json:h}=await r(g.type,p),x=g.filepath;o.render("preview",{name:c,filepath:x,currentPath:i,address:s,search:f,json:h,entities:e,version:F.version,prefix:this.prefix});}else o.redirect("/");}),this.router.get(`/${this.prefix}/:name`,async(n,o)=>{try{let s=n.params.name,i=await this.handleQueries(n),c=e.get(s.toLowerCase());if(c){let{data:p}=await r(c.type,i);o.status(200).json(p);}else o.status(400).json({message:"The requested interface is not found"});}catch(s){o.status(500).send(s);}});}};var V=fileURLToPath(import.meta.url),C=P.dirname(V);function X(t,e,r){let{port:n}=e.serverOpts(r.pathPrefix,r.port);t.listen(n,"localhost",async()=>{a.info(`Server: http://localhost:${n}`),console.log(await Q.text("FAKELAB"));});}function H(t,e,r){e.setHeader("x-powered-by","fakelab"),r();}function Z(t){t.disable("x-powered-by"),t.use(k.json()),t.use(M({methods:"GET"})),t.use(k.static(C+"/public")),t.use(H);}function W(t){t.set("views",P.join(C,"views")),t.set("view engine","ejs"),t.use(K),t.set("layout","layouts/main");}async function _(t,e){let r=k(),n=k.Router(),o=q.createServer(r);Z(r),W(r),await new v(n,t,e).register(),r.use(n),X(o,t,e);}async function j(){try{let e=await new ee().resolve({files:["fakelab.config.ts"]});return e||(a.error("No fakelab config file is detected."),process.exit(1)),(await bundleRequire({filepath:e})).mod.default}catch{a.error("Could not load the config file."),process.exit(1);}}var T=new Command,ne=fileURLToPath(import.meta.url),se=P.dirname(ne),b=$.readJSONSync(P.join(se,"../package.json"));T.name(b.name).description(b.description).version(b.version);var ie=l.object({source:l.string().optional(),pathPrefix:l.string().optional(),port:l.number().int().optional(),locale:l.string().optional()});T.command("serve").description("start server").option("-s, --source <char>","config source path").option("-x, --pathPrefix <char>","server url path prefix").option("-p, --port <number>","server port number",parseInt).option("-l, --locale <char>","faker custom locale").action(async t=>{let e=await ie.safeParseAsync(t);e.error&&(a.error(l.treeifyError(e.error).errors.join(`
|
|
2
|
+
`)),process.exit(1));let r=await j();_(r,e.data);});T.parse();
|
package/lib/main.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
type FakerLocale = "af" | "ar" | "az" | "bn" | "cs" | "cy" | "da" | "de" | "dv" | "el" | "en" | "eo" | "es" | "fa" | "fi" | "fr" | "he" | "hr" | "hu" | "hy" | "id" | "it" | "ja" | "ka" | "ko" | "ku" | "lv" | "mk" | "nb" | "ne" | "nl" | "pl" | "pt" | "ro";
|
|
2
|
-
|
|
3
1
|
type ServerOptions = {
|
|
4
2
|
/**
|
|
5
3
|
* @default 5200
|
|
@@ -14,14 +12,29 @@ type FakerEngineOptions = {
|
|
|
14
12
|
locale?: FakerLocale;
|
|
15
13
|
};
|
|
16
14
|
type ConfigOptions = {
|
|
17
|
-
sourcePath: string;
|
|
15
|
+
sourcePath: string | string[];
|
|
18
16
|
server?: ServerOptions;
|
|
19
17
|
faker?: FakerEngineOptions;
|
|
20
18
|
};
|
|
21
|
-
|
|
19
|
+
type UserConfig = {
|
|
22
20
|
files: string[];
|
|
23
21
|
serverOptions: Required<ServerOptions>;
|
|
24
22
|
fakerOptions: Required<FakerEngineOptions>;
|
|
25
|
-
}
|
|
23
|
+
};
|
|
24
|
+
type FakerLocale = "af" | "ar" | "az" | "bn" | "cs" | "cy" | "da" | "de" | "dv" | "el" | "en" | "eo" | "es" | "fa" | "fi" | "fr" | "he" | "hr" | "hu" | "hy" | "id" | "it" | "ja" | "ka" | "ko" | "ku" | "lv" | "mk" | "nb" | "ne" | "nl" | "pl" | "pt" | "ro";
|
|
25
|
+
|
|
26
|
+
declare class Config {
|
|
27
|
+
private readonly opts;
|
|
28
|
+
constructor(opts: ConfigOptions);
|
|
29
|
+
files(_sourcePath?: string): Promise<string[]>;
|
|
30
|
+
serverOpts(prefix?: string, port?: number): Required<ServerOptions>;
|
|
31
|
+
fakerOpts(locale?: FakerLocale): Required<FakerEngineOptions>;
|
|
32
|
+
private tryStat;
|
|
33
|
+
private isReadable;
|
|
34
|
+
private resolveSourcePath;
|
|
35
|
+
private resolveTSFiles;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare function defineConfig(options: ConfigOptions): Config;
|
|
26
39
|
|
|
27
|
-
export { defineConfig };
|
|
40
|
+
export { type UserConfig, defineConfig };
|
package/lib/main.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import g from'fast-glob';import l from'path';import {stat,access,constants}from'fs/promises';import i from'picocolors';var s=class o{static prefix(t){let r=new Date().toLocaleTimeString();return {info:i.blue,warn:i.yellow,error:i.red,success:i.green,debug:i.magenta}[t](`[${r}] FAKELAB_${t.toUpperCase()}`)}static log(t,r,...e){let n=i.white,c=o.prefix(t);(t==="error"?console.error:t==="warn"?console.warn:console.log)(c,n(r),...e);}static info(t,...r){this.log("info",t,...r);}static warn(t,...r){this.log("warn",t,...r);}static error(t,...r){this.log("error",t,...r);}static success(t,...r){this.log("success",t,...r);}};function p(){let o=Intl.DateTimeFormat().resolvedOptions().locale;if(!o)return "en";let[t]=o.split("-");return t.toLowerCase()}var a=class{constructor(t){this.opts=t;this.files=this.files.bind(this),this.serverOpts=this.serverOpts.bind(this),this.fakerOpts=this.fakerOpts.bind(this);}async files(t){let r=this.resolveSourcePath(t||this.opts.sourcePath),e=Array.from(new Set((await Promise.all(r.map(n=>this.resolveTSFiles(n)))).flat()));return e.length===0&&(s.error(`No Typescript files found in:
|
|
2
|
+
%s`,r.join(`
|
|
3
|
+
`)),process.exit(1)),e}serverOpts(t,r){return {pathPrefix:t||this.opts.server?.pathPrefix||"api",port:r||this.opts.server?.port||5200}}fakerOpts(t){return {locale:t||this.opts.faker?.locale||p()}}async tryStat(t){try{return await stat(t)}catch{return null}}async isReadable(t){try{return await access(t,constants.R_OK),!0}catch{return false}}resolveSourcePath(t){return (Array.isArray(t)?t:[t]).map(e=>l.resolve(e))}async resolveTSFiles(t){let r=l.resolve(t),e=r.endsWith(".ts")?r:r+".ts";if((await this.tryStat(e))?.isFile()){if(!await this.isReadable(e))throw new Error(`Cannot read file: ${e}`);return s.info("Source:",e),[e]}if((await this.tryStat(r))?.isDirectory())return s.info("Source:",r),g("**/*.ts",{cwd:r,absolute:true,ignore:["**/*.d.ts"]});s.error(`Invalid source path: ${t}`),process.exit(1);}};function w(o){return new a(o)}export{w as defineConfig};
|
package/lib/public/css/style.css
CHANGED
|
@@ -115,22 +115,46 @@ pre {
|
|
|
115
115
|
padding: 12px 8px;
|
|
116
116
|
border-radius: 4px;
|
|
117
117
|
cursor: pointer;
|
|
118
|
+
display: flex;
|
|
119
|
+
gap: 8px;
|
|
120
|
+
justify-content: space-between;
|
|
121
|
+
align-items: center;
|
|
122
|
+
text-decoration: none;
|
|
123
|
+
&:hover > .item_name {
|
|
124
|
+
color: oklch(98.5% 0.002 247.85);
|
|
125
|
+
}
|
|
126
|
+
&:hover > .item_filepath {
|
|
127
|
+
color: oklch(98.463% 0.00181 249.248 / 0.8);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.sidebar_content_list_item .item_name {
|
|
118
132
|
transition: all 250ms ease-in-out;
|
|
119
133
|
color: oklch(98.463% 0.00181 249.248 / 0.726);
|
|
120
|
-
|
|
134
|
+
user-select: none;
|
|
121
135
|
font-size: 14px;
|
|
122
|
-
|
|
123
|
-
color: oklch(98.5% 0.002 247.839);
|
|
124
|
-
}
|
|
136
|
+
}
|
|
125
137
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
.sidebar_content_list_item .item_filepath {
|
|
139
|
+
transition: all 250ms ease-in-out;
|
|
140
|
+
white-space: nowrap;
|
|
141
|
+
line-clamp: 1;
|
|
142
|
+
text-overflow: ellipsis;
|
|
143
|
+
font-size: 12px;
|
|
144
|
+
color: oklch(98.463% 0.00181 249.248 / 0.6);
|
|
145
|
+
font-style: italic;
|
|
129
146
|
}
|
|
130
147
|
|
|
131
148
|
.sidebar_content_list_item.active {
|
|
132
|
-
color: oklch(98.5% 0.002 247.839);
|
|
133
149
|
background-color: oklch(37.306% 0.03436 260.191 / 0.26);
|
|
150
|
+
|
|
151
|
+
> .item_name {
|
|
152
|
+
color: oklch(98.5% 0.002 247.85);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
> .item_filepath {
|
|
156
|
+
color: oklch(98.463% 0.00181 249.248 / 0.8);
|
|
157
|
+
}
|
|
134
158
|
}
|
|
135
159
|
|
|
136
160
|
.sidebar_content_leading .sidebar_content_title {
|
|
@@ -180,7 +204,13 @@ pre {
|
|
|
180
204
|
|
|
181
205
|
.header .interface_name {
|
|
182
206
|
font-size: 16px;
|
|
183
|
-
color: oklch(98.463% 0.00181 249.248 / 0.
|
|
207
|
+
color: oklch(98.463% 0.00181 249.248 / 0.8);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.interface_name .interface_source_filepath {
|
|
211
|
+
font-size: 12px;
|
|
212
|
+
color: oklch(98.463% 0.00181 249.248 / 0.6);
|
|
213
|
+
font-style: italic;
|
|
184
214
|
}
|
|
185
215
|
|
|
186
216
|
.preview {
|
|
@@ -1,12 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
function copyAddressUrl() {
|
|
2
|
+
var e = document.getElementById("request_address_url");
|
|
3
3
|
try {
|
|
4
|
-
|
|
4
|
+
navigator.clipboard.writeText(e.textContent);
|
|
5
5
|
} catch (e) {
|
|
6
6
|
console.info(e);
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function copyJsonCode() {
|
|
10
|
+
var e = document.getElementById("source_code");
|
|
11
|
+
try {
|
|
12
|
+
navigator.clipboard.writeText(e.textContent);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.info(e);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function downloadJsonCode(e) {
|
|
18
|
+
var t = document.getElementById("source_code").textContent.trim(),
|
|
19
|
+
t = new Blob([t], { type: "application/json" });
|
|
20
|
+
let n = URL.createObjectURL(t);
|
|
21
|
+
var t = e.getAttribute("data-source-name"),
|
|
22
|
+
d = new Date().toISOString().replace(/[:.]/g, "-");
|
|
23
|
+
(e.download = t + `-${d}.json`),
|
|
24
|
+
(e.href = n),
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
URL.revokeObjectURL(n), (e.download = ""), (e.href = "");
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function openSettings() {
|
|
10
30
|
document.getElementById("setting_overlay").setAttribute("data-visible", "true");
|
|
11
31
|
}
|
|
12
32
|
function handleCloseSetting(e) {
|
|
@@ -19,29 +39,29 @@ function submitForm(e) {
|
|
|
19
39
|
e = new FormData(e.target),
|
|
20
40
|
n = e.get("count")?.trim(),
|
|
21
41
|
e = e.get("unique_id_key")?.trim(),
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
42
|
+
d = new URLSearchParams(),
|
|
43
|
+
o = document.getElementById("unique_id"),
|
|
44
|
+
i = document.getElementById("unique_id_strategy"),
|
|
25
45
|
n =
|
|
26
|
-
(n && 0 < Number(n) ? (Number(n),
|
|
27
|
-
|
|
28
|
-
e &&
|
|
46
|
+
(n && 0 < Number(n) ? (Number(n), d.set("count", n.toString()), (window.location.search = d.toString())) : (d.delete("count"), t.add("count")),
|
|
47
|
+
o.checked || (d.delete("uid"), t.add("uid")),
|
|
48
|
+
e && o.checked ? (d.set("uid", e), i.checked && d.set("strategy", "uuid"), (window.location.search = d.toString())) : (d.delete("uid"), d.delete("strategy"), t.add("uid")),
|
|
29
49
|
t.has("uid")),
|
|
30
|
-
|
|
31
|
-
|
|
50
|
+
o = t.has("count");
|
|
51
|
+
o && n
|
|
32
52
|
? window.location.href.includes("?") && (([href] = window.location.href.split("?")), (window.location.href = href))
|
|
33
|
-
: ((
|
|
53
|
+
: ((o && !n) || (!o && n)) && (window.location.search = d.toString());
|
|
34
54
|
}
|
|
35
55
|
function resetForm(e) {
|
|
36
56
|
e.preventDefault();
|
|
37
57
|
e = new URLSearchParams(window.location.search);
|
|
38
|
-
e.delete("count"), e.delete("uid"), e.delete("
|
|
58
|
+
e.delete("count"), e.delete("uid"), e.delete("strategy"), window.location.href.includes("?") && (window.location.href = window.location.href.split("?")[0]);
|
|
39
59
|
}
|
|
40
60
|
function onChangeGenerateUniqueId(e) {
|
|
41
61
|
var t = document.getElementById("unique_id"),
|
|
42
62
|
n = document.getElementById("unique_id_key_field"),
|
|
43
|
-
|
|
44
|
-
(t.checked = !t.checked), n.setAttribute("data-visible", t.checked.toString()),
|
|
63
|
+
d = document.getElementById("unique_strategy_container");
|
|
64
|
+
(t.checked = !t.checked), n.setAttribute("data-visible", t.checked.toString()), d.setAttribute("data-visible", t.checked.toString());
|
|
45
65
|
}
|
|
46
66
|
function onHandleUniqueIdStrategy(e) {
|
|
47
67
|
var t = document.getElementById("unique_id_strategy");
|
|
@@ -52,11 +72,11 @@ window.addEventListener("click", handleCloseSetting),
|
|
|
52
72
|
var e = document.getElementById("count"),
|
|
53
73
|
t = document.getElementById("unique_id"),
|
|
54
74
|
n = document.getElementById("unique_id_strategy"),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
d = document.getElementById("unique_id_key"),
|
|
76
|
+
o = document.getElementById("unique_id_key_field"),
|
|
77
|
+
i = document.getElementById("unique_strategy_container"),
|
|
58
78
|
a = new URLSearchParams(window.location.search),
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
79
|
+
c = a.get("count"),
|
|
80
|
+
r = a.get("uid");
|
|
81
|
+
c && (e.value = c), r && ((t.checked = !0), (d.value = r), o.setAttribute("data-visible", "true"), i.setAttribute("data-visible", "true"), a.has("s")) && (n.checked = !0);
|
|
62
82
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<pre class="code loading"><code class="language-<%= lang %>"><%- code %></code></pre>
|
|
1
|
+
<pre class="code loading"><code id="source_code" class="language-<%= lang %>"><%- code %></code></pre>
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
<span class="sidebar_content_title">Found interfaces</span>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="sidebar_content_list">
|
|
9
|
-
<% entities.forEach((
|
|
9
|
+
<% entities.forEach((entity,name) => { %>
|
|
10
10
|
<a class="sidebar_content_list_item <%= currentPath === `/${name}` ? 'active' : '' %>" href="/<%= name %>">
|
|
11
|
-
<span><%= name %></span>
|
|
11
|
+
<span class="item_name"><%= name %></span>
|
|
12
|
+
<span class="item_filepath"><%= entity.filepath %></span>
|
|
12
13
|
</a>
|
|
13
14
|
<% }) %>
|
|
14
15
|
</div>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<div class="preview_toolbar loading">
|
|
2
|
+
<div class="toolbar_setting">
|
|
3
|
+
<div class="data_fetch_address">
|
|
4
|
+
<div class="address">
|
|
5
|
+
<span class="address_method">GET</span>
|
|
6
|
+
<span id="request_address_url" class="address_url"><%= address %><%= prefix %>/<%= name %><%= search %></span>
|
|
7
|
+
</div>
|
|
8
|
+
<img id="copy_btn" onclick="copyAddressUrl()" class="icon pointer_auto" src="/icons/copy.svg" width="16px" height="16px" />
|
|
9
|
+
</div>
|
|
10
|
+
<div id="overlay_trigger" class="toolbar_setting_option" onclick="openSettings()">
|
|
11
|
+
<img class="icon" src="/icons/settings.svg" width="18px" height="18px" />
|
|
12
|
+
</div>
|
|
13
|
+
<div id="setting_overlay" data-visible="false" class="toolbar_setting_overlay">
|
|
14
|
+
<span class="setting_title">Generator settings</span>
|
|
15
|
+
<form class="setting_form" onsubmit="submitForm(event)">
|
|
16
|
+
<div class="form_input">
|
|
17
|
+
<label for="count">Count</label>
|
|
18
|
+
<input id="count" autocomplete="off" name="count" type="text" />
|
|
19
|
+
<span>Set count field to generate array of data items.</span>
|
|
20
|
+
</div>
|
|
21
|
+
<div style="display: flex; flex-direction: column; gap: 8px">
|
|
22
|
+
<div class="form_input inline">
|
|
23
|
+
<label for="unique_id">Generate unique id</label>
|
|
24
|
+
<div class="switch" onclick="onChangeGenerateUniqueId()">
|
|
25
|
+
<input type="checkbox" id="unique_id" name="unique_id" />
|
|
26
|
+
<span class="slider"></span>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
<div id="unique_id_key_field" class="form_input" data-visible="false">
|
|
30
|
+
<input id="unique_id_key" autocomplete="off" name="unique_id_key" type="text" value="_id" placeholder="unique id key" />
|
|
31
|
+
</div>
|
|
32
|
+
<div id="unique_strategy_container" class="unique_strategy" data-visible="false">
|
|
33
|
+
<span class="unique_id_hint">By default unique id is auto incremented integer.</span>
|
|
34
|
+
<div class="form_input inline">
|
|
35
|
+
<label for="unique_id_strategy">Generate as uuid</label>
|
|
36
|
+
<div class="switch" onclick="onHandleUniqueIdStrategy()">
|
|
37
|
+
<input type="checkbox" id="unique_id_strategy" name="unique_id_strategy" />
|
|
38
|
+
<span class="slider"></span>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="form_buttons">
|
|
44
|
+
<button class="form_reset_btn" type="button" onclick="resetForm(event)">Reset</button>
|
|
45
|
+
<button class="form_apply_btn" type="submit">Apply</button>
|
|
46
|
+
</div>
|
|
47
|
+
</form>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="toolbar_actions">
|
|
52
|
+
<div class="toolbar_action_item" onclick="copyJsonCode()">
|
|
53
|
+
<img class="icon" src="/icons/copy.svg" width="18px" height="18px" />
|
|
54
|
+
</div>
|
|
55
|
+
<div class="divider"></div>
|
|
56
|
+
<a class="toolbar_action_item" data-source-name="<%= name %>" onclick="downloadJsonCode(this)">
|
|
57
|
+
<img class="icon" src="/icons/download.svg" width="18px" height="18px" />
|
|
58
|
+
</a>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
package/lib/views/preview.ejs
CHANGED
|
@@ -7,195 +7,7 @@
|
|
|
7
7
|
<div class="preview-loading loading">
|
|
8
8
|
<span class="loader visible"></span><span class="error">Some libraries could not be loaded. check your internet connection and try again.</span>
|
|
9
9
|
</div>
|
|
10
|
-
|
|
11
|
-
<div class="toolbar_setting">
|
|
12
|
-
<div class="data_fetch_address">
|
|
13
|
-
<div class="address">
|
|
14
|
-
<span class="address_method">GET</span>
|
|
15
|
-
<span class="address_url"><%= address %><%= prefix %>/<%= name %><%= search %></span>
|
|
16
|
-
</div>
|
|
17
|
-
<img id="copy_btn" onclick="copy()" class="icon pointer_auto" src="/icons/copy.svg" width="16px" height="16px" />
|
|
18
|
-
</div>
|
|
19
|
-
<div id="overlay_trigger" class="toolbar_setting_option" onclick="open_settings()">
|
|
20
|
-
<img class="icon" src="/icons/settings.svg" width="18px" height="18px" />
|
|
21
|
-
</div>
|
|
22
|
-
<div id="setting_overlay" data-visible="false" class="toolbar_setting_overlay">
|
|
23
|
-
<span class="setting_title">Generator settings</span>
|
|
24
|
-
<form class="setting_form" onsubmit="submitForm(event)">
|
|
25
|
-
<div class="form_input">
|
|
26
|
-
<label for="count">Count</label>
|
|
27
|
-
<input id="count" autocomplete="off" name="count" type="text" />
|
|
28
|
-
<span>Set count field to generate array of data items.</span>
|
|
29
|
-
</div>
|
|
30
|
-
<div style="display: flex; flex-direction: column; gap: 8px">
|
|
31
|
-
<div class="form_input inline">
|
|
32
|
-
<label for="unique_id">Generate unique id</label>
|
|
33
|
-
<div class="switch" onclick="onChangeGenerateUniqueId()">
|
|
34
|
-
<input type="checkbox" id="unique_id" name="unique_id" />
|
|
35
|
-
<span class="slider"></span>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
<div id="unique_id_key_field" class="form_input" data-visible="false">
|
|
39
|
-
<input id="unique_id_key" autocomplete="off" name="unique_id_key" type="text" value="_id" placeholder="unique id key" />
|
|
40
|
-
</div>
|
|
41
|
-
<div id="unique_strategy_container" class="unique_strategy" data-visible="false">
|
|
42
|
-
<span class="unique_id_hint">By default unique id is auto incremented integer.</span>
|
|
43
|
-
<div class="form_input inline">
|
|
44
|
-
<label for="unique_id_strategy">Generate as uuid</label>
|
|
45
|
-
<div class="switch" onclick="onHandleUniqueIdStrategy()">
|
|
46
|
-
<input type="checkbox" id="unique_id_strategy" name="unique_id_strategy" />
|
|
47
|
-
<span class="slider"></span>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="form_buttons">
|
|
53
|
-
<button class="form_reset_btn" type="button" onclick="resetForm(event)">Reset</button>
|
|
54
|
-
<button class="form_apply_btn" type="submit">Apply</button>
|
|
55
|
-
</div>
|
|
56
|
-
</form>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
|
|
60
|
-
<div class="toolbar_actions">
|
|
61
|
-
<div class="toolbar_action_item">
|
|
62
|
-
<img class="icon" src="/icons/copy.svg" width="18px" height="18px" />
|
|
63
|
-
</div>
|
|
64
|
-
<div class="divider"></div>
|
|
65
|
-
<div class="toolbar_action_item">
|
|
66
|
-
<img class="icon" src="/icons/download.svg" width="18px" height="18px" />
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
<%- include("components/code", { lang: "json", code: json }) %>
|
|
10
|
+
<%- include("components/toolbar", { address, prefix, name, search }) %> <%- include("components/code", { lang: "json", code: json }) %>
|
|
71
11
|
</div>
|
|
72
12
|
</main>
|
|
73
13
|
<script src="/js/fakelab.min.js"></script>
|
|
74
|
-
<!-- <script>
|
|
75
|
-
const address_url = document.querySelector(".address_url");
|
|
76
|
-
|
|
77
|
-
async function copy() {
|
|
78
|
-
try {
|
|
79
|
-
await navigator.clipboard.writeText(address_url.textContent);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
console.info(err);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function open_settings() {
|
|
86
|
-
const element = document.getElementById("setting_overlay");
|
|
87
|
-
element.setAttribute("data-visible", "true");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function handleCloseSetting(event) {
|
|
91
|
-
const element = document.getElementById("setting_overlay");
|
|
92
|
-
|
|
93
|
-
if (!event.target) return;
|
|
94
|
-
if (!element.contains(event.target) && event.target.id !== "overlay_trigger") {
|
|
95
|
-
element.setAttribute("data-visible", "false");
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
window.addEventListener("click", handleCloseSetting);
|
|
100
|
-
|
|
101
|
-
window.addEventListener("DOMContentLoaded", () => {
|
|
102
|
-
const countEl = document.getElementById("count");
|
|
103
|
-
const uniqueIdEl = document.getElementById("unique_id");
|
|
104
|
-
const strategyEl = document.getElementById("unique_id_strategy");
|
|
105
|
-
const uniqueIdKeyEl = document.getElementById("unique_id_key");
|
|
106
|
-
const keyEl = document.getElementById("unique_id_key_field");
|
|
107
|
-
const strategyContainerEl = document.getElementById("unique_strategy_container");
|
|
108
|
-
const params = new URLSearchParams(window.location.search);
|
|
109
|
-
const countValue = params.get("count");
|
|
110
|
-
const uniqueIdValue = params.get("uid");
|
|
111
|
-
if (countValue) countEl.value = countValue;
|
|
112
|
-
if (uniqueIdValue) {
|
|
113
|
-
uniqueIdEl.checked = true;
|
|
114
|
-
uniqueIdKeyEl.value = uniqueIdValue;
|
|
115
|
-
keyEl.setAttribute("data-visible", "true");
|
|
116
|
-
strategyContainerEl.setAttribute("data-visible", "true");
|
|
117
|
-
if (params.has("s")) {
|
|
118
|
-
strategyEl.checked = true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
function submitForm(event) {
|
|
124
|
-
event.preventDefault();
|
|
125
|
-
const resetReasons = new Set();
|
|
126
|
-
const formData = new FormData(event.target);
|
|
127
|
-
const countValue = formData.get("count")?.trim();
|
|
128
|
-
const uniqueIdValue = formData.get("unique_id_key")?.trim();
|
|
129
|
-
const params = new URLSearchParams();
|
|
130
|
-
|
|
131
|
-
const switcher = document.getElementById("unique_id");
|
|
132
|
-
const strategySwitcher = document.getElementById("unique_id_strategy");
|
|
133
|
-
|
|
134
|
-
if (countValue && Number(countValue) > 0) {
|
|
135
|
-
const valueAsNumber = Number(countValue);
|
|
136
|
-
|
|
137
|
-
params.set("count", countValue.toString());
|
|
138
|
-
window.location.search = params.toString();
|
|
139
|
-
} else {
|
|
140
|
-
params.delete("count");
|
|
141
|
-
resetReasons.add("count");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (!switcher.checked) {
|
|
145
|
-
params.delete("uid");
|
|
146
|
-
resetReasons.add("uid");
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (uniqueIdValue && switcher.checked) {
|
|
150
|
-
params.set("uid", uniqueIdValue);
|
|
151
|
-
|
|
152
|
-
if (strategySwitcher.checked) {
|
|
153
|
-
params.set("s", "uuid");
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
window.location.search = params.toString();
|
|
157
|
-
} else {
|
|
158
|
-
params.delete("uid");
|
|
159
|
-
params.delete("s");
|
|
160
|
-
resetReasons.add("uid");
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const hasUidReason = resetReasons.has("uid");
|
|
164
|
-
const hasCountReason = resetReasons.has("count");
|
|
165
|
-
|
|
166
|
-
if (hasCountReason && hasUidReason) {
|
|
167
|
-
if (window.location.href.includes("?")) {
|
|
168
|
-
[href] = window.location.href.split("?");
|
|
169
|
-
|
|
170
|
-
window.location.href = href;
|
|
171
|
-
}
|
|
172
|
-
} else if ((hasCountReason && !hasUidReason) || (!hasCountReason && hasUidReason)) {
|
|
173
|
-
window.location.search = params.toString();
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function resetForm(event) {
|
|
178
|
-
event.preventDefault();
|
|
179
|
-
const params = new URLSearchParams(window.location.search);
|
|
180
|
-
params.delete("count");
|
|
181
|
-
params.delete("uid");
|
|
182
|
-
params.delete("s");
|
|
183
|
-
if (window.location.href.includes("?")) {
|
|
184
|
-
window.location.href = window.location.href.split("?")[0];
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function onChangeGenerateUniqueId(element) {
|
|
189
|
-
const switcher = document.getElementById("unique_id");
|
|
190
|
-
const key = document.getElementById("unique_id_key_field");
|
|
191
|
-
const strategy = document.getElementById("unique_strategy_container");
|
|
192
|
-
switcher.checked = !switcher.checked;
|
|
193
|
-
key.setAttribute("data-visible", switcher.checked.toString());
|
|
194
|
-
strategy.setAttribute("data-visible", switcher.checked.toString());
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function onHandleUniqueIdStrategy(element) {
|
|
198
|
-
const strategy = document.getElementById("unique_id_strategy");
|
|
199
|
-
strategy.checked = !strategy.checked;
|
|
200
|
-
}
|
|
201
|
-
</script> -->
|