Compare commits

...

28 Commits

Author SHA1 Message Date
Miroslav Bajtoš b668116fab
2.26.2
* Ignore js sourcemap files from boot (Zak Barbuto)
2017-09-15 10:43:45 +02:00
Miroslav Bajtoš 35e668318b Merge pull request #263 from NextFaze/fix/ignore-maps
Ignore js sourcemap files from boot
2017-09-15 10:43:03 +02:00
Zak Barbuto 3d3609defe Ignore js sourcemap files from boot 2017-09-15 09:46:20 +09:30
Miroslav Bajtoš cdab45d40e
2.26.1
* Do not call callbacks twice in async boot scripts (Jürg Lehni)
2017-08-17 09:58:23 +02:00
Miroslav Bajtoš ded190ee8a Merge pull request #260 from lehni/feature/async-boot-scripts-2.x
Do not call callbacks twice in async boot scripts
2017-08-17 09:57:42 +02:00
Jürg Lehni c9a1e0cc69 Do not call callbacks twice in async boot scripts
See #252 for details
2017-08-16 20:32:06 +02:00
Miroslav Bajtoš fa656e4bee
2.26.0
* Add support for ES6 style async boot scripts (Jürg Lehni)
 * Update Italian translated strings Q2 2017 (Allen Boone)
 * Update translated strings Q2 2017 (Allen Boone)
2017-07-31 17:34:06 +02:00
Miroslav Bajtoš 7f34b0dff6 Merge pull request #252 from lehni/feature/async-boot-scripts-2.x
Add support for ES6 style async boot scripts
2017-07-31 17:33:34 +02:00
Jürg Lehni 51326091b2
Add support for ES6 style async boot scripts 2017-07-31 16:11:22 +02:00
Diana Lau 39b885f9fb Merge pull request #251 from strongloop/update-translations-2.x-backport
Update translations 2.x backport
2017-06-26 09:09:35 -04:00
Miroslav Bajtoš 6db7cadc9b
2.25.0
* Support es2015 module exports (Babel, TypeScript) (John McLaughlin)
2017-06-26 15:04:00 +02:00
Miroslav Bajtoš 06855c1fcd Merge pull request #250 from zamb3zi/2.x
Support for Typescript/Babel emitted ES2015 modules
2017-06-26 15:03:22 +02:00
John McLaughlin 2b596c8c8b
Support es2015 module exports (Babel, TypeScript)
Detect when a script file is an es2015 module created by
a transpiler like Babel or TypeScript and use the `default`
export instead of `module.exports` in such case.

The following artefacts support the new syntax now:

  - boot scripts
  - components
  - middleware
  - model scripts
2017-06-26 14:35:43 +02:00
Allen Boone 4f91a4f78e Update Italian translated strings Q2 2017 2017-06-23 16:16:16 -04:00
Allen Boone b607f969b8 Update translated strings Q2 2017 2017-06-22 10:23:58 -04:00
Miroslav Bajtoš e5224368d4
2.24.1
* add support for absolute middleware paths on win32 (Benjamin Kroeger)
2017-06-07 14:08:51 +02:00
Miroslav Bajtoš b076286235 Merge pull request #233 from benkroeger/2.x
adds support for absolute middleware paths on win32
2017-06-07 14:07:52 +02:00
Miroslav Bajtoš 7f14a24ed2
2.24.0
* Provide options.scriptExtensions (Supasate Choochaisri)
 * Fix browser tests on Node.js 0.10 (Miroslav Bajtoš)
2017-04-03 15:14:51 +02:00
Miroslav Bajtoš 440a75d6f5 Merge pull request #242 from supasate/2.x
Provide options.scriptExtensions for 2.x
2017-04-03 15:13:49 +02:00
Supasate Choochaisri 95e5201255 Provide options.scriptExtensions 2017-04-01 02:10:31 +07:00
Miroslav Bajtoš cda21ea481 Merge pull request #244 from strongloop/fix/node-0.10-ci
Fix browser tests on Node.js 0.10
2017-03-24 12:22:09 +01:00
Miroslav Bajtoš 67c4f1e1a3
Fix browser tests on Node.js 0.10 2017-03-24 12:04:25 +01:00
Benjamin Kroeger 49016b4e66 add support for absolute middleware paths on win32
uses simple regex check to test if a path matches NTFS notation
2016-11-29 11:03:09 +01:00
Miroslav Bajtoš 9cb3d0648b 2.23.0
* Fix resolution of middleware modules (Miroslav Bajtoš)
 * Normalize line endings to support both LF and CRLF (Miroslav Bajtoš)
2016-10-13 10:15:17 +02:00
David Cheung d9e744a6a7 Merge pull request #222 from strongloop/fix/middleware-outside-node-modules-2x
Fix resolution of middleware modules [2.x]
2016-10-12 14:20:47 -04:00
Miroslav Bajtoš d2d9e8789e Fix resolution of middleware modules
Fix the code loading "loopback#errorhandler" (for example) to correctly
look up the "loopback" module in node_modules of the bootstrapped
application, instead of looking it up in node_modules of loopback-boot.
2016-10-12 14:38:37 +02:00
Miroslav Bajtoš eeea74e0f7 Merge pull request #217 from strongloop/fix-ci-windows
Normalize line endings to support both LF and CRLF [2.x]
2016-09-23 15:55:29 +02:00
Miroslav Bajtoš efea20feb5 Normalize line endings to support both LF and CRLF
This should fix build failures on Windows caused by line-ending
mismatch.
2016-09-23 12:42:56 +02:00
36 changed files with 678 additions and 100 deletions

View File

@ -1,3 +1,53 @@
2017-09-15, Version 2.26.2
==========================
* Ignore js sourcemap files from boot (Zak Barbuto)
2017-08-17, Version 2.26.1
==========================
* Do not call callbacks twice in async boot scripts (Jürg Lehni)
2017-07-31, Version 2.26.0
==========================
* Add support for ES6 style async boot scripts (Jürg Lehni)
* Update Italian translated strings Q2 2017 (Allen Boone)
* Update translated strings Q2 2017 (Allen Boone)
2017-06-26, Version 2.25.0
==========================
* Support es2015 module exports (Babel, TypeScript) (John McLaughlin)
2017-06-07, Version 2.24.1
==========================
* add support for absolute middleware paths on win32 (Benjamin Kroeger)
2017-04-03, Version 2.24.0
==========================
* Provide options.scriptExtensions (Supasate Choochaisri)
* Fix browser tests on Node.js 0.10 (Miroslav Bajtoš)
2016-10-13, Version 2.23.0
==========================
* Fix resolution of middleware modules (Miroslav Bajtoš)
* Normalize line endings to support both LF and CRLF (Miroslav Bajtoš)
2016-09-05, Version 2.22.0
==========================

