@michijs/dev-server 0.4.3 → 0.5.0

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.
Files changed (43) hide show
  1. package/README.md +23 -2
  2. package/bin/actions/build.js +2 -2
  3. package/bin/actions/dist.js +5 -5
  4. package/bin/actions/generateAssets.d.ts +4 -0
  5. package/bin/actions/generateAssets.js +125 -0
  6. package/bin/actions/start.d.ts +1 -1
  7. package/bin/actions/start.js +46 -30
  8. package/bin/cli.js +33 -33
  9. package/bin/config/config.d.ts +111 -6
  10. package/bin/config/config.js +40 -31
  11. package/bin/config/getIPAddress.js +5 -3
  12. package/bin/config/michi.config.cjs +130 -134
  13. package/bin/config/public/client.js +1 -1
  14. package/bin/config/tsconfig.d.ts +1 -1
  15. package/bin/config/tsconfig.js +3 -3
  16. package/bin/config/userConfig.d.ts +1 -1
  17. package/bin/config/userConfig.js +18 -14
  18. package/bin/constants.d.ts +8 -0
  19. package/bin/constants.js +12 -0
  20. package/bin/index.d.ts +1 -1
  21. package/bin/index.js +1 -1
  22. package/bin/tsconfig.tsbuildinfo +1 -1
  23. package/bin/types.d.ts +71 -7
  24. package/bin/utils/copy.js +4 -4
  25. package/bin/utils/feature-image-template.svg +62 -0
  26. package/bin/utils/getAllFiles.js +2 -2
  27. package/bin/utils/getHostURL.d.ts +1 -0
  28. package/bin/utils/getHostURL.js +4 -0
  29. package/bin/utils/getLocalURL.d.ts +1 -0
  30. package/bin/utils/getLocalURL.js +3 -0
  31. package/bin/utils/getPath.js +1 -1
  32. package/bin/utils/minify.js +3 -3
  33. package/bin/utils/serviceWorkerTransformer.d.ts +2 -1
  34. package/bin/utils/serviceWorkerTransformer.js +8 -8
  35. package/bin/utils/transformers.d.ts +1 -1
  36. package/bin/utils/transformers.js +4 -4
  37. package/package.json +6 -17
  38. package/bin/actions/generateIcons.d.ts +0 -1
  39. package/bin/actions/generateIcons.js +0 -35
  40. package/bin/utils/transpileFileInThread.d.ts +0 -1
  41. package/bin/utils/transpileFileInThread.js +0 -15
  42. package/bin/utils/transpileFilesWithThreads.d.ts +0 -2
  43. package/bin/utils/transpileFilesWithThreads.js +0 -25
package/bin/types.d.ts CHANGED
@@ -1,11 +1,13 @@
1
- import { BuildOptions } from 'esbuild';
2
- import type { WebAppManifest } from 'web-app-manifest';
1
+ import type { BuildOptions } from "esbuild";
2
+ import type { WebAppManifest } from "web-app-manifest";
3
+ import type { assetsSizes } from "./constants.js";
4
+ import type { Page } from "puppeteer";
3
5
  export interface AssetDescriptorWeb {
4
- namespace: 'web';
6
+ namespace: "web";
5
7
  site: string;
6
8
  }
