fakelab 0.0.14 โ†’ 0.0.15

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
@@ -6,7 +6,7 @@
6
6
 
7
7
  - ๐Ÿš€ Instant mock server
8
8
  - ๐Ÿ—‚๏ธ Mock from Typescript files
9
- - ๐Ÿ“ฆ Lightweight ~ 653 kB
9
+ - ๐Ÿ“ฆ Lightweight ~ 665 kB
10
10
  - ๐Ÿงช Perfect for local development, prototyping, and frontend testing
11
11
 
12
12
  ## Installation
package/lib/cli.js CHANGED
@@ -1,2 +1,5 @@
1
- import P from'path';import {fileURLToPath}from'url';import M from'fs-extra';import m from'zod';import {Command}from'commander';import k from'express';import J from'cors';import K from'express-ejs-layouts';import q from'http';import'ejs';import $ 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 c=class o{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 t=u.white,s=o.prefix(e);(e==="error"?console.error:e==="warn"?console.warn:console.log)(s,t(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 y=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 t=>{let s=t.getTypeAtLocation(t.getValueDeclarationOrThrow());n[t.getName()]=await r(s,this,this.readJSDocTags(t));})),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[t]=n.getText();if(!t)return;let s=t.text.trim().match(this.FAKER_TAG_REGEX);if(!s)return;let[,i,a]=s,p=this.evalArgs(a);return {path:i,args:p}})}execute(e,r){if(!e)return r();let n=e.path.split("."),t=this.faker;for(let s of n)t=t[s],t||(c.error("Invalid faker module path:",e.path),process.exit(1));typeof t!="function"&&(c.error("Unresolvable faker function.",e.path),process.exit(1));try{return e.args?t(e.args):t()}catch{return c.error("Passed invalid arguments to faker function."),t()}}};var d=class{constructor(e){this.files=e;let n=new Project({tsConfigFilePath:"tsconfig.json"}).addSourceFilesAtPaths(e);this.__targets=n.flatMap(t=>{let s=t.getInterfaces(),i=t.getTypeAliases(),a=t.getExportDeclarations().flatMap(p=>p.getNamedExports().flatMap(f=>f.getLocalTargetDeclarations()));return [...s,...i,...a]});}__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(),t=r.getType(),s=this.normalizePath(process.cwd()),a=this.normalizePath(r.getSourceFile().getDirectoryPath()).replace(s,""),p=r.getSourceFile().getBaseName(),f=`${a}/${p}`;return [n,{type:t,filepath:f}]});return new Map(e)}async loadFaker(e){let{faker:r}=await import(`@faker-js/faker/locale/${e.locale}`);return r}};async function l(o,e,r=[],n=0){if(o.isString())return e.string(r[n]);if(o.isNumber())return e.int(r[n]);if(o.isBoolean())return e.bool(r[n]);if(o.isBigInt())return e.bigInt(r[n]);if(o.isBooleanLiteral())return e.litbool(o.getText());if(o.isLiteral())return o.getLiteralValue();if(!o.isUndefined()){if(o.isUnion()){let t=o.getUnionTypes();return await e.union(t.map((s,i)=>l(s,e,r,i)))}if(o.isIntersection()){let t=o.getIntersectionTypes();return await e.intersection(t.map((s,i)=>l(s,e,r,i)))}if(o.isArray()){let t=o.getArrayElementTypeOrThrow();return [await l(t,e,r,n)]}if(o.isObject()){let t=o.getProperties();return await e.object(t,(s,i,a)=>l(s,i,a,n))}return null}}function D({each:o}){return {resolve:async r=>await Promise.all(Array.from({length:r},(n,t)=>o(t)))}}function R(o,e){return o==="uuid"?v4():e+1}function N(o,e,r){return async n=>{let t=await l(o,e);return r.uid&&typeof t=="object"?{[r.uid]:R(r.strategy,n),...t}:t}}async function L(o,e){let r=await o.files(e.source),n=new d(r),t=await n.loadFaker(o.fakerOpts(e.locale)),s=new y(t),i=n.entities();async function a(p,f){let g=D({each:N(p,s,f)}),h=await(f.count?g.resolve(parseInt(f.count)):l(p,s)),x=JSON.stringify(h,null,2);return {data:h,json:x}}return {entities:i,forge:a}}var U=fileURLToPath(import.meta.url),B=P.dirname(U),A=M.readJSONSync(P.join(B,"../package.json")),v=class{constructor(e,r,n){this.router=e;this.config=r;this.opts=n;let{pathPrefix:t}=this.config.serverOpts(this.opts.pathPrefix,this.opts.port);this.prefix=t;}prefix;get querySchema(){return m.object({count:m.string().optional(),uid:m.string().optional(),strategy:m.string().optional()})}async handleQueries(e){let{success:r,data:n,error:t}=await this.querySchema.safeParseAsync(e.query);return r?n:(c.warn(t.message),{})}async register(){let{entities:e,forge:r}=await L(this.config,this.opts);this.router.get("/",(n,t)=>{let s=n.path;t.render("index",{currentPath:s,entities:e,version:A.version});}),this.router.get("/:name",async(n,t)=>{let s=`${n.protocol}://${n.host}/`,i=n.path,a=n.params.name,p=await this.handleQueries(n),f=$.stringify(p,{addQueryPrefix:true}),g=e.get(a.toLowerCase());if(g){let{json:h}=await r(g.type,p),x=g.filepath;t.render("preview",{name:a,filepath:x,currentPath:i,address:s,search:f,json:h,entities:e,version:A.version,prefix:this.prefix});}else t.redirect("/");}),this.router.get(`/${this.prefix}/:name`,async(n,t)=>{try{let s=n.params.name,i=await this.handleQueries(n),a=e.get(s.toLowerCase());if(a){let{data:p}=await r(a.type,i);t.status(200).json(p);}else t.status(400).json({message:"The requested interface is not found"});}catch(s){t.status(500).send(s);}});}};var V=fileURLToPath(import.meta.url),C=P.dirname(V);function X(o,e,r){let{port:n}=e.serverOpts(r.pathPrefix,r.port);o.listen(n,"localhost",async()=>{c.info(`Server: http://localhost:${n}`),console.log(await Q.text("FAKELAB"));});}function H(o,e,r){e.setHeader("x-powered-by","fakelab"),r();}function Z(o){o.disable("x-powered-by"),o.use(k.json()),o.use(J({methods:"GET"})),o.use(k.static(C+"/public")),o.use(H);}function W(o){o.set("views",P.join(C,"views")),o.set("view engine","ejs"),o.use(K),o.set("layout","layouts/main");}async function E(o,e){let r=k(),n=k.Router(),t=q.createServer(r);Z(r),W(r),await new v(n,o,e).register(),r.use(n),X(t,o,e);}async function _(){try{let e=await new ee().resolve({files:["fakelab.config.ts"]});return e||(c.error("No fakelab config file is detected."),process.exit(1)),(await bundleRequire({filepath:e})).mod.default}catch{c.error("Could not load the config file."),process.exit(1);}}var b=new Command,ne=fileURLToPath(import.meta.url),se=P.dirname(ne),T=M.readJSONSync(P.join(se,"../package.json"));b.name(T.name).description(T.description).version(T.version);var ie=m.object({source:m.string().optional(),pathPrefix:m.string().optional(),port:m.number().int().optional(),locale:m.string().optional()});b.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 o=>{let e=await ie.safeParseAsync(o);e.error&&(c.error(m.treeifyError(e.error).errors.join(`
2
- `)),process.exit(1));let r=await _();E(r,e.data);});b.parse();
1
+ import y from'path';import {fileURLToPath}from'url';import E from'fs-extra';import {Command}from'commander';import v from'express';import G from'cors';import z from'express-ejs-layouts';import K from'http';import'ejs';import M from'qs';import {Project}from'ts-morph';import l from'picocolors';import Q from'figlet';import {bundleRequire}from'bundle-require';import Y from'joycon';var p=class r{static prefix(e){let t=new Date().toLocaleTimeString();return {info:l.blue,warn:l.yellow,error:l.red,success:l.green,debug:l.magenta}[e](`[${t}] FAKELAB_${e.toUpperCase()}`)}static log(e,t,...n){let o=l.white,s=r.prefix(e);(e==="error"?console.error:e==="warn"?console.warn:console.log)(s,o(t),...n);}static info(e,...t){this.log("info",e,...t);}static warn(e,...t){this.log("warn",e,...t);}static error(e,...t){this.log("error",e,...t);}static success(e,...t){this.log("success",e,...t);}};var h=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,t){let n={};return await Promise.all(e.map(async o=>{let s=o.getTypeAtLocation(o.getValueDeclarationOrThrow());n[o.getName()]=await t(s,this,this.readJSDocTags(o));})),n}async union(e){let t=await Promise.all(e);return t[Math.floor(Math.random()*t.length)]}async intersection(e){let t=await Promise.all(e);return t[Math.floor(Math.random()*t.length)]}evalArgs(e){if(!(!e||!e.trim()))return Function(`"use strict"; return (${e});`)()}readJSDocTags(e){let t=e.getJsDocTags().filter(n=>n.getName()===this.JSDOC_FAKER_FIELD);return t.length===0?[]:t.map(n=>{let[o]=n.getText();if(!o)return;let s=o.text.trim().match(this.FAKER_TAG_REGEX);if(!s)return;let[,i,a]=s,c=this.evalArgs(a);return {path:i,args:c}})}execute(e,t){if(!e)return t();let n=e.path.split("."),o=this.faker;for(let s of n)o=o[s],o||(p.error("Invalid faker module path:",e.path),process.exit(1));typeof o!="function"&&(p.error("Unresolvable faker function.",e.path),process.exit(1));try{return e.args?o(e.args):o()}catch{return p.error("Passed invalid arguments to faker function."),o()}}};var D=fileURLToPath(import.meta.url),O=y.dirname(D),d=class{constructor(e){this.files=e;let n=new Project({tsConfigFilePath:"tsconfig.json"}).addSourceFilesAtPaths(e);this.__targets=n.flatMap(o=>{let s=o.getInterfaces(),i=o.getTypeAliases(),a=o.getExportDeclarations().flatMap(c=>c.getNamedExports().flatMap(f=>f.getLocalTargetDeclarations()));return [...s,...i,...a]}),this.generateInFileEntitiyMap(this.__targets);}__targets;async run(e){return await e()}normalizePath(e){return e.split(y.sep).join(y.posix.sep)}generateInFileEntitiyMap(e){let n=`declare global {
2
+ interface FakeRuntime {${[...new Set(e.map(o=>{let s=o.getName(),i=o.getSourceFile().getFilePath();return `${s}: import("${i}").${s}`}))].join(`
3
+ `)}
4
+ }
5
+ }`;E.appendFile(y.resolve(O,"runtime.d.ts"),n);}entities(){let e=this.__targets.map(t=>{let n=t.getName().toLowerCase(),o=t.getType(),s=this.normalizePath(process.cwd()),a=this.normalizePath(t.getSourceFile().getDirectoryPath()).replace(s,""),c=t.getSourceFile().getBaseName(),f=`${a}/${c}`;return [n,{type:o,filepath:f}]});return new Map(e)}async loadFaker(e){let{faker:t}=await import(`@faker-js/faker/locale/${e.locale}`);return t}};async function m(r,e,t=[],n=0){if(r.isString())return e.string(t[n]);if(r.isNumber())return e.int(t[n]);if(r.isBoolean())return e.bool(t[n]);if(r.isBigInt())return e.bigInt(t[n]);if(r.isBooleanLiteral())return e.litbool(r.getText());if(r.isLiteral())return r.getLiteralValue();if(!r.isUndefined()){if(r.isUnion()){let o=r.getUnionTypes();return await e.union(o.map((s,i)=>m(s,e,t,i)))}if(r.isIntersection()){let o=r.getIntersectionTypes();return await e.intersection(o.map((s,i)=>m(s,e,t,i)))}if(r.isArray()){let o=r.getArrayElementTypeOrThrow();return [await m(o,e,t,n)]}if(r.isObject()){let o=r.getProperties();return await e.object(o,(s,i,a)=>m(s,i,a,n))}return null}}function R({each:r}){return {resolve:async t=>await Promise.all(Array.from({length:t},r))}}async function F(r,e){let t=await r.files(e.source),n=new d(t),o=await n.loadFaker(r.fakerOpts(e.locale)),s=new h(o),i=n.entities();async function a(c,f){let u=R({each:()=>m(c,s)}),g=await(f.count?u.resolve(parseInt(f.count)):m(c,s)),k=JSON.stringify(g,null,2);return {data:g,json:k}}return {entities:i,forge:a}}var U=fileURLToPath(import.meta.url),B=y.dirname(U),b=E.readJSONSync(y.join(B,"../package.json")),w=class{constructor(e,t,n){this.router=e;this.config=t;this.opts=n;let{pathPrefix:o}=this.config.serverOpts(this.opts.pathPrefix,this.opts.port);this.prefix=o;}prefix;async handleQueries(e){let t=e.query.count;return t?{count:t.toString()}:{}}async register(){let{entities:e,forge:t}=await F(this.config,this.opts);this.router.get("/",(n,o)=>{let s=n.path;o.render("index",{currentPath:s,entities:e,version:b.version});}),this.router.get("/:name",async(n,o)=>{let s=`${n.protocol}://${n.host}/`,i=n.path,a=n.params.name,c=await this.handleQueries(n),f=M.stringify(c,{addQueryPrefix:true}),u=e.get(a.toLowerCase());if(u){let{json:g}=await t(u.type,c),k=u.filepath;o.render("preview",{name:a,filepath:k,currentPath:i,address:s,search:f,json:g,entities:e,version:b.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),a=e.get(s.toLowerCase());if(a){let{data:c}=await t(a.type,i);o.status(200).json(c);}else o.status(400).json({message:"The requested interface is not found"});}catch(s){o.status(500).send(s);}});}};var q=fileURLToPath(import.meta.url),x=y.dirname(q);function V(r,e,t){let{port:n}=e.serverOpts(t.pathPrefix,t.port);r.listen(n,"localhost",async()=>{p.info(`Server: http://localhost:${n}`),console.log(await Q.text("FAKELAB"));});}function X(r,e,t){e.setHeader("x-powered-by","fakelab"),t();}function H(r){r.disable("x-powered-by"),r.use(v.json()),r.use(G({methods:"GET"})),r.use(v.static(x+"/public")),r.use(X);}function Z(r){r.set("views",y.join(x,"views")),r.set("view engine","ejs"),r.use(z),r.set("layout","layouts/main");}async function _(r,e){let t=v(),n=v.Router(),o=K.createServer(t);H(t),Z(t),await r.generateInFileRuntimeConfig(x,e),await new w(n,r,e).register(),t.use(n),V(o,r,e);}async function C(){try{let e=await new Y().resolve({files:["fakelab.config.ts"]});return e||(p.error("No fakelab config file is detected."),process.exit(1)),(await bundleRequire({filepath:e})).mod.default}catch{p.error("Could not load the config file."),process.exit(1);}}var P=new Command,oe=fileURLToPath(import.meta.url),ne=y.dirname(oe),T=E.readJSONSync(y.join(ne,"../package.json"));P.name(T.name).description(T.description).version(T.version);P.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 r=>{let e=await C();_(e,r);});P.parse();
package/lib/main.d.ts CHANGED
@@ -19,6 +19,12 @@ type ConfigOptions = {
19
19
  server?: ServerOptions;
20
20
  faker?: FakerEngineOptions;
21
21
  };