17
intl/de/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "Pfad \"{0}\" kann nicht aufgelöst werden",
"34319676975b1abf107da7a056abb434": "Ungültiges Normalisierungsformat - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "Die `app` wird von einer nicht kompatiblen Loopback-Version {0} betrieben. Unterstützte Versionen: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "WARNUNG: Hauptkonfigurationsdatei \"{0}{{.json}}\" fehlt",
"4d052d84c8620730afd4a30832f11724": "Unbekanntes Modell {0} kann nicht konfiguriert werden",
"4ed668e9187650d898acf97707df445a": "Die {{phase}} \"{0}\" ist in der Hauptkonfiguration nicht definiert.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Sortierungskonflikt: \"{0}\" kann nicht nach \"{1}\" hinzugefügt werden, da die entgegengesetzte Reihenfolge bereits angegeben wurde",
"70654dc6eb565613a33344efed3de998": "Laden von Boot-Script fehlgeschlagen: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} wird nicht in einen gültigen Wert aufgelöst; zurückgegeben als {1}. \"{2}\" muss in der Umgebungsvariable oder über {{app.get()}} auflösbar sein.",
"91a742b7c3568cf6b6755741a70b3c52": "Die {{middleware}} \"{0}\" in {{phase}} \"{1}\" ist in der Hauptkonfiguration nicht definiert.",
"a3aa22086ae4976cd013065c9a3ff81c": "{0} kann nicht angewendet werden: ",
"be2cf2868ba54624fe38e9908dde5e9e": "Die Daten in {{model-config.json}} haben das nicht unterstützte {{1.x}}-Format.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "{{middleware}}-Anweisungen werden verworfen, {{loopback}}-Client unterstützt {{middleware}} nicht.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Middleware \"{0}\" nicht gefunden: {1}"
}

17
intl/es/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "No se puede resolver la vía de acceso \"{0}\"",
"34319676975b1abf107da7a056abb434": "Formato de normalización no válido - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "La `app` está basada en una versión de loopback incompatible {0}. Versiones soportadas: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "AVISO: falta el archivo de configuración principal \"{0}{{.json}}\"",
"4d052d84c8620730afd4a30832f11724": "No se puede configurar el modelo desconocido {0}",
"4ed668e9187650d898acf97707df445a": "La {{phase}} \"{0}\" no está definida en la configuración principal.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Conflicto de orden: no se puede añadir \"{0}\" después de \"{1}\", porque ya se ha especificado el orden inverso.",
"70654dc6eb565613a33344efed3de998": "No se ha podido cargar el script de arranque: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} no se resuelve como un valor válido, se ha devuelto como {1}. \"{2}\" debe poder resolverse en la variable de entorno o por medio de {{app.get()}}.",
"91a742b7c3568cf6b6755741a70b3c52": "El {{middleware}} \"{0}\" en la {{phase}} \"{1}\" no está definido en la configuración principal.",
"a3aa22086ae4976cd013065c9a3ff81c": "No se puede aplicar {0}: ",
"be2cf2868ba54624fe38e9908dde5e9e": "Los datos de {{model-config.json}} están en un formato {{1.x}} no soportado.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "Descartando instrucciones de {{middleware}}, el cliente de {{loopback}} no da soporte a {{middleware}}.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Middleware \"{0}\" no encontrado: {1}"
}

17
intl/fr/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "Impossible de résoudre le chemin \"{0}\"",
"34319676975b1abf107da7a056abb434": "Format de normalisation non valide - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "L'application `app` est basée sur une version loopback {0} incompatible. Versions prises en charge : {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "AVERTISSEMENT : le fichier de configuration principal \"{0}{{.json}}\" est manquant",
"4d052d84c8620730afd4a30832f11724": "Impossible de configurer le modèle inconnu {0}",
"4ed668e9187650d898acf97707df445a": "{{phase}} \"{0}\" n'est pas défini dans la configuration principale.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Conflit concernant l'ordre : impossible d'ajouter \"{0}\" après \"{1}\" car l'ordre opposé à déjà été spécifié",
"70654dc6eb565613a33344efed3de998": "Echec du chargement du script d'amorçage : {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} n'est pas résolu en une valeur valide, renvoyé sous forme de {1}. \"{2}\" doit pouvoir être résolu dans la variable d'environnement ou par {{app.get()}}.",
"91a742b7c3568cf6b6755741a70b3c52": "Le {{middleware}} \"{0}\" dans {{phase}} \"{1}\" n'est pas défini dans la configuration principale.",
"a3aa22086ae4976cd013065c9a3ff81c": "Impossible d'appliquer {0} : ",
"be2cf2868ba54624fe38e9908dde5e9e": "Les données contenues dans {{model-config.json}} sont au format {{1.x}} qui n'est pas pris en charge.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "Les instructions {{middleware}} sont ignorées ; le client {{loopback}} ne prend pas en charge {{middleware}}.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Middleware \"{0}\" introuvable : {1}"
}

17
intl/it/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "Impossibile risolvere il percorso \"{0}\"",
"34319676975b1abf107da7a056abb434": "Formato di normalizzazione non valido - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "La `app` si basa su una versione loopback non compatibile {0}. Versioni supportate: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "AVVERTENZA: file di configurazione principale \"{0}{{.json}}\" mancante",
"4d052d84c8620730afd4a30832f11724": "Impossibile configurare il modello {0} sconosciuto",
"4ed668e9187650d898acf97707df445a": "{{phase}} \"{0}\" non definita nella configurazione principale.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Conflitto di ordinamento: impossibile aggiungere \"{0}\" dopo \"{1}\", perché è già stato specificato l'ordine opposto",
"70654dc6eb565613a33344efed3de998": "Caricamento dello script di boot non riuscito: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} non viene risolto in un valore valido, restituito come {1}. \"{2}\" deve essere risolto in una variabile di ambiente o da {{app.get()}}.",
"91a742b7c3568cf6b6755741a70b3c52": "{{middleware}} \"{0}\" in {{phase}} \"{1}\" non definito nella configurazione principale.",
"a3aa22086ae4976cd013065c9a3ff81c": "Impossibile applicare {0}: ",
"be2cf2868ba54624fe38e9908dde5e9e": "I dati in {{model-config.json}} sono nel formato {{1.x}} non supportato.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "Eliminazione delle istruzioni {{middleware}}, il client {{loopback}} non supporta {{middleware}}.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Middleware \"{0}\" non trovato: {1}"
}