7
9
  export interface AssetDescriptorAndroid {
8
- namespace: 'android_app';
10
+ namespace: "android_app";
9
11
  package_name: string;
10
12
  /**
11
13
  * The sha256_cert_fingerprints field is a list of colon-separated hex strings.
@@ -13,7 +15,7 @@ export interface AssetDescriptorAndroid {
13
15
  sha256_cert_fingerprints: string[];
14
16
  }
15
17
  export interface AssetDescriptorIos {
16
- namespace: 'ios_app';
18
+ namespace: "ios_app";
17
19
  appid: string;
18
20
  }
19
21
  export type AssetDescriptor = AssetDescriptorWeb | AssetDescriptorAndroid | AssetDescriptorIos;
@@ -28,6 +30,12 @@ export interface WellKnown {
28
30
  relation: string[];
29
31
  target: AssetDescriptor;
30
32
  }
33
+ export interface PageCallback<R = string | void> {
34
+ /**
35
+ * @returns A folder name suffix
36
+ */
37
+ (page: Page): Promise<R> | R;
38
+ }
31
39
  export interface PublicOptions {
32
40
  /**
33
41
  * A URI with the path component /.well-known/assetlinks.json is used by the AssetLinks protocol to identify one or more digital assets (such as web sites or mobile apps) that are related to the hosting web site in some fashion.
@@ -49,6 +57,52 @@ export interface PublicOptions {
49
57
  * @default true if environment is PRODUCTION
50
58
  */
51
59
  minify?: boolean;
60
+ assets?: {
61
+ /**
62
+ * Assets folder path
63
+ * @default assets
64
+ */
65
+ path?: string;
66
+ /**
67
+ * Screenshots to take
68
+ */
69
+ screenshots?: {
70
+ /**
71
+ * Paths to use.
72
+ * @example ["/demo"]
73
+ */
74
+ paths?: string[];
75
+ /**
76
+ * An array of callbacks used to manipulate the page. Each callback returns the folder name suffix
77
+ * @example
78
+ * [
79
+ * async (page) => {
80
+ * await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
81
+ * return 'dark'
82
+ * }
83
+ * ]
84
+ */
85
+ pageCallbacks?: PageCallback[];
86
+ };
87
+ /**
88
+ * Feature image to take
89
+ */
90
+ featureImage?: {
91
+ /**
92
+ * Path to use.
93
+ * @example "/demo"
94
+ */
95
+ path?: string;
96
+ /**
97
+ * A callback used to manipulate the page.
98
+ * @example
99
+ * async (page) => {
100
+ * await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
101
+ * }
102
+ */
103
+ pageCallback?: PageCallback<void>;
104
+ };
105
+ };
52
106
  /**
53
107
  * Is a JSON document that contains startup parameters and application defaults for when a web application is launched.
54
108
  *
@@ -67,6 +121,11 @@ export interface PublicOptions {
67
121
  };
68
122
  }
69
123
  export interface Config {
124
+ /**
125
+ * If the server should watch for changes on the folders
126
+ * @default true
127
+ */
128
+ watch?: boolean;
70
129
  /**
71
130
  * Port to run dev server on
72
131
  * @default 3000
@@ -87,7 +146,7 @@ export interface Config {
87
146
  /** Documentation: https://esbuild.github.io/plugins/#build-options */
88
147
  esbuildOptions?: BuildOptions;
89
148
  }