22
+ type ServerCLIOptions = {
23
+ source?: string;
24
+ pathPrefix?: string;
25
+ port?: number;
26
+ locale?: string;
27
+ };
22
28
 
23
29
  declare class Config {
24
30
  private readonly opts;
@@ -26,6 +32,7 @@ declare class Config {
26
32
  files(_sourcePath?: string): Promise<string[]>;
27
33
  serverOpts(prefix?: string, port?: number): Required<ServerOptions>;
28
34
  fakerOpts(locale?: FakerLocale): Required<FakerEngineOptions>;
35
+ generateInFileRuntimeConfig(dir: string, options: ServerCLIOptions): Promise<void>;
29
36
  private tryStat;
30
37
  private isReadable;
31
38
  private resolveSourcePath;
package/lib/main.js CHANGED
@@ -1,3 +1,35 @@
1
- import h from'fast-glob';import f 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,l=o.prefix(t);(t==="error"?console.error:t==="warn"?console.warn:console.log)(l,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);}};var c=["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"];function p(){let o=Intl.DateTimeFormat().resolvedOptions().locale;if(!o)return "en";let[t]=o.split("-"),r=t.toLowerCase();return c.includes(r)?r:"en"}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){let r=(t||this.opts.faker?.locale)?.toLowerCase();return r&&c.includes(r)?{locale:r}:{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=>f.resolve(e))}async resolveTSFiles(t){let r=f.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),h("**/*.ts",{cwd:r,absolute:true,ignore:["**/*.d.ts"]});s.error(`Invalid source path: ${t}`),process.exit(1);}};function d(o){return new a(o)}export{d as defineConfig};
1
+ import k from'fast-glob';import l from'path';import m from'fs-extra';import {stat,access,constants}from'fs/promises';import a from'picocolors';var s=class o{static prefix(e){let t=new Date().toLocaleTimeString();return {info:a.blue,warn:a.yellow,error:a.red,success:a.green,debug:a.magenta}[e](`[${t}] FAKELAB_${e.toUpperCase()}`)}static log(e,t,...r){let n=a.white,c=o.prefix(e);(e==="error"?console.error:e==="warn"?console.warn:console.log)(c,n(t),...r);}static info(e,...t){this.log("info",e,...t);}static warn(e,...t){this.log("warn",e,...t);}static error(e,...t){this.log("error",e,...t);}static success(e,...t){this.log("success",e,...t);}};var f=["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"];function h(){let o=Intl.DateTimeFormat().resolvedOptions().locale;if(!o)return "en";let[e]=o.split("-"),t=e.toLowerCase();return f.includes(t)?t:"en"}var i=class{static source(e,t){return `global.fakelab = {};
2
+ global.fakelab.URL = "http://localhost:${e}/${t}/";
3
+ global.fakelab.fetch = async function (name, count) {
4
+ const search = count ? "?count=" + count : "";
5
+
6
+ const response = await fetch(global.fakelab.URL + name + search);
7
+
8
+ if (!response.ok) throw new Error("[fakelab] Failed to retreived mock data.");
9
+
10
+ const result = await response.json();
11
+
12
+ return result;
13
+ };
14
+ `}static decl(){return `export {};
15
+
16
+ declare global {
17
+ const fakelab: {
18
+ fetch<T extends keyof FakeRuntime, Count extends number | undefined = undefined>(name: T, count?: Count): Promise<FakeResult<FakeRuntime[T], Count>>;
19
+ readonly URL: string;
20
+ };
21
+ type FakeResult<T, Count> = Count extends number ? (Count extends 0 ? T : T[]) : T;
22
+ interface FakeRuntime {}
23
+ interface Window {
24
+ readonly fakelab: typeof fakelab;
25
+ }
26
+
27
+ namespace NodeJS {
28
+ interface Global {
29
+ fakelab: typeof fakelab;
30
+ }
31
+ }
32
+ }
33
+ `}};var p=class{constructor(e){this.opts=e;this.files=this.files.bind(this),this.serverOpts=this.serverOpts.bind(this),this.fakerOpts=this.fakerOpts.bind(this);}async files(e){let t=this.resolveSourcePath(e||this.opts.sourcePath),r=Array.from(new Set((await Promise.all(t.map(n=>this.resolveTSFiles(n)))).flat()));return r.length===0&&(s.error(`No Typescript files found in:
34
+ %s`,t.join(`
35
+ `)),process.exit(1)),r}serverOpts(e,t){return {pathPrefix:e||this.opts.server?.pathPrefix||"api",port:t||this.opts.server?.port||5200}}fakerOpts(e){let t=(e||this.opts.faker?.locale)?.toLowerCase();return t&&f.includes(t)?{locale:t}:{locale:h()}}async generateInFileRuntimeConfig(e,t){let{port:r,pathPrefix:n}=this.serverOpts(t.pathPrefix,t.port),c=l.resolve(e,"runtime.js"),u=l.resolve(e,"runtime.d.ts");await Promise.all([m.writeFile(c,i.source(r,n)),m.writeFile(u,i.decl())]);}async tryStat(e){try{return await stat(e)}catch{return null}}async isReadable(e){try{return await access(e,constants.R_OK),!0}catch{return false}}resolveSourcePath(e){return (Array.isArray(e)?e:[e]).map(r=>l.resolve(r))}async resolveTSFiles(e){let t=l.resolve(e),r=t.endsWith(".ts")?t:t+".ts";if((await this.tryStat(r))?.isFile()){if(!await this.isReadable(r))throw new Error(`Cannot read file: ${r}`);return s.info("Source:",r),[r]}if((await this.tryStat(t))?.isDirectory())return s.info("Source:",t),k("**/*.ts",{cwd:t,absolute:true,ignore:["**/*.d.ts"]});s.error(`Invalid source path: ${e}`),process.exit(1);}};function b(o){return new p(o)}export{b as defineConfig};
@@ -294,17 +294,6 @@ pre {
294
294
  align-items: center;
295
295
  gap: 8px;
296
296
  position: relative;
297
-
298
- /* > .toolbar_setting_count_input {
299
- border: 1px solid oklch(98.463% 0.00181 249.248 / 0.171);
300
- outline: none;
301
- border-radius: 4px;
302
- padding-inline: 8px;
303
- height: 32px;
304
- color: oklch(98.463% 0.00181 249.248 / 0.801);
305
- background: transparent;
306
- font-family: inter;
307
- } */
308
297
  }