17
intl/ja/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "パス \"{0}\" を解決できません",
"34319676975b1abf107da7a056abb434": "無効な正規化形式 - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "「アプリケーション」は、互換性のない loopback バージョン {0} を使用しています。サポートされるバージョン: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "警告: メイン構成ファイル \"{0}{{.json}}\" が欠落しています",
"4d052d84c8620730afd4a30832f11724": "不明なモデル {0} を構成できません",
"4ed668e9187650d898acf97707df445a": "メイン構成内に {{phase}} \"{0}\" が定義されていません。",
"6447e6b342a2c51ab0bc53b3cbdf3742": "順序付けの競合: \"{0}\" を \"{1}\" の後に追加することはできません。既に逆の順序が指定されています",
"70654dc6eb565613a33344efed3de998": "ブート・スクリプトのロードに失敗しました: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} は有効な値に解決されず、{1} として返されました。 \"{2}\" は環境変数または {{app.get()}} で解決できなければなりません。",
"91a742b7c3568cf6b6755741a70b3c52": "{{phase}} \"{1}\" の {{middleware}} \"{0}\" がメイン構成内に定義されていません。",
"a3aa22086ae4976cd013065c9a3ff81c": "{0} を適用できません: ",
"be2cf2868ba54624fe38e9908dde5e9e": "{{model-config.json}} のデータが、サポートされていない {{1.x}} 形式になっています。",
"ec551b6f2fafd8d40af801ebe5bb09f6": "{{middleware}} 命令を破棄します。{{loopback}} クライアントでは {{middleware}} はサポートされません。",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "ミドルウェア \"{0}\" が見つかりません: {1}"
}

17
intl/ko/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "\"{0}\" 경로를 해석할 수 없음",
"34319676975b1abf107da7a056abb434": "올바르지 않은 정규화 형식 - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "`앱`이 호환되지 않는 루프백 버전 {0}을(를) 기반으로 합니다. 지원되는 버전: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "경고: 기본 구성 파일 \"{0}{{.json}}\"이(가) 누락됨",
"4d052d84c8620730afd4a30832f11724": "알 수 없는 모델 {0}을(를) 구성할 수 없음",
"4ed668e9187650d898acf97707df445a": "{{phase}} \"{0}\"이(가) 기본 구성에 정의되어 있지 않습니다.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "순서 지정 충돌: 반대 순서로 이미 지정되어서 \"{1}\" 뒤에 \"{0}\"을(를) 추가할 수 없음",
"70654dc6eb565613a33344efed3de998": "부트 스크립트를 로드하는 데 실패함: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0}이(가) 올바른 값으로 해석되지 않아서 {1}(으)로 리턴되었습니다. \"{2}\"은(는) 환경 변수에서 또는 {{app.get()}}에 의해 해석 가능해야 합니다. ",
"91a742b7c3568cf6b6755741a70b3c52": "{{phase}} \"{1}\"의 {{middleware}} \"{0}\"이(가) 기본 구성에 정의되어 있지 않습니다. ",
"a3aa22086ae4976cd013065c9a3ff81c": "{0}을(를) 적용할 수 없음: ",
"be2cf2868ba54624fe38e9908dde5e9e": "{{model-config.json}}의 데이터가 지원되지 않는 {{1.x}} 형식입니다. ",
"ec551b6f2fafd8d40af801ebe5bb09f6": "{{middleware}} 지시사항을 버리십시오. {{loopback}} 클라이언트가 {{middleware}}을(를) 지원하지 않습니다.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "미들웨어 \"{0}\"을(를) 찾을 수 없음: {1}"
}

17
intl/nl/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "Pad \"{0}\" kan niet worden omgezet.",
"34319676975b1abf107da7a056abb434": "Ongeldige normalisatie-indeling - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "De 'app' wordt aangestuurd door een incompatibele versie van loopback, {0}. Ondersteunde versies: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "WAARSCHUWING: Hoofdconfiguratiebestand \"{0}{{.json}}\" ontbreekt.",
"4d052d84c8620730afd4a30832f11724": "Configuratie van onbekend model {0} kan niet ongedaan worden gemaakt",
"4ed668e9187650d898acf97707df445a": "De {{phase}} \"{0}\" is niet gedefinieerd in de hoofdconfiguratie.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Volgordeconflict: \"{0}\" kan niet worden toegevoegd na \"{1}\", omdat de omgekeerde volgorde al is opgegeven.",
"70654dc6eb565613a33344efed3de998": "Laden van opstartscript is mislukt: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} wordt niet omgezet in een geldige waarde; wordt geretourneerd als {1}. \"{2}\" moet omgezet kunnen worden in een omgevingsvariabele of door {{app.get()}}.",
"91a742b7c3568cf6b6755741a70b3c52": "De {{middleware}} \"{0}\" in {{phase}} \"{1}\" is niet gedefinieerd in de hoofdconfiguratie.",
"a3aa22086ae4976cd013065c9a3ff81c": "{0} kan niet worden toegepast: ",
"be2cf2868ba54624fe38e9908dde5e9e": "De gegevens in {{model-config.json}} hebben de niet ondersteunde indeling {{1.x}}.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "{{middleware}} instructies worden verwijderd, {{loopback}}-client ondersteunt geen {{middleware}}.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Middleware \"{0}\" is niet gevonden: {1}"
}

17
intl/pt/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "Não é possível resolver caminho \"{0}\"",
"34319676975b1abf107da7a056abb434": "Formato de normalização inválido - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "O `app` é desenvolvido com uma versão de loopback incompatível {0}. Versões suportadas: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "AVISO: o arquivo de configuração principal \"{0}{{.json}}\" está ausente",
"4d052d84c8620730afd4a30832f11724": "Não é possível configurar modelo desconhecido {0}",
"4ed668e9187650d898acf97707df445a": "A {{phase}} \"{0}\" não foi definida na configuração principal.",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Conflito de ordem: não é possível incluir \"{0}\" após \"{1}\", porque a ordem oposta já foi especificada",
"70654dc6eb565613a33344efed3de998": "Falha ao carregar script de inicialização: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} não resolve para um valor válido, retornado como {1}. \"{2}\" deve ser resolvível na variável de ambiente ou pelo {{app.get()}}.",
"91a742b7c3568cf6b6755741a70b3c52": "O {{middleware}} \"{0}\" em {{phase}} \"{1}\" não é definido na configuração principal.",
"a3aa22086ae4976cd013065c9a3ff81c": "Não é possível aplicar {0}: ",
"be2cf2868ba54624fe38e9908dde5e9e": "Os dados em {{model-config.json}} estão no formato não suportado {{1.x}}.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "Descartando instruções de {{middleware}}, cliente de {{loopback}} não suporta {{middleware}}.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Middleware \"{0}\" não localizado: {1}"
}