90
- export type DefaultEnvironment = 'PRODUCTION' | 'DISTRIBUTION' | 'DEVELOPMENT';
149
+ export type DefaultEnvironment = "PRODUCTION" | "DISTRIBUTION" | "DEVELOPMENT";
91
150
  export interface ServerConfig extends Config {
92
151
  /**
93
152
  * Allows to add environment variables
@@ -103,4 +162,9 @@ export interface MichiProcessType {
103
162
  NODE_ENV: DefaultEnvironment;
104
163
  };
105
164
  }
106
- export type ServerConfigFactory<T extends string = DefaultEnvironment> = (environment: T) => ServerConfig;
165
+ interface ServerConfigFactoryProps<T extends string> {
166
+ assetsSizes: typeof assetsSizes;
167
+ environment: T;
168
+ }
169
+ export type ServerConfigFactory<T extends string = DefaultEnvironment> = (props: ServerConfigFactoryProps<T>) => ServerConfig;
170
+ export {};
package/bin/utils/copy.js CHANGED
@@ -1,6 +1,6 @@
1
- import fs from 'fs';
2
- import { getPath } from './getPath.js';
3
- import { transformers } from './transformers.js';
1
+ import fs from "fs";
2
+ import { getPath } from "./getPath.js";
3
+ import { transformers } from "./transformers.js";
4
4
  export function copyFile(src, fileName, dest, omit) {
5
5
  if (!omit?.find((x) => x.test(fileName))) {
6
6
  const srcPath = getPath(`${src}/${fileName}`);
@@ -13,7 +13,7 @@ export function copyFile(src, fileName, dest, omit) {
13
13
  else {
14
14
  const fileTransformer = transformers?.find((x) => x.fileRegex.test(fileName));
15
15
  if (fileTransformer) {
16
- const srcFileContent = fs.readFileSync(srcPath, { encoding: 'utf-8' });
16
+ const srcFileContent = fs.readFileSync(srcPath, { encoding: "utf-8" });
17
17
  const finalDestPath = fileTransformer.pathTransformer?.(destPath) ?? destPath;
18
18
  const transformedFile = fileTransformer.transformer(srcFileContent);
19
19
  fs.writeFileSync(finalDestPath, transformedFile);
@@ -0,0 +1,62 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1024" height="500">
2
+ <style>
3
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
4
+ </style>
5
+ <!-- Background color -->
6
+ <rect width="100%" height="100%" fill="rgb(106,8,12)" />
7
+
8
+ <!-- Background image with blurred logo -->
9
+ <image x="-295" y="90" width="100%" height="100%" filter="url(#blur)" href="./assets/icon.svg"></image>
10
+
11
+ <!-- Filter for blurring the logo -->
12
+ <filter id="blur">
13
+ <feGaussianBlur stdDeviation="5" />
14
+ </filter>
15
+
16
+ <!-- PC -->
17
+ <svg x="50%" y="-5%" width="50%" viewBox="0 0 200 200">
18
+ <!-- Border -->
19
+ <rect x="10" y="40" width="180" height="120" rx="5" ry="5" stroke="#000" stroke-width="5" fill="#000" />
20
+ <!-- PC screen -->
21
+ <image x="10" y="43" width="180" height="110" href="./assets/generated/screenshots/900x550.png"></image>
22
+ <!-- PC stand -->
23
+ <g>
24
+ <rect x="80" y="160" width="40" height="20" rx="0" ry="3" fill="#000" />
25
+ <!-- Monitor base -->
26
+ <polygon points="80,180 70,200 130,200 120,180" fill="#000" />
27
+ </g>
28
+ <!-- PC button -->
29
+ <circle cx="100" cy="158" r="2" fill="#FFF" />
30
+ </svg>
31
+
32
+ <!-- Tablet -->
33
+ <svg x="40%" y="30%" width="25%" viewBox="0 0 200 200">
34
+ <defs>
35
+ <clipPath id="tablet-clip">
36
+ <rect x="22.5" y="42.5" width="155" height="115" rx="10" ry="10" />
37
+ </clipPath>
38
+ </defs>
39
+ <!-- Tablet frame -->
40
+ <rect x="20" y="40" width="160" height="120" rx="10" ry="10" stroke="#000000" stroke-width="5" fill="#FFF" />
41
+ <!-- Tablet screen -->
42
+ <image clip-path="url(#tablet-clip)" x="22.5" y="45" width="155" height="110"
43
+ href="./assets/generated/screenshots/387x275.png"></image>
44
+ </svg>
45
+
46
+ <!-- Phone -->
47
+ <svg x="41%" y="-7%" width="15%" viewBox="0 0 200 200">
48
+ <!-- Phone frame -->
49
+ <rect x="20" y="40" width="120" height="180" rx="10" ry="10" stroke="#000000" stroke-width="5" fill="#FFF" />
50
+ <!-- Phone screen -->
51
+ <image x="22.5" y="48" width="115" height="155" href="./assets/generated/screenshots/287x387.png"></image>
52
+
53
+ <circle cx="80" cy="210" r="5" fill="#000000" />
54
+ </svg>
55
+
56
+
57
+ <!-- App title -->
58
+ <text x="21%" y="20%" text-anchor="middle" style="filter: invert(1)" font-family="Roboto" font-size="40"
59
+ font-weight="bold">
60
+ Michi Media Player
61
+ </text>
62
+ </svg>
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import { getPath } from './getPath.js';
1
+ import fs from "fs";
2
+ import { getPath } from "./getPath.js";
3
3
  export const getAllFiles = function (dirPath, dirToShow = dirPath, arrayOfFiles = []) {
4
4
  const files = fs.readdirSync(dirPath);
5
5
  files.forEach((file) => {
@@ -0,0 +1 @@
1
+ export declare const getHostURL: (port: number) => string;
@@ -0,0 +1,4 @@
1
+ import { getIPAddress } from "../config/getIPAddress.js";
2
+ export const getHostURL = (port) => {
3
+ return `http://${getIPAddress()}:${port}`;
4
+ };
@@ -0,0 +1 @@
1
+ export declare const getLocalURL: (port: number) => string;
@@ -0,0 +1,3 @@
1
+ export const getLocalURL = (port) => {
2
+ return `http://localhost:${port}`;
3
+ };
@@ -1,4 +1,4 @@
1
- import { normalize, sep } from 'path';
1
+ import { normalize, sep } from "path";
2
2
  export function getPath(path) {
3
3
  return normalize(path).replace(/\\/g, sep);
4
4
  }
@@ -1,7 +1,7 @@
1
- export function replaceEnter(json, replaceWith = '') {
1
+ export function replaceEnter(json, replaceWith = "") {
2
2
  return json.replace(/\s+/g, replaceWith).trim();
3
3
  }
4
4
  export function minifyXMLLike(xml) {
5
- const removeEnterResult = replaceEnter(xml, ' ');
6
- return removeEnterResult.replace(/> </g, '><').trim();
5
+ const removeEnterResult = replaceEnter(xml, " ");
6
+ return removeEnterResult.replace(/> </g, "><").trim();
7
7
  }
@@ -1,2 +1,3 @@
1
- import { Loader } from 'esbuild';
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { Loader } from "esbuild";
2
3
  export declare const serviceWorkerTransformer: (serviceWorkerCode: string, loader?: Loader) => string | Buffer;
@@ -1,19 +1,19 @@
1
- import { config } from '../config/config.js';
2
- import { getAllFiles } from './getAllFiles.js';
3
- import { transformSync as esbuild } from 'esbuild';
4
- export const serviceWorkerTransformer = (serviceWorkerCode, loader = 'ts') => {
1
+ import { config } from "../config/config.js";
2
+ import { getAllFiles } from "./getAllFiles.js";
3
+ import { transformSync as esbuild } from "esbuild";
4
+ export const serviceWorkerTransformer = (serviceWorkerCode, loader = "ts") => {
5
5
  const { sourcemap, keepNames, format, outdir, define, target } = config.esbuildOptions;
6
6
  try {
7
- const allFiles = getAllFiles(outdir, '.');
7
+ const allFiles = getAllFiles(outdir, ".");
8
8
  const result = esbuild(serviceWorkerCode, {
9
9
  define: {
10
- 'michiProcess.env.BUILD_FILES': `${JSON.stringify(allFiles)}`,
10
+ "michiProcess.env.BUILD_FILES": `${JSON.stringify(allFiles)}`,
11
11
  // Time at GMT+0
12
- 'michiProcess.env.CACHE_NAME': `"${new Date(new Date().toLocaleString('en-US', { timeZone: 'Etc/GMT' })).getTime()}"`,
12
+ "michiProcess.env.CACHE_NAME": `"${new Date(new Date().toLocaleString("en-US", { timeZone: "Etc/GMT" })).getTime()}"`,
13
13
  ...define,
14
14
  },
15
15
  loader,
16
- logLevel: 'error',
16
+ logLevel: "error",
17
17
  format,
18
18
  target,
19
19
  sourcemap,
@@ -1,4 +1,4 @@
1
- import { Tranformer } from './copy.js';
1
+ import { Tranformer } from "./copy.js";
2
2
  export declare const jsAndTsRegex: RegExp;
3
3
  export declare const notJsAndTsRegex: RegExp;
4
4
  export declare const jsonTransformer: Tranformer;
@@ -1,6 +1,6 @@
1
- import { config } from '../config/config.js';
2
- import { minifyXMLLike } from './minify.js';
3
- import { serviceWorkerTransformer } from './serviceWorkerTransformer.js';
1
+ import { config } from "../config/config.js";
2
+ import { minifyXMLLike } from "./minify.js";
3
+ import { serviceWorkerTransformer } from "./serviceWorkerTransformer.js";
4
4
  export const jsAndTsRegex = /.*\.(?:ts|js)/;
5
5
  export const notJsAndTsRegex = /.*\.(?!ts|js)/;
6
6
  export const jsonTransformer = {
@@ -18,6 +18,6 @@ export const transformers = [
18
18
  {
19
19
  fileRegex: jsAndTsRegex,
20
20
  transformer: serviceWorkerTransformer,
21
- pathTransformer: (destPath) => destPath.replace('.ts', '.js'),
21
+ pathTransformer: (destPath) => destPath.replace(".ts", ".js"),
22
22
  },
23
23
  ];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@michijs/dev-server",
3
3
  "license": "MIT",
4
- "version": "0.4.3",
4
+ "version": "0.5.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/michijs/dev-server.git"
@@ -27,11 +27,8 @@
27
27
  "publish-npm": "npm run dist && npm publish --access public"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/node": "20.1.7",
31
- "@types/yargs": "17.0.24",
32
- "lint-staged": "13.2.2",
33
- "rome": "12.1.0",
34
- "simple-git-hooks": "2.8.1"
30
+ "@types/node": "20.3.2",
31
+ "@types/yargs": "17.0.24"
35
32
  },
36
33
  "keywords": [
37
34
  "react",
@@ -52,23 +49,15 @@
52
49
  "node": ">=14.16"
53
50
  },
54
51
  "dependencies": {
55
- "@types/web-app-manifest": "1.0.3",
56
- "esbuild": "0.17.19",
52
+ "@types/web-app-manifest": "1.0.4",
53
+ "esbuild": "0.18.9",
57
54
  "node-watch": "0.7.3",
58
55
  "open": "9.1.0",
56
+ "puppeteer": "^20.5.0",
59
57
  "sharp": "0.32.1",
60
58
  "yargs": "17.7.2"
61
59
  },
62
60
  "peerDependencies": {
63
61
  "typescript": "5.0.4"
64
- },
65
- "simple-git-hooks": {
66
- "pre-commit": "npx lint-staged"
67
- },
68
- "lint-staged": {
69
- "*.{js,jsx,ts,tsx}": [
70
- "rome check --apply",
71
- "rome format --write"
72
- ]
73
62
  }
74
63
  }
@@ -1 +0,0 @@
1
- export declare function generateIcons(callback: () => void, src: string): Promise<void>;
@@ -1,35 +0,0 @@
1
- import { getPath } from '../utils/getPath.js';
2
- import { config } from '../config/config.js';
3
- import { mkdirSync, existsSync, writeFileSync } from 'fs';
4
- import { pngToIco } from '../utils/pngToIco.js';
5
- const generateFavicon = async (src, dest) => {
6
- const { default: sharp } = await import('sharp');
7
- const image = await sharp(src);
8
- const iconSizes = [16, 24, 32, 48, 64, 128, 256];
9
- const resizedBuffers = await Promise.all(iconSizes.map((size) => {
10
- return image.resize(size, size).png().toBuffer();
11
- }));
12
- writeFileSync(dest, await pngToIco(resizedBuffers, iconSizes));
13
- };
14
- export async function generateIcons(callback, src) {
15
- const destPath = getPath(`${config.public.path}/assets/generated`);
16
- if (!existsSync(destPath))
17
- mkdirSync(destPath, { recursive: true });
18
- const { default: sharp } = await import('sharp');
19
- const sizes = [24, 48, 72, 96, 128, 256, 512];
20
- const image = sharp(src);
21
- await Promise.all([
22
- ...sizes.map((x) => {
23
- return image
24
- .resize(x, x)
25
- .webp()
26
- .toFile(getPath(`${destPath}/${src.split('/').at(-1)?.split('.')[0]}-${x}.webp`));
27
- }),
28
- image
29
- .resize(512, 512)
30
- .png()
31
- .toFile(getPath(`${destPath}/${src.split('/').at(-1)?.split('.')[0]}-512.png`)),
32
- generateFavicon(src, getPath(`${config.public.path}/favicon.ico`)),
33
- ]);
34
- callback();
35
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,15 +0,0 @@
1
- import worker_threads from 'worker_threads';
2
- import ts from 'typescript';
3
- function transpileFile(inputFilePath, compilerOptions) {
4
- compilerOptions.incremental = false;
5
- const program = ts.createProgram([inputFilePath], compilerOptions);
6
- const emitResult = program.emit();
7
- const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
8
- if (allDiagnostics.length > 0) {
9
- throw allDiagnostics[0].messageText;
10
- }
11
- }
12
- worker_threads.parentPort?.once('message', (message) => {
13
- const result = transpileFile(...message);
14
- worker_threads.parentPort?.postMessage(result);
15
- });
@@ -1,2 +0,0 @@
1
- import ts from 'typescript';
2
- export declare function transpileFilesWithThreads(filePaths: string[], compilerOptions: ts.CompilerOptions): Promise<string[]>;
@@ -1,25 +0,0 @@
1
- import { fileURLToPath } from 'url';
2
- import { Worker } from 'worker_threads';
3
- import { dirname } from 'path';
4
- import { getPath } from './getPath.js';
5
- function runInThread(args) {
6
- return new Promise((resolve, reject) => {
7
- const worker = new Worker(getPath(`${dirname(fileURLToPath(import.meta.url))}/transpileFileInThread`));
8
- worker.on('message', resolve);
9
- worker.on('error', reject);
10
- worker.on('exit', (code) => {
11
- if (code !== 0) {
12
- reject(new Error(`Worker stopped with exit code ${code}`));
13
- }
14
- });
15
- worker.postMessage(args);
16
- });
17
- }
18
- export async function transpileFilesWithThreads(filePaths, compilerOptions) {
19
- const resultPromises = filePaths.map(inputFilePath => {
20
- return runInThread([inputFilePath, compilerOptions]);
21
- });
22
- const results = await Promise.all(resultPromises);
23
- console.log(results);
24
- return results;
25
- }