309
298
  .toolbar_setting .toolbar_setting_option {
310
299
  display: flex;
@@ -523,67 +512,6 @@ pre {
523
512
  .icon.pointer_auto {
524
513
  pointer-events: auto;
525
514
  }
526
- .switch {
527
- position: relative;
528
- display: inline-block;
529
- width: 28px;
530
- height: 6px;
531
- }
532
-
533
- .switch input {
534
- opacity: 0;
535
- width: 0;
536
- height: 0;
537
- }
538
-
539
- .slider {
540
- position: absolute;
541
- cursor: pointer;
542
- top: 0;
543
- left: 0;
544
- right: 0;
545
- bottom: 0;
546
- background-color: hsl(216, 31%, 25%);
547
- -webkit-transition: 0.4s;
548
- transition: 0.4s;
549
- border-radius: 24px;
550
- height: 6px;
551
- }
552
-
553
- .slider:before {
554
- position: absolute;
555
- content: "";
556
- height: 16px;
557
- width: 16px;
558
- left: -1px;
559
- bottom: -5px;
560
- background-color: hsl(216, 31%, 32%);
561
- -webkit-transition: 0.4s;
562
- transition: 0.4s;
563
- border-radius: 50%;
564
- }
565
-
566
- input:checked + .slider:before {
567
- -webkit-transform: translateX(13px);
568
- -ms-transform: translateX(13px);
569
- transform: translateX(13px);
570
- background-color: oklch(68.5% 0.169 237.323);
571
- }
572
-
573
- .unique_id_hint {
574
- font-size: 10px;
575
- color: oklch(98.463% 0.00181 249.248 / 0.801);
576
- }
577
-
578
- .unique_strategy {
579
- margin-top: 8px;
580
- display: none;
581
- flex-direction: column;
582
- gap: 16px;
583
- &[data-visible="true"] {
584
- display: flex;
585
- }
586
- }
587
515
 
588
516
  @keyframes rotation {
589
517
  0% {
@@ -19,8 +19,8 @@ function downloadJsonCode(e) {
19
19
  t = new Blob([t], { type: "application/json" });
20
20
  let n = URL.createObjectURL(t);
21
21
  var t = e.getAttribute("data-source-name"),
22
- d = new Date().toISOString().replace(/[:.]/g, "-");
23
- (e.download = t + `-${d}.json`),
22
+ o = new Date().toISOString().replace(/[:.]/g, "-");
23
+ (e.download = t + `-${o}.json`),
24
24
  (e.href = n),
25
25
  setTimeout(() => {
26
26
  URL.revokeObjectURL(n), (e.download = ""), (e.href = "");
@@ -36,48 +36,19 @@ function handleCloseSetting(e) {
36
36
  function submitForm(e) {
37
37
  e.preventDefault();
38
38
  var t = new Set(),
39
- e = new FormData(e.target),
40
- n = e.get("count")?.trim(),
41
- e = e.get("unique_id_key")?.trim(),
42
- d = new URLSearchParams(),
43
- o = document.getElementById("unique_id"),
44
- i = document.getElementById("unique_id_strategy"),
45
- n =
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")),
49
- t.has("uid")),
50
- o = t.has("count");
51
- o && n
52
- ? window.location.href.includes("?") && (([href] = window.location.href.split("?")), (window.location.href = href))
53
- : ((o && !n) || (!o && n)) && (window.location.search = d.toString());
39
+ e = new FormData(e.target).get("count")?.trim(),
40
+ n = new URLSearchParams(),
41
+ e = (e && 0 < Number(e) ? (n.set("count", e.toString()), (window.location.search = n.toString())) : (n.delete("count"), t.add("count")), t.has("count"));
42
+ e && window.location.href.includes("?") && (([href] = window.location.href.split("?")), (window.location.href = href));
54
43
  }
55
44
  function resetForm(e) {
56
- e.preventDefault();
57
- e = new URLSearchParams(window.location.search);
58
- e.delete("count"), e.delete("uid"), e.delete("strategy"), window.location.href.includes("?") && (window.location.href = window.location.href.split("?")[0]);
59
- }
60
- function onChangeGenerateUniqueId(e) {
61
- var t = document.getElementById("unique_id"),
62
- n = document.getElementById("unique_id_key_field"),
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());
65
- }
66
- function onHandleUniqueIdStrategy(e) {
67
- var t = document.getElementById("unique_id_strategy");
68
- t.checked = !t.checked;
45
+ e.preventDefault(),
46
+ new URLSearchParams(window.location.search).delete("count"),
47
+ window.location.href.includes("?") && (window.location.href = window.location.href.split("?")[0]);
69
48
  }
70
49
  window.addEventListener("click", handleCloseSetting),
71
50
  window.addEventListener("DOMContentLoaded", () => {
72
51
  var e = document.getElementById("count"),
73
- t = document.getElementById("unique_id"),
74
- n = document.getElementById("unique_id_strategy"),
75
- d = document.getElementById("unique_id_key"),
76
- o = document.getElementById("unique_id_key_field"),
77
- i = document.getElementById("unique_strategy_container"),
78
- a = new URLSearchParams(window.location.search),
79
- c = a.get("count"),
80
- r = a.get("uid");
81
- c && (e.value = c),
82
- r && ((t.checked = !0), (d.value = r), o.setAttribute("data-visible", "true"), i.setAttribute("data-visible", "true"), a.has("strategy")) && (n.checked = !0);
52
+ t = new URLSearchParams(window.location.search).get("count");
53
+ t && (e.value = t);
83
54
  });
@@ -18,28 +18,6 @@
18
18
  <input id="count" autocomplete="off" name="count" type="text" />
19
19
  <span>Set count field to generate array of data items.</span>
20
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
21
  <div class="form_buttons">
44
22
  <button class="form_reset_btn" type="button" onclick="resetForm(event)">Reset</button>
45
23
  <button class="form_apply_btn" type="submit">Apply</button>
package/package.json CHANGED
@@ -1,12 +1,23 @@
1
1
  {
2
2
  "name": "fakelab",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "A easy-config mock server for frontend developers.",
7
7
  "main": "lib/main.js",
8
8
  "module": "lib/main.js",
9
9
  "types": "lib/main.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./lib/main.d.ts",
13
+ "default": "./lib/main.js"
14
+ },
15
+ "./runtime": {
16
+ "types": "./lib/runtime.d.ts",
17
+ "node": "./lib/runtime.js",
18
+ "default": "./lib/runtime.js"
19
+ }
20
+ },
10
21
  "engines": {
11
22
  "node": ">=18"
12
23
  },
@@ -32,7 +43,8 @@
32
43
  },
33
44
  "files": [
34
45
  "bin",
35
- "lib"
46
+ "lib",
47
+ "package.json"
36
48
  ],
37
49
  "keywords": [
38
50
  "typescript",
@@ -44,7 +56,6 @@
44
56
  "devDependencies": {
45
57
  "@release-it/conventional-changelog": "^10.0.2",
46
58
  "@types/cors": "^2.8.19",
47
- "@types/doctrine": "^0.0.9",
48
59
  "@types/ejs": "^3.1.5",
49
60
  "@types/express": "^5.0.6",
50
61
  "@types/express-ejs-layouts": "^2.5.4",
@@ -53,14 +64,14 @@
53
64
  "release-it": "^19.0.6",
54
65
  "tsup": "^8.5.1",
55
66
  "tsx": "^4.21.0",
56
- "typescript": "~5.9.3"
67
+ "typescript": "~5.9.3",
68
+ "uglify-js": "^3.19.3"
57
69
  },
58
70
  "dependencies": {
59
71
  "@faker-js/faker": "^10.1.0",
60
72
  "bundle-require": "^5.1.0",
61
73
  "commander": "^14.0.2",
62
74
  "cors": "^2.8.5",
63
- "doctrine": "^3.0.0",
64
75
  "ejs": "^3.1.10",
65
76
  "express": "^5.2.1",
66
77
  "express-ejs-layouts": "^2.5.1",
@@ -70,10 +81,7 @@
70
81
  "joycon": "^3.1.1",
71
82
  "picocolors": "^1.1.1",
72
83
  "qs": "^6.14.0",
73
- "ts-morph": "^27.0.2",
74
- "uglify-js": "^3.19.3",
75
- "uuid": "^13.0.0",
76
- "zod": "^4.1.13"
84
+ "ts-morph": "^27.0.2"
77
85
  },
78
86
  "bin": {
79
87
  "fakelab": "bin/run.js"