2022-01-06 05:44:13 -08:00
import fs from 'fs' ;
2021-06-17 17:38:48 -04:00
import browserSync from 'browser-sync' ;
import chalk from 'chalk' ;
import commandLineArgs from 'command-line-args' ;
import copy from 'recursive-copy' ;
import del from 'del' ;
import esbuild from 'esbuild' ;
2022-01-06 05:44:13 -08:00
import getPort , { portNumbers } from 'get-port' ;
import { globby } from 'globby' ;
2021-06-24 18:24:54 -04:00
import { execSync } from 'child_process' ;
2022-01-17 11:40:09 -08:00
import open from 'open' ;
2021-02-26 09:09:13 -05:00
2021-10-22 10:51:17 -04:00
const { bundle , copydir , dir , serve , types } = commandLineArgs ( [
{ name : 'bundle' , type : Boolean } ,
{ name : 'copydir' , type : String } ,
2021-10-13 17:12:50 -04:00
{ name : 'dir' , type : String , defaultValue : 'dist' } ,
{ name : 'serve' , type : Boolean } ,
{ name : 'types' , type : Boolean }
] ) ;
2021-05-11 08:35:31 -04:00
2021-10-16 10:35:42 -04:00
const outdir = dir ;
2021-10-13 17:12:50 -04:00
del . sync ( outdir ) ;
2022-01-06 05:44:13 -08:00
fs . mkdirSync ( outdir , { recursive : true } ) ;
2021-02-26 09:09:13 -05:00
( async ( ) => {
2021-10-13 17:12:50 -04:00
try {
execSync ( ` node scripts/make-metadata.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
execSync ( ` node scripts/make-search.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
2021-11-04 07:27:18 -04:00
execSync ( ` node scripts/make-react.js ` , { stdio : 'inherit' } ) ;
2021-10-13 17:12:50 -04:00
execSync ( ` node scripts/make-vscode-data.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
execSync ( ` node scripts/make-css.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
execSync ( ` node scripts/make-icons.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
2022-01-15 21:47:14 -08:00
if ( types ) execSync ( ` tsc --project ./tsconfig.prod.json --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
2021-10-13 17:12:50 -04:00
} catch ( err ) {
console . error ( chalk . red ( err ) ) ;
process . exit ( 1 ) ;
}
2021-11-04 07:27:18 -04:00
const alwaysExternal = [ '@lit-labs/react' , 'react' ] ;
2021-02-26 09:09:13 -05:00
const buildResult = await esbuild
. build ( {
format : 'esm' ,
target : 'es2017' ,
2021-10-08 10:11:12 -04:00
entryPoints : [
2021-10-13 17:12:50 -04:00
// The whole shebang
2021-10-08 10:11:12 -04:00
'./src/shoelace.ts' ,
// Components
2022-01-06 05:44:13 -08:00
... ( await globby ( './src/components/**/!(*.(style|test)).ts' ) ) ,
2021-12-06 10:57:54 -05:00
// Translations
2022-01-06 05:44:13 -08:00
... ( await globby ( './src/translations/**/*.ts' ) ) ,
2021-10-08 10:11:12 -04:00
// Public utilities
2022-01-06 05:44:13 -08:00
... ( await globby ( './src/utilities/**/!(*.(style|test)).ts' ) ) ,
2021-10-08 10:11:12 -04:00
// Theme stylesheets
2022-01-06 05:44:13 -08:00
... ( await globby ( './src/themes/**/!(*.test).ts' ) ) ,
2021-11-04 07:27:18 -04:00
// React wrappers
2022-01-06 05:44:13 -08:00
... ( await globby ( './src/react/**/*.ts' ) )
2021-10-08 10:11:12 -04:00
] ,
2021-10-13 17:12:50 -04:00
outdir ,
2021-03-02 17:23:49 -05:00
chunkNames : 'chunks/[name].[hash]' ,
2021-10-13 17:12:50 -04:00
incremental : serve ,
2021-02-26 09:09:13 -05:00
define : {
2021-11-04 07:27:18 -04:00
// Popper.js requires this to be set
2021-02-26 09:09:13 -05:00
'process.env.NODE_ENV' : '"production"'
} ,
bundle : true ,
2021-10-13 17:12:50 -04:00
//
2021-10-22 10:51:17 -04:00
// We don't bundle certain dependencies in the unbundled build. This ensures we ship bare module specifiers,
// allowing end users to better optimize when using a bundler. (Only packages that ship ESM can be external.)
2021-10-13 17:12:50 -04:00
//
2021-11-04 07:27:18 -04:00
// We never bundle React or @lit-labs/react though!
//
external : bundle
? alwaysExternal
: [ ... alwaysExternal , '@popperjs/core' , '@shoelace-style/animations' , 'lit' , 'qr-creator' ] ,
2021-02-26 09:09:13 -05:00
splitting : true ,
2021-08-05 16:48:15 -04:00
plugins : [ ]
2021-02-26 09:09:13 -05:00
} )
. catch ( err => {
console . error ( chalk . red ( err ) ) ;
process . exit ( 1 ) ;
} ) ;
2021-10-22 10:51:17 -04:00
// Copy the build output to an additional directory
if ( copydir ) {
del . sync ( copydir ) ;
copy ( outdir , copydir ) ;
}
2021-10-13 17:12:50 -04:00
console . log ( chalk . green ( ` The build has been generated at ${ outdir } 📦 \n ` ) ) ;
2021-02-26 09:09:13 -05:00
2021-10-08 10:11:12 -04:00
// Dev server
2021-10-13 17:12:50 -04:00
if ( serve ) {
2022-01-17 11:40:09 -08:00
const bs = browserSync . create ( ) ;
2021-02-26 09:09:13 -05:00
const port = await getPort ( {
2022-01-06 05:44:13 -08:00
port : portNumbers ( 4000 , 4999 )
2021-02-26 09:09:13 -05:00
} ) ;
2021-10-22 10:51:17 -04:00
// Make sure docs/dist is empty since we're serving it virtually
del . sync ( 'docs/dist' ) ;
2022-01-18 14:52:53 -08:00
const browserSyncConfig = {
2022-01-17 11:40:09 -08:00
open : false ,
2021-02-26 09:09:13 -05:00
startPath : '/' ,
port ,
logLevel : 'silent' ,
logPrefix : '[shoelace]' ,
logFileChanges : true ,
notify : false ,
2021-08-24 08:49:27 -04:00
single : true ,
2021-08-24 09:03:01 -04:00
ghostMode : false ,
2021-02-26 09:09:13 -05:00
server : {
2021-10-14 08:39:17 -04:00
baseDir : 'docs' ,
routes : {
'/dist' : './dist'
}
2022-01-17 11:40:09 -08:00
} ,
socket : {
socketIoClientConfig : {
2022-01-18 14:52:53 -08:00
// Configure socketIO to retry forever when disconnected to enable the auto-reattach timeout below to work
2022-01-17 11:40:09 -08:00
reconnectionAttempts : Infinity ,
reconnectionDelay : 500 ,
reconnectionDelayMax : 500 ,
timeout : 1000
}
2021-02-26 09:09:13 -05:00
}
2022-01-18 14:52:53 -08:00
} ;
2021-02-26 09:09:13 -05:00
2022-01-18 14:52:53 -08:00
// Launch browser sync
bs . init ( browserSyncConfig , ( ) => {
// This init callback gets executed after the server has started
const socketIoConfig = browserSyncConfig . socket . socketIoClientConfig ;
// Wait enough time for any open, detached clients to have a chance to reconnect. This will be used to determine if we reload an existing tab or open a new one.
const tabReattachDelay = socketIoConfig . reconnectionDelayMax * 2 + socketIoConfig . timeout ;
setTimeout ( ( ) => {
const url = ` http://localhost: ${ port } ` ;
console . log ( chalk . cyan ( ` Launched the Shoelace dev server at ${ url } 🥾 \n ` ) ) ;
if ( Object . keys ( bs . sockets . sockets ) . length === 0 ) {
open ( url ) ;
} else {
bs . reload ( ) ;
}
} , tabReattachDelay ) ;
} ) ;
2022-01-17 11:40:09 -08:00
2021-02-26 09:09:13 -05:00
// Rebuild and reload when source files change
2021-05-27 16:50:58 -04:00
bs . watch ( [ 'src/**/!(*.test).*' ] ) . on ( 'change' , async filename => {
2021-02-26 09:09:13 -05:00
console . log ( ` Source file changed - ${ filename } ` ) ;
buildResult
2021-06-24 18:24:54 -04:00
// Rebuild and reload
2021-02-26 09:09:13 -05:00
. rebuild ( )
2021-10-22 10:51:17 -04:00
. then ( ( ) => {
2021-08-05 16:48:15 -04:00
// Rebuild stylesheets when a theme file changes
if ( /^src\/themes/ . test ( filename ) ) {
2021-10-13 17:12:50 -04:00
execSync ( ` node scripts/make-css.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
2021-08-04 18:03:24 -04:00
}
} )
. then ( ( ) => {
// Skip metadata when styles are changed
if ( /(\.css|\.styles\.ts)$/ . test ( filename ) ) {
return ;
}
2021-10-13 17:12:50 -04:00
execSync ( ` node scripts/make-metadata.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
2021-08-04 18:03:24 -04:00
} )
2021-10-22 10:51:17 -04:00
. then ( ( ) => {
bs . reload ( ) ;
} )
2021-02-26 09:09:13 -05:00
. catch ( err => console . error ( chalk . red ( err ) ) ) ;
} ) ;
// Reload without rebuilding when the docs change
2021-09-07 13:13:18 -04:00
bs . watch ( [ 'docs/**/*.md' ] ) . on ( 'change' , filename => {
2021-02-26 09:09:13 -05:00
console . log ( ` Docs file changed - ${ filename } ` ) ;
2021-10-13 17:12:50 -04:00
execSync ( ` node scripts/make-search.js --outdir " ${ outdir } " ` , { stdio : 'inherit' } ) ;
2021-02-26 09:09:13 -05:00
bs . reload ( ) ;
} ) ;
}
2021-10-08 10:11:12 -04:00
// Cleanup on exit
process . on ( 'SIGTERM' , ( ) => buildResult . rebuild . dispose ( ) ) ;
2021-02-26 09:09:13 -05:00
} ) ( ) ;