@shuvi/platform-shared 1.0.0-rc.0 → 1.0.0-rc.3

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.
@@ -6,4 +6,5 @@ export * from './loader';
6
6
  export { errorModel } from './models/error';
7
7
  export * from './applicationTypes';
8
8
  export type { Application } from './application';
9
+ export type { IRuntimeConfig } from './runtimeConfigTypes';
9
10
  export { IAppModule, IPluginInstance, BuiltInRuntimePluginHooks, CustomRuntimePluginHooks, RuntimePluginHooks, createRuntimePlugin, RuntimePluginInstance } from './lifecycle';
@@ -4,21 +4,16 @@ export declare type IURLQuery = ParsedQuery;
4
4
  export declare type IURLParams = IParams;
5
5
  export interface IPageRouteRecord extends IRouteRecord {
6
6
  id: string;
7
+ path: string;
7
8
  component?: any;
8
9
  children?: IPageRouteRecord[];
9
- path: string;
10
- fullPath?: string;
11
- __componentSource__?: never;
12
- __componentSourceWithAffix__?: string;
13
- __import__?: never;
14
- __resolveWeak__?: () => any;
15
10
  [x: string]: any;
16
11
  }
17
12
  export interface IRawPageRouteRecord extends IRouteRecord {
18
13
  id: string;
14
+ path: string;
19
15
  component?: any;
20
16
  children?: IRawPageRouteRecord[];
21
- path: string;
22
17
  fullPath: string;
23
18
  __componentSource__: string;
24
19
  __componentSourceWithAffix__: string;
@@ -26,3 +21,30 @@ export interface IRawPageRouteRecord extends IRouteRecord {
26
21
  __resolveWeak__: () => any;
27
22
  [x: string]: any;
28
23
  }
24
+ export interface IPlatformConfig {
25
+ name: string;
26
+ framework?: string;
27
+ target?: string;
28
+ [index: string]: any;
29
+ }
30
+ export declare type IRouterHistoryMode = 'browser' | 'hash' | 'memory';
31
+ export interface IPageRouteConfig {
32
+ children?: IPageRouteConfig[];
33
+ name?: string;
34
+ component?: string;
35
+ redirect?: string;
36
+ path: string;
37
+ fullPath?: string;
38
+ }
39
+ export interface IPageRouteConfigWithId extends IPageRouteConfig {
40
+ id: string;
41
+ children?: IPageRouteConfigWithId[];
42
+ }
43
+ export interface IMiddlewareRouteConfig {
44
+ path: string;
45
+ middleware: string;
46
+ }
47
+ export interface IApiRouteConfig {
48
+ path: string;
49
+ api: string;
50
+ }
@@ -0,0 +1 @@
1
+ export declare type IRuntimeConfig = Record<string, string>;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { IRuntimeConfig } from '@shuvi/service/lib/core';
1
+ import { IRuntimeConfig } from './runtimeConfigTypes';
2
2
  /**
3
3
  * getRuntimeConfig function
4
4
  *
@@ -1,6 +1,7 @@
1
1
  export * from './runtimeFiles';
2
2
  export declare const SharedPlugins: {
3
3
  core: import("@shuvi/hook").IPluginInstance<{
4
+ extendConfig: import("@shuvi/hook").SyncWaterfallHook<import("@shuvi/service").Config, void>;
4
5
  afterInit: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
5
6
  afterBuild: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
6
7
  afterDestroy: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
@@ -11,6 +12,6 @@ export declare const SharedPlugins: {
11
12
  addResource: import("@shuvi/hook").AsyncParallelHook<void, void, import("@shuvi/service/lib/core/lifecycleTypes").Resources | import("@shuvi/service/lib/core/lifecycleTypes").Resources[]>;
12
13
  addRuntimeFile: import("@shuvi/hook").AsyncParallelHook<void, import("@shuvi/service/lib/core/lifecycleTypes").AddRuntimeFileUtils, import("@shuvi/service/lib/project/index").FileOptions<any, any> | import("@shuvi/service/lib/project/index").FileOptions<any, any>[]>;
13
14
  addRuntimeService: import("@shuvi/hook").AsyncParallelHook<void, void, import("@shuvi/service/lib/core/lifecycleTypes").RuntimeService | import("@shuvi/service/lib/core/lifecycleTypes").RuntimeService[]>;
14
- } & import("@shuvi/runtime").CustomCorePluginHooks, import("@shuvi/service").IPluginContext>;
15
+ } & import("@shuvi/service/lib/core/apiTypes").CustomCorePluginHooks, import("@shuvi/service").IPluginContext>;
15
16
  types: string;
16
17
  }[];
@@ -1,4 +1,4 @@
1
- import { IRuntimeConfig } from '@shuvi/service/lib/core';
1
+ import { IRuntimeConfig } from '../../../../shared';
2
2
  export declare const extendedHooks: {
3
3
  addEntryCode: import("@shuvi/hook").AsyncParallelHook<void, void, string | string[]>;
4
4
  addPolyfill: import("@shuvi/hook").AsyncParallelHook<void, void, string | string[]>;
@@ -1,5 +1,6 @@
1
1
  declare const _default: {
2
2
  core: import("@shuvi/hook").IPluginInstance<{
3
+ extendConfig: import("@shuvi/hook").SyncWaterfallHook<import("@shuvi/service").Config, void>;
3
4
  afterInit: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
4
5
  afterBuild: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
5
6
  afterDestroy: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
@@ -10,7 +11,7 @@ declare const _default: {
10
11
  addResource: import("@shuvi/hook").AsyncParallelHook<void, void, import("@shuvi/service/lib/core/lifecycleTypes").Resources | import("@shuvi/service/lib/core/lifecycleTypes").Resources[]>;
11
12
  addRuntimeFile: import("@shuvi/hook").AsyncParallelHook<void, import("@shuvi/service/lib/core/lifecycleTypes").AddRuntimeFileUtils, import("@shuvi/service/lib/project/index").FileOptions<any, any> | import("@shuvi/service/lib/project/index").FileOptions<any, any>[]>;
12
13
  addRuntimeService: import("@shuvi/hook").AsyncParallelHook<void, void, import("@shuvi/service/lib/core/lifecycleTypes").RuntimeService | import("@shuvi/service/lib/core/lifecycleTypes").RuntimeService[]>;
13
- } & import("@shuvi/runtime").CustomCorePluginHooks, import("@shuvi/service").IPluginContext>;
14
+ } & import("@shuvi/service/lib/core/apiTypes").CustomCorePluginHooks, import("@shuvi/service").IPluginContext>;
14
15
  types: string;
15
16
  };
16
17
  export default _default;
@@ -1,8 +1,4 @@
1
1
  import { IPluginContext } from '@shuvi/service';
2
- export declare const getRuntimeConfigFromConfig: (pluginContext: IPluginContext) => Promise<{
3
- public: import("@shuvi/service/lib/core/apiTypes").IRuntimeConfig;
4
- server: import("@shuvi/service/lib/core/apiTypes").IRuntimeConfig;
5
- }>;
6
2
  /**
7
3
  * A creator for `getPresetRuntimeFiles` which helps platforms to build a bunch of runtime files including
8
4
  * `core/error`, `core/platform`, `core/plugins`, `core/polyfill`, `core/runtimeConfig`, `core/setRuntimeConfig`,
@@ -9,32 +9,46 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getPresetRuntimeFilesCreator = exports.getRuntimeConfigFromConfig = void 0;
12
+ exports.getPresetRuntimeFilesCreator = void 0;
13
13
  const project_1 = require("@shuvi/service/lib/project");
14
+ const shuvi_singleton_runtimeConfig_1 = require("../../shared/shuvi-singleton-runtimeConfig");
14
15
  const projectContext_1 = require("../project/projectContext");
15
16
  const file_presets_1 = require("../project/file-presets");
16
- const getRuntimeConfigFromConfig = (pluginContext) => __awaiter(void 0, void 0, void 0, function* () {
17
- const { pluginRunner, config } = pluginContext;
18
- return yield pluginRunner.modifyRuntimeConfig({
19
- public: config.publicRuntimeConfig || {},
20
- server: config.runtimeConfig || {}
21
- });
22
- });
23
- exports.getRuntimeConfigFromConfig = getRuntimeConfigFromConfig;
24
17
  /**
25
18
  * A creator for `getPresetRuntimeFiles` which helps platforms to build a bunch of runtime files including
26
19
  * `core/error`, `core/platform`, `core/plugins`, `core/polyfill`, `core/runtimeConfig`, `core/setRuntimeConfig`,
27
20
  * `user/error`, `user/runtime` and `entry`
28
21
  */
29
22
  const getPresetRuntimeFilesCreator = (platformModule, polyfills) => (pluginContext) => __awaiter(void 0, void 0, void 0, function* () {
23
+ const { pluginRunner, config } = pluginContext;
30
24
  const getCandidates = (fileName, fallbackType) => project_1.fileUtils.getUserCustomFileCandidates(pluginContext.paths.rootDir, fileName, fallbackType);
25
+ const { public: publicRuntimeConfig, server: serverRuntimeConfig } = yield pluginRunner.modifyRuntimeConfig({
26
+ public: config.publicRuntimeConfig || {},
27
+ server: config.runtimeConfig || {}
28
+ });
29
+ const serverKeys = Object.keys(serverRuntimeConfig);
30
+ const publicKeys = Object.keys(publicRuntimeConfig);
31
+ for (let index = 0; index < serverKeys.length; index++) {
32
+ const key = serverKeys[index];
33
+ const hasSameKey = publicKeys.includes(key);
34
+ if (hasSameKey) {
35
+ console.warn(`Warning: key "${key}" exist in both "runtimeConfig" and "publicRuntimeConfig". Please rename the key, or the value from "publicRuntimeConfig" will be applied.\n`);
36
+ break;
37
+ }
38
+ }
39
+ if (serverKeys) {
40
+ (0, shuvi_singleton_runtimeConfig_1.setRuntimeConfig)(serverRuntimeConfig);
41
+ }
42
+ if (publicKeys) {
43
+ (0, shuvi_singleton_runtimeConfig_1.setPublicRuntimeConfig)(publicRuntimeConfig);
44
+ }
31
45
  const context = (0, projectContext_1.createProjectContext)();
32
46
  context.userModule = {
33
47
  error: getCandidates('error', 'nullish'),
34
- app: getCandidates('app', 'noop')
48
+ app: getCandidates('app', 'noop'),
49
+ server: getCandidates('server', 'noop')
35
50
  };
36
51
  context.platformModule = platformModule;
37
- const { public: publicRuntimeConfig, server: serverRuntimeConfig } = yield (0, exports.getRuntimeConfigFromConfig)(pluginContext);
38
52
  context.runtimeConfig = Object.assign(Object.assign({}, serverRuntimeConfig), publicRuntimeConfig);
39
53
  const runner = pluginContext.pluginRunner;
40
54
  const appPolyfills = (yield runner.addPolyfill()).flat();
@@ -0,0 +1,3 @@
1
+ import { ProjectContext } from '../../../../projectContext';
2
+ declare const _default: (context: ProjectContext) => Omit<import("@shuvi/service/lib/project").DefineFileOption, "name">;
3
+ export default _default;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const project_1 = require("@shuvi/service/lib/project");
4
+ const __1 = require("../../..");
5
+ const { getAllFiles, getFirstModuleExport } = project_1.fileUtils;
6
+ exports.default = (context) => {
7
+ const { server } = context.userModule;
8
+ const candidates = Array.isArray(server) ? server : [server];
9
+ return (0, __1.defineFile)({
10
+ dependencies: candidates,
11
+ content: () => {
12
+ return getFirstModuleExport(getAllFiles(candidates), candidates);
13
+ }
14
+ });
15
+ };
@@ -1,7 +1,8 @@
1
- import { IRuntimeConfig } from '@shuvi/service/lib/core';
1
+ import { IRuntimeConfig } from '../../shared';
2
2
  export interface UserModule {
3
3
  app: string | string[];
4
4
  error: string | string[];
5
+ server: string | string[];
5
6
  }
6
7
  export interface ProjectContext {
7
8
  entryCodes: string[];
@@ -9,7 +9,8 @@ const createProjectContext = () => {
9
9
  platformModule: '',
10
10
  userModule: {
11
11
  app: '',
12
- error: ''
12
+ error: '',
13
+ server: ''
13
14
  }
14
15
  };
15
16
  };
@@ -1,20 +1,19 @@
1
- import { IApiRouteConfig, IMiddlewareRouteConfig, IPageRouteConfig } from './route';
2
1
  declare const supportFileTypes: readonly ["page", "layout", "middleware", "api"];
3
2
  declare type GetArrayElementType<T extends readonly any[]> = T extends readonly any[] ? T[number] : never;
4
3
  export declare type SupportFileType = GetArrayElementType<typeof supportFileTypes>;
5
4
  declare type CapName = Capitalize<SupportFileType>;
6
5
  declare type FileTypeChecker = Record<`is${CapName}`, (filename: string) => boolean>;
7
- export declare function normalizeFilePath(filepath: string): string;
8
6
  export declare function parseDynamicPath(normalizedRoute: string): string;
9
7
  export declare function normalizeRoutePath(rawPath: string): string;
10
- export declare const normalize: (path: string) => string;
8
+ export declare function combineComponents(fisrt: string, sec: string): string;
11
9
  export declare const isRouteFile: (file: string) => boolean;
12
10
  export declare const getAllowFilesAndDirs: (dirname: string) => Promise<string[]>;
13
11
  export declare const hasAllowFiles: (files: string[]) => boolean;
14
12
  export declare const readDir: (fullPath: string) => Promise<string[]>;
15
13
  export declare const hasRouteChildren: (files: string[], parentPath: string) => Promise<boolean>;
16
14
  declare const fileTypeChecker: FileTypeChecker;
17
- declare function sortRoutes(routes: IApiRouteConfig[]): IApiRouteConfig[];
18
- declare function sortRoutes(routes: IMiddlewareRouteConfig[]): IMiddlewareRouteConfig[];
19
- declare function sortRoutes(routes: IPageRouteConfig[]): IPageRouteConfig[];
15
+ declare function sortRoutes<T extends {
16
+ path: string;
17
+ children?: T[];
18
+ }>(routes: T[]): T[];
20
19
  export { fileTypeChecker, sortRoutes };
@@ -12,7 +12,7 @@ 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.sortRoutes = exports.fileTypeChecker = exports.hasRouteChildren = exports.readDir = exports.hasAllowFiles = exports.getAllowFilesAndDirs = exports.isRouteFile = exports.normalize = exports.normalizeRoutePath = exports.parseDynamicPath = exports.normalizeFilePath = void 0;
15
+ exports.sortRoutes = exports.fileTypeChecker = exports.hasRouteChildren = exports.readDir = exports.hasAllowFiles = exports.getAllowFilesAndDirs = exports.isRouteFile = exports.combineComponents = exports.normalizeRoutePath = exports.parseDynamicPath = void 0;
16
16
  const fs_1 = __importDefault(require("fs"));
17
17
  const path_1 = require("path");
18
18
  const file_1 = require("@shuvi/utils/lib/file");
@@ -22,20 +22,9 @@ const supportFileTypes = ['page', 'layout', 'middleware', 'api'];
22
22
  const allowReadFilExtList = ['ts', 'js', 'tsx', 'jsx'];
23
23
  const dynamicMatchAllRegex = /\[\[(.+?)\]\]/g;
24
24
  const dynamicMatchPartRegex = /\[(.+?)\]/g;
25
- function normalizeFilePath(filepath) {
26
- const res = filepath
27
- // Remove the file extension from the end
28
- .replace(/\.\w+$/, '')
29
- // Convert to unix path
30
- .replace(/\\/g, '/');
31
- return res.charAt(0) !== '/' ? '/' + res : res;
32
- }
33
- exports.normalizeFilePath = normalizeFilePath;
34
25
  function parseDynamicPath(normalizedRoute) {
35
- (0, invariant_1.default)(normalizedRoute.length >= 1, 'parseDynamicPath param normalizedRoute length should not >= 1');
36
26
  (0, invariant_1.default)(!checkSpecialRegexChars(normalizedRoute), 'filePath should not be special regex chars: |\\{}()^$+*?');
37
27
  return normalizedRoute
38
- .slice(1)
39
28
  .split('/')
40
29
  .map(segment => {
41
30
  let result = '';
@@ -45,9 +34,9 @@ function parseDynamicPath(normalizedRoute) {
45
34
  result = result.replace(dynamicMatchPartRegex, function (matchString, ...matchArr) {
46
35
  return parseMatchRepeat(matchArr[0], false);
47
36
  });
48
- return `/${result}`;
37
+ return `${result}`;
49
38
  })
50
- .join('');
39
+ .join('/');
51
40
  }
52
41
  exports.parseDynamicPath = parseDynamicPath;
53
42
  function parseMatchRepeat(param, optional) {
@@ -65,8 +54,13 @@ function checkSpecialRegexChars(string) {
65
54
  return /[|\\{}()^$+*?]/g.test(string);
66
55
  }
67
56
  function normalizeRoutePath(rawPath) {
57
+ let routePath = rawPath
58
+ // Remove the file extension from the end
59
+ .replace(/\.\w+$/, '')
60
+ // Convert to unix path
61
+ .replace(/\\/g, '/');
68
62
  // /xxxx/index -> /xxxx/
69
- let routePath = rawPath.replace(/\/index$/, '/');
63
+ routePath = rawPath.replace(/\/index$/, '/');
70
64
  // remove the last slash
71
65
  // e.g. /abc/ -> /abc
72
66
  if (routePath !== '/' && routePath.slice(-1) === '/') {
@@ -76,14 +70,26 @@ function normalizeRoutePath(rawPath) {
76
70
  return routePath;
77
71
  }
78
72
  exports.normalizeRoutePath = normalizeRoutePath;
79
- const normalize = (path) => {
80
- const result = normalizeRoutePath(normalizeFilePath(path));
81
- if (result === '/') {
82
- return result;
73
+ function combineComponents(fisrt, sec) {
74
+ if (fisrt === '' || sec === '') {
75
+ return `${fisrt}${sec}`;
83
76
  }
84
- return result.replace(/^\//, '');
85
- };
86
- exports.normalize = normalize;
77
+ if (fisrt.endsWith('/')) {
78
+ if (sec.startsWith('/')) {
79
+ return `${fisrt}${sec.slice(1)}`;
80
+ }
81
+ else {
82
+ return `${fisrt}${sec}`;
83
+ }
84
+ }
85
+ else if (sec.startsWith('/')) {
86
+ return `${fisrt}${sec}`;
87
+ }
88
+ else {
89
+ return `${fisrt}/${sec}`;
90
+ }
91
+ }
92
+ exports.combineComponents = combineComponents;
87
93
  const isRouteFile = (file) => {
88
94
  return Object.keys(fileTypeChecker).some(key => {
89
95
  return fileTypeChecker[key](file);
@@ -0,0 +1,8 @@
1
+ export interface FileMatcherPatterns {
2
+ excludePattern: string | undefined;
3
+ }
4
+ export declare function getRegularExpressionsForWildcards(specs: readonly string[] | undefined, basePath: string): readonly string[] | undefined;
5
+ export declare function getRegularExpressionForWildcard(specs: readonly string[] | undefined, basePath: string, usage: 'exclude'): string | undefined;
6
+ export declare function getRegexFromPattern(pattern: string, caseSensitive: boolean): RegExp;
7
+ export declare function getFileMatcherPatterns(basePath: string, excludes: readonly string[] | undefined): FileMatcherPatterns;
8
+ export declare function matchFile(file: string, patterns: FileMatcherPatterns, caseSensitive: boolean): boolean;
@@ -0,0 +1,138 @@
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
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.matchFile = exports.getFileMatcherPatterns = exports.getRegexFromPattern = exports.getRegularExpressionForWildcard = exports.getRegularExpressionsForWildcards = void 0;
27
+ // port from typescript
28
+ const nodePath = __importStar(require("path"));
29
+ const directorySeparator = '/';
30
+ // Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
31
+ // It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future
32
+ // proof.
33
+ const reservedCharacterPattern = /[^\w\s\/]/g;
34
+ const commonPackageFolders = ['node_modules'];
35
+ // does not match centeain directories or directories that start with a . character
36
+ const implicitExcludePathRegexPattern = `/((${commonPackageFolders.join('|')})|([/.][^/]*))`;
37
+ function replaceWildcardCharacter(match, singleAsteriskRegexFragment) {
38
+ return match === '*'
39
+ ? singleAsteriskRegexFragment
40
+ : match === '?'
41
+ ? '[^/]'
42
+ : '\\' + match;
43
+ }
44
+ const wildcardMatcher = {
45
+ singleAsteriskRegexFragment: '[^/]*',
46
+ doubleAsteriskRegexFragment: '(/.+?)?',
47
+ replaceWildcardCharacter: match => replaceWildcardCharacter(match, wildcardMatcher.singleAsteriskRegexFragment)
48
+ };
49
+ /**
50
+ * An "includes" path "foo" is implicitly a glob "foo/** /*" (without the space) if its last component has no extension,
51
+ * and does not contain any glob characters itself.
52
+ */
53
+ function isImplicitGlob(lastPathComponent) {
54
+ return !/[.*?]/.test(lastPathComponent);
55
+ }
56
+ function normalizePath(path, currentDirectory) {
57
+ return currentDirectory
58
+ ? nodePath.posix.resolve(currentDirectory, path)
59
+ : nodePath.posix.normalize(path);
60
+ }
61
+ function getNormalizedPathComponents(path, currentDirectory) {
62
+ const normalizedPath = normalizePath(path, currentDirectory);
63
+ const comps = normalizedPath.split('/');
64
+ if (comps.length && !comps[comps.length - 1])
65
+ comps.pop();
66
+ return comps;
67
+ }
68
+ function getSubPatternFromSpec(spec, basePath, { doubleAsteriskRegexFragment, replaceWildcardCharacter }) {
69
+ let subpattern = '';
70
+ let hasWrittenComponent = false;
71
+ const components = getNormalizedPathComponents(spec, basePath);
72
+ const lastComponent = components[components.length - 1];
73
+ // remove trailing slash
74
+ components[0] = components[0].replace(/[/]$/, '');
75
+ if (isImplicitGlob(lastComponent)) {
76
+ components.push('**', '*');
77
+ }
78
+ for (let component of components) {
79
+ if (component === '**') {
80
+ subpattern += doubleAsteriskRegexFragment;
81
+ }
82
+ else {
83
+ if (hasWrittenComponent) {
84
+ subpattern += directorySeparator;
85
+ }
86
+ subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
87
+ }
88
+ hasWrittenComponent = true;
89
+ }
90
+ return subpattern;
91
+ }
92
+ function getRegularExpressionsForWildcards(specs, basePath) {
93
+ if (specs === undefined || specs.length === 0) {
94
+ return undefined;
95
+ }
96
+ const result = [];
97
+ for (const spec of specs) {
98
+ if (spec) {
99
+ let r = getSubPatternFromSpec(spec, basePath, wildcardMatcher);
100
+ if (r) {
101
+ result.push(r);
102
+ }
103
+ }
104
+ }
105
+ return result;
106
+ }
107
+ exports.getRegularExpressionsForWildcards = getRegularExpressionsForWildcards;
108
+ function getRegularExpressionForWildcard(specs, basePath, usage) {
109
+ const patterns = getRegularExpressionsForWildcards(specs, basePath);
110
+ if (!patterns || !patterns.length) {
111
+ return undefined;
112
+ }
113
+ const pattern = patterns.map(pattern => `(${pattern})`).join('|');
114
+ // If excluding, match "foo/bar/baz...", but if including, only allow "foo".
115
+ const terminator = usage === 'exclude' ? '($|/)' : '$';
116
+ return `^(${pattern})${terminator}`;
117
+ }
118
+ exports.getRegularExpressionForWildcard = getRegularExpressionForWildcard;
119
+ function getRegexFromPattern(pattern, caseSensitive) {
120
+ return new RegExp(pattern, caseSensitive ? '' : 'i');
121
+ }
122
+ exports.getRegexFromPattern = getRegexFromPattern;
123
+ function getFileMatcherPatterns(basePath, excludes) {
124
+ const absolutePath = normalizePath(basePath);
125
+ return {
126
+ excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, 'exclude')
127
+ };
128
+ }
129
+ exports.getFileMatcherPatterns = getFileMatcherPatterns;
130
+ function matchFile(file, patterns, caseSensitive) {
131
+ file = normalizePath(file);
132
+ const excludeRegex = patterns.excludePattern &&
133
+ getRegexFromPattern(patterns.excludePattern, caseSensitive);
134
+ const implicitExcludeRegex = getRegexFromPattern(implicitExcludePathRegexPattern, caseSensitive);
135
+ return (!implicitExcludeRegex.test(file) &&
136
+ (!excludeRegex || !excludeRegex.test(file)));
137
+ }
138
+ exports.matchFile = matchFile;
@@ -1,22 +1,19 @@
1
- import { IUserRouteConfig, IApiRouteConfig, IMiddlewareRouteConfig } from '@shuvi/service';
1
+ import { IPageRouteConfig, IApiRouteConfig, IMiddlewareRouteConfig } from '../../shared';
2
2
  import { SupportFileType } from './helpers';
3
- export declare type IPageRouteConfig = IUserRouteConfig;
4
- export type { IApiRouteConfig, IMiddlewareRouteConfig };
3
+ export type { IPageRouteConfig, IApiRouteConfig, IMiddlewareRouteConfig };
5
4
  interface RawFileRoute {
6
5
  kind: 'file';
7
6
  type: SupportFileType;
8
- name: string;
9
- segment: string;
10
7
  filepath: string;
8
+ segment: string;
11
9
  }
12
- interface RawDirRoute {
10
+ export interface RawDirRoute {
13
11
  kind: 'dir';
14
12
  filepath: string;
15
13
  segment: string;
16
- parentSegment: string;
17
14
  children: (RawFileRoute | RawDirRoute)[];
18
15
  }
19
- declare type RawRoute = RawFileRoute | RawDirRoute;
16
+ export declare type RawRoute = RawFileRoute | RawDirRoute;
20
17
  export interface RouteException {
21
18
  type: SupportFileType | 'dir';
22
19
  msg: string;
@@ -31,7 +28,7 @@ export declare type PageRoutes = RouteResult<IPageRouteConfig>;
31
28
  export declare type ApiRoutes = RouteResult<IApiRouteConfig>;
32
29
  export declare type MiddlewareRoutes = RouteResult<IMiddlewareRouteConfig>;
33
30
  export declare type RouteConfigType = IPageRouteConfig | IApiRouteConfig | IMiddlewareRouteConfig;
34
- export declare const getRawRoutesFromDir: (dirname: string) => Promise<RawRoutes>;
35
- export declare const getPageRoutes: (dirname: string) => Promise<PageRoutes>;
36
- export declare const getApiRoutes: (dir: string) => Promise<ApiRoutes>;
37
- export declare const getMiddlewareRoutes: (dirname: string) => Promise<MiddlewareRoutes>;
31
+ export declare const getRawRoutesFromDir: (dirname: string, excludes?: string[]) => Promise<RawRoutes>;
32
+ export declare const getPageRoutes: (dirname: string, excludes?: string[]) => Promise<PageRoutes>;
33
+ export declare const getApiRoutes: (dir: string, excludes?: string[]) => Promise<ApiRoutes>;
34
+ export declare const getMiddlewareRoutes: (dirname: string, excludes?: string[]) => Promise<MiddlewareRoutes>;
@@ -13,8 +13,10 @@ exports.getMiddlewareRoutes = exports.getApiRoutes = exports.getPageRoutes = exp
13
13
  const path_1 = require("path");
14
14
  const file_1 = require("@shuvi/utils/lib/file");
15
15
  const helpers_1 = require("./helpers");
16
- const getRawRoutesFromDir = (dirname) => __awaiter(void 0, void 0, void 0, function* () {
17
- if (!(yield (0, file_1.isDirectory)(dirname))) {
16
+ const matchSpec_1 = require("./matchSpec");
17
+ const getRawRoutesFromDir = (dirname, excludes) => __awaiter(void 0, void 0, void 0, function* () {
18
+ const rootDirname = dirname;
19
+ if (!(yield (0, file_1.isDirectory)(rootDirname))) {
18
20
  return {
19
21
  routes: [],
20
22
  warnings: [],
@@ -23,7 +25,9 @@ const getRawRoutesFromDir = (dirname) => __awaiter(void 0, void 0, void 0, funct
23
25
  }
24
26
  const warnings = [];
25
27
  const errors = [];
26
- const _getRawRoutesFromDir = (dirname, rawRoutes, segment) => __awaiter(void 0, void 0, void 0, function* () {
28
+ const routes = [];
29
+ const patterns = (0, matchSpec_1.getFileMatcherPatterns)(rootDirname, excludes);
30
+ const visitDirectory = (dirname, routes, parentDir) => __awaiter(void 0, void 0, void 0, function* () {
27
31
  const files = yield (0, helpers_1.getAllowFilesAndDirs)(dirname);
28
32
  const onlyHasDir = !(0, helpers_1.hasAllowFiles)(files);
29
33
  if (!files.length) {
@@ -33,38 +37,46 @@ const getRawRoutesFromDir = (dirname) => __awaiter(void 0, void 0, void 0, funct
33
37
  });
34
38
  }
35
39
  for (const file of files) {
36
- const filepath = (0, path_1.join)(dirname, file);
40
+ let filepath = (0, path_1.join)(dirname, file);
37
41
  const isDir = yield (0, file_1.isDirectory)(filepath);
42
+ if (isDir) {
43
+ // transform '/foo' to '/foo/' if `foo` is a dir,
44
+ // this is required for matchFile to wrok properly
45
+ filepath = (0, path_1.join)(filepath, path_1.sep);
46
+ }
47
+ if (!(0, matchSpec_1.matchFile)(filepath, patterns, false)) {
48
+ continue;
49
+ }
50
+ const segment = parentDir === '' ? '/' : (0, helpers_1.normalizeRoutePath)(parentDir);
38
51
  if (isDir) {
39
52
  if (onlyHasDir) {
40
53
  // only indent segment,routes was in same level.
41
- yield _getRawRoutesFromDir(filepath, rawRoutes, `${segment}/${file}`);
42
- continue;
54
+ yield visitDirectory(filepath, routes, `${parentDir}/${file}`);
55
+ }
56
+ else {
57
+ const route = {
58
+ kind: 'dir',
59
+ filepath,
60
+ segment: segment,
61
+ children: []
62
+ };
63
+ routes.push(route);
64
+ yield visitDirectory(filepath, route.children, file);
43
65
  }
44
- const rawRoute = {
45
- kind: 'dir',
66
+ }
67
+ else {
68
+ const ext = (0, path_1.extname)(file);
69
+ const type = (0, path_1.basename)(file, ext);
70
+ routes.push({
71
+ kind: 'file',
72
+ segment: segment,
46
73
  filepath,
47
- segment: (0, helpers_1.normalize)(file).replace(/^\//, ''),
48
- parentSegment: (0, helpers_1.normalize)(segment).replace(/^\//, ''),
49
- children: []
50
- };
51
- yield _getRawRoutesFromDir(filepath, rawRoute.children, file);
52
- rawRoutes.push(rawRoute);
53
- continue;
74
+ type
75
+ });
54
76
  }
55
- const ext = (0, path_1.extname)(file);
56
- const type = (0, path_1.basename)(file, ext);
57
- rawRoutes.push({
58
- kind: 'file',
59
- name: file,
60
- segment: (0, helpers_1.normalize)(segment),
61
- filepath,
62
- type
63
- });
64
77
  }
65
- return rawRoutes;
66
78
  });
67
- const routes = yield _getRawRoutesFromDir(dirname, [], '');
79
+ yield visitDirectory(rootDirname, routes, '');
68
80
  return {
69
81
  routes,
70
82
  warnings,
@@ -72,9 +84,9 @@ const getRawRoutesFromDir = (dirname) => __awaiter(void 0, void 0, void 0, funct
72
84
  };
73
85
  });
74
86
  exports.getRawRoutesFromDir = getRawRoutesFromDir;
75
- const getPageRoutes = (dirname) => __awaiter(void 0, void 0, void 0, function* () {
76
- const { routes: rawRoutes, warnings, errors } = yield (0, exports.getRawRoutesFromDir)(dirname);
77
- const _getPageRoutes = (rawRoutes, routes, segment = '') => {
87
+ const getPageRoutes = (dirname, excludes) => __awaiter(void 0, void 0, void 0, function* () {
88
+ const { routes: rawRoutes, warnings, errors } = yield (0, exports.getRawRoutesFromDir)(dirname, excludes);
89
+ const _getPageRoutes = (rawRoutes, routes, parentSegment = '') => {
78
90
  const layoutRoute = rawRoutes.some(route => route.kind === 'file' && route.type === 'layout');
79
91
  const route = {};
80
92
  if (layoutRoute) {
@@ -83,10 +95,10 @@ const getPageRoutes = (dirname) => __awaiter(void 0, void 0, void 0, function* (
83
95
  for (const rawRoute of rawRoutes) {
84
96
  if (rawRoute.kind === 'dir') {
85
97
  const workRoutes = layoutRoute ? route.children : routes;
86
- const preSegment = layoutRoute
98
+ const nextSegment = layoutRoute
87
99
  ? ''
88
- : `${segment}${rawRoute.parentSegment}/`;
89
- _getPageRoutes(rawRoute.children, workRoutes, preSegment);
100
+ : (0, helpers_1.combineComponents)(parentSegment, rawRoute.segment);
101
+ _getPageRoutes(rawRoute.children, workRoutes, nextSegment);
90
102
  }
91
103
  else if (rawRoute.type === 'page' || rawRoute.type === 'layout') {
92
104
  if (rawRoute.type === 'page' && layoutRoute) {
@@ -96,10 +108,8 @@ const getPageRoutes = (dirname) => __awaiter(void 0, void 0, void 0, function* (
96
108
  });
97
109
  }
98
110
  else {
99
- let prefix = segment;
100
- let suffix = rawRoute.segment;
101
111
  route.component = rawRoute.filepath;
102
- route.path = `${prefix}${suffix}`;
112
+ route.path = (0, helpers_1.combineComponents)(parentSegment, rawRoute.segment);
103
113
  routes.push(Object.assign({}, route));
104
114
  }
105
115
  }
@@ -107,11 +117,6 @@ const getPageRoutes = (dirname) => __awaiter(void 0, void 0, void 0, function* (
107
117
  return routes;
108
118
  };
109
119
  const routes = (0, helpers_1.sortRoutes)(_getPageRoutes(rawRoutes, []));
110
- routes.forEach(route => {
111
- if (!route.path.startsWith('/')) {
112
- route.path = `/${route.path}`;
113
- }
114
- });
115
120
  return {
116
121
  routes,
117
122
  warnings,
@@ -119,44 +124,39 @@ const getPageRoutes = (dirname) => __awaiter(void 0, void 0, void 0, function* (
119
124
  };
120
125
  });
121
126
  exports.getPageRoutes = getPageRoutes;
122
- const getApiRoutes = (dir) => __awaiter(void 0, void 0, void 0, function* () {
127
+ const getApiRoutes = (dir, excludes) => __awaiter(void 0, void 0, void 0, function* () {
123
128
  const getConflictWaring = (rawRoute, conflictRawRoute) => {
124
129
  return `Find both ${(0, path_1.basename)(conflictRawRoute.filepath)} and ${(0, path_1.basename)(rawRoute.filepath)} in "${(0, path_1.dirname)(rawRoute.filepath)}"!, only "${(0, path_1.basename)(conflictRawRoute.filepath)}" is used.`;
125
130
  };
126
- const { routes: rawRoutes, warnings, errors } = yield (0, exports.getRawRoutesFromDir)(dir);
127
- const _getApiRoutes = (rawRoutes, routes, prefix = '') => {
131
+ const { routes: rawRoutes, warnings, errors } = yield (0, exports.getRawRoutesFromDir)(dir, excludes);
132
+ const _getApiRoutes = (rawRoutes, routes, parentSegment = '') => {
128
133
  const page = rawRoutes.find(route => route.kind === 'file' && route.type === 'page');
129
134
  const layout = rawRoutes.find(route => route.kind === 'file' && route.type === 'layout');
130
135
  const allowedRoutes = rawRoutes.filter(route => route.kind === 'dir' || route.type === 'api');
131
136
  for (let rawRoute of allowedRoutes) {
132
- prefix = prefix === '/' ? '' : prefix;
137
+ const currentPath = (0, helpers_1.combineComponents)(parentSegment, rawRoute.segment);
133
138
  if (rawRoute.kind === 'dir') {
134
- _getApiRoutes(rawRoute.children, routes, prefix + '/' + rawRoute.parentSegment);
135
- continue;
139
+ _getApiRoutes(rawRoute.children, routes, currentPath);
136
140
  }
137
- if (rawRoute.type === 'api') {
141
+ else if (rawRoute.type === 'api') {
138
142
  if (layout) {
139
143
  warnings.push({
140
144
  type: 'api',
141
145
  msg: getConflictWaring(rawRoute, layout)
142
146
  });
143
- continue;
144
147
  }
145
- if (page) {
148
+ else if (page) {
146
149
  warnings.push({
147
150
  type: 'api',
148
151
  msg: getConflictWaring(rawRoute, page)
149
152
  });
150
- continue;
151
153
  }
152
- let path = prefix + '/' + rawRoute.segment;
153
- if (path === '//') {
154
- path = '/';
154
+ else {
155
+ routes.push({
156
+ path: currentPath,
157
+ api: rawRoute.filepath
158
+ });
155
159
  }
156
- routes.push({
157
- path,
158
- api: rawRoute.filepath
159
- });
160
160
  }
161
161
  }
162
162
  return routes;
@@ -170,26 +170,20 @@ const getApiRoutes = (dir) => __awaiter(void 0, void 0, void 0, function* () {
170
170
  };
171
171
  });
172
172
  exports.getApiRoutes = getApiRoutes;
173
- const getMiddlewareRoutes = (dirname) => __awaiter(void 0, void 0, void 0, function* () {
174
- const { routes: rawRoutes, warnings, errors } = yield (0, exports.getRawRoutesFromDir)(dirname);
175
- const _getMiddlewareRoutes = (rawRoutes, routes, segment) => {
176
- segment = segment === '/' ? '' : segment;
173
+ const getMiddlewareRoutes = (dirname, excludes) => __awaiter(void 0, void 0, void 0, function* () {
174
+ const { routes: rawRoutes, warnings, errors } = yield (0, exports.getRawRoutesFromDir)(dirname, excludes);
175
+ const _getMiddlewareRoutes = (rawRoutes, routes, parentSegment) => {
177
176
  for (const rawRoute of rawRoutes) {
177
+ const currentPath = (0, helpers_1.combineComponents)(parentSegment, rawRoute.segment);
178
178
  if (rawRoute.kind === 'dir') {
179
- _getMiddlewareRoutes(rawRoute.children, routes, segment + '/' + rawRoute.parentSegment);
180
- continue;
179
+ _getMiddlewareRoutes(rawRoute.children, routes, currentPath);
181
180
  }
182
- if (rawRoute.type === 'middleware') {
183
- let path = segment + '/' + rawRoute.segment;
184
- let catchAllOp = '/*';
185
- if (path === '//') {
186
- path = '/';
187
- }
188
- if (path === '/') {
189
- catchAllOp = catchAllOp.slice(1);
190
- }
181
+ else if (rawRoute.type === 'middleware') {
191
182
  routes.push({
192
- path: path + catchAllOp,
183
+ // catch all
184
+ path: currentPath.endsWith('/')
185
+ ? `${currentPath}*`
186
+ : `${currentPath}/*`,
193
187
  middleware: rawRoute.filepath
194
188
  });
195
189
  }
@@ -197,11 +191,6 @@ const getMiddlewareRoutes = (dirname) => __awaiter(void 0, void 0, void 0, funct
197
191
  return routes;
198
192
  };
199
193
  const routes = (0, helpers_1.sortRoutes)(_getMiddlewareRoutes(rawRoutes, [], ''));
200
- routes.forEach(route => {
201
- if (!route.path.startsWith('/')) {
202
- route.path = `/${route.path}`;
203
- }
204
- });
205
194
  const exceptionFilter = (e) => e.type === 'middleware';
206
195
  return {
207
196
  routes,
@@ -6,4 +6,5 @@ export * from './loader';
6
6
  export { errorModel } from './models/error';
7
7
  export * from './applicationTypes';
8
8
  export type { Application } from './application';
9
+ export type { IRuntimeConfig } from './runtimeConfigTypes';
9
10
  export { IAppModule, IPluginInstance, BuiltInRuntimePluginHooks, CustomRuntimePluginHooks, RuntimePluginHooks, createRuntimePlugin, RuntimePluginInstance } from './lifecycle';
@@ -4,21 +4,16 @@ export declare type IURLQuery = ParsedQuery;
4
4
  export declare type IURLParams = IParams;
5
5
  export interface IPageRouteRecord extends IRouteRecord {
6
6
  id: string;
7
+ path: string;
7
8
  component?: any;
8
9
  children?: IPageRouteRecord[];
9
- path: string;
10
- fullPath?: string;
11
- __componentSource__?: never;
12
- __componentSourceWithAffix__?: string;
13
- __import__?: never;
14
- __resolveWeak__?: () => any;
15
10
  [x: string]: any;
16
11
  }
17
12
  export interface IRawPageRouteRecord extends IRouteRecord {
18
13
  id: string;
14
+ path: string;
19
15
  component?: any;
20
16
  children?: IRawPageRouteRecord[];
21
- path: string;
22
17
  fullPath: string;
23
18
  __componentSource__: string;
24
19
  __componentSourceWithAffix__: string;
@@ -26,3 +21,30 @@ export interface IRawPageRouteRecord extends IRouteRecord {
26
21
  __resolveWeak__: () => any;
27
22
  [x: string]: any;
28
23
  }
24
+ export interface IPlatformConfig {
25
+ name: string;
26
+ framework?: string;
27
+ target?: string;
28
+ [index: string]: any;
29
+ }
30
+ export declare type IRouterHistoryMode = 'browser' | 'hash' | 'memory';
31
+ export interface IPageRouteConfig {
32
+ children?: IPageRouteConfig[];
33
+ name?: string;
34
+ component?: string;
35
+ redirect?: string;
36
+ path: string;
37
+ fullPath?: string;
38
+ }
39
+ export interface IPageRouteConfigWithId extends IPageRouteConfig {
40
+ id: string;
41
+ children?: IPageRouteConfigWithId[];
42
+ }
43
+ export interface IMiddlewareRouteConfig {
44
+ path: string;
45
+ middleware: string;
46
+ }
47
+ export interface IApiRouteConfig {
48
+ path: string;
49
+ api: string;
50
+ }
@@ -0,0 +1 @@
1
+ export declare type IRuntimeConfig = Record<string, string>;
@@ -1,4 +1,4 @@
1
- import { IRuntimeConfig } from '@shuvi/service/lib/core';
1
+ import { IRuntimeConfig } from './runtimeConfigTypes';
2
2
  /**
3
3
  * getRuntimeConfig function
4
4
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuvi/platform-shared",
3
- "version": "1.0.0-rc.0",
3
+ "version": "1.0.0-rc.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/shuvijs/shuvi.git",
@@ -12,9 +12,9 @@
12
12
  "files": [
13
13
  "lib",
14
14
  "esm",
15
- "types",
16
15
  "template",
17
- "shuvi-app-extensions.d.ts"
16
+ "shuvi-type-extensions-node.d.js",
17
+ "shuvi-type-extensions-runtime.d.ts"
18
18
  ],
19
19
  "exports": {
20
20
  "./shared": {
@@ -62,21 +62,11 @@
62
62
  "default": "./esm/shuvi-app/*.js"
63
63
  },
64
64
  "./template/*": "./template/*",
65
- "./shuvi-app-extensions.d.ts": "./shuvi-app-extensions.d.ts"
66
- },
67
- "engines": {
68
- "node": ">= 12.0.0"
69
- },
70
- "dependencies": {
71
- "redux": "4.1.2",
72
- "@shuvi/redox": "0.0.3",
73
- "@shuvi/hook": "1.0.0-rc.0",
74
- "@shuvi/service": "1.0.0-rc.0",
75
- "@shuvi/toolpack": "1.0.0-rc.0",
76
- "@shuvi/router": "1.0.0-rc.0",
77
- "@shuvi/runtime": "1.0.0-rc.0",
78
- "@shuvi/shared": "1.0.0-rc.0",
79
- "@shuvi/utils": "1.0.0-rc.0"
65
+ "./shuvi-type-extensions-node": {
66
+ "types": "./shuvi-type-extensions-node.d.js",
67
+ "default": "./shuvi-type-extensions-node.js"
68
+ },
69
+ "./shuvi-type-extensions-runtime": "./shuvi-type-extensions-runtime.d.ts"
80
70
  },
81
71
  "scripts": {
82
72
  "dev": "run-p watch:*",
@@ -86,5 +76,25 @@
86
76
  "build": "run-p build:*",
87
77
  "build:esm": "tsc -p tsconfig.build.browser.json",
88
78
  "build:cjs": "tsc -p tsconfig.build.node.json"
79
+ },
80
+ "engines": {
81
+ "node": ">= 12.0.0"
82
+ },
83
+ "dependencies": {
84
+ "@shuvi/hook": "1.0.0-rc.3",
85
+ "@shuvi/redox": "0.0.3",
86
+ "@shuvi/router": "1.0.0-rc.3",
87
+ "@shuvi/runtime": "1.0.0-rc.3",
88
+ "@shuvi/service": "1.0.0-rc.3",
89
+ "@shuvi/shared": "1.0.0-rc.3",
90
+ "@shuvi/toolpack": "1.0.0-rc.3",
91
+ "@shuvi/utils": "1.0.0-rc.3",
92
+ "redux": "4.1.2"
93
+ },
94
+ "peerDependencies": {
95
+ "@shuvi/service": "1.0.0-rc.3"
96
+ },
97
+ "devDependencies": {
98
+ "@types/minimatch": "3.0.5"
89
99
  }
90
- }
100
+ }
@@ -1,8 +0,0 @@
1
- import { extendedHooks } from './hooks';
2
- declare module '@shuvi/runtime' {
3
- interface CustomCorePluginHooks {
4
- addEntryCode: typeof extendedHooks.addEntryCode;
5
- addPolyfill: typeof extendedHooks.addPolyfill;
6
- modifyRuntimeConfig: typeof extendedHooks.modifyRuntimeConfig;
7
- }
8
- }