@shuvi/service 1.0.0 → 1.0.2

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.
@@ -16,7 +16,7 @@ export interface NormalizedBundlerOptions {
16
16
  ignoreTypeScriptErrors: boolean;
17
17
  }
18
18
  export declare type BundlerOptions = Partial<NormalizedBundlerOptions>;
19
- export interface Bunlder {
19
+ export interface Bundler {
20
20
  targets: Target[];
21
21
  watching: Watching;
22
22
  watch(): Watching;
@@ -32,9 +32,9 @@ export interface CompilerStats {
32
32
  warnings: CompilerErr[];
33
33
  }
34
34
  export declare type FinishedCallback = (stats: CompilerStats) => any;
35
- export interface BunlderEvent {
35
+ export interface BundlerEvent {
36
36
  'build-done': (stats: CompilerStats) => void;
37
37
  'ts-error': (err: CompilerErr) => void;
38
38
  'ts-warnings': (warnings: CompilerErr[]) => void;
39
39
  }
40
- export declare function getBundler(ctx: IPluginContext): Promise<Bunlder>;
40
+ export declare function getBundler(ctx: IPluginContext): Promise<Bundler>;
@@ -392,7 +392,9 @@ class WebpackBundler {
392
392
  function getBundler(ctx) {
393
393
  return __awaiter(this, void 0, void 0, function* () {
394
394
  try {
395
- yield (0, typescript_1.setupTypeScript)(ctx.paths, ctx.mode === 'production');
395
+ yield (0, typescript_1.setupTypeScript)(ctx.paths, {
396
+ reportMissingError: ctx.mode === 'production'
397
+ });
396
398
  const options = Object.assign(Object.assign({}, defaultBundleOptions), { preBundle: ctx.config.experimental.preBundle, ignoreTypeScriptErrors: ctx.config.typescript.ignoreBuildErrors });
397
399
  if (ctx.mode !== 'development') {
398
400
  options.preBundle = false;
@@ -36,7 +36,7 @@ function createWebpackConfig({ mode, assetPublicPath, paths, config }, _a) {
36
36
  const lightningCss = !!config.experimental.lightningCss;
37
37
  const experimental = config.experimental;
38
38
  const compiler = Object.assign(Object.assign({}, config.compiler), { modularizeImports: experimental.modularizeImports, swcPlugins: experimental.swcPlugins });
39
- const typescript = (0, typescript_1.getTypeScriptInfo)();
39
+ const jsConfig = (0, typescript_1.getJavaScriptInfo)();
40
40
  if (opts.node) {
41
41
  chain = (0, config_1.createNodeWebpackChain)({
42
42
  name,
@@ -47,7 +47,7 @@ function createWebpackConfig({ mode, assetPublicPath, paths, config }, _a) {
47
47
  publicPath,
48
48
  lightningCss,
49
49
  compiler,
50
- typescript,
50
+ jsConfig,
51
51
  include,
52
52
  env,
53
53
  webpackHelpers
@@ -63,7 +63,7 @@ function createWebpackConfig({ mode, assetPublicPath, paths, config }, _a) {
63
63
  publicPath,
64
64
  lightningCss,
65
65
  compiler,
66
- typescript,
66
+ jsConfig,
67
67
  include,
68
68
  env,
69
69
  webpackHelpers,
@@ -1,3 +1,3 @@
1
1
  export { BundlerResult } from './runCompiler';
2
- export { getBundler, Bunlder } from './bundler';
2
+ export { getBundler, Bundler } from './bundler';
3
3
  export { Watching } from './watchingProxy';
@@ -1,4 +1,3 @@
1
- import { TsConfig, TypeScriptModule } from './types';
2
1
  export interface PackageDep {
3
2
  file: string;
4
3
  pkg: string;
@@ -7,7 +6,6 @@ export declare type CheckedDependenciesResult = {
7
6
  resovled: Map<string, string>;
8
7
  missing: PackageDep[];
9
8
  };
9
+ export declare function resolveDependencies(dir: string, deps: PackageDep[]): CheckedDependenciesResult;
10
10
  export declare function hasTypescriptFiles(projectDir: string): Promise<boolean>;
11
11
  export declare function checkNecessaryDeps(projectDir: string): CheckedDependenciesResult;
12
- export declare function hasTsConfig(tsConfigPath: string): Promise<boolean>;
13
- export declare function getTsConfig(ts: TypeScriptModule, tsConfigPath: string): Promise<TsConfig>;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.checkNecessaryDeps = exports.hasTypescriptFiles = exports.resolveDependencies = void 0;
13
+ const fs_extra_1 = require("fs-extra");
14
+ const resolve_1 = require("@shuvi/utils/lib/resolve");
15
+ const recursiveReaddir_1 = require("@shuvi/utils/lib/recursiveReaddir");
16
+ const requiredPackages = [
17
+ { file: 'typescript', pkg: 'typescript' },
18
+ { file: '@types/react/index.d.ts', pkg: '@types/react' },
19
+ { file: '@types/react-dom/index.d.ts', pkg: '@types/react-dom' },
20
+ { file: '@types/node/index.d.ts', pkg: '@types/node' }
21
+ ];
22
+ function resolveDependencies(dir, deps) {
23
+ let resolutions = new Map();
24
+ const missingPackages = deps.filter(p => {
25
+ try {
26
+ resolutions.set(p.pkg, (0, resolve_1.resolve)(p.file, { basedir: dir }));
27
+ return false;
28
+ }
29
+ catch (_) {
30
+ return true;
31
+ }
32
+ });
33
+ return {
34
+ resovled: resolutions,
35
+ missing: missingPackages
36
+ };
37
+ }
38
+ exports.resolveDependencies = resolveDependencies;
39
+ function hasTypescriptFiles(projectDir) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ try {
42
+ const stats = yield (0, fs_extra_1.stat)(projectDir);
43
+ if (!stats.isDirectory()) {
44
+ return false;
45
+ }
46
+ }
47
+ catch (error) {
48
+ return false;
49
+ }
50
+ const typescriptFiles = yield (0, recursiveReaddir_1.recursiveReadDir)(projectDir, {
51
+ filter: /.*\.(ts|tsx)$/,
52
+ ignore: /(\.shuvi)|(node_modules|.*\.d\.ts)/
53
+ });
54
+ return typescriptFiles.length > 0;
55
+ });
56
+ }
57
+ exports.hasTypescriptFiles = hasTypescriptFiles;
58
+ function checkNecessaryDeps(projectDir) {
59
+ return resolveDependencies(projectDir, requiredPackages);
60
+ }
61
+ exports.checkNecessaryDeps = checkNecessaryDeps;
@@ -1,3 +1,3 @@
1
1
  import { IPaths } from '../../core/apiTypes';
2
- import { TypeScriptModule, TsConfig } from './types';
3
- export declare function writeDefaultConfigurations(ts: TypeScriptModule, tsConfigPath: string, tsConfig: TsConfig, paths: IPaths, isFirstTimeSetup: boolean): Promise<void>;
2
+ import { TypeScriptModule, TsParsedConfig } from './types';
3
+ export declare function writeDefaultConfigurations(ts: TypeScriptModule, tsConfigPath: string, tsConfig: TsParsedConfig, paths: IPaths, isFirstTimeSetup: boolean): Promise<void>;
@@ -0,0 +1,4 @@
1
+ import { TsParsedConfig, TypeScriptModule } from './types';
2
+ export declare function hasTypescriptFiles(projectDir: string): Promise<boolean>;
3
+ export declare function hasTsConfig(tsConfigPath: string): Promise<boolean>;
4
+ export declare function getTsConfig(ts: TypeScriptModule, tsConfigPath: string): Promise<TsParsedConfig>;
@@ -12,36 +12,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getTsConfig = exports.hasTsConfig = exports.checkNecessaryDeps = exports.hasTypescriptFiles = void 0;
15
+ exports.getTsConfig = exports.hasTsConfig = exports.hasTypescriptFiles = void 0;
16
16
  const fs_extra_1 = require("fs-extra");
17
17
  const os_1 = __importDefault(require("os"));
18
18
  const path_1 = __importDefault(require("path"));
19
19
  const chalk_1 = __importDefault(require("@shuvi/utils/lib/chalk"));
20
20
  const logger_1 = __importDefault(require("@shuvi/utils/lib/logger"));
21
- const resolve_1 = require("@shuvi/utils/lib/resolve");
22
21
  const recursiveReaddir_1 = require("@shuvi/utils/lib/recursiveReaddir");
23
- const requiredPackages = [
24
- { file: 'typescript', pkg: 'typescript' },
25
- { file: '@types/react/index.d.ts', pkg: '@types/react' },
26
- { file: '@types/react-dom/index.d.ts', pkg: '@types/react-dom' },
27
- { file: '@types/node/index.d.ts', pkg: '@types/node' }
28
- ];
29
- function checkDependencies(dir, deps) {
30
- let resolutions = new Map();
31
- const missingPackages = deps.filter(p => {
32
- try {
33
- resolutions.set(p.pkg, (0, resolve_1.resolve)(p.file, { basedir: dir }));
34
- return false;
35
- }
36
- catch (_) {
37
- return true;
38
- }
39
- });
40
- return {
41
- resovled: resolutions,
42
- missing: missingPackages
43
- };
44
- }
45
22
  function hasTypescriptFiles(projectDir) {
46
23
  return __awaiter(this, void 0, void 0, function* () {
47
24
  try {
@@ -61,10 +38,6 @@ function hasTypescriptFiles(projectDir) {
61
38
  });
62
39
  }
63
40
  exports.hasTypescriptFiles = hasTypescriptFiles;
64
- function checkNecessaryDeps(projectDir) {
65
- return checkDependencies(projectDir, requiredPackages);
66
- }
67
- exports.checkNecessaryDeps = checkNecessaryDeps;
68
41
  function hasTsConfig(tsConfigPath) {
69
42
  return __awaiter(this, void 0, void 0, function* () {
70
43
  const hasTsConfig = yield (0, fs_extra_1.pathExists)(tsConfigPath);
@@ -1,2 +1,2 @@
1
- export { setupTypeScript, getTypeScriptInfo } from './setupTypeScript';
1
+ export { setupTypeScript, getJavaScriptInfo, JavaScriptInfo as TypeScriptInfo, ParsedJsConfig, loadJsConfig } from './setupTypeScript';
2
2
  export * from './types';
@@ -14,8 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.getTypeScriptInfo = exports.setupTypeScript = void 0;
17
+ exports.loadJsConfig = exports.getJavaScriptInfo = exports.setupTypeScript = void 0;
18
18
  var setupTypeScript_1 = require("./setupTypeScript");
19
19
  Object.defineProperty(exports, "setupTypeScript", { enumerable: true, get: function () { return setupTypeScript_1.setupTypeScript; } });
20
- Object.defineProperty(exports, "getTypeScriptInfo", { enumerable: true, get: function () { return setupTypeScript_1.getTypeScriptInfo; } });
20
+ Object.defineProperty(exports, "getJavaScriptInfo", { enumerable: true, get: function () { return setupTypeScript_1.getJavaScriptInfo; } });
21
+ Object.defineProperty(exports, "loadJsConfig", { enumerable: true, get: function () { return setupTypeScript_1.loadJsConfig; } });
21
22
  __exportStar(require("./types"), exports);
@@ -1,12 +1,23 @@
1
1
  import { IPaths } from '../../core/apiTypes';
2
- import { TsCompilerOptions } from './types';
3
- interface TypeScriptInfo {
2
+ import { TsCompilerOptions, TsParsedConfig } from './types';
3
+ export interface JavaScriptInfo {
4
4
  useTypeScript: boolean;
5
5
  typeScriptPath?: string;
6
- tsConfigPath?: string;
7
- tsCompilerOptions: TsCompilerOptions;
8
- resolvedBaseUrl?: string;
6
+ compilerOptions: TsCompilerOptions;
7
+ resolvedBaseUrl: string;
9
8
  }
10
- export declare function getTypeScriptInfo(): TypeScriptInfo;
11
- export declare function setupTypeScript(paths: IPaths, reportMissingError?: Boolean): Promise<void>;
12
- export {};
9
+ export interface ParsedJsConfig {
10
+ useTypescript: boolean;
11
+ tsParsedConfig?: TsParsedConfig;
12
+ compilerOptions: TsCompilerOptions;
13
+ resolvedBaseUrl: string;
14
+ }
15
+ export declare function getJavaScriptInfo(): JavaScriptInfo;
16
+ export declare function loadJsConfig(projectDir: string, { typeScriptPath, typescript }: {
17
+ typeScriptPath?: string;
18
+ typescript?: boolean;
19
+ }): Promise<ParsedJsConfig>;
20
+ export declare function setupTypeScript(paths: IPaths, { reportMissingError, enableTypeScript }: {
21
+ reportMissingError: boolean;
22
+ enableTypeScript?: boolean;
23
+ }): Promise<void>;
@@ -35,20 +35,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.setupTypeScript = exports.getTypeScriptInfo = void 0;
38
+ exports.setupTypeScript = exports.loadJsConfig = exports.getJavaScriptInfo = void 0;
39
39
  const path = __importStar(require("path"));
40
40
  const chalk_1 = __importDefault(require("@shuvi/utils/lib/chalk"));
41
41
  const fs_extra_1 = __importDefault(require("fs-extra"));
42
42
  const error_1 = require("../../error");
43
43
  const getPkgManager_1 = require("../helper/getPkgManager");
44
44
  const configTypeScript_1 = require("./configTypeScript");
45
- const getTypeScriptInfo_1 = require("./getTypeScriptInfo");
45
+ const getTsConfig_1 = require("./getTsConfig");
46
+ const checkDependencies_1 = require("./checkDependencies");
46
47
  const installDependencies_1 = require("./installDependencies");
47
48
  let hasSetup = false;
48
49
  let useTypeScript;
50
+ let compilerOptions;
49
51
  let typeScriptPath;
50
- let tsConfigPath;
51
- let tsCompilerOptions;
52
+ let typescriptModule;
52
53
  let resolvedBaseUrl;
53
54
  function missingPackagesError(dir, pkgs) {
54
55
  const packageManager = (0, getPkgManager_1.getPkgManager)(dir);
@@ -80,30 +81,63 @@ function missingPackagesError(dir, pkgs) {
80
81
  removalMsg +
81
82
  '\n');
82
83
  }
83
- function getTypeScriptInfo() {
84
+ function getJavaScriptInfo() {
84
85
  if (!hasSetup) {
85
- throw error_1.Error.Fatal("please call 'setupTypeScript' before calling 'getTypeScriptInfo'");
86
+ throw error_1.Error.Fatal("please call 'setupTypeScript' before calling 'getJavaScriptInfo'");
86
87
  }
87
88
  return {
88
89
  useTypeScript,
89
90
  typeScriptPath,
90
- tsConfigPath,
91
- tsCompilerOptions,
91
+ compilerOptions,
92
92
  resolvedBaseUrl
93
93
  };
94
94
  }
95
- exports.getTypeScriptInfo = getTypeScriptInfo;
96
- function setupTypeScript(paths, reportMissingError = false) {
95
+ exports.getJavaScriptInfo = getJavaScriptInfo;
96
+ function loadJsConfig(projectDir, { typeScriptPath, typescript = false }) {
97
97
  return __awaiter(this, void 0, void 0, function* () {
98
- if (hasSetup) {
99
- return;
98
+ let useTypescript = typescript;
99
+ let tsParsedConfig;
100
+ let compilerOptions = {};
101
+ let resolvedBaseUrl;
102
+ if (useTypeScript) {
103
+ const tsConfigPath = path.join(projectDir, 'tsconfig.json');
104
+ if (!typeScriptPath) {
105
+ const deps = (0, checkDependencies_1.resolveDependencies)(projectDir, [
106
+ { file: 'typescript', pkg: 'typescript' }
107
+ ]);
108
+ typeScriptPath = deps.resovled.get('typescript');
109
+ }
110
+ if (typeScriptPath && (yield (0, getTsConfig_1.hasTsConfig)(tsConfigPath))) {
111
+ const typescriptModule = require(typeScriptPath);
112
+ tsParsedConfig = yield (0, getTsConfig_1.getTsConfig)(typescriptModule, tsConfigPath);
113
+ compilerOptions = tsParsedConfig.options;
114
+ }
115
+ }
116
+ else {
117
+ const jsConfigPath = path.join(projectDir, 'jsconfig.json');
118
+ if (yield fs_extra_1.default.pathExists(jsConfigPath)) {
119
+ const jsConfig = yield fs_extra_1.default.readJSON(jsConfigPath);
120
+ compilerOptions = jsConfig.compilerOptions;
121
+ }
122
+ }
123
+ if (compilerOptions === null || compilerOptions === void 0 ? void 0 : compilerOptions.baseUrl) {
124
+ resolvedBaseUrl = path.resolve(projectDir, compilerOptions.baseUrl);
100
125
  }
126
+ else {
127
+ resolvedBaseUrl = projectDir;
128
+ }
129
+ return { useTypescript, tsParsedConfig, compilerOptions, resolvedBaseUrl };
130
+ });
131
+ }
132
+ exports.loadJsConfig = loadJsConfig;
133
+ function setupTypeScript(paths, { reportMissingError = false, enableTypeScript }) {
134
+ return __awaiter(this, void 0, void 0, function* () {
101
135
  hasSetup = true;
136
+ useTypeScript = enableTypeScript || (yield (0, getTsConfig_1.hasTypescriptFiles)(paths.srcDir));
102
137
  const projectDir = paths.rootDir;
103
- useTypeScript = yield (0, getTypeScriptInfo_1.hasTypescriptFiles)(paths.srcDir);
104
- tsCompilerOptions = {};
138
+ let parsedJsConfig;
105
139
  if (useTypeScript) {
106
- let deps = (0, getTypeScriptInfo_1.checkNecessaryDeps)(projectDir);
140
+ let deps = (0, checkDependencies_1.checkNecessaryDeps)(projectDir);
107
141
  if (deps.missing.length > 0) {
108
142
  if (reportMissingError) {
109
143
  missingPackagesError(projectDir, deps.missing);
@@ -124,29 +158,27 @@ function setupTypeScript(paths, reportMissingError = false) {
124
158
  }
125
159
  throw err;
126
160
  });
127
- deps = (0, getTypeScriptInfo_1.checkNecessaryDeps)(projectDir);
161
+ deps = (0, checkDependencies_1.checkNecessaryDeps)(projectDir);
128
162
  }
129
163
  typeScriptPath = deps.resovled.get('typescript');
130
- tsConfigPath = path.join(projectDir, 'tsconfig.json');
131
- const needDefaultTsConfig = !(yield (0, getTypeScriptInfo_1.hasTsConfig)(tsConfigPath));
164
+ const tsConfigPath = path.join(projectDir, 'tsconfig.json');
165
+ const needDefaultTsConfig = !(yield (0, getTsConfig_1.hasTsConfig)(tsConfigPath));
132
166
  if (needDefaultTsConfig) {
133
167
  console.log(chalk_1.default.cyan(`We detected TypeScript in your project and created a ${chalk_1.default.bold('tsconfig.json')} file for you.`));
134
168
  console.log();
135
169
  yield fs_extra_1.default.writeJson(tsConfigPath, {});
136
170
  }
137
- const ts = require(typeScriptPath);
138
- const tsConfig = yield (0, getTypeScriptInfo_1.getTsConfig)(ts, tsConfigPath);
139
- tsCompilerOptions = tsConfig.options;
140
- yield (0, configTypeScript_1.writeDefaultConfigurations)(ts, tsConfigPath, tsConfig, paths, needDefaultTsConfig);
141
- }
142
- const jsConfigPath = path.join(projectDir, 'jsconfig.json');
143
- if (!useTypeScript && (yield fs_extra_1.default.pathExists(jsConfigPath))) {
144
- const userJsConfig = yield fs_extra_1.default.readJSON(jsConfigPath);
145
- tsCompilerOptions = userJsConfig.compilerOptions;
171
+ typescriptModule = require(typeScriptPath);
172
+ parsedJsConfig = yield loadJsConfig(projectDir, {
173
+ typescript: true
174
+ });
175
+ yield (0, configTypeScript_1.writeDefaultConfigurations)(typescriptModule, tsConfigPath, parsedJsConfig.tsParsedConfig, paths, needDefaultTsConfig);
146
176
  }
147
- if (tsCompilerOptions === null || tsCompilerOptions === void 0 ? void 0 : tsCompilerOptions.baseUrl) {
148
- resolvedBaseUrl = path.resolve(projectDir, tsCompilerOptions.baseUrl);
177
+ else {
178
+ parsedJsConfig = yield loadJsConfig(projectDir, { typescript: false });
149
179
  }
180
+ compilerOptions = parsedJsConfig.compilerOptions;
181
+ resolvedBaseUrl = parsedJsConfig.resolvedBaseUrl;
150
182
  });
151
183
  }
152
184
  exports.setupTypeScript = setupTypeScript;
@@ -1,3 +1,3 @@
1
1
  export declare type TypeScriptModule = typeof import('typescript');
2
- export declare type TsConfig = import('typescript').ParsedCommandLine;
2
+ export declare type TsParsedConfig = import('typescript').ParsedCommandLine;
3
3
  export declare type TsCompilerOptions = import('typescript').CompilerOptions;
package/lib/core/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FileOption } from '../project';
2
- import { Bunlder } from '../bundler';
2
+ import { Bundler } from '../bundler';
3
3
  import { ServerPluginInstance } from '../server';
4
4
  import { ShuviConfig, IPluginConfig, IPresetConfig, IServiceMode, IServicePhase, IPlatform, IPlatformContent, IPluginContext, RuntimePluginConfig } from './apiTypes';
5
5
  interface IApiOPtions {
@@ -48,7 +48,7 @@ declare class Api {
48
48
  get pluginContext(): IPluginContext;
49
49
  get serverConfigs(): ServerConfigs;
50
50
  init(): Promise<void>;
51
- getBundler(): Promise<Bunlder>;
51
+ getBundler(): Promise<Bundler>;
52
52
  get assetPublicPath(): string;
53
53
  buildApp(): Promise<void>;
54
54
  addRuntimeFile(option: FileOption<any>): void;
package/lib/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './namespace';
2
2
  export * from './constants';
3
- export { Bunlder } from './bundler';
3
+ export { Bundler } from './bundler';
4
4
  export { ProjectBuilder } from './project';
5
5
  export { IShuviServer, ShuviRequest, ShuviResponse, IServerPluginContext, ShuviRequestHandler, ServerPluginConstructor, ServerPluginInstance, IServerMiddleware, createShuviServer, createServerPlugin, createServerPluginBefore, createServerPluginAfter } from './server';
6
6
  export { Api, IPaths, ShuviConfig, IServicePhase, IServiceMode, IPluginConfig, IPresetConfig, PresetFunction, IPresetContent, NormalizedShuviConfig, IPluginContext, IPlatform, IPlatformContent, CorePluginConstructor, CorePluginInstance, getApi, createPlugin, createPluginBefore, createPluginAfter, ResolvedPlugin } from './core';
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getRouter = void 0;
7
+ const util_1 = require("util");
7
8
  const utils_1 = require("@shuvi/utils");
8
9
  const invariant_1 = __importDefault(require("@shuvi/utils/lib/invariant"));
9
10
  const router_1 = require("@shuvi/router");
@@ -35,14 +36,14 @@ class RouterImpl {
35
36
  }
36
37
  handleRequest(req, res, out) {
37
38
  let index = 0;
38
- let done = (err) => out(err);
39
+ let done = err => out(err);
39
40
  const next = err => {
40
41
  // next callback
41
42
  const route = this._routes[index++];
42
43
  // all done
43
44
  if (!route) {
44
45
  // final function handler
45
- setImmediate(done, err);
46
+ this._handleError(done, err);
46
47
  return;
47
48
  }
48
49
  const { path, handler } = route;
@@ -67,33 +68,46 @@ class RouterImpl {
67
68
  req.params = match.params;
68
69
  // call the route handler
69
70
  if (err) {
70
- this._callRouteErrorHandler(handler, err, req, res, next);
71
+ this._callRouteErrorHandler(handler, err, req, res, next, done);
71
72
  }
72
73
  else {
73
- this._callRouteRequestHandler(handler, req, res, next);
74
+ this._callRouteRequestHandler(handler, req, res, next, done);
74
75
  }
75
76
  };
76
77
  return next();
77
78
  }
78
- _callRouteRequestHandler(handler, req, res, next) {
79
+ _handleError(done, err) {
80
+ setImmediate(done, err);
81
+ }
82
+ _callRouteRequestHandler(handler, req, res, next, done) {
79
83
  if (handler.length > 3) {
80
84
  // not a standard request handler
81
85
  return next();
82
86
  }
83
87
  try {
84
- handler(req, res, next);
88
+ const result = handler(req, res, next);
89
+ if (util_1.types.isPromise(result)) {
90
+ result.catch(err => {
91
+ this._handleError(done, err);
92
+ });
93
+ }
85
94
  }
86
95
  catch (err) {
87
96
  next(err);
88
97
  }
89
98
  }
90
- _callRouteErrorHandler(handler, error, req, res, next) {
99
+ _callRouteErrorHandler(handler, error, req, res, next, done) {
91
100
  if (handler.length !== 4) {
92
101
  // not a standard error handler
93
102
  return next(error);
94
103
  }
95
104
  try {
96
- handler(error, req, res, next);
105
+ const result = handler(error, req, res, next);
106
+ if (util_1.types.isPromise(result)) {
107
+ result.catch(err => {
108
+ this._handleError(done, err);
109
+ });
110
+ }
97
111
  }
98
112
  catch (err) {
99
113
  next(err);
@@ -1,13 +1,13 @@
1
1
  import { IPluginContext } from '../core';
2
2
  import { IShuviServer, ShuviServerOptions, ShuviRequest, ShuviResponse, ShuviRequestHandler } from './shuviServerTypes';
3
- import { Bunlder } from '../bundler';
3
+ import { Bundler } from '../bundler';
4
4
  export { Server } from './http-server';
5
5
  export * from './plugin';
6
6
  export * from './shuviServerTypes';
7
7
  export { ShuviRequest, ShuviResponse, ShuviRequestHandler };
8
8
  export interface CreateShuviDevServerOptions extends ShuviServerOptions {
9
9
  context: IPluginContext;
10
- bundler: Bunlder;
10
+ bundler: Bundler;
11
11
  dev: true;
12
12
  }
13
13
  export interface CreateShuviProdServerOptions extends ShuviServerOptions {
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  import { IncomingMessage } from 'http';
4
- import { Bunlder } from '../../../bundler';
4
+ import { Bundler } from '../../../bundler';
5
5
  import { Server } from '../../http-server';
6
6
  import { IServerPluginContext } from '../../plugin';
7
7
  export interface DevMiddleware {
@@ -11,4 +11,4 @@ export interface DevMiddleware {
11
11
  waitUntilValid(force?: boolean): void;
12
12
  onHMR(req: IncomingMessage, socket: any, head: Buffer): void;
13
13
  }
14
- export declare function getDevMiddleware(bundler: Bunlder, serverPluginContext: IServerPluginContext): DevMiddleware;
14
+ export declare function getDevMiddleware(bundler: Bundler, serverPluginContext: IServerPluginContext): DevMiddleware;
@@ -1,3 +1,3 @@
1
1
  import { IServerPluginContext } from '../plugin';
2
2
  import { ShuviRequestHandler } from '../../server';
3
- export declare const getAssetMiddleware: (context: IServerPluginContext, isDev?: boolean) => ShuviRequestHandler;
3
+ export declare const getAssetMiddleware: (context: IServerPluginContext) => ShuviRequestHandler;
@@ -12,27 +12,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getAssetMiddleware = void 0;
13
13
  const constants_1 = require("../../constants");
14
14
  const utils_1 = require("../utils");
15
- const getAssetMiddleware = (context, isDev = false) => {
15
+ const getAssetMiddleware = (context) => {
16
16
  return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
17
- const fullUrl = new URL(req.url, `http://${req.headers.host}`);
18
- let assetPath = fullUrl.pathname;
19
17
  const candidatePaths = [];
20
- if (context.assetPublicPath.startsWith('/')) {
21
- assetPath = assetPath.replace(context.assetPublicPath, '');
22
- candidatePaths.push(context.resolveBuildFile(constants_1.CLIENT_OUTPUT_DIR, assetPath));
23
- }
24
- else {
25
- fullUrl.search = '';
26
- const urlWithoutQuery = fullUrl.toString();
27
- // when assetPublicPath is http:localhost:3000/xx
28
- if (urlWithoutQuery.startsWith(context.assetPublicPath)) {
29
- assetPath = urlWithoutQuery.replace(context.assetPublicPath, '');
18
+ try {
19
+ const fullUrl = new URL(req.url, `http://${req.headers.host}`);
20
+ let assetPath = fullUrl.pathname;
21
+ if (context.assetPublicPath.startsWith('/')) {
22
+ assetPath = assetPath.replace(context.assetPublicPath, '');
30
23
  candidatePaths.push(context.resolveBuildFile(constants_1.CLIENT_OUTPUT_DIR, assetPath));
31
24
  }
32
- }
33
- if (isDev) {
25
+ else {
26
+ fullUrl.search = '';
27
+ const urlWithoutQuery = fullUrl.toString();
28
+ // when assetPublicPath is http:localhost:3000/xx
29
+ if (urlWithoutQuery.startsWith(context.assetPublicPath)) {
30
+ assetPath = urlWithoutQuery.replace(context.assetPublicPath, '');
31
+ candidatePaths.push(context.resolveBuildFile(constants_1.CLIENT_OUTPUT_DIR, assetPath));
32
+ }
33
+ }
34
34
  candidatePaths.push(context.resolvePublicFile(assetPath));
35
35
  }
36
+ catch (err) {
37
+ return next(err);
38
+ }
36
39
  if (!candidatePaths.length) {
37
40
  return next();
38
41
  }
@@ -6,6 +6,7 @@ export declare class ShuviDevServer extends ShuviServer {
6
6
  private verifyingTypeScript?;
7
7
  constructor(corePluginContext: any, { bundler, ...options }: ShuviDevServerOptions);
8
8
  init(): Promise<void>;
9
+ private _catchUnexpectedError;
9
10
  private _setupWebSocketHandler;
10
11
  private startWatcher;
11
12
  private verifyTypeScript;
@@ -45,6 +45,7 @@ class ShuviDevServer extends shuviServer_1.ShuviServer {
45
45
  }
46
46
  });
47
47
  };
48
+ this._catchUnexpectedError();
48
49
  this._bundler = bundler;
49
50
  }
50
51
  init() {
@@ -80,7 +81,7 @@ class ShuviDevServer extends shuviServer_1.ShuviServer {
80
81
  }
81
82
  // keep the order
82
83
  devMiddleware.apply(server);
83
- server.use((0, getAssetMiddleware_1.getAssetMiddleware)(context, true));
84
+ server.use((0, getAssetMiddleware_1.getAssetMiddleware)(context));
84
85
  yield this._initMiddlewares();
85
86
  // setup upgrade listener eagerly when we can otherwise
86
87
  // it will be done on the first request via req.socket.server
@@ -88,6 +89,14 @@ class ShuviDevServer extends shuviServer_1.ShuviServer {
88
89
  yield this.startWatcher(devMiddleware);
89
90
  });
90
91
  }
92
+ _catchUnexpectedError() {
93
+ process.on('unhandledRejection', reason => {
94
+ console.error(`Caught unhandledRejection: \n`, reason, '\n');
95
+ });
96
+ process.on('uncaughtException', err => {
97
+ console.error(`Caught uncaughtException: \n`, err, '\n');
98
+ });
99
+ }
91
100
  startWatcher(devMiddleware) {
92
101
  return __awaiter(this, void 0, void 0, function* () {
93
102
  if (this._webpackWatcher) {
@@ -98,8 +107,8 @@ class ShuviDevServer extends shuviServer_1.ShuviServer {
98
107
  const directories = [routesDir];
99
108
  const fileWatchTimes = new Map();
100
109
  const configs = this._bundler.targets;
101
- let { useTypeScript } = (0, typescript_1.getTypeScriptInfo)();
102
- let enabledTypeScript = useTypeScript;
110
+ let { useTypeScript } = (0, typescript_1.getJavaScriptInfo)();
111
+ let enableTypeScript = useTypeScript;
103
112
  const envFiles = [
104
113
  '.env.development.local',
105
114
  '.env.local',
@@ -134,23 +143,52 @@ class ShuviDevServer extends shuviServer_1.ShuviServer {
134
143
  }
135
144
  continue;
136
145
  }
146
+ if (tsconfigPaths.includes(fileName)) {
147
+ if (fileName.endsWith('tsconfig.json') &&
148
+ fileWatchTimes.get(fileName)) {
149
+ enableTypeScript = true;
150
+ }
151
+ if (watchTimeChange) {
152
+ tsconfigChange = true;
153
+ }
154
+ continue;
155
+ }
137
156
  if (fileName.endsWith('.ts') || fileName.endsWith('.tsx')) {
138
- enabledTypeScript = true;
157
+ enableTypeScript = true;
139
158
  }
140
159
  }
141
- if (!useTypeScript && enabledTypeScript) {
142
- yield this.verifyTypeScript();
160
+ if (!useTypeScript && enableTypeScript) {
161
+ yield this.verifyTypeScript(enableTypeScript);
143
162
  useTypeScript = true;
144
163
  tsconfigChange = true;
145
164
  }
146
165
  if (tsconfigChange || envChange) {
166
+ let parseJsConfig;
167
+ if (tsconfigChange) {
168
+ parseJsConfig = yield (0, typescript_1.loadJsConfig)(rootDir, { typescript: true });
169
+ }
147
170
  if (envChange) {
148
171
  (0, env_1.loadDotenvConfig)({ rootDir, forceReloadEnv: true });
149
172
  }
150
173
  configs.forEach(({ config }) => {
151
- var _a;
174
+ var _a, _b, _c;
175
+ if (tsconfigChange) {
176
+ (_b = (_a = config.resolve) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.forEach((plugin) => {
177
+ // look for the JsConfigPathsPlugin and update with the latest paths/baseUrl config
178
+ if (plugin && plugin.jsConfigPlugin && parseJsConfig) {
179
+ const { resolvedBaseUrl, compilerOptions } = parseJsConfig;
180
+ if (compilerOptions.paths && resolvedBaseUrl) {
181
+ Object.keys(plugin.paths).forEach(key => {
182
+ delete plugin.paths[key];
183
+ });
184
+ plugin.paths = Object.assign({}, compilerOptions.paths);
185
+ plugin.resolvedBaseUrl = resolvedBaseUrl;
186
+ }
187
+ }
188
+ });
189
+ }
152
190
  if (envChange) {
153
- (_a = config.plugins) === null || _a === void 0 ? void 0 : _a.forEach((plugin) => {
191
+ (_c = config.plugins) === null || _c === void 0 ? void 0 : _c.forEach((plugin) => {
154
192
  // we look for the DefinePlugin definitions so we can
155
193
  // update them on the active compilers
156
194
  if (plugin &&
@@ -172,14 +210,17 @@ class ShuviDevServer extends shuviServer_1.ShuviServer {
172
210
  }));
173
211
  });
174
212
  }
175
- verifyTypeScript() {
213
+ verifyTypeScript(enableTypeScript) {
176
214
  return __awaiter(this, void 0, void 0, function* () {
177
215
  if (this.verifyingTypeScript) {
178
216
  return;
179
217
  }
180
218
  try {
181
219
  this.verifyingTypeScript = true;
182
- yield (0, typescript_1.setupTypeScript)(this._serverContext.paths);
220
+ yield (0, typescript_1.setupTypeScript)(this._serverContext.paths, {
221
+ reportMissingError: false,
222
+ enableTypeScript: enableTypeScript
223
+ });
183
224
  }
184
225
  finally {
185
226
  this.verifyingTypeScript = false;
@@ -14,6 +14,7 @@ const string_1 = require("@shuvi/utils/lib/string");
14
14
  const serverMiddleware_1 = require("./serverMiddleware");
15
15
  const http_server_1 = require("./http-server");
16
16
  const plugin_1 = require("./plugin");
17
+ const utils_1 = require("./utils");
17
18
  class ShuviServer {
18
19
  constructor(corePluginContext, options) {
19
20
  this._pluginManager = (0, plugin_1.getManager)();
@@ -28,6 +29,8 @@ class ShuviServer {
28
29
  const fullAssetPath = (0, string_1.joinPath)(this._serverContext.assetPublicPath, assetPath);
29
30
  return fullAssetPath;
30
31
  };
32
+ // Parsing of cookies
33
+ shuviReq.cookies = (0, utils_1.getCookieParser)(req);
31
34
  }
32
35
  _normalizeResp(_resp) {
33
36
  // do nothing
@@ -2,14 +2,16 @@
2
2
  import { RequestListener } from 'http';
3
3
  import { ServerPluginInstance } from './plugin';
4
4
  import { IPlatformContent } from '../core';
5
- import { Bunlder } from '../bundler';
5
+ import { Bundler } from '../bundler';
6
6
  import { IRequest, IResponse, IRequestHandlerWithNext } from '../server/http-server';
7
+ import type { getCookieParser } from './utils';
7
8
  export interface CustomShuviRequest {
8
9
  }
9
10
  export interface CustomShuviResponse {
10
11
  }
11
12
  export interface ShuviRequest extends IRequest, CustomShuviRequest {
12
13
  getAssetUrl(assetPath: string): string;
14
+ cookies: ReturnType<typeof getCookieParser>;
13
15
  }
14
16
  export interface ShuviResponse extends IResponse, CustomShuviResponse {
15
17
  }
@@ -26,5 +28,5 @@ export interface ShuviServerOptions {
26
28
  getMiddlewaresBeforeDevMiddlewares?: IPlatformContent['getMiddlewaresBeforeDevMiddlewares'];
27
29
  }
28
30
  export interface ShuviDevServerOptions extends ShuviServerOptions {
29
- bundler: Bunlder;
31
+ bundler: Bundler;
30
32
  }
@@ -2,4 +2,11 @@
2
2
  import { IncomingMessage, ServerResponse } from 'http';
3
3
  export declare function isStaticFileExist(path: string): Boolean;
4
4
  export declare function serveStatic(req: IncomingMessage, res: ServerResponse, path: string): Promise<void>;
5
+ /**
6
+ * Parse cookies from `req` header
7
+ * @param req request object
8
+ */
9
+ export declare function getCookieParser(req: IncomingMessage): {
10
+ [key: string]: string;
11
+ };
5
12
  export declare function sendHTML(req: IncomingMessage, res: ServerResponse, html: string): void;
@@ -1,11 +1,35 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sendHTML = exports.serveStatic = exports.isStaticFileExist = void 0;
29
+ exports.sendHTML = exports.getCookieParser = exports.serveStatic = exports.isStaticFileExist = void 0;
7
30
  const fs_1 = require("fs");
8
31
  const send_1 = __importDefault(require("send"));
32
+ const cookie = __importStar(require("cookie"));
9
33
  function isStaticFileExist(path) {
10
34
  if ((0, fs_1.existsSync)(path)) {
11
35
  return !(0, fs_1.statSync)(path).isDirectory() && (0, fs_1.statSync)(path).isFile();
@@ -31,6 +55,18 @@ function serveStatic(req, res, path) {
31
55
  });
32
56
  }
33
57
  exports.serveStatic = serveStatic;
58
+ /**
59
+ * Parse cookies from `req` header
60
+ * @param req request object
61
+ */
62
+ function getCookieParser(req) {
63
+ const header = req.headers.cookie;
64
+ if (!header) {
65
+ return {};
66
+ }
67
+ return cookie.parse(Array.isArray(header) ? header.join(';') : header);
68
+ }
69
+ exports.getCookieParser = getCookieParser;
34
70
  function sendHTML(req, res, html) {
35
71
  if (res.writableEnded || res.headersSent)
36
72
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuvi/service",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/shuvijs/shuvi.git",
@@ -29,13 +29,13 @@
29
29
  "@babel/generator": "7.14.5",
30
30
  "@babel/parser": "7.14.7",
31
31
  "@babel/traverse": "7.14.7",
32
- "@shuvi/hook": "1.0.0",
33
- "@shuvi/router": "1.0.0",
34
- "@shuvi/runtime": "1.0.0",
35
- "@shuvi/shared": "1.0.0",
36
- "@shuvi/toolpack": "1.0.0",
37
- "@shuvi/utils": "1.0.0",
38
- "@shuvi/error-overlay": "1.0.0",
32
+ "@shuvi/hook": "1.0.2",
33
+ "@shuvi/router": "1.0.2",
34
+ "@shuvi/runtime": "1.0.2",
35
+ "@shuvi/shared": "1.0.2",
36
+ "@shuvi/toolpack": "1.0.2",
37
+ "@shuvi/utils": "1.0.2",
38
+ "@shuvi/error-overlay": "1.0.2",
39
39
  "commander": "5.1.0",
40
40
  "comment-json": "4.2.2",
41
41
  "cross-spawn": "7.0.3",
@@ -43,6 +43,7 @@
43
43
  "fs-extra": "9.0.1",
44
44
  "http-proxy-middleware": "1.0.6",
45
45
  "rimraf": "3.0.2",
46
+ "cookie": "0.4.1",
46
47
  "send": "0.17.1",
47
48
  "ws": "8.2.3",
48
49
  "dotenv": "16.0.3",
@@ -55,6 +56,7 @@
55
56
  "@types/babel__traverse": "^7.14.2",
56
57
  "@types/cross-spawn": "6.0.1",
57
58
  "@types/detect-port": "1.3.0",
59
+ "@types/cookie": "^0.4.1",
58
60
  "@types/ejs": "3.0.4",
59
61
  "@types/ws": "8.2.0"
60
62
  }