From c02c096ad2ca8ccea1a25638cf07158d2c15f231 Mon Sep 17 00:00:00 2001 From: Dmitrii Filippov Date: Wed, 29 Jul 2020 13:16:12 +0200 Subject: [PATCH] Convert app-context-init to typescript and fix server.go Typescript doesn't add .js extension to the imported file name. As a result, the browser imports the same file twice with different names: for example app-context and app-context.js. After the fix, server.go patches the typescript output and adds .js extension. Rollup handles such cases correctly. Change-Id: I3290f9244bb6d6dd8547fbceed8ed57186c6f638 --- .../app/services/app-context-init.ts | 62 ++++++++++++------- polygerrit-ui/server.go | 17 ++--- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/polygerrit-ui/app/services/app-context-init.ts b/polygerrit-ui/app/services/app-context-init.ts index b54e35db73..b249d160d0 100644 --- a/polygerrit-ui/app/services/app-context-init.ts +++ b/polygerrit-ui/app/services/app-context-init.ts @@ -14,17 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {appContext} from './app-context.js'; -import {FlagsServiceImplementation} from './flags/flags_impl.js'; -import {GrReporting} from './gr-reporting/gr-reporting_impl.js'; -import {EventEmitter} from './gr-event-interface/gr-event-interface_impl.js'; -import {Auth} from './gr-auth/gr-auth_impl.js'; +import {appContext, AppContext} from './app-context'; +import {FlagsServiceImplementation} from './flags/flags_impl'; +import {GrReporting} from './gr-reporting/gr-reporting_impl'; +import {EventEmitter} from './gr-event-interface/gr-event-interface_impl'; +import {Auth} from './gr-auth/gr-auth_impl'; -const initializedServices = new Map(); +type ServiceName = keyof AppContext; +type ServiceCreator = () => T; -function getService(serviceName, serviceInit) { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const initializedServices: Map = new Map(); + +function getService( + serviceName: K, + serviceCreator: ServiceCreator +): AppContext[K] { if (!initializedServices.has(serviceName)) { - initializedServices.set(serviceName, serviceInit()); + initializedServices.set(serviceName, serviceCreator()); } return initializedServices.get(serviceName); } @@ -33,23 +40,30 @@ function getService(serviceName, serviceInit) { * The AppContext lazy initializator for all services */ export function initAppContext() { - const registeredServices = {}; - function addService(serviceName, serviceCreator) { - if (registeredServices[serviceName]) { - throw new Error(`Service ${serviceName} already registered.`); - } - registeredServices[serviceName] = { - configurable: true, // Tests can mock properties - get() { - return getService(serviceName, serviceCreator); + function populateAppContext( + serviceCreators: {[P in ServiceName]: ServiceCreator} + ) { + const registeredServices = Object.keys(serviceCreators).reduce( + (registeredServices, key) => { + const serviceName = key as ServiceName; + const serviceCreator = serviceCreators[serviceName]; + registeredServices[serviceName] = { + configurable: true, // Tests can mock properties + get() { + return getService(serviceName, serviceCreator); + }, + }; + return registeredServices; }, - }; + {} as PropertyDescriptorMap + ); + Object.defineProperties(appContext, registeredServices); } - addService('flagsService', () => new FlagsServiceImplementation()); - addService('reportingService', - () => new GrReporting(appContext.flagsService)); - addService('eventEmitter', () => new EventEmitter()); - addService('authService', () => new Auth(appContext.eventEmitter)); - Object.defineProperties(appContext, registeredServices); + populateAppContext({ + flagsService: () => new FlagsServiceImplementation(), + reportingService: () => new GrReporting(appContext.flagsService), + eventEmitter: () => new EventEmitter(), + authService: () => new Auth(appContext.eventEmitter), + }); } diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go index d03dadae80..5c9b30050d 100644 --- a/polygerrit-ui/server.go +++ b/polygerrit-ui/server.go @@ -168,17 +168,20 @@ func handleSrcRequest(compiledSrcPath string, dirListingMux *http.ServeMux, writ writer.Header().Set("Content-Type", "text/html") } else if isJsFile { // The following code updates import statements. - // 1. Keep all imports started with '.' character unchanged (i.e. all relative - // imports like import ... from './a.js' or import ... from '../b/c/d.js' - // 2. For other imports it adds '/node_modules/' prefix. Additionally, - // if an in imported file has .js or .mjs extension, the code keeps - // the file extension unchanged. Otherwise, it adds .js extension. + // 1. if an in imported file has .js or .mjs extension, the code keeps + // the file extension unchanged. Otherwise, it adds .js extension + // 2. For module imports it adds '/node_modules/' prefix. // Examples: // '@polymer/polymer.js' -> '/node_modules/@polymer/polymer.js' // 'page/page.mjs' -> '/node_modules/page.mjs' // '@polymer/iron-icon' -> '/node_modules/@polymer/iron-icon.js' - moduleImportRegexp := regexp.MustCompile("(?m)^(import.*)'([^/.].*?)(\\.(m?)js)?';$") - data = moduleImportRegexp.ReplaceAll(data, []byte("$1 '/node_modules/$2.${4}js';")) + // './element/file' -> './element/file.js' + moduleImportRegexp := regexp.MustCompile("(?m)^(import.*)'(.*?)(\\.(m?)js)?';$") + data = moduleImportRegexp.ReplaceAll(data, []byte("$1 '$2.${4}js';")) + + moduleImportRegexp = regexp.MustCompile("(?m)^(import.*)'([^/.].*)';$") + data = moduleImportRegexp.ReplaceAll(data, []byte("$1 '/node_modules/$2';")) + writer.Header().Set("Content-Type", "application/javascript") } else if strings.HasSuffix(normalizedContentPath, ".css") { writer.Header().Set("Content-Type", "text/css")