17
intl/tr/messages.json Normal file
View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "\"{0}\" yolu çözülemiyor",
"34319676975b1abf107da7a056abb434": "Geçersiz normalleştirme biçimi - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "`app` uyumsuz olan geri döngü {0} sürümüyle güçlendirilmiş. Desteklenen sürümler: {1}",
"3f93b626dd9a1c33d67490f6e71018b5": "UYARI: Ana yapılandırma dosyası \"{0}{{.json}}\" eksik",
"4d052d84c8620730afd4a30832f11724": "Bilinmeyen {0} modeli yapılandırılamıyor",
"4ed668e9187650d898acf97707df445a": "{{phase}} \"{0}\", ana yapılandırmada tanımlı değil",
"6447e6b342a2c51ab0bc53b3cbdf3742": "Sıralama çakışması: \"{0}\", \"{1}\" sonrasına eklenemez; karşıt sıra belirtilmiş",
"70654dc6eb565613a33344efed3de998": "Önyükleme komut dosyasının yüklenmesi başarısız oldu: {0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} geçerli bir değere çözülmüyor, {1} olarak döndürüldü. \"{2}\" ortam değişkeninde ya da {{app.get()}} ile çözülebilir olmalıdır.",
"91a742b7c3568cf6b6755741a70b3c52": "{{phase}} \"{1}\" aşamasındaki {{middleware}} \"{0}\" ana yapılandırmada tanımlı değil.",
"a3aa22086ae4976cd013065c9a3ff81c": "{0} uygulanamıyor: ",
"be2cf2868ba54624fe38e9908dde5e9e": "{{model-config.json}} içindeki verileri desteklenmeyen {{1.x}} biçiminde.",
"ec551b6f2fafd8d40af801ebe5bb09f6": "{{middleware}} yönergeleri atılıyor, {{middleware}}, {{loopback}} istemcisi tarafından desteklenmiyor.",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "Ara katman \"{0}\" bulunamadı: {1}"
}

View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "无法解析路径“{0}”",
"34319676975b1abf107da7a056abb434": "标准化格式无效 -“{0}”",
"3a7049e42006e8bc19e0f4fc8df63b6b": "应用程序由不兼容的回环版本 {0} 支持。受支持的版本:{1}",
"3f93b626dd9a1c33d67490f6e71018b5": "警告:缺失主要配置文件“{0}{{.json}}”",
"4d052d84c8620730afd4a30832f11724": "无法配置未知的模型 {0}",
"4ed668e9187650d898acf97707df445a": "未在主配置中定义 {{phase}}“{0}”。",
"6447e6b342a2c51ab0bc53b3cbdf3742": "顺序冲突:不能在“{1}”之后添加“{0}”,因为已指定相反顺序",
"70654dc6eb565613a33344efed3de998": "无法装入引导脚本:{0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} 未解析为有效值,返回为 {1}。“{2}”必须可在环境变量中解析或由 {{app.get()}} 解析。",
"91a742b7c3568cf6b6755741a70b3c52": "未在主配置中定义 {{phase}}“{1}”中的 {{middleware}}“{0}”。",
"a3aa22086ae4976cd013065c9a3ff81c": "无法应用 {0}",
"be2cf2868ba54624fe38e9908dde5e9e": "{{model-config.json}} 中的数据不是受支持的 {{1.x}} 格式。",
"ec551b6f2fafd8d40af801ebe5bb09f6": "正在丢弃 {{middleware}} 指示信息,{{loopback}} 客户机不支持 {{middleware}}。",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "找不到中间件“{0}”:{1}"
}

View File

@ -0,0 +1,17 @@
{
"1e5fea50eef843cbffd1d438494912c8": "無法解析路徑 \"{0}\"",
"34319676975b1abf107da7a056abb434": "無效的正規化格式 - \"{0}\"",
"3a7049e42006e8bc19e0f4fc8df63b6b": "'app' 採用不相容的 LoopBack 版本 {0}。支援的版本:{1}",
"3f93b626dd9a1c33d67490f6e71018b5": "警告:遺漏主要配置檔 \"{0}{{.json}}\"",
"4d052d84c8620730afd4a30832f11724": "無法配置不明模型 {0}",
"4ed668e9187650d898acf97707df445a": "主要配置中未定義 {{phase}} \"{0}\"。",
"6447e6b342a2c51ab0bc53b3cbdf3742": "排序衝突:不能將 \"{0}\" 新增至 \"{1}\" 後面,因為已指定相反順序",
"70654dc6eb565613a33344efed3de998": "載入啟動 Script 時失敗:{0}\n{1}",
"7f7bdcadb75abfef1bd8a126d547dd6d": "{0} 未解析成有效的值,傳回 {1}。\"{2}\" 必須可在環境變數中解析或由 {{app.get()}} 解析。",
"91a742b7c3568cf6b6755741a70b3c52": "主要配置中未定義 {{phase}} \"{1}\" 中的 {{middleware}} \"{0}\"。",
"a3aa22086ae4976cd013065c9a3ff81c": "無法套用 {0}",
"be2cf2868ba54624fe38e9908dde5e9e": "{{model-config.json}} 中的資料採用不受支援的 {{1.x}} 格式。",
"ec551b6f2fafd8d40af801ebe5bb09f6": "正在捨棄 {{middleware}} 指令,{{loopback}} 用戶端不支援 {{middleware}}。",
"fdc23df1bd0fe55fe3faabcc89ff60f3": "找不到中介軟體 \"{0}\"{1}"
}

View File

