diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index d80d73f252..43b3d29452 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -25,6 +25,7 @@ const _dirname = dirname(_filename); const staticAssets = `${_dirname}/../../../assets/`; const clientAssets = `${_dirname}/../../../../client/assets/`; const assets = `${_dirname}/../../../../../built/_client_dist_/`; +const swAssets = `${_dirname}/../../../../../built/_sw_dist_/`; // Init app const app = new Koa(); @@ -100,7 +101,7 @@ router.get('/twemoji/(.*)', async ctx => { // ServiceWorker router.get('/sw.js', async ctx => { await send(ctx as any, `/sw.${config.version}.js`, { - root: assets + root: swAssets }); }); diff --git a/packages/client/src/scripts/get-note-summary.ts b/packages/client/src/scripts/get-note-summary.ts index da5ad20df2..bd394279cb 100644 --- a/packages/client/src/scripts/get-note-summary.ts +++ b/packages/client/src/scripts/get-note-summary.ts @@ -1,11 +1,11 @@ import * as misskey from 'misskey-js'; -import { I18n } from '@/scripts/i18n'; +import { i18n } from '@/i18n'; /** * 投稿を表す文字列を取得します。 * @param {*} note (packされた)投稿 */ -export const getNoteSummary = (note: misskey.entities.Note, i18n: I18n): string => { +export const getNoteSummary = (note: misskey.entities.Note): string => { if (note.deletedAt) { return `(${i18n.locale.deletedNote})`; } @@ -36,7 +36,7 @@ export const getNoteSummary = (note: misskey.entities.Note, i18n: I18n): st // 返信のとき if (note.replyId) { if (note.reply) { - summary += `\n\nRE: ${getNoteSummary(note.reply, i18n)}`; + summary += `\n\nRE: ${getNoteSummary(note.reply)}`; } else { summary += '\n\nRE: ...'; } @@ -45,7 +45,7 @@ export const getNoteSummary = (note: misskey.entities.Note, i18n: I18n): st // Renoteのとき if (note.renoteId) { if (note.renote) { - summary += `\n\nRN: ${getNoteSummary(note.renote, i18n)}`; + summary += `\n\nRN: ${getNoteSummary(note.renote)}`; } else { summary += '\n\nRN: ...'; } diff --git a/packages/client/src/scripts/initialize-sw.ts b/packages/client/src/scripts/initialize-sw.ts index 785096f284..13c0c4565b 100644 --- a/packages/client/src/scripts/initialize-sw.ts +++ b/packages/client/src/scripts/initialize-sw.ts @@ -8,7 +8,7 @@ export async function initializeSw() { ('serviceWorker' in navigator) && ('PushManager' in window) && $i && $i.token) { - navigator.serviceWorker.register(`/sw.js`); + navigator.serviceWorker.register(`/sw.js`, { scope: '/', type: 'module' }); navigator.serviceWorker.ready.then(registration => { registration.active?.postMessage({ diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index b44cf2f895..db91b99e7d 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -28,8 +28,7 @@ ], "lib": [ "esnext", - "dom", - "webworker" + "dom" ] }, "compileOnSave": false, diff --git a/packages/client/webpack.config.js b/packages/client/webpack.config.js index 7bcfdcb15d..8333b30803 100644 --- a/packages/client/webpack.config.js +++ b/packages/client/webpack.config.js @@ -37,7 +37,6 @@ const postcss = { module.exports = { entry: { app: './src/init.ts', - sw: './src/sw/sw.ts' }, module: { rules: [{ diff --git a/packages/sw/.eslintrc.js b/packages/sw/.eslintrc.js new file mode 100644 index 0000000000..8e4ff6e455 --- /dev/null +++ b/packages/sw/.eslintrc.js @@ -0,0 +1,61 @@ +module.exports = { + root: true, + env: { + "node": false + }, + parser: "vue-eslint-parser", + parserOptions: { + "parser": "@typescript-eslint/parser", + tsconfigRootDir: __dirname, + //project: ['./tsconfig.json'], + }, + extends: [ + //"../shared/.eslintrc.js", + "plugin:vue/vue3-recommended" + ], + rules: { + "vue/attributes-order": ["error", { + "alphabetical": false + }], + "vue/no-use-v-if-with-v-for": ["error", { + "allowUsingIterationVar": false + }], + "vue/no-ref-as-operand": "error", + "vue/no-multi-spaces": ["error", { + "ignoreProperties": false + }], + "vue/no-v-html": "error", + "vue/order-in-components": "error", + "vue/html-indent": ["warn", "tab", { + "attribute": 1, + "baseIndent": 0, + "closeBracket": 0, + "alignAttributesVertically": true, + "ignores": [] + }], + "vue/html-closing-bracket-spacing": ["warn", { + "startTag": "never", + "endTag": "never", + "selfClosingTag": "never" + }], + "vue/multi-word-component-names": "warn", + "vue/require-v-for-key": "warn", + "vue/no-unused-components": "warn", + "vue/valid-v-for": "warn", + "vue/return-in-computed-property": "warn", + "vue/max-attributes-per-line": "off", + "vue/html-self-closing": "off", + "vue/singleline-html-element-content-newline": "off", + }, + globals: { + "require": false, + "_DEV_": false, + "_LANGS_": false, + "_VERSION_": false, + "_ENV_": false, + "_PERF_PREFIX_": false, + "_DATA_TRANSFER_DRIVE_FILE_": false, + "_DATA_TRANSFER_DRIVE_FOLDER_": false, + "_DATA_TRANSFER_DECK_COLUMN_": false + } +} diff --git a/packages/sw/.npmrc b/packages/sw/.npmrc new file mode 100644 index 0000000000..6b5f38e890 --- /dev/null +++ b/packages/sw/.npmrc @@ -0,0 +1,2 @@ +save-exact = true +package-lock = false diff --git a/packages/sw/.yarnrc b/packages/sw/.yarnrc new file mode 100644 index 0000000000..788570fcd5 --- /dev/null +++ b/packages/sw/.yarnrc @@ -0,0 +1 @@ +network-timeout 600000 diff --git a/packages/sw/package.json b/packages/sw/package.json new file mode 100644 index 0000000000..f0deb7fb78 --- /dev/null +++ b/packages/sw/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "scripts": { + "watch": "webpack --watch", + "build": "webpack", + "lint": "eslint --quiet src/**/*.{ts}" + }, + "resolutions": {}, + "dependencies": { + "idb-keyval": "6.0.3", + "misskey-js": "0.0.10" + }, + "devDependencies": {} +} diff --git a/packages/client/src/sw/create-notification.ts b/packages/sw/src/create-notification.ts similarity index 98% rename from packages/client/src/sw/create-notification.ts rename to packages/sw/src/create-notification.ts index 5ac8525a5c..9dd8426ef2 100644 --- a/packages/client/src/sw/create-notification.ts +++ b/packages/sw/src/create-notification.ts @@ -3,12 +3,12 @@ */ declare var self: ServiceWorkerGlobalScope; +import { swLang } from '@/lang'; +import { cli } from '@/operations'; +import { pushNotificationDataMap } from '@/types'; import { getNoteSummary } from '@/scripts/get-note-summary'; import getUserName from '@/scripts/get-user-name'; -import { swLang } from '@/sw/lang'; import { I18n } from '@/scripts/i18n'; -import { pushNotificationDataMap } from '@/sw/types'; -import { cli } from './operations'; import { getAccountFromId } from '@/scripts/get-account-from-id'; export async function createNotification(data: pushNotificationDataMap[K]) { diff --git a/packages/sw/src/filters/user.ts b/packages/sw/src/filters/user.ts new file mode 100644 index 0000000000..09437eb19a --- /dev/null +++ b/packages/sw/src/filters/user.ts @@ -0,0 +1,14 @@ +import * as misskey from 'misskey-js'; +import * as Acct from 'misskey-js/built/acct'; + +export const acct = (user: misskey.Acct) => { + return Acct.toString(user); +}; + +export const userName = (user: misskey.entities.User) => { + return user.name || user.username; +}; + +export const userPage = (user: misskey.Acct, path?, absolute = false) => { + return `${absolute ? origin : ''}/@${acct(user)}${(path ? `/${path}` : '')}`; +}; diff --git a/packages/client/src/sw/lang.ts b/packages/sw/src/lang.ts similarity index 100% rename from packages/client/src/sw/lang.ts rename to packages/sw/src/lang.ts diff --git a/packages/client/src/sw/notification-read.ts b/packages/sw/src/notification-read.ts similarity index 92% rename from packages/client/src/sw/notification-read.ts rename to packages/sw/src/notification-read.ts index 672c48167b..bc7b64e8ed 100644 --- a/packages/client/src/sw/notification-read.ts +++ b/packages/sw/src/notification-read.ts @@ -1,8 +1,8 @@ declare var self: ServiceWorkerGlobalScope; import { get } from 'idb-keyval'; -import { pushNotificationDataMap } from '@/sw/types'; -import { api } from '@/sw/operations'; +import { pushNotificationDataMap } from '@/types'; +import { api } from '@/operations'; type Accounts = { [x: string]: { diff --git a/packages/client/src/sw/operations.ts b/packages/sw/src/operations.ts similarity index 97% rename from packages/client/src/sw/operations.ts rename to packages/sw/src/operations.ts index 0bdcf6992d..02cf0d96cf 100644 --- a/packages/client/src/sw/operations.ts +++ b/packages/sw/src/operations.ts @@ -5,7 +5,7 @@ declare var self: ServiceWorkerGlobalScope; import * as Misskey from 'misskey-js'; -import { SwMessage, swMessageOrderType } from '@/sw/types'; +import { SwMessage, swMessageOrderType } from '@/types'; import { acct as getAcct } from '@/filters/user'; import { getAccountFromId } from '@/scripts/get-account-from-id'; import { getUrlWithLoginId } from '@/scripts/login-id'; diff --git a/packages/sw/src/scripts/get-account-from-id.ts b/packages/sw/src/scripts/get-account-from-id.ts new file mode 100644 index 0000000000..be4cfaeba4 --- /dev/null +++ b/packages/sw/src/scripts/get-account-from-id.ts @@ -0,0 +1,7 @@ +import { get } from 'idb-keyval'; + +export async function getAccountFromId(id: string) { + const accounts = await get('accounts') as { token: string; id: string; }[]; + if (!accounts) console.log('Accounts are not recorded'); + return accounts.find(e => e.id === id); +} diff --git a/packages/sw/src/scripts/get-note-summary.ts b/packages/sw/src/scripts/get-note-summary.ts new file mode 100644 index 0000000000..da5ad20df2 --- /dev/null +++ b/packages/sw/src/scripts/get-note-summary.ts @@ -0,0 +1,55 @@ +import * as misskey from 'misskey-js'; +import { I18n } from '@/scripts/i18n'; + +/** + * 投稿を表す文字列を取得します。 + * @param {*} note (packされた)投稿 + */ +export const getNoteSummary = (note: misskey.entities.Note, i18n: I18n): string => { + if (note.deletedAt) { + return `(${i18n.locale.deletedNote})`; + } + + if (note.isHidden) { + return `(${i18n.locale.invisibleNote})`; + } + + let summary = ''; + + // 本文 + if (note.cw != null) { + summary += note.cw; + } else { + summary += note.text ? note.text : ''; + } + + // ファイルが添付されているとき + if ((note.files || []).length != 0) { + summary += ` (${i18n.t('withNFiles', { n: note.files.length })})`; + } + + // 投票が添付されているとき + if (note.poll) { + summary += ` (${i18n.locale.poll})`; + } + + // 返信のとき + if (note.replyId) { + if (note.reply) { + summary += `\n\nRE: ${getNoteSummary(note.reply, i18n)}`; + } else { + summary += '\n\nRE: ...'; + } + } + + // Renoteのとき + if (note.renoteId) { + if (note.renote) { + summary += `\n\nRN: ${getNoteSummary(note.renote, i18n)}`; + } else { + summary += '\n\nRN: ...'; + } + } + + return summary.trim(); +}; diff --git a/packages/sw/src/scripts/get-user-name.ts b/packages/sw/src/scripts/get-user-name.ts new file mode 100644 index 0000000000..d499ea0203 --- /dev/null +++ b/packages/sw/src/scripts/get-user-name.ts @@ -0,0 +1,3 @@ +export default function(user: { name?: string | null, username: string }): string { + return user.name || user.username; +} diff --git a/packages/sw/src/scripts/i18n.ts b/packages/sw/src/scripts/i18n.ts new file mode 100644 index 0000000000..8f9f5e654f --- /dev/null +++ b/packages/sw/src/scripts/i18n.ts @@ -0,0 +1,33 @@ +export class I18n> { + public locale: T; + + constructor(locale: T) { + this.locale = locale; + + //#region BIND + this.t = this.t.bind(this); + //#endregion + } + + // string にしているのは、ドット区切りでのパス指定を許可するため + // なるべくこのメソッド使うよりもlocale直接参照の方がvueのキャッシュ効いてパフォーマンスが良いかも + public t(key: string, args?: Record): string { + try { + let str = key.split('.').reduce((o, i) => o[i], this.locale as T | any | string); + + if (typeof str !== 'string') { + return key; + } + + if (args) { + for (const [k, v] of Object.entries(args)) { + str = str.replace(`{${k}}`, v); + } + } + return str; + } catch (e) { + console.warn(`missing localization '${key}'`); + return key; + } + } +} diff --git a/packages/sw/src/scripts/login-id.ts b/packages/sw/src/scripts/login-id.ts new file mode 100644 index 0000000000..0f9c6be4a9 --- /dev/null +++ b/packages/sw/src/scripts/login-id.ts @@ -0,0 +1,11 @@ +export function getUrlWithLoginId(url: string, loginId: string) { + const u = new URL(url, origin); + u.searchParams.append('loginId', loginId); + return u.toString(); +} + +export function getUrlWithoutLoginId(url: string) { + const u = new URL(url); + u.searchParams.delete('loginId'); + return u.toString(); +} diff --git a/packages/client/src/sw/sw.ts b/packages/sw/src/sw.ts similarity index 95% rename from packages/client/src/sw/sw.ts rename to packages/sw/src/sw.ts index ea3a60568d..513be9c84e 100644 --- a/packages/client/src/sw/sw.ts +++ b/packages/sw/src/sw.ts @@ -3,11 +3,11 @@ */ declare var self: ServiceWorkerGlobalScope; -import { createEmptyNotification, createNotification } from '@/sw/create-notification'; -import { swLang } from '@/sw/lang'; -import { swNotificationRead } from '@/sw/notification-read'; -import { pushNotificationDataMap } from '@/sw/types'; -import * as swos from './operations'; +import { createEmptyNotification, createNotification } from '@/create-notification'; +import { swLang } from '@/lang'; +import { swNotificationRead } from '@/notification-read'; +import { pushNotificationDataMap } from '@/types'; +import * as swos from '@/operations'; import { acct as getAcct } from '@/filters/user'; //#region Lifecycle: Install diff --git a/packages/client/src/sw/types.ts b/packages/sw/src/types.ts similarity index 100% rename from packages/client/src/sw/types.ts rename to packages/sw/src/types.ts diff --git a/packages/sw/tsconfig.json b/packages/sw/tsconfig.json new file mode 100644 index 0000000000..089cd08b5e --- /dev/null +++ b/packages/sw/tsconfig.json @@ -0,0 +1,39 @@ +{ + "compilerOptions": { + "allowJs": true, + "noEmitOnError": false, + "noImplicitAny": false, + "noImplicitReturns": true, + "noUnusedParameters": false, + "noUnusedLocals": true, + "noFallthroughCasesInSwitch": true, + "declaration": false, + "sourceMap": false, + "target": "es2017", + "module": "esnext", + "moduleResolution": "node", + "removeComments": false, + "noLib": false, + "strict": true, + "strictNullChecks": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + }, + "typeRoots": [ + "node_modules/@types", + "@types", + ], + "lib": [ + "esnext", + "webworker" + ] + }, + "compileOnSave": false, + "include": [ + "./**/*.ts", + "./**/*.vue" + ] +} diff --git a/packages/sw/webpack.config.js b/packages/sw/webpack.config.js new file mode 100644 index 0000000000..fc16e56c57 --- /dev/null +++ b/packages/sw/webpack.config.js @@ -0,0 +1,98 @@ +/** + * webpack configuration + */ + +const fs = require('fs'); +const webpack = require('webpack'); +const { VueLoaderPlugin } = require('vue-loader'); + +class WebpackOnBuildPlugin { + constructor(callback) { + this.callback = callback; + } + + apply(compiler) { + compiler.hooks.done.tap('WebpackOnBuildPlugin', this.callback); + } +} + +const isProduction = process.env.NODE_ENV === 'production'; + +const locales = require('../../locales'); +const meta = require('../../package.json'); + +const postcss = { + loader: 'postcss-loader', + options: { + postcssOptions: { + plugins: [ + require('cssnano')({ + preset: 'default' + }) + ] + } + }, +}; + +module.exports = { + entry: { + sw: './src/sw.ts' + }, + module: { + rules: [{ + test: /\.ts$/, + exclude: /node_modules/, + use: [{ + loader: 'ts-loader', + options: { + happyPackMode: true, + transpileOnly: true, + configFile: __dirname + '/tsconfig.json', + appendTsSuffixTo: [/\.vue$/] + } + }] + }] + }, + plugins: [ + new webpack.ProgressPlugin({}), + new webpack.DefinePlugin({ + _VERSION_: JSON.stringify(meta.version), + _LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]) => [k, v._lang_])), + _ENV_: JSON.stringify(process.env.NODE_ENV), + _DEV_: process.env.NODE_ENV !== 'production', + _PERF_PREFIX_: JSON.stringify('Misskey:'), + _DATA_TRANSFER_DRIVE_FILE_: JSON.stringify('mk_drive_file'), + _DATA_TRANSFER_DRIVE_FOLDER_: JSON.stringify('mk_drive_folder'), + _DATA_TRANSFER_DECK_COLUMN_: JSON.stringify('mk_deck_column'), + __VUE_OPTIONS_API__: true, + __VUE_PROD_DEVTOOLS__: false, + }), + new VueLoaderPlugin(), + new WebpackOnBuildPlugin(() => { + fs.mkdirSync(__dirname + '/../../built', { recursive: true }); + fs.writeFileSync(__dirname + '/../../built/meta.json', JSON.stringify({ version: meta.version }), 'utf-8'); + }), + ], + output: { + path: __dirname + '/../../built/_sw_dist_', + filename: `[name].${meta.version}.js`, + publicPath: `/`, + pathinfo: false, + }, + resolve: { + extensions: [ + '.js', '.ts', '.json' + ], + alias: { + '@': __dirname + '/src/', + } + }, + resolveLoader: { + modules: ['node_modules'] + }, + experiments: { + topLevelAwait: true + }, + devtool: false, //'source-map', + mode: isProduction ? 'production' : 'development' +}; diff --git a/packages/sw/yarn.lock b/packages/sw/yarn.lock new file mode 100644 index 0000000000..bf7734dd92 --- /dev/null +++ b/packages/sw/yarn.lock @@ -0,0 +1,39 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +autobind-decorator@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-2.4.0.tgz#ea9e1c98708cf3b5b356f7cf9f10f265ff18239c" + integrity sha512-OGYhWUO72V6DafbF8PM8rm3EPbfuyMZcJhtm5/n26IDwO18pohE4eNazLoCGhPiXOCD0gEGmrbU3849QvM8bbw== + +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +idb-keyval@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.0.3.tgz#e47246a15e55d0fff9fa204fd9ca06f90ff30c52" + integrity sha512-yh8V7CnE6EQMu9YDwQXhRxwZh4nv+8xm/HV4ZqK4IiYFJBWYGjJuykADJbSP+F/GDXUBwCSSNn/14IpGL81TuA== + dependencies: + safari-14-idb-fix "^3.0.0" + +misskey-js@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/misskey-js/-/misskey-js-0.0.10.tgz#f305dd37cecfbaeb7a277d5e0c769ca12c6eb9a6" + integrity sha512-2rdqFrCOwggMKYitsUPyupesqCNpNooqEHQQRfdjttbhiqLbNFJE1UuWQ04ffmiJ08UJt+1ZN2kVAYNEN3HRsg== + dependencies: + autobind-decorator "^2.4.0" + eventemitter3 "^4.0.7" + reconnecting-websocket "^4.4.0" + +reconnecting-websocket@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783" + integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng== + +safari-14-idb-fix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz#450fc049b996ec7f3fd9ca2f89d32e0761583440" + integrity sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog== diff --git a/scripts/build.js b/scripts/build.js index 783af78271..608648b953 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -17,6 +17,14 @@ const execa = require('execa'); stderr: process.stderr, }); + console.log('building packages/sw ...'); + + await execa('npm', ['run', 'build'], { + cwd: __dirname + '/../packages/sw', + stdout: process.stdout, + stderr: process.stderr, + }); + console.log('build finishing ...'); await execa('npm', ['run', 'gulp'], { diff --git a/scripts/clean-all.js b/scripts/clean-all.js index 814ff3f257..456b88032b 100644 --- a/scripts/clean-all.js +++ b/scripts/clean-all.js @@ -7,6 +7,9 @@ const fs = require('fs'); fs.rmSync(__dirname + '/../packages/client/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../packages/client/node_modules', { recursive: true, force: true }); + fs.rmSync(__dirname + '/../packages/sw/built', { recursive: true, force: true }); + fs.rmSync(__dirname + '/../packages/sw/node_modules', { recursive: true, force: true }); + fs.rmSync(__dirname + '/../built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../node_modules', { recursive: true, force: true }); })(); diff --git a/scripts/clean.js b/scripts/clean.js index a14f1fb35b..70b9d882b5 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -3,5 +3,6 @@ const fs = require('fs'); (async () => { fs.rmSync(__dirname + '/../packages/backend/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../packages/client/built', { recursive: true, force: true }); + fs.rmSync(__dirname + '/../packages/sw/built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../built', { recursive: true, force: true }); })(); diff --git a/scripts/dev.js b/scripts/dev.js index 7096f3bf65..cab3e539ee 100644 --- a/scripts/dev.js +++ b/scripts/dev.js @@ -19,6 +19,12 @@ const execa = require('execa'); stderr: process.stderr, }); + execa('npm', ['run', 'watch'], { + cwd: __dirname + '/../packages/sw', + stdout: process.stdout, + stderr: process.stderr, + }); + const start = async () => { try { await execa('npm', ['run', 'start'], { diff --git a/scripts/install-packages.js b/scripts/install-packages.js index c25063b29a..bc8e016a3c 100644 --- a/scripts/install-packages.js +++ b/scripts/install-packages.js @@ -16,4 +16,12 @@ const execa = require('execa'); stdout: process.stdout, stderr: process.stderr, }); + + console.log('installing dependencies of packages/sw ...'); + + await execa('yarn', ['install'], { + cwd: __dirname + '/../packages/sw', + stdout: process.stdout, + stderr: process.stderr, + }); })(); diff --git a/scripts/lint.js b/scripts/lint.js index 11aa4909b1..72a63f4ba3 100644 --- a/scripts/lint.js +++ b/scripts/lint.js @@ -14,4 +14,11 @@ const execa = require('execa'); stdout: process.stdout, stderr: process.stderr, }); + + console.log('linting packages/sw ...'); + await execa('npm', ['run', 'lint'], { + cwd: __dirname + '/../packages/sw', + stdout: process.stdout, + stderr: process.stderr, + }); })();