@@ -19,7 +19,7 @@ import strings from '../../../resources';
1919import * as urlBuilder from '../../domain/url-builder' ;
2020import * as validator from '../../domain/validators' ;
2121import type { Repository } from '../../domain/repository' ;
22- import { Config } from '../../../types' ;
22+ import { Component , Config } from '../../../types' ;
2323import { IncomingHttpHeaders } from 'http' ;
2424import { fromPromise } from 'universalify' ;
2525
@@ -61,6 +61,22 @@ export default function getComponent(conf: Config, repository: Repository) {
6161 refreshInterval : conf . refreshInterval
6262 } ) ;
6363
64+ const getEnv = async (
65+ component : Component
66+ ) : Promise < Record < string , string > > => {
67+ const cacheKey = `${ component . name } /${ component . version } /.env` ;
68+ const cached = cache . get ( 'file-contents' , cacheKey ) ;
69+
70+ if ( cached ) return cached ;
71+
72+ const env = component . oc . files . env
73+ ? await repository . getEnv ( component . name , component . version )
74+ : { } ;
75+ cache . set ( 'file-contents' , cacheKey , env ) ;
76+
77+ return env ;
78+ } ;
79+
6480 const renderer = function (
6581 options : RendererOptions ,
6682 cb : ( result : GetComponentResult ) => void
@@ -411,136 +427,152 @@ export default function getComponent(conf: Config, repository: Repository) {
411427 if ( ! component . oc . files . dataProvider ) {
412428 returnComponent ( null , { } ) ;
413429 } else {
414- const cacheKey = `${ component . name } /${ component . version } /server.js` ;
415- const cached = cache . get ( 'file-contents' , cacheKey ) ;
416- const domain = Domain . create ( ) ;
417- const setEmptyResponse =
418- emptyResponseHandler . contextDecorator ( returnComponent ) ;
419- const contextObj = {
420- acceptLanguage : acceptLanguageParser . parse ( acceptLanguage ! ) ,
421- baseUrl : conf . baseUrl ,
422- env : conf . env ,
423- params,
424- plugins : conf . plugins ,
425- renderComponent : fromPromise ( nestedRenderer . renderComponent ) ,
426- renderComponents : fromPromise ( nestedRenderer . renderComponents ) ,
427- requestHeaders : options . headers ,
428- requestIp : options . ip ,
429- setEmptyResponse,
430- staticPath : repository
431- . getStaticFilePath ( component . name , component . version , '' )
432- . replace ( 'https:' , '' ) ,
433- setHeader : ( header ?: string , value ?: string ) => {
434- if ( ! ( typeof header === 'string' && typeof value === 'string' ) ) {
435- throw strings . errors . registry
436- . COMPONENT_SET_HEADER_PARAMETERS_NOT_VALID ;
437- }
438-
439- if ( header && value ) {
440- responseHeaders = responseHeaders || { } ;
441- responseHeaders [ header . toLowerCase ( ) ] = value ;
442- }
443- } ,
444- templates : repository . getTemplatesInfo ( )
445- } ;
446-
447- const setCallbackTimeout = ( ) => {
448- const executionTimeout = conf . executionTimeout ;
449- if ( executionTimeout ) {
450- setTimeout ( ( ) => {
451- const message = `timeout (${ executionTimeout * 1000 } ms)` ;
452- returnComponent ( { message } , undefined ) ;
453- domain . exit ( ) ;
454- } , executionTimeout * 1000 ) ;
430+ fromPromise ( getEnv ) ( component , ( err , env ) => {
431+ if ( err ) {
432+ componentCallbackDone = true ;
433+
434+ return callback ( {
435+ status : 502 ,
436+ response : {
437+ code : 'ENV_RESOLVING_ERROR' ,
438+ error : strings . errors . registry . RESOLVING_ERROR
439+ }
440+ } ) ;
455441 }
456- } ;
457442
458- if ( ! ! cached && ! conf . hotReloading ) {
459- domain . on ( 'error' , returnComponent ) ;
443+ const cacheKey = `${ component . name } /${ component . version } /server.js` ;
444+ const cached = cache . get ( 'file-contents' , cacheKey ) ;
445+ const domain = Domain . create ( ) ;
446+ const setEmptyResponse =
447+ emptyResponseHandler . contextDecorator ( returnComponent ) ;
448+ const contextObj = {
449+ acceptLanguage : acceptLanguageParser . parse ( acceptLanguage ! ) ,
450+ baseUrl : conf . baseUrl ,
451+ env : { ...conf . env , ...env } ,
452+ params,
453+ plugins : conf . plugins ,
454+ renderComponent : fromPromise ( nestedRenderer . renderComponent ) ,
455+ renderComponents : fromPromise ( nestedRenderer . renderComponents ) ,
456+ requestHeaders : options . headers ,
457+ requestIp : options . ip ,
458+ setEmptyResponse,
459+ staticPath : repository
460+ . getStaticFilePath ( component . name , component . version , '' )
461+ . replace ( 'https:' , '' ) ,
462+ setHeader : ( header ?: string , value ?: string ) => {
463+ if (
464+ ! ( typeof header === 'string' && typeof value === 'string' )
465+ ) {
466+ throw strings . errors . registry
467+ . COMPONENT_SET_HEADER_PARAMETERS_NOT_VALID ;
468+ }
460469
461- try {
462- domain . run ( ( ) => {
463- cached ( contextObj , returnComponent ) ;
464- setCallbackTimeout ( ) ;
465- } ) ;
466- } catch ( e ) {
467- return returnComponent ( e , undefined ) ;
468- }
469- } else {
470- fromPromise ( repository . getDataProvider ) (
471- component . name ,
472- component . version ,
473- ( err , dataProvider ) => {
474- if ( err ) {
475- componentCallbackDone = true ;
476-
477- return callback ( {
478- status : 502 ,
479- response : {
480- code : 'DATA_RESOLVING_ERROR' ,
481- error : strings . errors . registry . RESOLVING_ERROR
482- }
483- } ) ;
470+ if ( header && value ) {
471+ responseHeaders = responseHeaders || { } ;
472+ responseHeaders [ header . toLowerCase ( ) ] = value ;
484473 }
474+ } ,
475+ templates : repository . getTemplatesInfo ( )
476+ } ;
485477
486- const context = {
487- require : RequireWrapper ( conf . dependencies ) ,
488- module : {
489- exports : { } as Record <
490- string ,
491- ( ...args : unknown [ ] ) => unknown
492- >
493- } ,
494- console : conf . local ? console : { log : _ . noop } ,
495- setTimeout,
496- Buffer
497- } ;
498-
499- const handleError = ( err : {
500- code : string ;
501- missing : string [ ] ;
502- } ) => {
503- if ( err . code === 'DEPENDENCY_MISSING_FROM_REGISTRY' ) {
478+ const setCallbackTimeout = ( ) => {
479+ const executionTimeout = conf . executionTimeout ;
480+ if ( executionTimeout ) {
481+ setTimeout ( ( ) => {
482+ const message = `timeout (${ executionTimeout * 1000 } ms)` ;
483+ returnComponent ( { message } , undefined ) ;
484+ domain . exit ( ) ;
485+ } , executionTimeout * 1000 ) ;
486+ }
487+ } ;
488+
489+ if ( ! ! cached && ! conf . hotReloading ) {
490+ domain . on ( 'error' , returnComponent ) ;
491+
492+ try {
493+ domain . run ( ( ) => {
494+ cached ( contextObj , returnComponent ) ;
495+ setCallbackTimeout ( ) ;
496+ } ) ;
497+ } catch ( e ) {
498+ return returnComponent ( e , undefined ) ;
499+ }
500+ } else {
501+ fromPromise ( repository . getDataProvider ) (
502+ component . name ,
503+ component . version ,
504+ ( err , dataProvider ) => {
505+ if ( err ) {
504506 componentCallbackDone = true ;
505507
506508 return callback ( {
507- status : 501 ,
509+ status : 502 ,
508510 response : {
509- code : err . code ,
510- error : strings . errors . registry . DEPENDENCY_NOT_FOUND (
511- err . missing . join ( ', ' )
512- ) ,
513- missingDependencies : err . missing
511+ code : 'DATA_RESOLVING_ERROR' ,
512+ error : strings . errors . registry . RESOLVING_ERROR
514513 }
515514 } ) ;
516515 }
517516
518- returnComponent ( err , undefined ) ;
519- } ;
520-
521- const options = conf . local
522- ? {
523- displayErrors : true ,
524- filename : dataProvider . filePath
517+ const context = {
518+ require : RequireWrapper ( conf . dependencies ) ,
519+ module : {
520+ exports : { } as Record <
521+ string ,
522+ ( ...args : unknown [ ] ) => unknown
523+ >
524+ } ,
525+ console : conf . local ? console : { log : _ . noop } ,
526+ setTimeout,
527+ Buffer
528+ } ;
529+
530+ const handleError = ( err : {
531+ code : string ;
532+ missing : string [ ] ;
533+ } ) => {
534+ if ( err . code === 'DEPENDENCY_MISSING_FROM_REGISTRY' ) {
535+ componentCallbackDone = true ;
536+
537+ return callback ( {
538+ status : 501 ,
539+ response : {
540+ code : err . code ,
541+ error : strings . errors . registry . DEPENDENCY_NOT_FOUND (
542+ err . missing . join ( ', ' )
543+ ) ,
544+ missingDependencies : err . missing
545+ }
546+ } ) ;
525547 }
526- : { } ;
527548
528- try {
529- vm . runInNewContext ( dataProvider . content , context , options ) ;
530- const processData = context . module . exports [ 'data' ] ;
531- cache . set ( 'file-contents' , cacheKey , processData ) ;
549+ returnComponent ( err , undefined ) ;
550+ } ;
532551
533- domain . on ( 'error' , handleError ) ;
534- domain . run ( ( ) => {
535- processData ( contextObj , returnComponent ) ;
536- setCallbackTimeout ( ) ;
537- } ) ;
538- } catch ( err ) {
539- handleError ( err as any ) ;
552+ const options = conf . local
553+ ? {
554+ displayErrors : true ,
555+ filename : dataProvider . filePath
556+ }
557+ : { } ;
558+
559+ try {
560+ vm . runInNewContext ( dataProvider . content , context , options ) ;
561+ const processData = context . module . exports [ 'data' ] ;
562+ cache . set ( 'file-contents' , cacheKey , processData ) ;
563+
564+ domain . on ( 'error' , handleError ) ;
565+ domain . run ( ( ) => {
566+ processData ( contextObj , returnComponent ) ;
567+ setCallbackTimeout ( ) ;
568+ } ) ;
569+ } catch ( err ) {
570+ handleError ( err as any ) ;
571+ }
540572 }
541- }
542- ) ;
543- }
573+ ) ;
574+ }
575+ } ) ;
544576 }
545577 }
546578 ) ;
0 commit comments