@ -14,9 +14,17 @@ var debug = require('debug')('loopback:boot:compiler');
var Module = require('module');
var _ = require('lodash');
var g = require('strong-globalize')();
var requireNodeOrEsModule = require('./require');
var FILE_EXTENSION_JSON = '.json';
function arrayToObject(array) {
return array.reduce(function(obj, val) {
obj[val] = val;
return obj;
}, {});
}
/**
* Gather all bootstrap-related configuration data and compile it into
* a single object containing instruction for `boot.execute`.
@ -36,8 +44,14 @@ module.exports = function compile(options) {
options = { appRootDir: options };
}
// For setting properties without modifying the original object
options = Object.create(options);
var appRootDir = options.appRootDir = options.appRootDir || process.cwd();
var env = options.env || process.env.NODE_ENV || 'development';
var scriptExtensions = options.scriptExtensions ?
arrayToObject(options.scriptExtensions) :
require.extensions;
var appConfigRootDir = options.appConfigRootDir || appRootDir;
var appConfig = options.config ||
@ -76,9 +90,9 @@ module.exports = function compile(options) {
resolveRelativePaths(bootScripts, appRootDir);
bootDirs.forEach(function(dir) {
bootScripts = bootScripts.concat(findScripts(dir));
bootScripts = bootScripts.concat(findScripts(dir, scriptExtensions));
var envdir = dir + '/' + env;
bootScripts = bootScripts.concat(findScripts(envdir));
bootScripts = bootScripts.concat(findScripts(envdir, scriptExtensions));
});
// de-dedup boot scripts -ERS
@ -90,12 +104,12 @@ module.exports = function compile(options) {
var modelSources = options.modelSources || modelsMeta.sources || ['./models'];
var modelInstructions = buildAllModelInstructions(
modelsRootDir, modelsConfig, modelSources, options.modelDefinitions);
modelsRootDir, modelsConfig, modelSources, options.modelDefinitions,
scriptExtensions);
var mixinDirs = options.mixinDirs || [];
var mixinSources = options.mixinSources || modelsMeta.mixins || ['./mixins'];
var mixinInstructions = buildAllMixinInstructions(
appRootDir, mixinDirs, mixinSources, options, modelInstructions);
appRootDir, options, mixinSources, scriptExtensions, modelInstructions);
// When executor passes the instruction to loopback methods,
// loopback modifies the data. Since we are loading the data using `require`,
@ -151,11 +165,11 @@ function assertIsValidModelConfig(config) {
* @private
*/
function findScripts(dir, extensions) {
function findScripts(dir, scriptExtensions) {
assert(dir, g.f('cannot require directory contents without directory name'));
var files = tryReadDir(dir);
extensions = extensions || _.keys(require.extensions);
scriptExtensions = scriptExtensions || require.extensions;
// sort files in lowercase alpha for linux
files.sort(function(a, b) {
@ -181,9 +195,9 @@ function findScripts(dir, extensions) {
var filepath = path.resolve(path.join(dir, filename));
var stats = fs.statSync(filepath);
// only require files supported by require.extensions (.txt .md etc.)
// only require files supported by specified extensions
if (stats.isFile()) {
if (isPreferredExtension(filename))
if (scriptExtensions && isPreferredExtension(filename, scriptExtensions))
results.push(filepath);
else
debug('Skipping file %s - unknown extension', filepath);
@ -204,9 +218,12 @@ function tryReadDir() {
}
function buildAllModelInstructions(rootDir, modelsConfig, sources,
modelDefinitions) {
var registry = verifyModelDefinitions(rootDir, modelDefinitions) ||
findModelDefinitions(rootDir, sources);
modelDefinitions, scriptExtensions) {
var registry = verifyModelDefinitions(rootDir, modelDefinitions,
scriptExtensions);
if (!registry) {
registry = findModelDefinitions(rootDir, sources, scriptExtensions);
}
var modelNamesToBuild = addAllBaseModels(registry, Object.keys(modelsConfig));
@ -287,7 +304,7 @@ function sortByInheritance(instructions) {
});
}
function verifyModelDefinitions(rootDir, modelDefinitions) {
function verifyModelDefinitions(rootDir, modelDefinitions, scriptExtensions) {
if (!modelDefinitions || modelDefinitions.length < 1) {
return undefined;
}
@ -299,7 +316,7 @@ function verifyModelDefinitions(rootDir, modelDefinitions) {
definition.sourceFile = fixFileExtension(
fullPath,
tryReadDir(path.dirname(fullPath)),
true);
scriptExtensions);
if (!definition.sourceFile) {
debug('Model source code not found: %s - %s', definition.sourceFile);
}
@ -325,7 +342,7 @@ function verifyModelDefinitions(rootDir, modelDefinitions) {
return registry;
}
function findModelDefinitions(rootDir, sources) {
function findModelDefinitions(rootDir, sources, scriptExtensions) {
var registry = {};
sources.forEach(function(src) {
@ -343,7 +360,8 @@ function findModelDefinitions(rootDir, sources) {
})
.forEach(function(f) {
var fullPath = path.resolve(srcDir, f);
var entry = loadModelDefinition(rootDir, fullPath, files);
var entry = loadModelDefinition(rootDir, fullPath, files,
scriptExtensions);
var modelName = entry.definition.name;
if (!modelName) {
debug('Skipping model definition without Model name: %s',
@ -381,7 +399,10 @@ function tryResolveAppPath(rootDir, relativePath, resolveOptions) {
resolveOptions = resolveOptions || { strict: true };
var isModuleRelative = false;
if (relativePath[0] === '/') {
// would love to use `path.isAbsolute(relativePath)` from node's core module `path`
// but unfortunately that is not available in node v0.10.x
// https://nodejs.org/dist/latest-v6.x/docs/api/path.html#path_path_isabsolute_path
if (relativePath[0] === '/' || /^[a-zA-Z]:[\\]{1,2}/.test(relativePath)) {
fullPath = relativePath;
} else if (start === './' || start === '..') {
fullPath = path.resolve(rootDir, relativePath);
@ -445,13 +466,13 @@ function tryResolveAppPath(rootDir, relativePath, resolveOptions) {
return undefined;
}
function loadModelDefinition(rootDir, jsonFile, allFiles) {
function loadModelDefinition(rootDir, jsonFile, allFiles, scriptExtensions) {
var definition = require(jsonFile);
var basename = path.basename(jsonFile, path.extname(jsonFile));
definition.name = definition.name || _.capitalize(_.camelCase(basename));
// find a matching file with a supported extension like `.js` or `.coffee`
var sourceFile = fixFileExtension(jsonFile, allFiles, true);
var sourceFile = fixFileExtension(jsonFile, allFiles, scriptExtensions);
if (sourceFile === undefined) {
debug('Model source code not found: %s', sourceFile);
@ -569,7 +590,7 @@ function resolveMiddlewarePath(rootDir, middleware, config) {
// Try to require the module and check if <module>.<fragment> is a valid
// function
var m = require(pathName);
var m = requireNodeOrEsModule(sourceFile);
if (typeof m[fragment] === 'function') {
resolved.sourceFile = sourceFile;
return resolved;
@ -640,23 +661,31 @@ function resolveRelativePaths(relativePaths, appRootDir) {
function getExcludedExtensions() {
return {
'.json': '.json',
/**
* This is a temporary workaround for #246
* See discussion here for full description of the underlying issue
* https://github.com/strongloop/loopback-boot/pull/245#issuecomment-311052798
*/
'.map': '.map',
'.node': 'node',
};
}
function isPreferredExtension(filename) {
var includeExtensions = require.extensions;
function isPreferredExtension(filename, includeExtensions) {
assert(!!includeExtensions, '"includeExtensions" argument is required');
var ext = path.extname(filename);
return (ext in includeExtensions) && !(ext in getExcludedExtensions());
}
function fixFileExtension(filepath, files, onlyScriptsExportingFunction) {
function fixFileExtension(filepath, files, scriptExtensions) {
var results = [];
var otherFile;
/* Prefer coffee scripts over json */
if (isPreferredExtension(filepath)) return filepath;
if (scriptExtensions && isPreferredExtension(filepath, scriptExtensions)) {
return filepath;
}
var basename = path.basename(filepath, FILE_EXTENSION_JSON);
var sourceDir = path.dirname(filepath);
@ -670,10 +699,7 @@ function fixFileExtension(filepath, files, onlyScriptsExportingFunction) {
if (!(otherFileExtension in getExcludedExtensions()) &&
path.basename(f, otherFileExtension) == basename) {
if (!onlyScriptsExportingFunction)
results.push(otherFile);
else if (onlyScriptsExportingFunction &&
(typeof require.extensions[otherFileExtension]) === 'function') {
if (!scriptExtensions || otherFileExtension in scriptExtensions) {
results.push(otherFile);
}
}
@ -689,32 +715,33 @@ function resolveAppScriptPath(rootDir, relativePath, resolveOptions) {
}
var sourceDir = path.dirname(resolvedPath);
var files = tryReadDir(sourceDir);
var fixedFile = fixFileExtension(resolvedPath, files, false);
var fixedFile = fixFileExtension(resolvedPath, files);
return (fixedFile === undefined ? resolvedPath : fixedFile);
}
function buildAllMixinInstructions(appRootDir, mixinDirs, mixinSources, options,
modelInstructions) {
var extensions = _.without(_.keys(require.extensions),
_.keys(getExcludedExtensions()));
function buildAllMixinInstructions(appRootDir, options, mixinSources,
scriptExtensions, modelInstructions) {
// load mixins from `options.mixins`
var sourceFiles = options.mixins || [];
var instructionsFromMixins = loadMixins(sourceFiles, options);
var mixinDirs = options.mixinDirs || [];
var instructionsFromMixins = loadMixins(sourceFiles, options.normalization);
// load mixins from `options.mixinDirs`
sourceFiles = findMixinDefinitions(appRootDir, mixinDirs, extensions);
sourceFiles = findMixinDefinitions(appRootDir, mixinDirs, scriptExtensions);
if (sourceFiles === undefined) return;
var instructionsFromMixinDirs = loadMixins(sourceFiles, options);
var instructionsFromMixinDirs = loadMixins(sourceFiles,
options.normalization);
/* If `mixinDirs` and `mixinSources` have any directories in common,
* then remove the common directories from `mixinSources` */
mixinSources = _.difference(mixinSources, mixinDirs);
// load mixins from `options.mixinSources`
sourceFiles = findMixinDefinitions(appRootDir, mixinSources, extensions);
sourceFiles = findMixinDefinitions(appRootDir, mixinSources,
scriptExtensions);
if (sourceFiles === undefined) return;
var instructionsFromMixinSources = loadMixins(sourceFiles, options);
var instructionsFromMixinSources = loadMixins(sourceFiles,
options.normalization);
// Fetch unique list of mixin names, used in models
var modelMixins = fetchMixinNamesUsedInModelInstructions(modelInstructions);
@ -732,7 +759,7 @@ function buildAllMixinInstructions(appRootDir, mixinDirs, mixinSources, options,
return _.values(mixins);
}
function findMixinDefinitions(appRootDir, sourceDirs, extensions) {
function findMixinDefinitions(appRootDir, sourceDirs, scriptExtensions) {
var files = [];
sourceDirs.forEach(function(dir) {
var path = tryResolveAppPath(appRootDir, dir);
@ -740,12 +767,12 @@ function findMixinDefinitions(appRootDir, sourceDirs, extensions) {
debug('Skipping unknown module source dir %j', dir);
return;
}
files = files.concat(findScripts(path, extensions));
files = files.concat(findScripts(path, scriptExtensions));
});
return files;
}
function loadMixins(sourceFiles, options) {
function loadMixins(sourceFiles, normalization) {
var mixinInstructions = {};
sourceFiles.forEach(function(filepath) {
var dir = path.dirname(filepath);
@ -753,12 +780,12 @@ function loadMixins(sourceFiles, options) {
var name = path.basename(filepath, ext);
var metafile = path.join(dir, name + FILE_EXTENSION_JSON);
name = normalizeMixinName(name, options);
name = normalizeMixinName(name, normalization);
var meta = {};
meta.name = name;
if (utils.fileExistsSync(metafile)) {
// May overwrite name, not sourceFile
_.extend(meta, require(metafile));
_.extend(meta, requireNodeOrEsModule(metafile));
}
meta.sourceFile = filepath;
mixinInstructions[meta.name] = meta;
@ -788,8 +815,7 @@ function filterMixinInstructionsUsingWhitelist(instructions, includeMixins) {
return filteredInstructions;
}
function normalizeMixinName(str, options) {
var normalization = options.normalization;
function normalizeMixinName(str, normalization) {
switch (normalization) {
case false:
case 'none': return str;

View File

@ -10,6 +10,7 @@ var async = require('async');
var path = require('path');
var format = require('util').format;
var g = require('strong-globalize')();
var requireNodeOrEsModule = require('./require');
/**
* Execute bootstrap instructions gathered by `boot.compile`.
@ -211,7 +212,7 @@ function defineMixins(app, instructions) {
if (!modelBuilder.mixins || !mixins.length) return;
mixins.forEach(function(obj) {
var mixin = require(obj.sourceFile);
var mixin = requireNodeOrEsModule(obj.sourceFile);
if (typeof mixin === 'function' || mixin.prototype instanceof BaseClass) {
debug('Defining mixin %s', obj.name);
@ -244,7 +245,7 @@ function defineModels(app, instructions) {
model = registry.createModel(data.definition);
if (data.sourceFile) {
debug('Loading customization script %s', data.sourceFile);
var code = require(data.sourceFile);
var code = requireNodeOrEsModule(data.sourceFile);
if (typeof code === 'function') {
debug('Customizing model %s', name);
code(model);
@ -288,12 +289,12 @@ function runScripts(app, list, callback) {
list.forEach(function(filepath) {
debug('Requiring script %s', filepath);
try {
var exports = require(filepath);
if (typeof exports === 'function') {
var bootFn = requireNodeOrEsModule(filepath);
if (typeof bootFn === 'function') {
debug('Exported function detected %s', filepath);
functions.push({
path: filepath,
func: exports,
func: bootFn,
});
}
} catch (err) {
@ -304,17 +305,24 @@ function runScripts(app, list, callback) {
async.eachSeries(functions, function(f, done) {
debug('Running script %s', f.path);
if (f.func.length >= 2) {
debug('Starting async function %s', f.path);
f.func(app, function(err) {
debug('Async function finished %s', f.path);
done(err);
});
} else {
debug('Starting sync function %s', f.path);
f.func(app);
debug('Sync function finished %s', f.path);
done();
var cb = function(err) {
debug('Async function %s %s', err ? 'failed' : 'finished', f.path);
done(err);
// Make sure done() isn't called twice, e.g. if a script returns a
// thenable object and also calls the passed callback.
cb = function() {};
};
try {
var result = f.func(app, cb);
if (result && typeof result.then === 'function') {
result.then(function() { cb(); }, cb);
} else if (f.func.length < 2) {
debug('Sync function finished %s', f.path);
done();
}
} catch (err) {
debug('Sync function failed %s', f.path, err);
done(err);
}
}, callback);
}
@ -340,7 +348,7 @@ function setupMiddleware(app, instructions) {
middleware.forEach(function(data) {
debug('Configuring middleware %j%s', data.sourceFile,
data.fragment ? ('#' + data.fragment) : '');
var factory = require(data.sourceFile);
var factory = requireNodeOrEsModule(data.sourceFile);
if (data.fragment) {
factory = factory[data.fragment].bind(factory);
}
@ -429,7 +437,7 @@ function getUpdatedConfigObject(app, config, opts) {
function setupComponents(app, instructions) {
instructions.components.forEach(function(data) {
debug('Configuring component %j', data.sourceFile);
var configFn = require(data.sourceFile);
var configFn = requireNodeOrEsModule(data.sourceFile);
var opts = {
useEnvVars: true,
};

9
lib/require.js Normal file
View File

@ -0,0 +1,9 @@
// Copyright IBM Corp. 2015,2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = function requireNodeOrEsModule(sourceFile) {
var exports = require(sourceFile);
return exports && exports.__esModule ? exports.default : exports;
};

View File

@ -1,6 +1,6 @@
{
"name": "loopback-boot",
"version": "2.22.0",
"version": "2.26.2",
"description": "Convention-based bootstrapper for LoopBack applications",
"keywords": [
"StrongLoop",
@ -31,6 +31,7 @@
},
"devDependencies": {
"browserify": "^4.1.8",
"bluebird": "^3.1.1",
"chai": "^1.10.0",
"coffee-script": "^1.8.0",
"coffeeify": "^0.7.0",

View File

@ -57,10 +57,15 @@ describe('browser support', function() {
expect(Object.keys(app.models)).to.include('Customer');
expect(app.models.Customer.settings)
.to.have.property('_customized', 'Customer');
expect(Object.keys(app.models)).to.include('ProductUmd');
expect(app.models.ProductUmd.settings)
.to.have.property('_customized', 'UMD');
// configured in fixtures/browser-app/component-config.json
// and fixtures/browser-app/components/dummy-component.js
// configured in fixtures/browser-app/component-config.json,
// fixtures/browser-app/components/dummy-component.js and
// fixtures/browser-app/components/dummy-component-umd.js
expect(app.dummyComponentOptions).to.eql({ option: 'value' });
expect(app.dummyComponentUmdOptions).to.eql({ option: 'valueUmd' });
done();
});
@ -79,8 +84,9 @@ describe('browser support', function() {
var modelBuilder = app.registry.modelBuilder;
var registry = modelBuilder.mixins.mixins;
expect(Object.keys(registry)).to.eql(['TimeStamps']);
expect(Object.keys(registry)).to.eql(['AuditedUmd', 'TimeStamps']);
expect(app.models.Customer.timeStampsMixin).to.eql(true);
expect(app.models.ProductUmd.auditedMixin).to.eql(true);
done();
});

View File

@ -2016,6 +2016,22 @@ describe('compiler', function() {
.to.equal(require.resolve('loopback/server/middleware/url-not-found'));
});
it('supports absolute paths notation', function() {
var middlewarePath =
path.resolve(__dirname, './fixtures/simple-middleware.js');
var routes = {};
routes[middlewarePath] = {};
appdir.writeConfigFileSync('middleware.json', {
'routes': routes,
});
var instructions = boot.compile(appdir.PATH);
expect(instructions.middleware.middleware[0].sourceFile)
.to.equal(path.resolve(appdir.PATH,
middlewarePath));
});
it('supports shorthand notation for relative paths', function() {
appdir.writeConfigFileSync('middleware.json', {
'routes': {
@ -2171,6 +2187,24 @@ describe('compiler', function() {
'sourceFile', coffee);
});
it('ignores sourcmap files when loading middleware',
function() {
var middleware = appdir.writeFileSync('my-middleware.js',
'// I am the middleware');
var sourcemap = appdir.writeFileSync('my-middleware.js.map',
'// I am a sourcemap');
appdir.writeConfigFileSync('middleware.json', {
'routes': {
'./my-middleware': {},
},
});
var instructions = boot.compile(appdir.PATH);
expect(instructions.middleware.middleware[0]).have.property(
'sourceFile', middleware);
});
describe('config with relative paths in params', function() {
var RELATIVE_PATH_PARAMS = [
'$!./here',

View File

@ -265,6 +265,8 @@ describe('executor', function() {
'barLoaded',
'barSyncLoaded',
'fooLoaded',
'promiseLoaded',
'thenableLoaded',
'barStarted',
]);
@ -275,9 +277,16 @@ describe('executor', function() {
'barLoaded',
'barSyncLoaded',
'fooLoaded',
'promiseLoaded',
'thenableLoaded',
'barStarted',
'barFinished',
'barSyncExecuted',
'promiseStarted',
'promiseFinished',
'thenableStarted',
'thenableFinished',
'umdLoaded',
]);
done();
}, 10);
@ -291,51 +300,132 @@ describe('executor', function() {
'barLoaded',
'barSyncLoaded',
'fooLoaded',
'promiseLoaded',
'thenableLoaded',
'barStarted',
'barFinished',
'barSyncExecuted',
'promiseStarted',
'promiseFinished',
'thenableStarted',
'thenableFinished',
'umdLoaded',
]);
done();
});
});
describe('for mixins', function() {
var options;
beforeEach(function() {
appdir.writeFileSync('custom-mixins/example.js',
'module.exports = ' +
'function(Model, options) {}');
it('searches boot file extensions specified in options.scriptExtensions',
function(done) {
var options = {
app: app,
appRootDir: SIMPLE_APP,
scriptExtensions: ['.customjs', '.customjs2'],
};
boot.execute(app, boot.compile(options), function(err) {
if (err) return done(err);
expect(process.bootFlags, 'process: bootFlags').to.eql([
'customjs',
'customjs2',
]);
done();
});
});
});
appdir.writeFileSync('custom-mixins/time-stamps.js',
'module.exports = ' +
'function(Model, options) {}');
describe('with boot script returning a rejected promise', function() {
before(function() {
// Tell simple-app/boot/reject.js to return a rejected promise
process.rejectPromise = true;
});
appdir.writeConfigFileSync('custom-mixins/time-stamps.json', {
name: 'Timestamping',
});
after(function() {
delete process.rejectPromise;
});
options = {
appRootDir: appdir.PATH,
};
it('receives rejected promise as callback error',
function(done) {
boot.execute(app, simpleAppInstructions(), function(err) {
expect(err).to.exist.and.be.an.instanceOf(Error)
.with.property('message', 'reject');
done();
});
});
});
describe('with boot script throwing an error', function() {
before(function() {
// Tell simple-app/boot/throw.js to throw an error
process.throwError = true;
});
after(function() {
delete process.throwError;
});
it('receives thrown error as callback errors',
function(done) {
boot.execute(app, simpleAppInstructions(), function(err) {
expect(err).to.exist.and.be.an.instanceOf(Error)
.with.property('message', 'throw');
done();
});
});
});
describe('with boot script returning a promise and calling callback',
function() {
before(function() {
process.promiseAndCallback = true;
});
it('defines mixins from instructions - using `mixinDirs`', function() {
options.mixinDirs = ['./custom-mixins'];
boot(app, options);
var modelBuilder = app.registry.modelBuilder;
var registry = modelBuilder.mixins.mixins;
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
after(function() {
delete process.promiseAndCallback;
});
it('defines mixins from instructions - using `mixinSources`', function() {
options.mixinSources = ['./custom-mixins'];
boot(app, options);
var modelBuilder = app.registry.modelBuilder;
var registry = modelBuilder.mixins.mixins;
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
it('should only call the callback once', function(done) {
// Note: Mocha will fail this test if done() is called twice
boot.execute(app, simpleAppInstructions(), done);
});
}
);
describe('for mixins', function() {
var options;
beforeEach(function() {
appdir.writeFileSync('custom-mixins/example.js',
'module.exports = ' +
'function(Model, options) {}');
appdir.writeFileSync('custom-mixins/time-stamps.js',
'module.exports = ' +
'function(Model, options) {}');
appdir.writeConfigFileSync('custom-mixins/time-stamps.json', {
name: 'Timestamping',
});
options = {
appRootDir: appdir.PATH,
};
});
it('defines mixins from instructions - using `mixinDirs`', function() {
options.mixinDirs = ['./custom-mixins'];
boot(app, options);
var modelBuilder = app.registry.modelBuilder;
var registry = modelBuilder.mixins.mixins;
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
});
it('defines mixins from instructions - using `mixinSources`', function() {
options.mixinSources = ['./custom-mixins'];
boot(app, options);
var modelBuilder = app.registry.modelBuilder;
var registry = modelBuilder.mixins.mixins;
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
});
});
@ -804,10 +894,11 @@ describe('executor', function() {
.get('/')
.end(function(err, res) {
if (err) return done(err);
expect(res.text).to.eql(('<!DOCTYPE html>\n<html>\n<head lang="en">\n' +
var EXPECTED_TEXT = '<!DOCTYPE html>\n<html>\n<head lang="en">\n' +
' <meta charset="UTF-8">\n <title>simple-app</title>\n' +
'</head>\n<body>\n<h1>simple-app</h1>\n' +
'</body>\n</html>').replace(/\n/g, os.EOL));
'</body>\n</html>';
expect(normalizeEols(res.text)).to.eql(normalizeEols(EXPECTED_TEXT));
done();
});
});
@ -820,6 +911,7 @@ describe('executor', function() {
.end(function(err, res) {
if (err) return done(err);
expect(res.headers.names).to.equal('custom-middleware');
expect(res.headers.umd).to.equal('success');
done();
});
});
@ -1129,3 +1221,7 @@ function envAppInstructions() {
env: 'test',
});
}
function normalizeEols(str) {
return str.replace(/\r\n/g, '\n');
}

View File

@ -1,5 +1,8 @@
{
"./components/dummy-component": {
"option": "value"
},
"./components/dummy-component-umd": {
"option": "valueUmd"
}
}

View File

@ -0,0 +1,11 @@
// Copyright IBM Corp. 2015,2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = {
default: function(app, options) {
app.dummyComponentUmdOptions = options;
},
};
Object.defineProperty(module.exports, '__esModule', { value: true });

View File

@ -0,0 +1,11 @@
// Copyright IBM Corp. 2014,2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = {
default: function(Model, options) {
Model.auditedMixin = true;
},
};
Object.defineProperty(module.exports, '__esModule', { value: true });

View File

@ -7,5 +7,8 @@
},
"Customer": {
"dataSource": "db"
},
"ProductUmd": {
"dataSource": "db"
}
}

View File

@ -0,0 +1,11 @@
// Copyright IBM Corp. 2014,2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = {
default: function(ProductUmd) {
ProductUmd.settings._customized = 'UMD';
},
};
Object.defineProperty(module.exports, '__esModule', { value: true });

View File

@ -0,0 +1,5 @@
{
"name": "ProductUmd",
"base": "User",
"mixins": {"AuditedUmd": {} }
}

View File

@ -0,0 +1,6 @@
'use strict';
module.exports = function(app, callback) {
process.bootFlags.push('customjs');
callback();
};

View File

@ -0,0 +1,6 @@
'use strict';
module.exports = function(app, callback) {
process.bootFlags.push('customjs2');
callback();
};

View File

@ -0,0 +1,13 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var Promise = require('bluebird');
module.exports = function(app, callback) {
callback();
if (process.promiseAndCallback) {
return Promise.reject();
}
};

View File

@ -0,0 +1,19 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var Promise = require('bluebird');
process.bootFlags.push('promiseLoaded');
module.exports = function(app) {
process.bootFlags.push('promiseStarted');
return Promise.resolve({
then: function(onFulfill, onReject) {
process.nextTick(function() {
process.bootFlags.push('promiseFinished');
onFulfill();
});
},
});
};

12
test/fixtures/simple-app/boot/reject.js vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var Promise = require('bluebird');
module.exports = function(app) {
if (process.rejectPromise) {
return Promise.reject(new Error('reject'));
}
};

View File

@ -0,0 +1,17 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
process.bootFlags.push('thenableLoaded');
module.exports = function(app) {
process.bootFlags.push('thenableStarted');
return {
then: function(onFulfill, onReject) {
process.nextTick(function() {
process.bootFlags.push('thenableFinished');
onFulfill();
});
},
};
};

10
test/fixtures/simple-app/boot/throw.js vendored Normal file
View File

@ -0,0 +1,10 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = function(app) {
if (process.throwError) {
throw new Error('throw');
}
};

11
test/fixtures/simple-app/boot/umd.js vendored Normal file
View File

@ -0,0 +1,11 @@
// Copyright IBM Corp. 2014,2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = {
default: function(app) {
process.bootFlags.push('umdLoaded');
},
};
Object.defineProperty(module.exports, '__esModule', { value: true });

View File

@ -2,6 +2,9 @@
"initial": {
"../../helpers/push-name-middleware": {
"params": "custom-middleware"
}
},
"../../helpers/set-umd-middleware": {
"params": "success"
}
}
}

View File

@ -63,6 +63,12 @@ function createContext() {
// `window` is used by loopback to detect browser runtime
context.window = context;
// In Node.js 0.10, the Uint8Array is provided by Node.js glue,
// it's not available in the V8 runtime itself
if (/^v0\.10/.test(process.version)) {
context.Uint8Array = Uint8Array;
}
return vm.createContext(context);
}
exports.createContext = createContext;

View File

@ -0,0 +1,14 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-boot
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = {
default: function(value) {
return function(req, res, next) {
res.setHeader('umd', value);
next();
};
},
};
Object.defineProperty(module.exports, '__esModule', { value: true });