Browse Source

Merge pull request #14078 from abpframework/auto-merge/rel-6-0/1359

Merge branch dev with rel-6.0
pull/14086/head
Engincan VESKE 4 years ago
committed by GitHub
parent
commit
50663ee5d6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 60
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json
  2. 125
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json
  3. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/tr.json
  4. 259
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  5. 2
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json
  6. 4
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/tr.json
  7. 2
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/tr.json
  8. 3
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/tr.json
  9. 2
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/tr.json
  10. 4
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json
  11. 3
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json
  12. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml
  13. 6
      npm/ng-packs/packages/schematics/package.json
  14. 5
      npm/ng-packs/packages/schematics/src/collection.json
  15. 4
      npm/ng-packs/packages/schematics/src/commands/api/index.ts
  16. 9
      npm/ng-packs/packages/schematics/src/commands/api/schema.json
  17. 44
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/.eslintrc.json.template
  18. 7
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/ng-package.json.template
  19. 12
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/__libraryName@kebab__-config.module.ts.template
  20. 1
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/enums/index.ts.template
  21. 3
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/enums/route-names.ts.template
  22. 1
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/providers/index.ts.template
  23. 26
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/providers/route.provider.ts.template
  24. 3
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/public-api.ts.template
  25. 44
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/karma.conf.js.template
  26. 7
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/ng-package.json.template
  27. 11
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/package.json.template
  28. 18
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/lib/__libraryName@kebab__-routing.module.ts.template
  29. 22
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/lib/__libraryName@kebab__.module.ts.template
  30. 4
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/public-api.ts.template
  31. 26
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/test.ts.template
  32. 20
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/tsconfig.lib.json.template
  33. 10
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/tsconfig.lib.prod.json.template
  34. 17
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/tsconfig.spec.json.template
  35. 7
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/ng-package.json.template
  36. 11
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/src/lib/__target@kebab__-__libraryName@kebab__.module.ts.template
  37. 1
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/src/lib/index.ts.template
  38. 1
      npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/src/public-api.ts.template
  39. 159
      npm/ng-packs/packages/schematics/src/commands/create-lib/index.ts
  40. 17
      npm/ng-packs/packages/schematics/src/commands/create-lib/models/generate-lib-schema.ts
  41. 1
      npm/ng-packs/packages/schematics/src/commands/create-lib/models/index.ts
  42. 36
      npm/ng-packs/packages/schematics/src/commands/create-lib/schema.json
  43. 4
      npm/ng-packs/packages/schematics/src/commands/proxy-add/index.ts
  44. 9
      npm/ng-packs/packages/schematics/src/commands/proxy-add/schema.json
  45. 6
      npm/ng-packs/packages/schematics/src/commands/proxy-index/index.ts
  46. 9
      npm/ng-packs/packages/schematics/src/commands/proxy-index/schema.json
  47. 4
      npm/ng-packs/packages/schematics/src/commands/proxy-refresh/index.ts
  48. 10
      npm/ng-packs/packages/schematics/src/commands/proxy-refresh/schema.json
  49. 4
      npm/ng-packs/packages/schematics/src/commands/proxy-remove/index.ts
  50. 9
      npm/ng-packs/packages/schematics/src/commands/proxy-remove/schema.json
  51. 1
      npm/ng-packs/packages/schematics/src/constants/symbols.ts
  52. 1
      npm/ng-packs/packages/schematics/src/enums/exception.ts
  53. 5
      npm/ng-packs/packages/schematics/src/models/generate-proxy-schema.ts
  54. 52
      npm/ng-packs/packages/schematics/src/utils/angular-schematic/generate-lib.ts
  55. 1
      npm/ng-packs/packages/schematics/src/utils/angular-schematic/index.ts
  56. 2
      npm/ng-packs/packages/schematics/src/utils/angular/README.md
  57. 193
      npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts
  58. 32
      npm/ng-packs/packages/schematics/src/utils/angular/change.ts
  59. 541
      npm/ng-packs/packages/schematics/src/utils/angular/config.ts
  60. 12
      npm/ng-packs/packages/schematics/src/utils/angular/dependencies.ts
  61. 25
      npm/ng-packs/packages/schematics/src/utils/angular/find-module.ts
  62. 61
      npm/ng-packs/packages/schematics/src/utils/angular/generate-from-files.ts
  63. 6
      npm/ng-packs/packages/schematics/src/utils/angular/index.ts
  64. 43
      npm/ng-packs/packages/schematics/src/utils/angular/json-file.ts
  65. 221
      npm/ng-packs/packages/schematics/src/utils/angular/json-utils.ts
  66. 26
      npm/ng-packs/packages/schematics/src/utils/angular/latest-versions.ts
  67. 20
      npm/ng-packs/packages/schematics/src/utils/angular/latest-versions/package.json
  68. 54
      npm/ng-packs/packages/schematics/src/utils/angular/lint-fix.ts
  69. 9
      npm/ng-packs/packages/schematics/src/utils/angular/ng-ast-utils.ts
  70. 5
      npm/ng-packs/packages/schematics/src/utils/angular/parse-name.ts
  71. 2
      npm/ng-packs/packages/schematics/src/utils/angular/paths.ts
  72. 2
      npm/ng-packs/packages/schematics/src/utils/angular/project-targets.ts
  73. 76
      npm/ng-packs/packages/schematics/src/utils/angular/tsconfig.ts
  74. 60
      npm/ng-packs/packages/schematics/src/utils/angular/validation.ts
  75. 23
      npm/ng-packs/packages/schematics/src/utils/angular/workspace-models.ts
  76. 51
      npm/ng-packs/packages/schematics/src/utils/angular/workspace.ts
  77. 1
      npm/ng-packs/packages/schematics/src/utils/index.ts
  78. 9
      npm/ng-packs/packages/schematics/src/utils/lib.ts
  79. 2
      npm/ng-packs/packages/schematics/src/utils/source.ts
  80. 49
      npm/ng-packs/packages/schematics/src/utils/workspace.ts
  81. 6
      npm/ng-packs/scripts/build-schematics.ts

60
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json

@ -354,6 +354,64 @@
"SendWelcomeEmailWarningMessage": "Organizasyon üyelerine hoşgeldin emaili göndermek istediğinden emin misin?",
"SendWelcomeEmailSuccessMessage": "Hoşgeldin emaili başarıyla gönderilmiştir!",
"AdditionalDeveloperCount": "Ekstra geliştirici sayısı",
"LicensePrice": "Lisans ücreti"
"LicensePrice": "Lisans ücreti",
"FirstName": "Adı",
"Activate": "Aktif",
"ActivateTrialLicenseWarningMessage": "Bir deneme lisansını etkinleştirdiğinizde, kullanıcıya bir karşılama e-postası gönderilecektir. Etkinleştirmek istiyor musunuz?",
"ActivateTrialLicenseSuccessMessage": "Deneme lisansı başarıyla etkinleştirildi!",
"PaymentRequestId": "Ödeme talep kimliği",
"PurchaseDate": "Satın alma tarihi",
"IsAbpBookDownloaded": "Abp kitabı indirildi",
"IsMasteringAbpBookDownloadEnabled": "Abp kitabı indirme etkinleştirildi",
"Permission:Accounting:CustomPaymentLinkGenerator": "Özel Ödeme Bağlantısı",
"CustomPaymentLink": "Özel Ödeme Bağlantısı",
"Menu:CustomPaymentLink": "Özel Ödeme Bağlantısı",
"Amount": "Miktar",
"GenerateCustomPaymentLink": "Özel Ödeme Bağlantısı Oluştur",
"GeneratedPaymentLink": "Oluşturulan Ödeme Bağlantısı",
"CopyText": "Metni kopyala",
"Permission:CommunityEvents": "Etkinlikler",
"Menu:Events": "Etkinlikler",
"Events": "Etkinlikler",
"EventType": "Etkinlik türü",
"Number": "Numara",
"RegistrationURL": "Kayıt URL",
"URL": "URL",
"EventDeletionConfirmationMessage": "Etkinliği silmek istediğinizden emin misiniz?",
"Enum:EventType:0": "Topluluk Konuşmaları",
"CreateAnEvent": "Etkinlik Oluştur",
"Permission:CommunitySpeakers": "Konuşmacılar",
"CreateASpeaker": "Konuşmacı Oluştur",
"Speakers": "Konuşmacılar",
"Image": "Resim",
"GithubURL": "Github URL",
"SpeakerDeletionConfirmationMessage": "Konuşmacıyı silmek istediğinizden emin misiniz?",
"Menu:Speakers": "Konuşmacılar",
"ChooseSpeakerImage": "Konuşmacı resmi seç ...",
"SpeakerImage": "Konuşmacı resmi",
"AddSpeaker": "Konuşmacı Ekle",
"ShowPurchaseItemsOfOrganizations": "Satın alınan öğeler",
"Enum:OrganizationPurchaseState:0": "Teslim edilmedi",
"Enum:OrganizationPurchaseState:1": "Teslim edildi",
"PurchaseItems": "Satın alınan öğeler",
"SuccessfullyUpdated": "Başarıyla güncellendi",
"SuccessfullyAdded": "Başarıyla eklendi",
"PurchaseState": "Satın alma durumu",
"ShowBetweenDayCount": "Gün sayısını göster",
"PurchaseOrder": "Satın alma siparişi",
"ShowCreateInvoiceOfOrganization": "Fatura oluştur",
"ShowCreateQuotationOfOrganization": "Teklif oluştur",
"BookDiscounts": "Kitap indirimleri",
"Menu:BookDiscounts": "Kitap indirimleri",
"BookType": "Kitap türü",
"PurchasePlatform": "Satın alma platformu",
"StartTime": "Başlangıç zamanı",
"EndTime": "Bitiş zamanı",
"CreateABookDiscount": "Kitap indirimi oluştur",
"BookDiscountDeletionConfirmationMessage": "Kitap indirimini silmek istediğinizden emin misiniz?",
"CustomPaymentFlexSwitchDescription": "Lisanslı",
"AllowFeatureUpgradeOnLicenseExpire": "Lisans süresi dolunca özellik yükseltmesine izin ver",
"Deleted{0}": "[{0} silindi]",
"Permission:BookDiscount": "Kitap indirimleri"
}
}

125
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json

@ -40,6 +40,131 @@
"TrialLicensePeriodWillExpire": "Deneme lisansınızın süresi {0} gün içinde dolacak.",
"TrialLicensePeriodExpireToday": "Deneme lisans süreniz bugün sona erecek.",
"PurchaseNow": "Şimdi satın al!",
"Volo.AbpIo.Domain:030000": "Deneme sürenizi çoktan tamamladınız.",
"Volo.AbpIo.Domain:030001": "Bu kuruluş adı zaten mevcut.",
"Volo.AbpIo.Domain:030002": "Bir kez etkinleştirildiğinde, deneme lisansını -requested- duruma değiştiremezsiniz!",
"Volo.AbpIo.Domain:030003": "Böyle bir durum yok!",
"Volo.AbpIo.Domain:030004": "Beklenmeyen bir hata nedeniyle durum değiştirilemedi!",
"Volo.AbpIo.Domain:030005": "Deneme lisansı -activated- durumundayken başlangıç ve bitiş tarihi güncellenebilir!",
"Volo.AbpIo.Domain:030006": "Bitiş tarihi, başlangıç tarihinden büyük olmalıdır!",
"Volo.AbpIo.Domain:030007": "Bu deneme lisansı zaten etkinleştirildi!",
"Volo.AbpIo.Domain:030008": "Satın alma tarihi ancak durum -purchased- olduğunda ayarlanabilir!",
"Volo.AbpIo.Domain:030009": "Kullanıcı bulunamadı!",
"Volo.AbpIo.Domain:030010": "Deneme lisansını satın almak için önce deneme lisansınızı etkinleştirmeniz gerekir!",
"Volo.AbpIo.Domain:030011": "Satın alınan bir deneme lisansını silemezsiniz!",
"Volo.AbpIo.Domain:070000": "Kuruluş adı yalnızca latin harfleri, sayıları, noktaları ve kısa çizgileri içerebilir!",
"Volo.AbpIo.Domain:070001": "Şirket adı yalnızca latin harfleri, sayıları, noktaları, boşlukları ve kısa çizgileri içerebilir!",
"LatestReleaseLogs": "Son Sürüm Logları",
"RoadMap": "Yol Haritası",
"FAQ": "SSS",
"SourceCode": "Kaynak Kodu",
"SeeAllPosts": "Tüm Gönderileri Gör",
"Contribute": "Katkıda Bulun",
"LiveDemo": "Canlı Demo",
"GetLicense": "Lisans Al",
"OpenSource": "Açık Kaynak",
"WebApplication": "Web Uygulaması",
"MeetTheABP": "ABP'yi Tanıyın",
"CompleteWebDevelopment": "Eksiksiz Bir Web Geliştirme",
"Platform": "Platform",
"ABPDescription": "ABP Framework, en iyi yazılım geliştirme uygulamalarını ve kurallarını takip ederek modern web uygulamaları oluşturmak için eksiksiz bir altyapıdır.",
"StrongInfrastructure": "Güçlü Altyapı",
"CompleteArchitecture": "Eksiksiz Mimari",
"DeveloperFocused": "Geliştirici Odaklı",
"ShareYourExperiences": "ABP Çerçevesi ile ilgili deneyimlerinizi paylaşın",
"LatestPosts": "Son Gönderiler",
"Views": "Görüntülenme",
"LearnLatestNewsAboutABPFramework": "Yeni sürümler, ücretsiz kaynaklar, gönderiler ve daha fazlası gibi ABP'de olup bitenler hakkında bilgi alın.",
"DeveloperTools": "Geliştirici Araçları",
"StartupTemplates": "Başlangıç Şablonları",
"ApplicationModules": "Uygulama Modülleri",
"UI": "Kullanıcı Arayüzü",
"Themes": "Temalar",
"Premium": "Premium",
"PrivacyPolicy": "Gizlilik Politikası",
"TermsAndConditions": "Şartlar ve Koşullar",
"WouldLikeToReceiveMarketingMaterials": "Ürün fırsatları ve özel teklifler gibi pazarlama materyalleri almak istiyorum.",
"JoinOurMarketingNewsletter": "Pazarlama bültenimize katılın",
"CommunityPrivacyPolicyConfirmation": "Şartları, Koşulları ve <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Gizlilik Politikasını</a> kabul ediyorum.",
"WouldLikeToReceiveNotification": "abp.io web sitelerinden en son haberleri almak istiyorum.",
"CommercialNewsletterConfirmationMessage": "<a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/TermsConditions\">Şartlar ve Koşulları</a> ve <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Gizlilik Politikasını</a> kabul ediyorum.",
"FreeDDDEBook": "Ücretsiz DDD E-Kitabı",
"AdditionalServices": "Ek Hizmetler",
"Learn": "Öğren",
"AccountOverview": "Hesap Özeti",
"MyOrganizations": "Kuruluşlarım",
"MySupportQuestions": "Destek Sorularım",
"MyProfile": "Profilim",
"Logout": "Çıkış Yap",
"Home": "Ev",
"Posts": "Gönderiler",
"JoinTheABPCommunity": "ABP Topluluğuna Katılın",
"SubmitYourPost": "Gönderinizi Gönderin",
"Modules": "Modüller",
"Tools": "Araçlar",
"Pricing": "Fiyatlandırma",
"ChangeLogs": "Değişiklik Logları",
"SubscribeToNewsletter": "Bültenimize Abone Olun",
"SubscribeToNewsletterDescription": "Yeni sürümler, ücretsiz kaynaklar, gönderiler ve daha fazlası gibi ABP'de olup bitenler hakkında bilgi alın.",
"EmailAddress": "E-posta Adresi",
"Subscribe": "Abone Ol",
"WelcomeToABP": "ABP'ye Hoşgeldiniz",
"EULA": "SKLA",
"ABPCommercialIntroductionMessage": "Önceden oluşturulmuş uygulama modülleri, gelişmiş başlangıç şablonları, hızlı uygulama geliştirme araçları, profesyonel kullanıcı arayüzü temaları ve premium destek.",
"MasteringAbpFrameworkEBook": "Mastering ABP Framework",
"MasteringTheABPFrameworkExplanation": "ABP Çerçevesinin yaratıcısı tarafından yazılan bu kitap, çerçeveyi ve modern web uygulaması geliştirme tekniklerini tam olarak anlamanıza yardımcı olacaktır.",
"Speakers": "Konuşmacılar",
"PreviousEvents": "Önceki Etkinlikler",
"WatchTheEvent": "Etkinliği İzle",
"RegisterNow": "Şimdi Kaydol",
"ThereIsNoEvent": "Etkinlik yok",
"Events": "Etkinlikler",
"Volo.AbpIo.Domain:080000": "\"{name}\" adlı bir satın alma öğesi zaten var",
"MasteringAbpFrameworkBook": "Kitap: Mastering ABP Framework",
"ABPIO-CommonPreferenceDefinition": "Yeni gönderiler, etkinlikler ve daha fazlası gibi ABP Platformu hakkındaki en son haberleri alın.",
"BuiltOn": "Üzerinde inşa edildi",
"AbpFramework": "ABP Çerçevesi",
"Volo.AbpIo.Domain:080001": "Başlangıç Zamanı Bitiş Zamanından büyük olamaz",
"Enum:BookType:0": "Mastering ABP Framework",
"Enum:PurchasePlatform:0": "Amazon",
"Enum:PurchasePlatform:1": "Paket",
"Copied": "Kopyalandı!",
"CouldNotCopy": "Kopyalanamadı!",
"CopyNotSupportByYourBrowser": "Tarayıcınız kopyalamayı desteklemiyor",
"City": "Şehir",
"ZipCode": "Posta Kodu",
"Address": "Adres",
"Homepage": "Anasayfa",
"Year": "Yıl",
"Copyright": "Telif hakkı © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Alan Odaklı Tasarım",
"CrossCuttingConcerns": "Cross Cutting Concerns",
"AbpCommunity": "ABP Topluluğu",
"Footer_GithubStarCount": "{0} Star on GitHub",
"Footer_NugetDownloadCount": "{0} NuGet indirme",
"AbpDescription": "ABP, AspNet Core tabanlı web uygulaması geliştirmeye odaklanan açık kaynaklı bir uygulama çerçevesidir. Kendinizi tekrar etmeyin, kendi iş kodunuza odaklanın.",
"Layout_AbpFramework_MetaTitle": "ABP Framework - Açık Kaynak Web Uygulama Çerçevesi",
"CommunityTalks_CountdownDays": "Gün",
"CommunityTalks_CountdownHours": "Saat",
"CommunityTalks_CountdownMinutes": "Dk",
"CommunityTalks_CountdownSeconds": "Sn",
"SeePreviousEvents": "Önceki Etkinlikleri Gör",
"CookieConsent_Accept": "Kabul Et",
"CookieConsent_Explanation_1": "Web sitemizde size en iyi deneyimi sunmak için çerezleri kullanıyoruz.",
"CookieConsent_Explanation_2": "Göz atmaya devam ederseniz, <a href=\"@Url.Page(\"/Privacy\")\">Gizlilik politikamızı ve çerez politikamızı kabul etmiş olursunuz.</a>.",
"Error_Page_400_Title": "İstenen sayfa sunulurken bir sorun oluştu.",
"Error_Page_400_Description_1": "Genellikle bu, isteğiniz işlenirken beklenmedik bir hata oluştuğu anlamına gelir.",
"Error_Page_400_Description_2": "Sorun devam ederse, <a href=\"mailto:info@abp.io\">info@abp.io</a> adresinden bizimle iletişime geçin, size yardımcı olalım.",
"GoToHomepage": "Anasayfaya git",
"Error_Page_404_Title": "Sayfa bulunamadı!",
"Error_Page_404_Description_1": "Aradığınız web sayfası bu değil.",
"Error_Page_500_Title": "Görünüşe göre bir şeyler ters gitti!",
"Error_Page_500_Description_1": "Bu hataları otomatik olarak takip ediyoruz, ancak sorun devam ederse <br /> bizimle iletişime geçmekten çekinmeyin. Bu arada, yenilemeyi deneyin.",
"Error_Page_500_Description_2": "Bizimle <a href=\"mailto:info@abp.io\" target=\"_blank\">info@abp.io</a> adresinden iletişime geçin.",
"Books": "Kitaplar",
"ABPDiscordServer": "ABP Discord Sunucusu",
"ABPCommunityTalks": "ABP Topluluk Konuşmaları",
"ABPCommunityPosts": "ABP Topluluk Gönderileri",
"WelcomeFallCampaign": "Hoş Geldin Sonbahar Kampanyası!",
"GiveAwayForNewPurchases": "Yeni alımlar için Uygulama Geliştirme Sınıfı Eğitimi hediye edilecektir!"
}

2
abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/tr.json

@ -1,5 +1,7 @@
{
"culture": "tr",
"texts": {
"AbpTitle": "ABP Framework - Açık Kaynak Web Uygulama Çerçevesi",
"AbpDescription": "ABP, AspNet Core tabanlı web uygulaması geliştirmeye odaklanan açık kaynaklı bir uygulama çerçevesidir. Kendinizi tekrar etmeyin, kendi iş kodunuza odaklanın."
}
}

259
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -178,7 +178,7 @@
"HowManyDevelopers": "ABP Commercial'da kaç geliştirici çalışabilir?",
"HowManyDevelopersExplanation": "ABP Ticari lisansları geliştirici başınadır. Farklı lisans türlerinin farklı geliştirici sınırları vardır. Ancak, ihtiyacınız olduğunda herhangi bir lisans türüne daha fazla geliştirici ekleyebilirsiniz. Lisans türleri, geliştirici sınırları ve ek geliştirici maliyetleri için <a href=\"{0}\">fiyatlar</a> sayfasına bakın.",
"ChangingLicenseType": "Lisans türümü daha sonra yükseltebilir miyim?",
"ChangingLicenseTypeExplanation": "Aktif lisans süreniz içerisinde aradaki farkı ödeyerek bir üst lisansa geçebilirsiniz. Daha yüksek bir lisans planına yükselttiğinizde, yeni planın avantajlarından yararlanırsınız, ancak lisans yükseltmesi, lisansın sona erme tarihini değiştirmez. Ayrıca, mevcut lisansınıza yeni geliştirici lisansları da ekleyebilirsiniz, bkz. \"ABP Ticari üzerinde kaç geliştirici çalışabilir?\"",
"ChangingLicenseTypeExplanation": "Aktif lisans süreniz içerisinde aradaki farkı ödeyerek bir üst lisansa geçebilirsiniz. Daha yüksek bir lisans planına yükselttiğinizde, yeni planın avantajlarından yararlanırsınız, ancak lisans yükseltmesi, lisansın sona erme tarihini değiştirmez. Ayrıca, mevcut lisansınıza yeni geliştirici koltukları da ekleyebilirsiniz, bkz. \"ABP Ticari üzerinde kaç geliştirici çalışabilir?\"",
"LicenseExtendUpgradeDiff": "Lisans uzatma ve yükseltme arasındaki fark nedir?",
"LicenseExtendUpgradeDiffExplanation": "<strong>Uzatma:</strong> Lisansınızı uzatarak/yenileyerek, premium destek almaya ve modüller ve temalar için major veya minor güncellemeler almaya devam edeceksiniz. Ayrıca, yeni projeler oluşturmaya devam edebileceksiniz. Ve geliştirmenizi hızlandıran ABP Suite'i kullanmaya devam edebileceksiniz.<hr/><strong>Yükseltme:</strong> Lisansınızı yükselterek, ek avantajlar elde etmenizi sağlayacak daha yüksek bir lisans planına terfi edeceksiniz. . Lisans planları arasındaki farkları kontrol etmek için <a href=\"/pricing\">lisans karşılaştırma tablosuna</a> bakın.<strong>Öte yandan, yükseltme yaptığınızda lisans geçerlilik bitiş tarihiniz değişmez!</strong >Lisans bitiş tarihinizi uzatmak için lisansınızı uzatmanız gerekir.",
"LicenseRenewalCost": "1 yıl sonra ehliyet yenileme ücreti ne kadardır?",
@ -385,6 +385,261 @@
"RemoveCurrentUserFromOrganizationWarningMessage": "Organizasyondan kendinizi kaldırıyorsunuz. Artık bu organizasyonu yönetemeyeceksiniz, onaylıyor musunuz? ",
"RenewExistingOrganizationOrCreateNewOneMessage": "Aşağıdaki \"Şimdi Uzat\" buton(lar)una tıklayarak organizasyon(lar)ınızın lisansını yenileyebilir ve böylece lisans geçerlilik süresini 1 yıl uzatabilirsiniz. Ödemeye devam ederseniz, yeni bir organizasyonunuz olacak. Yeni bir organizasyonla devam etmek istiyor musunuz? ",
"ExtendNow": "Şimdi Uzat",
"ContinueWithNewOrganization": "Yeni bir organizasyon ile devam et"
"ContinueWithNewOrganization": "Yeni bir organizasyon ile devam et",
"Owner": "sahip",
"AddNewOwner": "Yeni sahip ekle",
"AddNewDeveloper": "Yeni geliştirici ekle",
"FirstNameField": "Ad",
"LastNameField": "Soyad",
"AbpCommercialMetaTitle": "ABP Commercial - Eksiksiz Web Geliştirme Platformu : {0} | ABP Commercial",
"AbpCommercialMetaDescription": "ABP Commercial, açık kaynaklı ABP çerçevesinin üzerine inşa edilmiş önceden oluşturulmuş uygulama modülleri, hızlı geliştirme araçları, kullanıcı arayüzü temaları ve hizmetlerinden oluşan bir settir.",
"WhatHappensWhenLicenseEnds": "Lisans sürem sona erdiğinde ne olacak?",
"WhatHappensWhenLicenseEndsExplanation1": "ABP Ticari lisansı <a href=\"{0}\" target=\"_blank\">kalıcı bir lisanstır</a>. Lisansınızın süresi dolduktan sonra projenizi geliştirmeye devam edebilirsiniz. Ve lisansınızı yenilemek zorunda değilsiniz. Lisansınız kutudan bir yıllık güncelleme ve destek planı ile birlikte gelir. Yeni özellikler, performans geliştirmeleri, hata düzeltmeleri, destek almaya devam etmek ve ABP Suite'i kullanmaya devam etmek için lisansınızı yenilemeniz gerekir. Lisansınızın süresi dolduğunda aşağıdaki avantajlardan yararlanamazsınız:",
"WhatHappensWhenLicenseEndsExplanation2": "ABP Ticari'yi kullanarak yeni çözümler oluşturamazsınız, ancak mevcut uygulamalarınızı sonsuza kadar geliştirmeye devam edebilirsiniz.",
"WhatHappensWhenLicenseEndsExplanation3": "MINOR sürümünüzdeki modüller ve temalar için güncellemeleri alabileceksiniz (RC veya Önizleme sürümleri hariç). Örneğin: bir modülün v3.2.0 sürümünü kullanıyorsanız, bu modülün v3.2.x (v3.2.1, v3.2.5... vb.) sürümleri için güncellemeleri almaya devam edebilirsiniz. Ancak bir sonraki büyük veya küçük sürüm için güncelleme alamazsınız (v3.3.0, v3.3.3, 4.x.x... gibi). Örneğin, lisansınızın süresi dolduğunda, en son sürüm v4.4.3 idi ve daha sonra hem 4.4.4 sürümünü hem de 4.5.0 sürümünü yayınladı, v4.4.X'e erişebilirsiniz, ancak v4.5.X'e erişemezsiniz.",
"WhatHappensWhenLicenseEndsExplanation4": "Lisansınız sona erdikten sonra ABP Ticari platformuna eklenen yeni modülleri ve temaları yükleyemezsiniz.",
"WhatHappensWhenLicenseEndsExplanation5": "ABP Suite'i kullanamazsınız.",
"WhatHappensWhenLicenseEndsExplanation6": "Artık <a href=\"{0}\">premium desteği</a> alamazsınız.",
"WhatHappensWhenLicenseEndsExplanation7": "Bu avantajlardan yararlanmaya devam etmek istiyorsanız lisansınızı uzatabilirsiniz (yenileyebilirsiniz). Lisansınızın süresi dolduktan sonra <strong>1 ay</strong> içinde lisansınızı uzatırsanız, aşağıdaki indirimler uygulanacaktır: Takım Lisansı {0} % indirim, İşletme Lisansı %{1} indirim, Kurumsal Lisans %{2} indirim.",
"WhatHappensWhenLicenseEndsExplanation8": "Oluşturduğunuz ABP projeleri sunucularımızda saklanmamaktadır. Bu nedenle indirdiğiniz kaynak kodunu saklamak sizin sorumluluğunuzdadır. Lisansınızın süresi dolduğunda, oluşturulan ABP proje kaynak kodunuzu almanın bir yolu yoktur.",
"TrialPlanExplanation": "ABP Ticari takım lisansı için 14 günlük deneme süresi var. Daha fazla bilgi için <a href={0} target='_blank'>burayı</a> ziyaret edin. Ayrıca, Takım lisansları için 30 günlük para iade garantisi veriyoruz. Sadece ilk 30 gün içinde geri ödeme talebinde bulunabilirsiniz. İşletme ve Kurumsal lisansları için 30 gün içinde %60 geri ödeme sağlıyoruz. Bunun nedeni, İşletme ve Kurumsal lisanslarının tüm modüllerin ve temaların tam kaynak kodunu içermesidir.",
"ContactUsQuestions": "Herhangi bir sorunuz varsa bizimle iletişime geçin",
"ActivationRequirement": "Denemenizi başlatmanıza son bir adım kaldı.<br>Bilgilerinizi kontrol ettikten sonra lisansınızı etkinleştireceğiz. Lisansınız etkinleştirildiğinde, <b>{0}</b> adresine bir e-posta göndereceğiz. Merak etmeyin bu süreç uzun sürmeyecek!",
"PurchaseNow": "Şimdi satın al",
"DowngradeLicensePlan": "Gelecekte daha düşük bir lisans planına geçebilir miyim?",
"DowngradeLicensePlanExplanation": "Mevcut lisans planınızı düşüremezsiniz. Ancak yeni bir daha düşük lisans planı satın alabilir ve yeni lisans üzerinde geliştirmenize devam edebilirsiniz. Daha düşük bir lisans satın aldıktan sonra, ABP CLI komutu ile yeni lisans planınıza giriş yapmanız yeterlidir: ` abp login <username> -o <organization> `.",
"LicenseTransfer": "Lisans bir geliştiriciden diğerine aktarılabilir mi?",
"LicenseTransferExplanation": "Evet! Bir lisans satın aldığınızda, lisans sahibi olursunuz, dolayısıyla kuruluş yönetim sayfasına erişiminiz olur. Bir kuruluşun sahip ve geliştirici rolleri vardır. Sahipler geliştirici lisanslarını yönetebilir ve geliştiriciler atayabilir. Atanan her geliştirici, ABP CLI komutu sisteme girecek ve geliştirme ve destek izinlerine sahip olacaktır.",
"UserOwnerDescription": "Kuruluşun 'Sahibi' bu hesabın yöneticisidir. Lisansları satın alarak ve geliştiricileri tahsis ederek organizasyonu yönetir. Bir 'Sahip' ABP Ticari projelerine kod yazamaz, ABP örnek projelerini indiremez ve destek web sitesinde soru soramaz. Tüm bunları yapmak istiyorsanız, kendinizi de geliştirici olarak eklemeniz gerekir.",
"UserDeveloperDescription": "'Geliştiriciler' ABP Ticari projelerinde kod yazabilir, ABP örnek projelerini indirebilir ve destek web sitesinde sorular sorabilir. Öte yandan, 'Geliştiriciler' bu organizasyonu yönetemezler.",
"PurchaseTrialOrganizationOrCreateNewOneMessage": "Deneme lisansınız var. Deneme lisansınızı satın almak için Şimdi Satın Al düğmesine tıklayın. Ödeme işlemine devam ederseniz, yeni bir kuruluşunuz olacak. Yeni bir organizasyon ile devam etmek istiyor musunuz?",
"CreateNewOrganization": "Yeni bir organizasyon oluştur",
"RenewLicenseEarly": "Lisansımı erken yenilersem, tüm yılı alacak mıyım?",
"RenewLicenseEarylExplanation": "Lisansınızı lisans bitiş tarihinizden önce yenilediğinizde, lisans bitiş tarihinize 1 yıl eklenecektir. Örneğin, lisansınızın süresi {0}-06-06 tarihinde doluyorsa ve lisansınızı {0}-01-01 tarihinde yenilediyseniz, yeni lisans bitiş tarihiniz {1}-06-06 olacaktır.",
"OpenSourceWebApplication": "Açık Kaynak Web Uygulaması",
"CompleteWebDevelopment": "Tam Web Geliştirme",
"ABPFrameworkDescription": "ABP Framework, yazılım geliştirme ve sözleşmelerin en iyi uygulamalarını takip ederek modern web uygulamaları oluşturmak için eksiksiz bir altyapıdır.",
"CommunityDescription": "ABP Çerçevesi ile ilgili deneyimlerinizi paylaşın!",
"GetStarted": "Başlayın",
"Views": "Görünümler",
"LatestPosts": "Son Gönderiler",
"PreBuiltApplication": "Önceden Oluşturulmuş Uygulama",
"DatabaseProviders": "Veritabanı Sağlayıcıları",
"UIFrameworks": "UI Çerçeveleri",
"UsefulLinks": "Faydalı Bağlantılar",
"Platform": "Platform",
"CoolestCompaniesUseABPCommercial": "En havalı şirketler zaten <span class=\"fw-6\">ABP Commercial</span> kullanıyor.",
"UserInterface": "Kullanıcı Arayüzü",
"APIGateway": "API Ağ Geçidi",
"Microservice": "Mikro Hizmet",
"Database": "Veritabanı",
"Architecture": "Mimari",
"MicroserviceArchitectureExplanation": "Bu, en son teknolojilerle ölçeklenebilir bir mikro hizmet çözümü oluşturmak için birden çok uygulama, API ağ geçidi, mikro hizmet ve veritabanlarından oluşan eksiksiz bir çözüm mimarisidir.",
"BusinessLogic": "İş Mantığı",
"DataAccessLayer": "Veri Erişim Katmanı",
"Monolith": "Monolit",
"ModularArchitectureExplanation": "Bu başlangıç şablonu, temiz ve sürdürülebilir bir kod tabanı oluşturmak için katmanlı, modüler ve DDD tabanlı bir çözüm mimarisi sağlar.",
"SeeDetails": "Ayrıntıları Gör",
"SeeDocumentation": "Belgelere göz atın",
"Bs5Compatible": "Bootstrap 5 uyumlu profesyonel tema, yönetici web siteniz için mükemmel.",
"LeptonXTheme": "LeptonX Tema",
"LeptonXDark": "LeptonX Koyu",
"LeptonXLight": "LeptonX Açık",
"LeptonXSemiDark": "LeptonX Yarı Koyu",
"BuiltOnBs5Library": "Bootstrap 5 kütüphanesi üzerine inşa edilmiştir.",
"FullyCompatibleWithBs5": "Bootstrap 5 HTML yapısı ve CSS sınıfları ile %100 uyumlu",
"ResponsiveAndMobileCompatible": "Responsive, mobil uyumlu, RTL desteği",
"ProvidesStylesForDatatables": "Datatables için stil sağlar",
"MultipleLayoutOptions": "Çoklu düzen seçenekleri",
"EasilyInstallAndUpgrade": "Kolay kurulum ve yükseltme",
"SupportForum": "Destek Forumu",
"TrustedBy": "Güvenenler",
"OurPricing": "<span class=\"gradient-commercial\">Fiyatlandırmamız</span>",
"Plans": "Planlar",
"NameSurname": "Ad Soyad",
"Unspecified": "Belirtilmemiş",
"LicenceType": "Lisans Türü",
"LicenseDiscountWarning": "BU İNDİRİM SAYFASI VARSAYILAN İNDİRİM KODU VE VOLOSOFT GELİŞTİRİCİLERİ İÇİN KULLANILMAKTADIR. AŞAĞIDAKİ SATIN ALMA LİNKLERİ ÇALIŞMAZ.",
"DiscountedLicenseExplanation": "Bu lisans fiyatları küçük girişimler, bireysel geliştiriciler, öğrenciler, kar amacı gütmeyen kuruluşlar ve projeler içindir!",
"General": "Genel",
"License": "Lisans",
"Development": "Geliştirme",
"Payment": "Ödeme",
"WatchExplainerVideo": "Hadi Tanışalım! Açıklayıcı Videoyu İzleyin",
"LightDarkAndSemiDarkThemes": "Açık, koyu ve yarı koyu temalar",
"LeptonXThemeExplanation": "Lepton Teması, temanızı sistem ayarlarınıza göre değiştirebilir.",
"PRO": "PRO",
"WelcomeToABPCommercial": "<span class=\"gradient-commercial\">ABP Commercial</span>'a hoş geldiniz!",
"YourAccountDetails": "Hesap bilgileriniz",
"OrganizationName": "Organizasyon Adı",
"AddDevelopers": "Geliştiriciler Ekle",
"StartDevelopment": "Geliştirmeye Başla",
"CreateAndRunApplicationUsingStartupTemplate": "ABP Ticari başlangıç şablonunu kullanarak yeni bir web uygulamasının nasıl oluşturulacağını ve çalıştırılacağını öğrenin.",
"CommunityDescription2": "<span class=\"fw-6\">community.abp.io</span>, insanların ABP ile ilgili makaleleri paylaşabileceği bir yerdir. Makaleler, öğreticiler, kod örnekleri, vaka çalışmaları arayın ve sizinle aynı kulvarda olan insanlarla tanışın.",
"UseABPSuiteExplanation": "Modüllerin ve temaların kaynak kodunu indirmek için ABP Suite'i kullanın.",
"ManageModulesWithSuite": "ABP modüllerinizi Suite ile de yönetebilirsiniz.",
"LearnHowToInstallSuite": "ABP Suite'in nasıl kurulacağını ve kullanılacağını öğrenin.",
"SeeMore": "Daha fazla göster",
"SeeLess": "Daha az göster",
"LayeredSolutionStructure": "Katmanlı Çözüm Yapısı",
"LayeredSolutionStructureExplanation": "Çözüm, iş mantığınızı altyapıdan ve entegrasyonlardan izole etmek ve kodun sürdürülebilirliğini ve yeniden kullanılabilirliğini en üst düzeye çıkarmak için Etki Alanı Güdümlü Tasarım ilkelerine ve modellerine dayalı olarak katmanlandırılmıştır. ABP Framework, uygulamanız için DDD'yi gerçekten uygulamak üzere soyutlamalar, temel sınıflar ve kılavuzlar sağlamaktadır.",
"MultipleUIOptions": "Çoklu UI Seçenekleri",
"MultipleUIOptionsExplanation": "Kullanıcı Arayüzü oluşturmanın farklı yollarını seviyoruz. Bu başlangıç çözümü, iş uygulamanız için üç farklı UI çerçeve seçeneği sunuyor.",
"MultipleDatabaseOptions": "Çoklu Veritabanı Seçenekleri",
"MultipleDatabaseOptionsExplanation": "İki veritabanı sağlayıcısı seçeneğiniz var (her ikisini de tek bir uygulamada kullanmanın yanı sıra). Herhangi bir ilişkisel veritabanıyla çalışmak için Entity Framework Core'u kullanın ve daha iyi bir performans için düşük seviyeli sorgular yazmanız gerektiğinde isteğe bağlı olarak Dapper'ı kullanın. Belge tabanlı bir NoSQL veritabanı kullanmanız gerekiyorsa MongoDB başka bir seçenektir. Bu sağlayıcılar iyi entegre edilmiş, soyutlanmış ve önceden yapılandırılmış olsa da, .NET ile kullanabileceğiniz herhangi bir veritabanı sistemiyle etkileşime girebilirsiniz. ",
"ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç çözümü zaten temel <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP Ticari modülleri</a> önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.",
"MultiTenancyForSaasBusiness": "Saas İşletmeleri için Çoklu Kiralama",
"MultiTenancyForSaasBusinessExplanation": "ABP Commercial, SaaS (Hizmet Olarak Yazılım) sistemlerinizi oluşturmak için eksiksiz, uçtan uca çoklu kiracılık sistemi sağlar. Anında veritabanı oluşturma ve taşıma sistemi ile kiracıların kendi veritabanlarını paylaşmalarına veya sahip olmalarına olanak tanır.",
"MicroserviceStartupSolution": "Mikro Hizmet Başlangıç Çözümü",
"MicroserviceArchitectureExplanation2": "Önceden oluşturulmuş temel çözümden ve damıtılmış deneyimden yararlanmak için bir sonraki mikro hizmet sisteminiz için alabilirsiniz.",
"PreIntegratedTools": "Popüler araçlara önceden entegre edilmiş",
"PreIntegratedToolsExplanation": "Çözüm halihazırda endüstri standardı araçlara ve teknolojilere entegre edilmiş durumda, ancak siz bunları her zaman değiştirebilir ve favori araçlarınıza entegre edebilirsiniz.",
"SingleSignOnAuthenticationServer": "Tek Oturum Açma Kimlik Doğrulama Sunucusu",
"SingleSignOnAuthenticationServerExplanation": "Çözüm, API erişim yönetimi özelliklerine sahip tek oturum açma sunucusu olarak diğer uygulamalar tarafından kullanılan bir kimlik doğrulama sunucusu uygulamasına sahiptir. IdentityServer tabanlıdır.",
"WebAppsWithGateways": "2 API Ağ Geçidi ile 2 Web Uygulaması",
"WebAppsWithGatewaysExplanation": "Çözüm, her biri özel bir API ağ geçidine sahip iki web uygulaması içeriyor (BFF - Backend For Frontend modeli).",
"BackOfficeApplication": "Back Office Uygulaması",
"BackOfficeApplicationExplanation": "Birden fazla UI çerçeve seçeneği ile sisteminizin gerçek web uygulaması. Her türlü iş uygulamasını oluşturabilirsiniz.",
"LandingWebsite": "Açılış Web Sitesi",
"LandingWebsiteExplanation": "Şirketinizi tanıtmak, ürünlerinizi satmak gibi çeşitli amaçlar için kullanılabilecek genel bir açılış/genel web sitesi.",
"ABPFrameworkEBook": "Mastering ABP Framework e-kitabı",
"MasteringAbpFrameworkEBookDescription": "ABP Ticari lisansınıza dahildir",
"FullName": "Tam Ad",
"LicenseTypeNotCorrect": "Lisans tipi doğru değil.",
"Trainings": "Eğitimler",
"ChooseTrainingPlaceholder": "Eğitim seçin ...",
"DoYouNeedTrainings": "Bu eğitimlerden birine ihtiyacınız var mı?",
"DoYouNeedTraining": "{0} eğitimine ihtiyacınız var mı?",
"GetInTouchUs": "Bize Ulaşın",
"ForMoreInformationClickHere": "Daha fazla bilgi için <a href='{0}'>buraya tıklayın.</a>",
"IsGetOnboardingTraining": "İşe alım ve web uygulaması geliştirme eğitimi almak ister misiniz?",
"OnboardingWebApplicationDevelopmentTrainingMessage": "Eğitim takviminizi planlamak için lütfen organizasyonu oluşturduktan sonra {0} ile iletişime geçin",
"CustomPurchaseMessage": "Bir sonraki adım için, bizimle iletişime geçmek üzere {0}'a tıklayın.",
"Note": "Not",
"AdditionalNote": "Ek Not",
"OnboardingTrainingFaqTitle": "ABP onboarding eğitiminiz var mı?",
"OnboardingTrainingFaqExplanation": " Evet, ABP projenizi hızlı bir şekilde başlatmanıza yardımcı olacak ABP Eğitim Hizmetlerimiz var. Bir ABP çekirdek ekip üyesinden ABP hakkında bilgi edinecek ve ABP projenize başlamak için gereken becerileri edineceksiniz. İlk katılım eğitiminde, geliştirme ortamınızı nasıl kuracağınızı, gerekli araçları nasıl yükleyeceğinizi ve tamamen işlevsel bir CRUD sayfasını nasıl oluşturacağınızı açıklayacağız. Eğitim canlı olacak ve Zoom uygulaması kullanılacaktır, ancak diğer çevrimiçi toplantı platformlarını kullanmaya da açığız. Eğitim dili İngilizce olacaktır. ABP ile ilgili sorularınızı oturumlar sırasında da sorabilirsiniz. Her iki taraf için de uygun bir zaman ve tarih planlanacaktır. Daha fazla bilgi almak için <a href=\"mailto:info@abp.io\">info@abp.io</a> adresinden bizimle iletişime geçebilirsiniz.",
"AddBasket": "Sepete Ekle",
"SendTrainingRequest": "Eğitim Talebi Gönder",
"OnlyEnglishVersionOfThisDocumentIsTheRecentAndValid": "* Bu belgenin İngilizce versiyonu en güncel olanıdır ve herhangi bir anlaşmazlıkta İngilizce versiyonu geçerli olacaktır.",
"Pricing_Page_Title": "Planlar ve Fiyatlandırma",
"Pricing_Page_Description": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevselliği seçin. Bir ABP Ticari lisansı satın alın ve sınırsız proje oluşturun.",
"Pricing_Page_HurryUp": "Acele edin!",
"Pricing_Page_BuyLicense": "16 Ocak'a kadar <strong>2021 fiyatlarıyla</strong> lisans satın alın!",
"Pricing_Page_ValidForExistingCustomers": "Mevcut müşteriler ve lisans yenilemeleri için de geçerlidir.",
"Pricing_Page_Hint1": "Lisans fiyatına belirli sayıda geliştirici koltuğu dahildir. Daha fazla geliştiriciniz varsa, her zaman ek koltuk satın alabilirsiniz.",
"Pricing_Page_Hint2": "Şimdi veya gelecekte daha fazla geliştirici koltuğu satın alabilirsiniz. Lisanlar koltuk bazlıdır, bu nedenle bir koltuğu bir geliştiriciden diğerine aktarabilirsiniz.",
"Pricing_Page_Hint3": "Lisansınız ile sınırsız sayıda farklı ürün geliştirebilirsiniz.",
"Pricing_Page_Hint4": "ABP Suite, üretkenliğinizi artırmak için geliştirmenize yardımcı olacak bir araçtır. CRUD sayfaları oluşturmayı ve yeni projeler oluşturmayı destekler.",
"Pricing_Page_Hint5": "Önceden oluşturulmuş tüm modülleri uygulamalarınızda kullanabilirsiniz.",
"Pricing_Page_Hint6": "Önceden oluşturulmuş tüm temaları uygulamalarınızda kullanabilirsiniz.",
"Pricing_Page_Hint7": "Başlangıç şablonu, projenize hızlı bir başlangıç yapmanızı sağlayan bir Visual Studio çözümüdür. Tüm temel modüller eklenir ve sizin için önceden yapılandırılır.",
"Pricing_Page_Hint8": "Mastering ABP Framework e-kitabı, .NET çözümlerinin en iyi uygulamalarla nasıl hayata geçirileceğini anlatıyor. Amazon.com'da satılmaktadır ve kitabı lisansınız dahilinde ücretsiz olarak indirebilirsiniz.",
"Pricing_Page_Hint9": "Herhangi bir modülün kaynak kodunu indirebilirsiniz. Köklü değişiklikler yapmak için kaynak kodunu çözümünüze eklemek veya güvenlik nedeniyle kendinize saklamak isteyebilirsiniz.",
"Pricing_Page_Hint10": "Lisanslar ömür boyu geçerlidir. Bu, uygulamanızı sonsuza kadar geliştirmeye devam edebileceğiniz anlamına gelir. En son sürüme erişim ve destek alma lisans süresi içinde (yenilemediğiniz sürece 1 yıl) verilir.",
"Pricing_Page_Hint11": "Dağıtım konusunda kısıtlama yok! Bulut hizmetleri veya şirket içi dahil olmak üzere istediğiniz kadar sunucuya dağıtabilirsiniz.",
"Pricing_Page_Hint12": "Aktif lisans süreniz içinde modülleri, temaları ve araçları en son sürüme güncelleyebilirsiniz. Lisansınızın süresi dolduktan sonra, hata düzeltmeleri, yeni özellikler ve geliştirmelerle ilgili güncellemeleri almaya devam etmek için lisansınızı yenilemeniz gerekir.",
"Pricing_Page_Hint13": "Premium desteği bir yıl boyunca alabilirsiniz (uzatmak için lisansınızı yenileyebilirsiniz).",
"Pricing_Page_Hint14": "Ekip ve İşletme lisanslarının olay/soru sayısı limiti vardır. Ek geliştirici lisansları satın alırsanız, olay limitiniz geliştirici başına {0} (Ekip Lisansı için) veya {1} (İşletme Lisansı için) artar.",
"Pricing_Page_Hint15": "Sadece Kurumsal Lisans özel destek içerir. Özel bilet seçeneği ile doğrudan ABP Ekibine e-posta gönderebilir veya support.abp.io adresinden soru sorabilirsiniz. Özel biletler herkese açık değildir.",
"Pricing_Page_Hint16": "Tüm ABP temalarının kaynak kodunu indirebilirsiniz. Köklü değişiklikler yapmak için kaynak kodunu çözümünüze eklemek isteyebilir veya güvenlik nedeniyle kendiniz için saklayabilirsiniz.",
"Pricing_Page_Testimonial_1": "ABP Commercial, SC Ventures'ın 9 ay içinde banka sınıfı çok kiracılı bir silo-veritabanı SaaS platformu sunmasını ve birden fazla entegre çapadan gelen önemli değerdeki faturaların alacak / borç hesapları tedarik zinciri finansmanını desteklemesini sağladı. ABP'nin modülerliği, ekibin rekor sürede teslimat yapmasını, tüm VAPT'leri geçmesini ve konteynerleştirilmiş mikro hizmet yığınını tam CI/CD ve boru hatları aracılığıyla üretime dağıtmasını mümkün kıldı.",
"Pricing_Page_Testimonial_2": "Özel geliştirme projelerinin ek yükünü azaltmak için ABP Commercial kullanmanın değerini görüyoruz. Ekip, farklı proje akışlarında kod modelini birleştirebiliyor. Yeni özellikleri eskisinden daha hızlı oluşturabilmemiz için çerçevede daha fazla potansiyel görüyoruz. ABP Commercial'dan yararlanmanın değerini sürekli olarak göreceğimize inanıyoruz.",
"Pricing_Page_Testimonial_3": "ABP'yi seviyoruz. Her şeyi sıfırdan yazmak zorunda kalmıyoruz. Kullanıma hazır özelliklerden başlıyoruz ve sadece gerçekten yazmamız gerekenlere odaklanıyoruz. Ayrıca, ABP iyi tasarlanmış ve kod daha az hata ile yüksek kalitede. İhtiyaç duyduğumuz her şeyi kendi başımıza yazmak zorunda kalsaydık, yıllarımızı harcamak zorunda kalabilirdik. Hoşumuza giden bir diğer şey de yeni sürümün, sorun düzeltmenin ya da iyileştirmenin iki haftada bir çıkması. Çok uzun süre beklemiyoruz.",
"Pricing_Page_Testimonial_4": "ABP Commercial harika bir ürün, tavsiye ederim. Müşterilerimiz için ticari ürünleri tek bir yapılandırılabilir platformda pazara sunuyor. Çerçeve ve araçların herhangi bir ekibe sağladığı hızlı başlangıç her kuruşa değer. ABP Commercial ihtiyaçlarımız için en uygun üründü.",
"Pricing_Page_Testimonial_5": "ABP Framework sadece bir framework değil, aynı zamanda bir proje geliştirme/yönetme rehberi, çünkü DDD, GenericRepository, DI, Microservice ve Modularity eğitimleri veriyor. Framework'ün kendisini kullanmayacak olsanız bile, iyi ve profesyonelce hazırlanmış docs.abp.io ile kendinizi geliştirebilirsiniz (OpenIddict, Redis, Quartz vb.). Birçok şey önceden hazır olduğu için proje geliştirme süresini önemli ölçüde kısaltıyor (Giriş sayfası, istisna işleme, veri filtreleme, tohumlama, denetim günlüğü, yerelleştirme, otomatik API denetleyicisi vb.) Uygulamamızdan bir örnek olarak, stok kontrolü için Local Event Bus kullandım. Böylece stok işleyicisi yazarak sipariş hareketlerini yönetebiliyorum. CreationTime, CreatorId için zaman kaybetmemek harika. Bunlar otomatik olarak dolduruluyor.",
"AbpBookDownloadArea_ClaimYourEBook": "<span class='gradient-framework'>Mastering ABP Framework</span> E-Kitabınızı talep edin",
"AddMemberModal_Warning_1": "Eklemeye çalıştığınız <strong>kullanıcı adı</strong> sistemde yoksa, lütfen ekip üyenizden <a href='{0}/Account/Register'>{0}</a> adresine kaydolmasını ve hesabının kullanıcı adını sizinle paylaşmasını isteyin.",
"MyOrganizations_Detail_WelcomeMessage": "Organizasyonunuza hoş geldiniz, {0}",
"MyOrganizations_Detail_OrganizationManagement": "Organizasyon <span class=\"gradient-commercial\">Yönetimi</span>",
"OrganizationDisplayName": "Organizasyon Görünür Adı",
"MyOrganizations_Detail_EditDisplayName": "Görünür adı düzenle",
"MyOrganizations_Detail_LicenseStartAndExpiryDate": "Lisans Başlangıç Tarihi - Sona Erme Tarihi",
"MyOrganizations_Detail_OwnerRightInfo": "{1} sahiplik hakkınızın {0}'ını kullanıyorsunuz.",
"MyOrganizations_Detail_CopyApiKey": "Anahtarı Kopyala",
"MyOrganizations_Detail_ApiKeyDescription": "API Anahtarı, <a href=\"{0}\" target=\"_blank\" class=\"text-primary\" rel=\"noopener\">{1}</a> üzerinde barındırılan PRO paketlerinin belirtecidir.",
"MyOrganizations_Detail_YourPrivateNugetSource": "Özel NuGet kaynağınız <a href=\"{0}\" arget=\"_blank\" class=\"text-primary\" rel=\"noopener\">{0}</a>",
"MyOrganizations_Detail_PrivateNugetSourceWarning": "Bu, ABP çözümünüzdeki NuGet.Config'inize otomatik olarak bir besleme olarak eklenir. Özel anahtarınızı yetkisiz kullanıcılarla paylaşmayın!",
"MyOrganizations_Detail_DeveloperSeatInfo": "{1} geliştirici koltuğunuzun {0} tanesini kullanıyorsunuz.",
"NeedMoreSeatsForYourTeam": "Takımınız için daha fazla geliştirici koltuğu gerekiyor mu?",
"MyOrganizations_Detail_PricePerYear": "{0} / per year",
"MyOrganizations_Detail_UpgradeYourLicense": "Lisansınızı yükseltin",
"MyOrganizations_Detail_PurchaseDeveloperSeats": "Geliştirici Koltuğu Satın Alın",
"Invoices": "Faturalar",
"RequestInvoice": "Fatura Talep Et",
"OrderNumber": "Sipariş Numarası",
"Date": "Tarih",
"Products": "Ürünler",
"TotalPrice": "Toplam Fiyat",
"ThereIsNoInvoice": "Fatura yok",
"MyOrganizations_Detail_PaymentProviderInfo": "Lisansınızı <i>{0}</i> ağ geçidi üzerinden satın aldıysanız, PDF faturasını e-posta adresinize gönderir, bkz. <a href=\"{1}\" target=\"_blank\"> {0} faturalandırma.</a>",
"MyOrganizations_Detail_PayUInfo": "If you have purchased through the <i>PayU</i> gateway, click the \"Request Invoice\" button and fill in the billing information.",
"MyOrganizations_Detail_ConclusionInfo": "Fatura talebiniz {0} iş günü içerisinde sonuçlandırılacaktır.",
"ExtendYourLicense": "{0} lisansınızı uzatın",
"Continue": "Devam et",
"DownloadInvoiceModal_DownloadInvoice": "Faturayı İndir",
"DownloadInvoiceModal_SaveInformationOnlyOnce": "Fatura bilgilerinizi yalnızca bir kez kaydedebilirsiniz.",
"InvoiceModal_EnterCompanyName": "Yasal şirket adınızı girin...",
"InvoiceModal_EnterCompanyAddress": "Yasal şirket adresinizi girin...",
"InvoiceModal_EnterTaxNumber": "Varsa VERGİ/KDV numaranızı girin...",
"RequestInvoiceModal_EnterNotes": "Faturanızla ilgili ekstra mesajınızı girin...",
"PrePayment_PayWithIyzico": "Iyzico ile ödeyeceksiniz",
"ContinueToCheckout": "Ödeme ekranına git",
"PrePayment_IyzicoRedirectionInfo": "Satın alma işleminizi güvenli bir şekilde tamamlamak için Iyzico Ödeme Geçidine yönlendirileceksiniz.",
"PrePayment_IyzicoAcceptVisaAndMasterCard": "Iyzico Visa ve MasterCard kabul etmektedir.",
"Purchase": "Satın al",
"AcceptTermsAndConditions": "<a href=\"{0}\" target=\"_blank\" class=\"text-primary\" rel=\"noopener\">Gizlilik politikasını</a>, <a href=\"{1}\" target=\"_blank\" class=\"text-primary\" rel=\"noopener\">hüküm ve koşulları</a> ve <a href=\"{2}\" target=\"_blank\" class=\"text-primary\">EULA</a>'yı okudum, anladım ve kabul ediyorum.",
"AcceptTermsAndConditionsWarningMessage": "Lütfen gizlilik politikasını ve hüküm ve koşulları kabul edin",
"SelectGatewayToContinue": "Devam etmek için lütfen bir Ağ Geçidi seçin!",
"GatewaySelection_SelectGateway": "Bir Ödeme Ağ Geçidi Seçin",
"GatewaySelection_RedirectionMessage": "Sonrasında, işlem için seçilen ödeme ağ geçidinin web sitesine yönlendirileceksiniz.",
"PaymentSucceed_PaymentSuccessMessage": "Ödeme Başarılı",
"PaymentSucceed_ThanksForPurchase": "Satın aldığınız için teşekkür ederiz!",
"PaymentSucceed_CreateYourOrganization": "Organizasyonunuzu oluşturun",
"PaymentSucceed_AddMeAsDeveloper": "Ben de bir geliştiriciyim, beni organizasyonuma bir geliştirici olarak ekleyin.",
"PaymentSucceed_CreateOrganization": "Organizasyon Oluştur",
"PaymentSucceed_OrganizationDescription": "Bir organizasyon geliştiriciler ve sahiplerden oluşur. Geliştiriciler, ABP projesinde kod yazan ve <a href=\"{0}\" target=\"_blank\">{1}</a> web sitesinden yararlanacak olan kullanıcılardır. Sahipler ise geliştirici koltuklarını tahsis eden ve lisanslamayı yöneten kullanıcılardır.",
"PaymentSucceed_ViewOrganization": "Organizasyonu görüntülemek için buraya tıklayın",
"Purchase_TotalAnnualPrice": "TOPLAM <small class=\"opacity-50\">(yıllık ücret)</small>",
"Purchase_TrainingPrice": "Eğitim Fiyatı",
"Purchase_OnboardingTraining": "ABP Onboarding & Web Uygulama Geliştirme Canlı Eğitimi",
"TotalDeveloperPrice": "Toplam Geliştirici Fiyatı",
"Purchase_PricePerDeveloper": "<span>{0} {1}</span> geliştirici başına",
"Purchase_IncludedDeveloperInfo": "{0} {1} dahil.",
"Purchase_LicenseExtraDeveloperPurchaseMessage": "<span class=\"fw-6\">{0} lisansı</span> {1} geliştirici(ler) içerir. Şimdi veya daha sonra ek geliştiriciler ekleyebilirsiniz.",
"StartupTemplates_Page_Title": "Başlangıç Şablonları",
"StartupTemplates_Page_Description": "ABP Commercial, her düzeyde karmaşıklığa sahip çözümler oluşturmanıza olanak tanır. Önceden oluşturulmuş iki ana başlangıç çözümü sunar. Gereksinimlerinize yakın olanı seçebilir ve bunun üzerine kendi özel çözümünüzü oluşturabilirsiniz.",
"MicroserviceStartupSolutionForDotnet": ".NET için Mikro Hizmet Başlatma Çözümü",
"MonolithSolutionForDotnet": ".NET için Monolith (modüler) Çözüm",
"TrainingDetailsHeaderInfo_TrainingHour": "{0} saat(ler)",
"Trainings_Content": "Eğitim İçeriği",
"Trial_Page_StartYourFreeTrial": "<span class=\"gradient-commercial\">Ücretsiz Denemenizi</span> Başlatın",
"TrialLicenseFeatures": "Tüm ABP ticari özelliklerinden yararlanabileceksiniz",
"TrialPeriodDays": "{0} günlük Takım Lisansınız olacak",
"TrialForumSupportIncident": "{0} forum destek olayınız olacak",
"Contact_Page_Title": "ABP Geliştirme Ekibi ile İletişime Geçin",
"Contact_Page_Description": "Herhangi bir yardıma ihtiyacınız olursa veya düşüncelerinizi ve görüşlerinizi paylaşırsanız ABP Geliştirme ekibi ile iletişime geçin! ABP Destek Ekibi yardıma hazır.",
"Demo_Page_Title": "Demo Oluştur",
"Demo_Page_Description": "ABP Ticari başlangıç şablonu kullanılarak oluşturulan örnek bir uygulamayı görmek için ücretsiz bir demo oluşturun. Ortak uygulama gereksinimleri için kendinizi tekrar etmeyin.",
"Discounted_Page_Title": "İndirimli fiyatlandırma",
"Discounted_Page_Description": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevselliği seçin. Bir ABP Ticari lisansı satın alın ve sınırsız proje oluşturun",
"Faq_Page_Title": "Sıkça Sorulan Sorular (SSS)",
"Faq_Page_Description": "Herhangi bir sorunuz var mı? Sıkça sorulan soruları arayın veya iletişim formunu kullanarak bize bir soru sorun.",
"Faq_Page_SwiftCode": "SWIFT Kodu",
"Faq_Page_BankName": "Banka Adı",
"Faq_Page_AccountName": "Hesap Adı",
"Faq_Page_AccountNumber": "Hesap Numarası",
"Faq_Page_Currency": "Para Birimi",
"Faq_Page_VatNumber": "Vergi Numarası",
"Faq_Page_OtherCurrenciesInfo": "Diğer para birimleri için <a href='{0}'>tüm hesaplar</a> bölümüne bakınız",
"ModuleDetail_Page_Title": "Modül Detayı - {0}",
"ProjectCreatedSuccess_Page_Title": "Projeniz oluşturuldu",
"ProjectCreatedSuccess_Page_Description": "ABP projeniz başarıyla oluşturuldu!",
"Suite_Page_Title": "ABP Suite - CRUD Sayfaları Oluşturun",
"Suite_Page_Description": "ABP Commercial, geliştirici verimliliğini artırmak için hızlı uygulama geliştirme araçları sağlar. ABP Suite, CRUD sayfalarını kolayca oluşturmanızı sağlar.",
"Themes_Page_Title": "Modern ve İşlevsel Kullanıcı Arayüzü Temaları",
"Themes_Page_Description": "ABP Commercial birden fazla profesyonel, modern kullanıcı arayüzü teması sunar. Kullanıcı arayüzünün neye benzediğini hızlıca görmek için ücretsiz bir demo oluşturun.",
"Tools_Page_Title": "Hızlı Uygulama Geliştirme Araçları"
}
}

2
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json

@ -38,7 +38,7 @@
"NoDataAvailableInDatatable": "Engar upplýsingar fáanlegar",
"Total": "Samtals",
"Selected": "valið",
"PagerShowMenuEntries": "Sýna færslur _Aðalvalmyndar_",
"PagerShowMenuEntries": "Sýna færslur _MENU_",
"DatatableActionDropdownDefaultText": "Aðgerðir",
"ChangePassword": "Breyta lykilorði",
"PersonalInfo": "Prófílinn minn",

4
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/tr.json

@ -29,6 +29,8 @@
"ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Bu alan en fazla {0} uzunluğunda bir metin olmalıdır.",
"ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Bu alan en az {1}, en fazla {0} uzunluğunda bir metin olmalıdır.",
"ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Bu alan geçerli bir http, https, ya da ftp adresi olmalıdır.",
"ThisFieldIsInvalid.": "Bu alan geçerli değil."
"ThisFieldIsInvalid.": "Bu alan geçerli değil.",
"ThisFieldMustBeGreaterThanOrEqual{0}": "Bu alan {0}'dan büyük veya eşit olmalıdır.",
"ThisFieldMustBeLessOrEqual{0}": "Bu alan {0}'dan küçük veya eşit olmalıdır."
}
}

2
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/tr.json

@ -1,6 +1,6 @@
{
"culture": "tr",
"texts": {
"Volo.Abp.Http.DynamicProxying:10001": "Verilerle ilgili iş istisnası: {0}"
}
}

3
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/tr.json

@ -5,6 +5,7 @@
"Car": "Araba",
"CarPlural": "Araba",
"MaxLenghtErrorMessage": "Bu alanın uzunluğu maksimum '{0}' karakter olabilir",
"Universe": "Evren"
"Universe": "Evren",
"FortyTwo": "Kırk iki"
}
}

2
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/tr.json

@ -1,6 +1,6 @@
{
"culture": "tr",
"texts": {
"SeeYou": "Görüşürüz"
}
}

4
modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json

@ -56,6 +56,8 @@
"ShareOn": "Paylaş",
"TitleLengthWarning": "Başlığınınz SEO dostu olabilmesi için 60 karakterden az olmasını sağlayın!",
"ClearCache": "Önbelleği temizle",
"ClearCacheConfirmationMessage": "Önbelleği temizlemek istediğinizden emin misiniz?"
"ClearCacheConfirmationMessage": "Önbelleği temizlemek istediğinizden emin misiniz?",
"MarkdownSupported": "Markdown destekleniyor",
"FileUploadInfo": "Kopyalanan bir görüntüyü sürükleyin, bırakın veya yapıştırın."
}
}

3
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json

@ -126,7 +126,6 @@
"ReplyTo": "Cevap",
"SamplePageMessage": "Pro modulünden örnek bir sayfa",
"SaveChanges": "Değişiklikleri Kaydet",
"Script": "Script Kodları",
"SelectAll": "Hepsini seç",
"Send": "Gönder",
"SendMessage": "Mesajı Gönder",
@ -137,7 +136,6 @@
"SourceUrl": "Kaynak Link",
"Star": "Yıldız",
"StartDate": "Başlangıç Tarihi",
"Style": "Stil Kodları",
"Subject": "Konu",
"SubjectPlaceholder": "Lütfen bir konu yazınız",
"Submit": "Kaydet",
@ -191,6 +189,7 @@
"Add": "Ekle",
"AddWidget": "Widget Ekle",
"PleaseConfigureWidgets": "Lütfen widget'leri yapılandırın",
"Permission:GlobalResources": "Global Kaynaklar",
"Feature:CmsKitGroup": "Cms Kit",
"Feature:BlogEnable": "Blog sayfasını etkinleştirin",
"Feature:BlogEnableDescription": "Uygulamınızdaki blog sayfasını etkinleştirir.",

2
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml

@ -29,7 +29,7 @@
var group = Model.SettingPageCreationContext.Groups[i];
var active = i == 0 ? "active" : string.Empty;
<li class="nav-item">
<a class="nav-link @active" data-id="@group.Id" data-bs-toggle="pill" role="tab">@group.DisplayName</a>
<a href="javascript:;" class="nav-link @active" data-id="@group.Id" data-bs-toggle="pill" role="tab">@group.DisplayName</a>
</li>
}
</ul>

6
npm/ng-packs/packages/schematics/package.json

@ -9,12 +9,12 @@
"license": "MIT",
"schematics": "./collection.json",
"dependencies": {
"@angular-devkit/core": "~11.0.2",
"@angular-devkit/schematics": "~11.0.2",
"@angular-devkit/core": "~13.3.9",
"@angular-devkit/schematics": "~13.3.9",
"got": "^11.5.2",
"jsonc-parser": "^2.3.0",
"should-quote": "^1.0.0",
"typescript": "~3.9.2"
"typescript": "~4.6.4"
},
"devDependencies": {
"@schematics/angular": "~11.0.2",

5
npm/ng-packs/packages/schematics/src/collection.json

@ -24,6 +24,11 @@
"description": "ABP API Generator Schematics",
"factory": "./commands/api",
"schema": "./commands/api/schema.json"
},
"create-lib": {
"description": "ABP Create Library Schematics",
"factory": "./commands/create-lib",
"schema": "./commands/create-lib/schema.json"
}
}
}

4
npm/ng-packs/packages/schematics/src/commands/api/index.ts

@ -13,7 +13,7 @@ import { Exception } from '../../enums';
import { GenerateProxySchema, ServiceGeneratorParams } from '../../models';
import {
applyWithOverwrite,
buildDefaultPath,
buildTargetPath,
createControllerToServiceMapper,
createImportRefsToModelReducer,
createImportRefToEnumMapper,
@ -42,7 +42,7 @@ export default function (schema: GenerateProxySchema) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const target = await resolveProject(tree, params.target!);
const targetPath = buildDefaultPath(target.definition);
const targetPath = buildTargetPath(target.definition, params.entryPoint);
const readProxyConfig = createProxyConfigReader(targetPath);
const createProxyConfigWriter = createProxyConfigWriterCreator(targetPath);
const data = readProxyConfig(tree);

9
npm/ng-packs/packages/schematics/src/commands/api/schema.json

@ -39,6 +39,15 @@
"index": 3
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
},
"entryPoint": {
"description": "Target Angular project to place the generated code",
"type": "string",
"$default": {
"$source": "argv",
"index": 5
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
}
},
"required": []

44
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/.eslintrc.json.template

@ -0,0 +1,44 @@
{
"extends": "../../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"projects/<%= kebab(libraryName) %>/tsconfig.lib.json",
"projects/<%= kebab(libraryName) %>/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "lib",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "lib",
"style": "kebab-case"
}
]
}
},
{
"files": [
"*.html"
],
"rules": {}
}
]
}

7
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/ng-package.json.template

@ -0,0 +1,7 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/<%= kebab(libraryName) %>/config",
"lib": {
"entryFile": "src/public-api.ts"
}
}

12
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/__libraryName@kebab__-config.module.ts.template

@ -0,0 +1,12 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { <%= macro(libraryName) %>_ROUTE_PROVIDERS } from './providers/route.provider';
@NgModule()
export class <%= pascal(libraryName) %>ConfigModule {
static forRoot(): ModuleWithProviders<<%= pascal(libraryName) %>ConfigModule> {
return {
ngModule: <%= pascal(libraryName) %>ConfigModule,
providers: [<%= macro(libraryName) %>_ROUTE_PROVIDERS],
};
}
}

1
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/enums/index.ts.template

@ -0,0 +1 @@
export * from './route-names';

3
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/enums/route-names.ts.template

@ -0,0 +1,3 @@
export const enum e<%= pascal(libraryName) %>RouteNames {
<%= pascal(libraryName) %> = '<%= pascal(libraryName) %>',
}

1
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/providers/index.ts.template

@ -0,0 +1 @@
export * from './route.provider';

26
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/providers/route.provider.ts.template

@ -0,0 +1,26 @@
import { eLayoutType, RoutesService } from '@abp/ng.core';
import { APP_INITIALIZER } from '@angular/core';
import { e<%= pascal(libraryName) %>RouteNames } from '../enums/route-names';
export const <%= macro(libraryName) %>_ROUTE_PROVIDERS = [
{
provide: APP_INITIALIZER,
useFactory: configureRoutes,
deps: [RoutesService],
multi: true,
},
];
export function configureRoutes(routesService: RoutesService) {
return () => {
routesService.add([
{
path: '/<%= kebab(libraryName) %>',
name: e<%= pascal(libraryName) %>RouteNames.<%= pascal(libraryName) %>,
iconClass: 'fas fa-book',
layout: eLayoutType.application,
order: 3,
},
]);
};
}

3
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/config/src/public-api.ts.template

@ -0,0 +1,3 @@
export * from './enums';
export * from './<%= kebab(libraryName) %>-config.module';
export * from './providers';

44
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/karma.conf.js.template

@ -0,0 +1,44 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/my-project-name'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

7
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/ng-package.json.template

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/<%= kebab(libraryName) %>",
"lib": {
"entryFile": "src/public-api.ts"
}
}

11
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/package.json.template

@ -0,0 +1,11 @@
{
"name": "@<%= kebab(libraryName) %>/<%= kebab(libraryName) %>",
"version": "0.0.1",
"peerDependencies": {
"@abp/ng.core": "<%= abpVersion %>",
"@abp/ng.theme.shared": "<%= abpVersion %>"
},
"dependencies": {
"tslib": "^2.1.0"
}
}

18
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/lib/__libraryName@kebab__-routing.module.ts.template

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { DynamicLayoutComponent } from '@abp/ng.core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: '',
pathMatch: 'full',
component: DynamicLayoutComponent,
children: [],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class <%= pascal(libraryName) %>RoutingModule {}

22
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/lib/__libraryName@kebab__.module.ts.template

@ -0,0 +1,22 @@
import { NgModule, NgModuleFactory, ModuleWithProviders } from '@angular/core';
import { CoreModule, LazyModuleFactory } from '@abp/ng.core';
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { <%= pascal(libraryName) %>RoutingModule } from './<%= kebab(libraryName) %>-routing.module';
@NgModule({
declarations: [],
imports: [CoreModule, ThemeSharedModule, <%= pascal(libraryName) %>RoutingModule],
exports: [],
})
export class <%= pascal(libraryName) %>Module {
static forChild(): ModuleWithProviders<<%= pascal(libraryName) %>Module> {
return {
ngModule: <%= pascal(libraryName) %>Module,
providers: [],
};
}
static forLazy(): NgModuleFactory<<%= pascal(libraryName) %>Module> {
return new LazyModuleFactory(<%= pascal(libraryName) %>Module.forChild());
}
}

4
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/public-api.ts.template

@ -0,0 +1,4 @@
/*
* Public API Surface of my-project-name
*/
export * from './lib/<%= kebab(libraryName) %>.module';

26
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/src/test.ts.template

@ -0,0 +1,26 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

20
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/tsconfig.lib.json.template

@ -0,0 +1,20 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

10
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/tsconfig.lib.prod.json.template

@ -0,0 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"compilationMode": "partial"
}
}

17
npm/ng-packs/packages/schematics/src/commands/create-lib/files-package/__libraryName@kebab__/tsconfig.spec.json.template

@ -0,0 +1,17 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

7
npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/ng-package.json.template

@ -0,0 +1,7 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/<%= kebab(target) %>/<%= kebab(libraryName) %>",
"lib": {
"entryFile": "src/public-api.ts"
}
}

11
npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/src/lib/__target@kebab__-__libraryName@kebab__.module.ts.template

@ -0,0 +1,11 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
@NgModule()
export class <%= pascal(target) %><%= pascal(libraryName) %>Module {
static forRoot(): ModuleWithProviders<<%= pascal(target) %><%= pascal(libraryName) %>Module> {
return {
ngModule:<%= pascal(target) %><%= pascal(libraryName) %>Module,
providers: []
}
}
}

1
npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/src/lib/index.ts.template

@ -0,0 +1 @@
export * from './<%= kebab(target) %>-<%= kebab(libraryName) %>.module';

1
npm/ng-packs/packages/schematics/src/commands/create-lib/files-secondary-entrypoint/__libraryName@kebab__/src/public-api.ts.template

@ -0,0 +1 @@
export * from './lib/index';

159
npm/ng-packs/packages/schematics/src/commands/create-lib/index.ts

@ -0,0 +1,159 @@
import {
applyTemplates,
chain,
move,
noop,
Rule,
SchematicContext,
SchematicsException,
Tree,
url,
} from '@angular-devkit/schematics';
import { GenerateLibSchema } from './models/generate-lib-schema';
import {
applyWithOverwrite,
getWorkspace,
interpolate,
isLibrary,
JSONFile,
kebab,
resolveProject,
updateWorkspace,
} from '../../utils';
import * as cases from '../../utils/text';
import { Exception } from '../../enums';
import { join, normalize } from '@angular-devkit/core';
import {
ProjectDefinition,
WorkspaceDefinition,
} from '@angular-devkit/core/src/workspace/definitions';
import { addLibToWorkspaceFile } from '../../utils/angular-schematic/generate-lib';
export default function (schema: GenerateLibSchema) {
return async (tree: Tree) => {
if (schema.override || !(await checkLibExist(schema, tree))) {
return chain([createLibrary(schema)]);
}
};
}
async function checkLibExist(options: GenerateLibSchema, tree: Tree) {
const packageName = kebab(options.packageName);
if (options.isSecondaryEntrypoint) {
const lib = await resolveProject(tree, options.target);
const ngPackagePath = `${lib?.definition.root}/${packageName}/ng-package.json`;
const packageInfo = tree.read(ngPackagePath);
if (packageInfo) {
throw new SchematicsException(
interpolate(Exception.LibraryAlreadyExists, `${lib.name}/${packageName}`),
);
}
return false;
}
const target = await resolveProject(tree, options.packageName, null);
if (target) {
throw new SchematicsException(interpolate(Exception.LibraryAlreadyExists, packageName));
}
return false;
}
function createLibrary(options: GenerateLibSchema): Rule {
return async (tree: Tree, _context: SchematicContext) => {
const target = await resolveProject(tree, options.packageName, null);
if (!target || options.override) {
if (options.isModuleTemplate) {
return createLibFromModuleTemplate(tree, options);
}
if (options.isSecondaryEntrypoint) {
return createLibSecondaryEntry(tree, options);
}
} else {
throw new SchematicsException(
interpolate(Exception.LibraryAlreadyExists, options.packageName),
);
}
};
}
async function resolvePackagesDirFromAngularJson(host: Tree) {
const workspace = await getWorkspace(host);
const projectFolder = readFirstLibInAngularJson(workspace);
return projectFolder?.root?.split('/')?.[0] || 'projects';
}
function readFirstLibInAngularJson(workspace: WorkspaceDefinition): ProjectDefinition | undefined {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, props] =
Array.from(workspace.projects.entries()).find(([_, value]) => isLibrary(value)) || [];
return props;
}
async function createLibFromModuleTemplate(tree: Tree, options: GenerateLibSchema) {
const packagesDir = await resolvePackagesDirFromAngularJson(tree);
const packageJson = JSON.parse(tree.read('./package.json')!.toString());
const abpVersion = packageJson.dependencies['@abp/ng.core'];
return chain([
applyWithOverwrite(url('./files-package'), [
applyTemplates({
...cases,
libraryName: options.packageName,
abpVersion,
}),
move(normalize(packagesDir)),
]),
addLibToWorkspaceIfNotExist(options.packageName, packagesDir),
]);
}
export function addLibToWorkspaceIfNotExist(name: string, packagesDir: string): Rule {
return async (tree: Tree, _: SchematicContext) => {
const workspace = await getWorkspace(tree);
const packageName = kebab(name);
const isProjectExist = workspace.projects.has(packageName);
const projectRoot = join(normalize(packagesDir), packageName);
const pathImportLib = `${packagesDir}/${packageName}`;
return chain([
isProjectExist
? updateWorkspace(w => {
w.projects.delete(packageName);
})
: noop(),
addLibToWorkspaceFile(projectRoot, packageName),
updateTsConfig(packageName, pathImportLib),
]);
};
}
export function updateTsConfig(packageName: string, path: string) {
return (host: Tree) => {
const files = ['tsconfig.json', 'tsconfig.app.json', 'tsconfig.base.json'];
const tsConfig = files.find(f => host.exists(f));
if (!tsConfig) {
return host;
}
const file = new JSONFile(host, tsConfig);
const jsonPath = ['compilerOptions', 'paths', packageName];
file.modify(jsonPath, [`${path}/src/public-api.ts`]);
};
}
export async function createLibSecondaryEntry(tree: Tree, options: GenerateLibSchema) {
const targetLib = await resolveProject(tree, options.target);
const packageName = `${kebab(targetLib.name)}/${kebab(options.packageName)}`;
const importPath = `${targetLib.definition.root}/${kebab(options.packageName)}`;
return chain([
applyWithOverwrite(url('./files-secondary-entrypoint'), [
applyTemplates({
...cases,
libraryName: options.packageName,
target: targetLib.name,
}),
move(normalize(targetLib.definition.root)),
updateTsConfig(packageName, importPath),
]),
]);
}

17
npm/ng-packs/packages/schematics/src/commands/create-lib/models/generate-lib-schema.ts

@ -0,0 +1,17 @@
export interface GenerateLibSchema {
/**
* Angular package name will create
*/
packageName: string;
/**
* İs the package a library or a library module
*/
isSecondaryEntrypoint: boolean;
isModuleTemplate: boolean;
override: boolean;
target: string;
}

1
npm/ng-packs/packages/schematics/src/commands/create-lib/models/index.ts

@ -0,0 +1 @@
export * from './generate-lib-schema';

36
npm/ng-packs/packages/schematics/src/commands/create-lib/schema.json

@ -0,0 +1,36 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "SchematicsABPModuleTemplateCreator",
"title": "ABP Module Template Generator API Schema",
"type": "object",
"properties": {
"packageName": {
"description": "The name of the package will create",
"type": "string",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Please enter the package name will create"
},
"isSecondaryEntrypoint": {
"description": "Is secondary entrypoint",
"type": "boolean",
"$default": false,
"x-prompt": "Is secondary entrypoint?"
},
"isModuleTemplate": {
"description": "Is module template",
"type": "boolean",
"$default": true,
"x-prompt": "Is module template?"
},
"override": {
"description": "Override existing files",
"type": "boolean",
"$default": false,
"x-prompt": "Override existing files?"
}
},
"required": []
}

4
npm/ng-packs/packages/schematics/src/commands/proxy-add/index.ts

@ -1,7 +1,7 @@
import { chain, SchematicContext, Tree } from '@angular-devkit/schematics';
import { GenerateProxySchema } from '../../models';
import {
buildDefaultPath,
buildTargetPath,
createApiDefinitionGetter,
createApisGenerator,
createProxyClearer,
@ -21,7 +21,7 @@ export default function (schema: GenerateProxySchema) {
return chain([
async (host: Tree, _context: SchematicContext) => {
const target = await resolveProject(host, params.target!);
const targetPath = buildDefaultPath(target.definition);
const targetPath = buildTargetPath(target.definition, params.entryPoint);
const readProxyConfig = createProxyConfigReader(targetPath);
let generated: string[] = [];

9
npm/ng-packs/packages/schematics/src/commands/proxy-add/schema.json

@ -50,5 +50,14 @@
"x-prompt": "Please enter URL for API definition (default: API Name's url in environment file)"
}
},
"entryPoint": {
"description": "Target Angular project to place the generated code",
"type": "string",
"$default": {
"$source": "argv",
"index": 5
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
},
"required": []
}

6
npm/ng-packs/packages/schematics/src/commands/proxy-index/index.ts

@ -1,18 +1,18 @@
import { SchematicContext, Tree } from '@angular-devkit/schematics';
import {
buildDefaultPath,
buildTargetPath,
createProxyIndexGenerator,
removeDefaultPlaceholders,
resolveProject,
} from '../../utils';
export default function (schema: { target?: string }) {
export default function (schema: { target?: string; entryPoint?: string }) {
const params = removeDefaultPlaceholders(schema);
return async (host: Tree, _context: SchematicContext) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const target = await resolveProject(host, params.target!);
const targetPath = buildDefaultPath(target.definition);
const targetPath = buildTargetPath(target.definition, params.entryPoint);
const generateIndex = createProxyIndexGenerator(targetPath);

9
npm/ng-packs/packages/schematics/src/commands/proxy-index/schema.json

@ -12,6 +12,15 @@
"index": 0
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
},
"entryPoint": {
"description": "Target Angular project to place the generated code",
"type": "string",
"$default": {
"$source": "argv",
"index": 5
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
}
},
"required": []

4
npm/ng-packs/packages/schematics/src/commands/proxy-refresh/index.ts

@ -1,7 +1,7 @@
import { chain, SchematicContext, Tree } from '@angular-devkit/schematics';
import { GenerateProxySchema } from '../../models';
import {
buildDefaultPath,
buildTargetPath,
createApiDefinitionGetter,
createApisGenerator,
createProxyClearer,
@ -18,7 +18,7 @@ export default function (schema: GenerateProxySchema) {
return async (host: Tree, _context: SchematicContext) => {
const target = await resolveProject(host, params.target!);
const targetPath = buildDefaultPath(target.definition);
const targetPath = buildTargetPath(target.definition, params.entryPoint);
const readProxyConfig = createProxyConfigReader(targetPath);
const { generated } = readProxyConfig(host);

10
npm/ng-packs/packages/schematics/src/commands/proxy-refresh/schema.json

@ -48,7 +48,17 @@
"index": 4
},
"x-prompt": "Please enter URL for api definition (default: API Name's url in environment file)"
},
"entryPoint": {
"description": "Target Angular project to place the generated code",
"type": "string",
"$default": {
"$source": "argv",
"index": 5
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
}
},
"required": []
}

4
npm/ng-packs/packages/schematics/src/commands/proxy-remove/index.ts

@ -1,7 +1,7 @@
import { chain, SchematicContext, Tree } from '@angular-devkit/schematics';
import { GenerateProxySchema } from '../../models';
import {
buildDefaultPath,
buildTargetPath,
createApiDefinitionGetter,
createApisGenerator,
createProxyClearer,
@ -20,7 +20,7 @@ export default function (schema: GenerateProxySchema) {
return async (host: Tree, _context: SchematicContext) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const target = await resolveProject(host, params.target!);
const targetPath = buildDefaultPath(target.definition);
const targetPath = buildTargetPath(target.definition, params.entryPoint);
const readProxyConfig = createProxyConfigReader(targetPath);
const { generated } = readProxyConfig(host);

9
npm/ng-packs/packages/schematics/src/commands/proxy-remove/schema.json

@ -48,6 +48,15 @@
"index": 4
},
"x-prompt": "Please enter URL for API definition (default: API Name's url in environment file)"
},
"entryPoint": {
"description": "Target Angular project to place the generated code",
"type": "string",
"$default": {
"$source": "argv",
"index": 5
},
"x-prompt": "Please enter target Angular project to place the generated code. (default: workspace \"defaultProject\")"
}
},
"required": []

1
npm/ng-packs/packages/schematics/src/constants/symbols.ts

@ -0,0 +1 @@
export const NOT_FOUND_VALUE = Symbol('NOT_FOUND_VALUE');

1
npm/ng-packs/packages/schematics/src/enums/exception.ts

@ -13,4 +13,5 @@ export const enum Exception {
NoEnvironment = '[Environment Not Found] An environment file cannot be located in "{0}" project.',
NoApiUrl = '[API URL Not Found] Cannot resolve API URL for "{1}" remote service name from "{0}" project.',
NoRootNamespace = '[Root Namespace Not Found] Cannot resolve root namespace for "{1}" api from "{0}" project.',
LibraryAlreadyExists = '[Library Already Exists] "{0}" already exists. Use --override to override.',
}

5
npm/ng-packs/packages/schematics/src/models/generate-proxy-schema.ts

@ -23,4 +23,9 @@ export interface GenerateProxySchema {
* Url to API definition
*/
url?: string;
/**
* Secondary entrypoint for proxy generation
*/
entryPoint?: string;
}

52
npm/ng-packs/packages/schematics/src/utils/angular-schematic/generate-lib.ts

@ -0,0 +1,52 @@
import { Rule, Tree } from '@angular-devkit/schematics';
import { Builders, JSONFile, ProjectType, updateWorkspace } from '../angular';
export function updateTsConfig(packageName: string, ...paths: string[]) {
return (host: Tree) => {
if (!host.exists('tsconfig.json')) {
return host;
}
const file = new JSONFile(host, 'tsconfig.json');
const jsonPath = ['compilerOptions', 'paths', packageName];
const value = file.get(jsonPath);
file.modify(jsonPath, Array.isArray(value) ? [...value, ...paths] : paths);
};
}
export function addLibToWorkspaceFile(projectRoot: string, projectName: string): Rule {
return updateWorkspace(workspace => {
workspace.projects.add({
name: projectName,
root: projectRoot,
sourceRoot: `${projectRoot}/src`,
projectType: ProjectType.Library,
prefix: 'lib',
targets: {
build: {
builder: Builders.NgPackagr,
defaultConfiguration: 'production',
options: {
project: `${projectRoot}/ng-package.json`,
},
configurations: {
production: {
tsConfig: `${projectRoot}/tsconfig.lib.prod.json`,
},
development: {
tsConfig: `${projectRoot}/tsconfig.lib.json`,
},
},
},
test: {
builder: Builders.Karma,
options: {
main: `${projectRoot}/src/test.ts`,
tsConfig: `${projectRoot}/tsconfig.spec.json`,
karmaConfig: `${projectRoot}/karma.conf.js`,
},
},
},
});
});
}

1
npm/ng-packs/packages/schematics/src/utils/angular-schematic/index.ts

@ -0,0 +1 @@
export * from './generate-lib';

2
npm/ng-packs/packages/schematics/src/utils/angular/README.md

@ -1,5 +1,5 @@
**DISCLAIMER**
This directory is a direct copy of https://github.com/angular/angular-cli/tree/master/packages/schematics/angular/utility and is used under terms and permissions by the MIT license granted by Google, Inc.
This directory is a direct copy of https://github.com/angular/angular-cli/tree/d091bb0c7b76a73e1b7d4b5690c532c68452b1d6 and is used under terms and permissions by the MIT license granted by Google, Inc.
All credits go to Angular team for building these utilities.

193
npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts

@ -1,10 +1,12 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { tags } from '@angular-devkit/core';
import * as ts from 'typescript';
import { Change, InsertChange, NoopChange } from './change';
@ -146,7 +148,7 @@ export function findNodes<T extends ts.Node>(
}
if (max > 0 && (recursive || !test(node))) {
for (const child of node.getChildren()) {
findNodes(child, test, max).forEach(node => {
findNodes(child, test, max, recursive).forEach(node => {
if (max > 0) {
arr.push(node);
}
@ -187,7 +189,6 @@ export function getSourceNodes(sourceFile: ts.SourceFile): ts.Node[] {
export function findNode(node: ts.Node, kind: ts.SyntaxKind, text: string): ts.Node | null {
if (node.kind === kind && node.getText() === text) {
// throw new Error(node.getText());
return node;
}
@ -244,20 +245,7 @@ export function insertAfterLastOccurrence(
return new InsertChange(file, lastItemPosition, toInsert);
}
export function getContentOfKeyLiteral(_source: ts.SourceFile, node: ts.Node): string | null {
if (node.kind == ts.SyntaxKind.Identifier) {
return (node as ts.Identifier).text;
} else if (node.kind == ts.SyntaxKind.StringLiteral) {
return (node as ts.StringLiteral).text;
} else {
return null;
}
}
function _angularImportsFromNode(
node: ts.ImportDeclaration,
_sourceFile: ts.SourceFile,
): { [name: string]: string } {
function _angularImportsFromNode(node: ts.ImportDeclaration): { [name: string]: string } {
const ms = node.moduleSpecifier;
let modulePath: string;
switch (ms.kind) {
@ -281,11 +269,11 @@ function _angularImportsFromNode(
if (nb.kind == ts.SyntaxKind.NamespaceImport) {
// This is of the form `import * as name from 'path'`. Return `name.`.
return {
[(nb as ts.NamespaceImport).name.text + '.']: modulePath,
[nb.name.text + '.']: modulePath,
};
} else {
// This is of the form `import {a,b,c} from 'path'`
const namedImports = nb as ts.NamedImports;
const namedImports = nb;
return namedImports.elements
.map((is: ts.ImportSpecifier) => (is.propertyName ? is.propertyName.text : is.name.text))
@ -310,7 +298,7 @@ export function getDecoratorMetadata(
module: string,
): ts.Node[] {
const angularImports = findNodes(source, ts.isImportDeclaration)
.map(node => _angularImportsFromNode(node, source))
.map(node => _angularImportsFromNode(node))
.reduce((acc, current) => {
for (const key of Object.keys(current)) {
acc[key] = current[key];
@ -354,38 +342,6 @@ export function getDecoratorMetadata(
.map(expr => expr.arguments[0] as ts.ObjectLiteralExpression);
}
function findClassDeclarationParent(node: ts.Node): ts.ClassDeclaration | undefined {
if (ts.isClassDeclaration(node)) {
return node;
}
return node.parent && findClassDeclarationParent(node.parent);
}
/**
* Given a source file with @NgModule class(es), find the name of the first @NgModule class.
*
* @param source source file containing one or more @NgModule
* @returns the name of the first @NgModule, or `undefined` if none is found
*/
export function getFirstNgModuleName(source: ts.SourceFile): string | undefined {
// First, find the @NgModule decorators.
const ngModulesMetadata = getDecoratorMetadata(source, 'NgModule', '@angular/core');
if (ngModulesMetadata.length === 0) {
return undefined;
}
// Then walk parent pointers up the AST, looking for the ClassDeclaration parent of the NgModule
// metadata.
const moduleClass = findClassDeclarationParent(ngModulesMetadata[0]);
if (!moduleClass || !moduleClass.name) {
return undefined;
}
// Get the class name of the module ClassDeclaration.
return moduleClass.name.text;
}
export function getMetadataField(
node: ts.ObjectLiteralExpression,
metadataField: string,
@ -396,9 +352,7 @@ export function getMetadataField(
// Filter out every fields that's not "metadataField". Also handles string literals
// (but not expressions).
.filter(({ name }) => {
return (
(ts.isIdentifier(name) || ts.isStringLiteral(name)) && name.getText() === metadataField
);
return (ts.isIdentifier(name) || ts.isStringLiteral(name)) && name.text === metadataField;
})
);
}
@ -411,36 +365,33 @@ export function addSymbolToNgModuleMetadata(
importPath: string | null = null,
): Change[] {
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
let node: any = nodes[0];
const node = nodes[0];
// Find the decorator declaration.
if (!node) {
if (!node || !ts.isObjectLiteralExpression(node)) {
return [];
}
// Get all the children property assignment of object literals.
const matchingProperties = getMetadataField(node as ts.ObjectLiteralExpression, metadataField);
const matchingProperties = getMetadataField(node, metadataField);
// Get the last node of the array literal.
if (!matchingProperties) {
return [];
}
if (matchingProperties.length == 0) {
// We haven't found the field in the metadata declaration. Insert a new field.
const expr = node as ts.ObjectLiteralExpression;
let position: number;
let toInsert: string;
if (expr.properties.length == 0) {
position = expr.getEnd() - 1;
toInsert = ` ${metadataField}: [${symbolName}]\n`;
if (node.properties.length == 0) {
position = node.getEnd() - 1;
toInsert = `\n ${metadataField}: [\n${tags.indentBy(4)`${symbolName}`}\n ]\n`;
} else {
node = expr.properties[expr.properties.length - 1];
position = node.getEnd();
const childNode = node.properties[node.properties.length - 1];
position = childNode.getEnd();
// Get the indentation of the last element, if any.
const text = node.getFullText(source);
const matches = text.match(/^\r?\n\s*/);
if (matches && matches.length > 0) {
toInsert = `,${matches[0]}${metadataField}: [${symbolName}]`;
const text = childNode.getFullText(source);
const matches = text.match(/^(\r?\n)(\s*)/);
if (matches) {
toInsert =
`,${matches[0]}${metadataField}: [${matches[1]}` +
`${tags.indentBy(matches[2].length + 2)`${symbolName}`}${matches[0]}]`;
} else {
toInsert = `, ${metadataField}: [${symbolName}]`;
}
@ -454,69 +405,48 @@ export function addSymbolToNgModuleMetadata(
return [new InsertChange(ngModulePath, position, toInsert)];
}
}
const assignment = matchingProperties[0] as ts.PropertyAssignment;
const assignment = matchingProperties[0];
// If it's not an array, nothing we can do really.
if (assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) {
if (
!ts.isPropertyAssignment(assignment) ||
!ts.isArrayLiteralExpression(assignment.initializer)
) {
return [];
}
const arrLiteral = assignment.initializer as ts.ArrayLiteralExpression;
if (arrLiteral.elements.length == 0) {
// Forward the property.
node = arrLiteral;
} else {
node = arrLiteral.elements;
}
if (!node) {
console.error('No app module found. Please add your new class to your component.');
let expresssion: ts.Expression | ts.ArrayLiteralExpression;
const assignmentInit = assignment.initializer;
const elements = assignmentInit.elements;
return [];
}
if (Array.isArray(node)) {
// eslint-disable-next-line @typescript-eslint/ban-types
const nodeArray = node as {} as Array<ts.Node>;
const symbolsArray = nodeArray.map(node => node.getText());
if (symbolsArray.includes(symbolName)) {
if (elements.length) {
const symbolsArray = elements.map(node => tags.oneLine`${node.getText()}`);
if (symbolsArray.includes(tags.oneLine`${symbolName}`)) {
return [];
}
node = node[node.length - 1];
expresssion = elements[elements.length - 1];
} else {
expresssion = assignmentInit;
}
let toInsert: string;
let position = node.getEnd();
if (node.kind == ts.SyntaxKind.ObjectLiteralExpression) {
// We haven't found the field in the metadata declaration. Insert a new
// field.
const expr = node as ts.ObjectLiteralExpression;
if (expr.properties.length == 0) {
position = expr.getEnd() - 1;
toInsert = ` ${symbolName}\n`;
} else {
// Get the indentation of the last element, if any.
const text = node.getFullText(source);
if (text.match(/^\r?\r?\n/)) {
toInsert = `,${text.match(/^\r?\n\s*/)[0]}${symbolName}`;
} else {
toInsert = `, ${symbolName}`;
}
}
} else if (node.kind == ts.SyntaxKind.ArrayLiteralExpression) {
let position = expresssion.getEnd();
if (ts.isArrayLiteralExpression(expresssion)) {
// We found the field but it's empty. Insert it just before the `]`.
position--;
toInsert = `${symbolName}`;
toInsert = `\n${tags.indentBy(4)`${symbolName}`}\n `;
} else {
// Get the indentation of the last element, if any.
const text = node.getFullText(source);
if (text.match(/^\r?\n/)) {
toInsert = `,${text.match(/^\r?\n(\r?)\s*/)[0]}${symbolName}`;
const text = expresssion.getFullText(source);
const matches = text.match(/^(\r?\n)(\s*)/);
if (matches) {
toInsert = `,${matches[1]}${tags.indentBy(matches[2].length)`${symbolName}`}`;
} else {
toInsert = `, ${symbolName}`;
}
}
if (importPath !== null) {
return [
new InsertChange(ngModulePath, position, toInsert),
@ -594,25 +524,6 @@ export function addBootstrapToModule(
return addSymbolToNgModuleMetadata(source, modulePath, 'bootstrap', classifiedName, importPath);
}
/**
* Custom function to insert an entryComponent into NgModule. It also imports it.
* @deprecated - Since version 9.0.0 with Ivy, entryComponents is no longer necessary.
*/
export function addEntryComponentToModule(
source: ts.SourceFile,
modulePath: string,
classifiedName: string,
importPath: string,
): Change[] {
return addSymbolToNgModuleMetadata(
source,
modulePath,
'entryComponents',
classifiedName,
importPath,
);
}
/**
* Determine if an import already exists.
*/
@ -690,10 +601,13 @@ export function getEnvironmentExportName(source: ts.SourceFile): string | null {
* Returns the RouterModule declaration from NgModule metadata, if any.
*/
export function getRouterModuleDeclaration(source: ts.SourceFile): ts.Expression | undefined {
const result = getDecoratorMetadata(source, 'NgModule', '@angular/core') as ts.Node[];
const node = result[0] as ts.ObjectLiteralExpression;
const matchingProperties = getMetadataField(node, 'imports');
const result = getDecoratorMetadata(source, 'NgModule', '@angular/core');
const node = result[0];
if (!node || !ts.isObjectLiteralExpression(node)) {
return undefined;
}
const matchingProperties = getMetadataField(node, 'imports');
if (!matchingProperties) {
return;
}
@ -721,7 +635,10 @@ export function addRouteDeclarationToModule(
): Change {
const routerModuleExpr = getRouterModuleDeclaration(source);
if (!routerModuleExpr) {
throw new Error(`Couldn't find a route declaration in ${fileToAdd}.`);
throw new Error(
`Couldn't find a route declaration in ${fileToAdd}.\n` +
`Use the '--module' option to specify a different routing module.`,
);
}
const scopeConfigMethodArgs = (routerModuleExpr as ts.CallExpression).arguments;
if (!scopeConfigMethodArgs.length) {

32
npm/ng-packs/packages/schematics/src/utils/angular/change.ts

@ -1,10 +1,13 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { UpdateRecorder } from '@angular-devkit/schematics';
export interface Host {
write(path: string, content: string): Promise<void>;
read(path: string): Promise<string>;
@ -56,7 +59,7 @@ export class InsertChange implements Change {
* This method does not insert spaces if there is none in the original string.
*/
apply(host: Host) {
return host.read(this.path).then(content => {
return host.read(this.path).then((content) => {
const prefix = content.substring(0, this.pos);
const suffix = content.substring(this.pos);
@ -72,7 +75,7 @@ export class RemoveChange implements Change {
order: number;
description: string;
constructor(public path: string, private pos: number, private toRemove: string) {
constructor(public path: string, private pos: number, public toRemove: string) {
if (pos < 0) {
throw new Error('Negative positions are invalid');
}
@ -81,7 +84,7 @@ export class RemoveChange implements Change {
}
apply(host: Host): Promise<void> {
return host.read(this.path).then(content => {
return host.read(this.path).then((content) => {
const prefix = content.substring(0, this.pos);
const suffix = content.substring(this.pos + this.toRemove.length);
@ -101,8 +104,8 @@ export class ReplaceChange implements Change {
constructor(
public path: string,
private pos: number,
private oldText: string,
private newText: string,
public oldText: string,
public newText: string,
) {
if (pos < 0) {
throw new Error('Negative positions are invalid');
@ -112,7 +115,7 @@ export class ReplaceChange implements Change {
}
apply(host: Host): Promise<void> {
return host.read(this.path).then(content => {
return host.read(this.path).then((content) => {
const prefix = content.substring(0, this.pos);
const suffix = content.substring(this.pos + this.oldText.length);
const text = content.substring(this.pos, this.pos + this.oldText.length);
@ -126,3 +129,18 @@ export class ReplaceChange implements Change {
});
}
}
export function applyToUpdateRecorder(recorder: UpdateRecorder, changes: Change[]): void {
for (const change of changes) {
if (change instanceof InsertChange) {
recorder.insertLeft(change.pos, change.toAdd);
} else if (change instanceof RemoveChange) {
recorder.remove(change.order, change.toRemove.length);
} else if (change instanceof ReplaceChange) {
recorder.remove(change.order, change.oldText.length);
recorder.insertLeft(change.order, change.newText);
} else if (!(change instanceof NoopChange)) {
throw new Error('Unknown Change type encountered when updating a recorder.');
}
}
}

541
npm/ng-packs/packages/schematics/src/utils/angular/config.ts

@ -1,541 +0,0 @@
/* eslint-disable @typescript-eslint/ban-types */
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { JsonParseMode, parseJson } from '@angular-devkit/core';
import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import { ProjectType, WorkspaceProject, WorkspaceSchema } from './workspace-models';
// The interfaces below are generated from the Angular CLI configuration schema
// https://github.com/angular/angular-cli/blob/master/packages/@angular/cli/lib/config/schema.json
export interface AppConfig {
/**
* Name of the app.
*/
name?: string;
/**
* Directory where app files are placed.
*/
appRoot?: string;
/**
* The root directory of the app.
*/
root?: string;
/**
* The output directory for build results.
*/
outDir?: string;
/**
* List of application assets.
*/
assets?: (
| string
| {
/**
* The pattern to match.
*/
glob?: string;
/**
* The dir to search within.
*/
input?: string;
/**
* The output path (relative to the outDir).
*/
output?: string;
}
)[];
/**
* URL where files will be deployed.
*/
deployUrl?: string;
/**
* Base url for the application being built.
*/
baseHref?: string;
/**
* The runtime platform of the app.
*/
platform?: 'browser' | 'server';
/**
* The name of the start HTML file.
*/
index?: string;
/**
* The name of the main entry-point file.
*/
main?: string;
/**
* The name of the polyfills file.
*/
polyfills?: string;
/**
* The name of the test entry-point file.
*/
test?: string;
/**
* The name of the TypeScript configuration file.
*/
tsconfig?: string;
/**
* The name of the TypeScript configuration file for unit tests.
*/
testTsconfig?: string;
/**
* The prefix to apply to generated selectors.
*/
prefix?: string;
/**
* Experimental support for a service worker from @angular/service-worker.
*/
serviceWorker?: boolean;
/**
* Global styles to be included in the build.
*/
styles?: (
| string
| {
input?: string;
[name: string]: any;
}
)[];
/**
* Options to pass to style preprocessors
*/
stylePreprocessorOptions?: {
/**
* Paths to include. Paths will be resolved to project root.
*/
includePaths?: string[];
};
/**
* Global scripts to be included in the build.
*/
scripts?: (
| string
| {
input: string;
[name: string]: any;
}
)[];
/**
* Source file for environment config.
*/
environmentSource?: string;
/**
* Name and corresponding file for environment config.
*/
environments?: {
[name: string]: any;
};
appShell?: {
app: string;
route: string;
};
budgets?: {
/**
* The type of budget
*/
type?: 'bundle' | 'initial' | 'allScript' | 'all' | 'anyScript' | 'any' | 'anyComponentStyle';
/**
* The name of the bundle
*/
name?: string;
/**
* The baseline size for comparison.
*/
baseline?: string;
/**
* The maximum threshold for warning relative to the baseline.
*/
maximumWarning?: string;
/**
* The maximum threshold for error relative to the baseline.
*/
maximumError?: string;
/**
* The minimum threshold for warning relative to the baseline.
*/
minimumWarning?: string;
/**
* The minimum threshold for error relative to the baseline.
*/
minimumError?: string;
/**
* The threshold for warning relative to the baseline (min & max).
*/
warning?: string;
/**
* The threshold for error relative to the baseline (min & max).
*/
error?: string;
}[];
}
export interface CliConfig {
$schema?: string;
/**
* The global configuration of the project.
*/
project?: {
/**
* The name of the project.
*/
name?: string;
/**
* Whether or not this project was ejected.
*/
ejected?: boolean;
};
/**
* Properties of the different applications in this project.
*/
apps?: AppConfig[];
/**
* Configuration for end-to-end tests.
*/
e2e?: {
protractor?: {
/**
* Path to the config file.
*/
config?: string;
};
};
/**
* Properties to be passed to TSLint.
*/
lint?: {
/**
* File glob(s) to lint.
*/
files?: string | string[];
/**
* Location of the tsconfig.json project file.
* Will also use as files to lint if 'files' property not present.
*/
project: string;
/**
* Location of the tslint.json configuration.
*/
tslintConfig?: string;
/**
* File glob(s) to ignore.
*/
exclude?: string | string[];
}[];
/**
* Configuration for unit tests.
*/
test?: {
karma?: {
/**
* Path to the karma config file.
*/
config?: string;
};
codeCoverage?: {
/**
* Globs to exclude from code coverage.
*/
exclude?: string[];
};
};
/**
* Specify the default values for generating.
*/
defaults?: {
/**
* The file extension to be used for style files.
*/
styleExt?: string;
/**
* How often to check for file updates.
*/
poll?: number;
/**
* Use lint to fix files after generation
*/
lintFix?: boolean;
/**
* Options for generating a class.
*/
class?: {
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
};
/**
* Options for generating a component.
*/
component?: {
/**
* Flag to indicate if a directory is created.
*/
flat?: boolean;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
/**
* Specifies if the style will be in the ts file.
*/
inlineStyle?: boolean;
/**
* Specifies if the template will be in the ts file.
*/
inlineTemplate?: boolean;
/**
* Specifies the view encapsulation strategy.
*/
viewEncapsulation?: 'Emulated' | 'Native' | 'None';
/**
* Specifies the change detection strategy.
*/
changeDetection?: 'Default' | 'OnPush';
};
/**
* Options for generating a directive.
*/
directive?: {
/**
* Flag to indicate if a directory is created.
*/
flat?: boolean;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
};
/**
* Options for generating a guard.
*/
guard?: {
/**
* Flag to indicate if a directory is created.
*/
flat?: boolean;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
};
/**
* Options for generating an interface.
*/
interface?: {
/**
* Prefix to apply to interface names. (i.e. I)
*/
prefix?: string;
};
/**
* Options for generating a module.
*/
module?: {
/**
* Flag to indicate if a directory is created.
*/
flat?: boolean;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
};
/**
* Options for generating a pipe.
*/
pipe?: {
/**
* Flag to indicate if a directory is created.
*/
flat?: boolean;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
};
/**
* Options for generating a service.
*/
service?: {
/**
* Flag to indicate if a directory is created.
*/
flat?: boolean;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
};
/**
* Properties to be passed to the build command.
*/
build?: {
/**
* Output sourcemaps.
*/
sourcemaps?: boolean;
/**
* Base url for the application being built.
*/
baseHref?: string;
/**
* The ssl key used by the server.
*/
progress?: boolean;
/**
* Enable and define the file watching poll time period (milliseconds).
*/
poll?: number;
/**
* Delete output path before build.
*/
deleteOutputPath?: boolean;
/**
* Do not use the real path when resolving modules.
*/
preserveSymlinks?: boolean;
/**
* Show circular dependency warnings on builds.
*/
showCircularDependencies?: boolean;
/**
* Use a separate bundle containing code used across multiple bundles.
*/
commonChunk?: boolean;
/**
* Use file name for lazy loaded chunks.
*/
namedChunks?: boolean;
};
/**
* Properties to be passed to the serve command.
*/
serve?: {
/**
* The port the application will be served on.
*/
port?: number;
/**
* The host the application will be served on.
*/
host?: string;
/**
* Enables ssl for the application.
*/
ssl?: boolean;
/**
* The ssl key used by the server.
*/
sslKey?: string;
/**
* The ssl certificate used by the server.
*/
sslCert?: string;
/**
* Proxy configuration file.
*/
proxyConfig?: string;
};
/**
* Properties about schematics.
*/
schematics?: {
/**
* The schematics collection to use.
*/
collection?: string;
/**
* The new app schematic.
*/
newApp?: string;
};
};
/**
* Specify which package manager tool to use.
*/
packageManager?: 'npm' | 'cnpm' | 'yarn' | 'default';
/**
* Allow people to disable console warnings.
*/
warnings?: {
versionMismatch?: boolean;
};
}
export function getWorkspacePath(host: Tree): string {
const possibleFiles = ['/angular.json', '/.angular.json'];
const path = possibleFiles.filter(path => host.exists(path))[0];
return path;
}
export function getWorkspaceSchema(host: Tree): WorkspaceSchema {
const path = getWorkspacePath(host);
const configBuffer = host.read(path);
if (configBuffer === null) {
throw new SchematicsException(`Could not find (${path})`);
}
const content = configBuffer.toString();
return parseJson(content, JsonParseMode.Loose) as {} as WorkspaceSchema;
}
export function addProjectToWorkspace<TProjectType extends ProjectType = ProjectType.Application>(
workspace: WorkspaceSchema,
name: string,
project: WorkspaceProject<TProjectType>,
): Rule {
return (_host: Tree, _context: SchematicContext) => {
if (workspace.projects[name]) {
throw new Error(`Project '${name}' already exists in workspace.`);
}
// Add project to workspace.
workspace.projects[name] = project;
if (!workspace.defaultProject && Object.keys(workspace.projects).length === 1) {
// Make the new project the default one.
workspace.defaultProject = name;
}
return updateWorkspaceSchema(workspace);
};
}
export function updateWorkspaceSchema(workspace: WorkspaceSchema): Rule {
return (host: Tree, _context: SchematicContext) => {
host.overwrite(getWorkspacePath(host), JSON.stringify(workspace, null, 2));
};
}
export const configPath = '/.angular-cli.json';
export function getConfig(host: Tree): CliConfig {
const configBuffer = host.read(configPath);
if (configBuffer === null) {
throw new SchematicsException('Could not find .angular-cli.json');
}
const config = parseJson(configBuffer.toString(), JsonParseMode.Loose) as {} as CliConfig;
return config;
}
export function getAppFromConfig(config: CliConfig, appIndexOrName: string): AppConfig | null {
if (!config.apps) {
return null;
}
if (parseInt(appIndexOrName) >= 0) {
return config.apps[parseInt(appIndexOrName)];
}
return config.apps.filter(app => app.name === appIndexOrName)[0];
}

12
npm/ng-packs/packages/schematics/src/utils/angular/dependencies.ts

@ -1,10 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Tree } from '@angular-devkit/schematics';
import { JSONFile } from './json-file';
@ -36,9 +37,6 @@ export function addPackageJsonDependency(
pkgJsonPath = PKG_JSON_PATH,
): void {
const json = new JSONFile(tree, pkgJsonPath);
if (json.error) {
throw json.error;
}
const { overwrite, type, name, version } = dependency;
const path = [type, name];
@ -53,9 +51,6 @@ export function removePackageJsonDependency(
pkgJsonPath = PKG_JSON_PATH,
): void {
const json = new JSONFile(tree, pkgJsonPath);
if (json.error) {
throw json.error;
}
for (const depType of ALL_DEPENDENCY_TYPE) {
json.remove([depType, name]);
@ -68,9 +63,6 @@ export function getPackageJsonDependency(
pkgJsonPath = PKG_JSON_PATH,
): NodeDependency | null {
const json = new JSONFile(tree, pkgJsonPath);
if (json.error) {
throw json.error;
}
for (const depType of ALL_DEPENDENCY_TYPE) {
const version = json.get([depType, name]);

25
npm/ng-packs/packages/schematics/src/utils/angular/find-module.ts

@ -1,21 +1,19 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { dirname, join, normalize, NormalizedRoot, Path, relative } from '@angular-devkit/core';
import { NormalizedRoot, Path, dirname, join, normalize, relative } from '@angular-devkit/core';
import { DirEntry, Tree } from '@angular-devkit/schematics';
export interface ModuleOptions {
project?: string; // added this
module?: string;
name: string;
flat?: boolean;
path?: string;
route?: string; // added this
selector?: string; // added this
skipImport?: boolean;
moduleExt?: string;
routingModuleExt?: string;
@ -28,7 +26,8 @@ export const ROUTING_MODULE_EXT = '-routing.module.ts';
* Find the module referred by a set of options passed to the schematics.
*/
export function findModuleFromOptions(host: Tree, options: ModuleOptions): Path | undefined {
if (Object.prototype.hasOwnProperty.call(options, 'skipImport') && options.skipImport) {
// eslint-disable-next-line no-prototype-builtins
if (options.hasOwnProperty('skipImport') && options.skipImport) {
return undefined;
}
@ -55,8 +54,8 @@ export function findModuleFromOptions(host: Tree, options: ModuleOptions): Path
const candidatesDirs = [...candidateSet].sort((a, b) => b.length - a.length);
for (const c of candidatesDirs) {
const candidateFiles = ['', `${moduleBaseName}.ts`, `${moduleBaseName}${moduleExt}`].map(x =>
join(c, x),
const candidateFiles = ['', `${moduleBaseName}.ts`, `${moduleBaseName}${moduleExt}`].map(
(x) => join(c, x),
);
for (const sc of candidateFiles) {
@ -86,8 +85,8 @@ export function findModule(
let foundRoutingModule = false;
while (dir) {
const allMatches = dir.subfiles.filter(p => p.endsWith(moduleExt));
const filteredMatches = allMatches.filter(p => !p.endsWith(routingModuleExt));
const allMatches = dir.subfiles.filter((p) => p.endsWith(moduleExt));
const filteredMatches = allMatches.filter((p) => !p.endsWith(routingModuleExt));
foundRoutingModule = foundRoutingModule || allMatches.length !== filteredMatches.length;
@ -95,7 +94,7 @@ export function findModule(
return join(dir.path, filteredMatches[0]);
} else if (filteredMatches.length > 1) {
throw new Error(
'More than one module matches. Use the skip-import option to skip importing ' +
`More than one module matches. Use the '--skip-import' option to skip importing ` +
'the component into the closest module or use the module option to specify a module.',
);
}
@ -106,8 +105,8 @@ export function findModule(
const errorMsg = foundRoutingModule
? 'Could not find a non Routing NgModule.' +
`\nModules with suffix '${routingModuleExt}' are strictly reserved for routing.` +
'\nUse the skip-import option to skip importing in NgModule.'
: 'Could not find an NgModule. Use the skip-import option to skip importing in NgModule.';
`\nUse the '--skip-import' option to skip importing in NgModule.`
: `Could not find an NgModule. Use the '--skip-import' option to skip importing in NgModule.`;
throw new Error(errorMsg);
}

61
npm/ng-packs/packages/schematics/src/utils/angular/generate-from-files.ts

@ -0,0 +1,61 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { strings } from '@angular-devkit/core';
import {
apply,
applyTemplates,
chain,
filter,
mergeWith,
move,
noop,
Rule,
Tree,
url,
} from '@angular-devkit/schematics';
import { parseName } from './parse-name';
import { createDefaultPath } from './workspace';
export interface GenerateFromFilesOptions {
flat?: boolean;
name: string;
path?: string;
prefix?: string;
project?: string;
skipTests?: boolean;
}
export function generateFromFiles(
options: GenerateFromFilesOptions,
extraTemplateValues: Record<string, string | ((v: string) => string)> = {},
): Rule {
return async (host: Tree) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
options.path ??= await createDefaultPath(host, options.project as string);
options.prefix ??= '';
options.flat ??= true;
const parsedPath = parseName(options.path!, options.name);
options.name = parsedPath.name;
options.path = parsedPath.path;
const templateSource = apply(url('./files'), [
options.skipTests ? filter(path => !path.endsWith('.spec.ts.template')) : noop(),
applyTemplates({
...strings,
...options,
...extraTemplateValues,
}),
move(parsedPath.path + (options.flat ? '' : '/' + strings.dasherize(options.name))),
]);
return chain([mergeWith(templateSource)]);
};
}

6
npm/ng-packs/packages/schematics/src/utils/angular/index.ts

@ -1,17 +1,13 @@
export * from './ast-utils';
export * from './change';
export * from './config';
export * from './dependencies';
export * from './find-module';
export * from './generate-from-files';
export * from './json-file';
export * from './json-utils';
export * from './latest-versions';
export * from './lint-fix';
export * from './ng-ast-utils';
export * from './parse-name';
export * from './paths';
export * from './project-targets';
export * from './tsconfig';
export * from './validation';
export * from './workspace';
export * from './workspace-models';

43
npm/ng-packs/packages/schematics/src/utils/angular/json-file.ts

@ -1,6 +1,6 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
@ -10,46 +10,62 @@ import { JsonValue } from '@angular-devkit/core';
import { Tree } from '@angular-devkit/schematics';
import {
Node,
ParseError,
applyEdits,
findNodeAtLocation,
getNodeValue,
modify,
parseTree,
printParseErrorCode,
} from 'jsonc-parser';
export type InsertionIndex = (properties: string[]) => number;
export type JSONPath = (string | number)[];
/** @internal */
export class JSONFile {
private content: string;
error: undefined | Error;
content: string;
constructor(private readonly host: Tree, private readonly path: string) {
const buffer = this.host.read(this.path);
if (buffer) {
this.content = buffer.toString();
} else {
this.error = new Error(`Could not read ${path}.`);
throw new Error(`Could not read '${path}'.`);
}
}
private _jsonAst: Node | undefined;
private get JsonAst(): Node {
private get JsonAst(): Node | undefined {
if (this._jsonAst) {
return this._jsonAst;
}
this._jsonAst = parseTree(this.content);
const errors: ParseError[] = [];
this._jsonAst = parseTree(this.content, errors, { allowTrailingComma: true });
if (errors.length) {
const { error, offset } = errors[0];
throw new Error(
`Failed to parse "${this.path}" as JSON AST Object. ${printParseErrorCode(
error,
)} at location: ${offset}.`,
);
}
return this._jsonAst;
}
get(jsonPath: JSONPath): unknown {
const jsonAstNode = this.JsonAst;
if (!jsonAstNode) {
return undefined;
}
if (jsonPath.length === 0) {
return getNodeValue(this.JsonAst);
return getNodeValue(jsonAstNode);
}
const node = findNodeAtLocation(this.JsonAst, jsonPath);
const node = findNodeAtLocation(jsonAstNode, jsonPath);
return node === undefined ? undefined : getNodeValue(node);
}
@ -57,12 +73,15 @@ export class JSONFile {
modify(
jsonPath: JSONPath,
value: JsonValue | undefined,
getInsertionIndex?: (properties: string[]) => number,
insertInOrder?: InsertionIndex | false,
): void {
if (!getInsertionIndex) {
let getInsertionIndex: InsertionIndex | undefined;
if (insertInOrder === undefined) {
const property = jsonPath.slice(-1)[0];
getInsertionIndex = properties =>
[...properties, property].sort().findIndex(p => p === property);
getInsertionIndex = (properties) =>
[...properties, property].sort().findIndex((p) => p === property);
} else if (insertInOrder !== false) {
getInsertionIndex = insertInOrder;
}
const edits = modify(this.content, jsonPath, value, {

221
npm/ng-packs/packages/schematics/src/utils/angular/json-utils.ts

@ -1,221 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
JsonAstArray,
JsonAstKeyValue,
JsonAstNode,
JsonAstObject,
JsonValue,
} from '@angular-devkit/core';
import { UpdateRecorder } from '@angular-devkit/schematics';
export function appendPropertyInAstObject(
recorder: UpdateRecorder,
node: JsonAstObject,
propertyName: string,
value: JsonValue,
indent: number,
) {
const indentStr = _buildIndent(indent);
let index = node.start.offset + 1;
if (node.properties.length > 0) {
// Insert comma.
const last = node.properties[node.properties.length - 1];
const { text, end } = last;
const commaIndex = text.endsWith('\n') ? end.offset - 1 : end.offset;
recorder.insertRight(commaIndex, ',');
index = end.offset;
}
const content = _stringifyContent(value, indentStr);
recorder.insertRight(
index,
(node.properties.length === 0 && indent ? '\n' : '') +
' '.repeat(indent) +
`"${propertyName}":${indent ? ' ' : ''}${content}` +
indentStr.slice(0, -indent),
);
}
export function insertPropertyInAstObjectInOrder(
recorder: UpdateRecorder,
node: JsonAstObject,
propertyName: string,
value: JsonValue,
indent: number,
) {
if (node.properties.length === 0) {
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
return;
}
// Find insertion info.
let insertAfterProp: JsonAstKeyValue | null = null;
let prev: JsonAstKeyValue | null = null;
let isLastProp = false;
const last = node.properties[node.properties.length - 1];
for (const prop of node.properties) {
if (prop.key.value > propertyName) {
if (prev) {
insertAfterProp = prev;
}
break;
}
if (prop === last) {
isLastProp = true;
insertAfterProp = last;
}
prev = prop;
}
if (isLastProp) {
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
return;
}
const indentStr = _buildIndent(indent);
const insertIndex =
insertAfterProp === null ? node.start.offset + 1 : insertAfterProp.end.offset + 1;
const content = _stringifyContent(value, indentStr);
recorder.insertRight(
insertIndex,
indentStr + `"${propertyName}":${indent ? ' ' : ''}${content}` + ',',
);
}
export function removePropertyInAstObject(
recorder: UpdateRecorder,
node: JsonAstObject,
propertyName: string,
) {
// Find the property inside the object.
const propIdx = node.properties.findIndex(prop => prop.key.value === propertyName);
if (propIdx === -1) {
// There's nothing to remove.
return;
}
if (node.properties.length === 1) {
// This is a special case. Everything should be removed, including indentation.
recorder.remove(node.start.offset, node.end.offset - node.start.offset);
recorder.insertRight(node.start.offset, '{}');
return;
}
// The AST considers commas and indentation to be part of the preceding property.
// To get around messy comma and identation management, we can work over the range between
// two properties instead.
const previousProp = node.properties[propIdx - 1];
const targetProp = node.properties[propIdx];
const nextProp = node.properties[propIdx + 1];
let start, end;
if (previousProp) {
// Given the object below, and intending to remove the `m` property:
// "{\n \"a\": \"a\",\n \"m\": \"m\",\n \"z\": \"z\"\n}"
// ^---------------^
// Removing the range above results in:
// "{\n \"a\": \"a\",\n \"z\": \"z\"\n}"
start = previousProp.end;
end = targetProp.end;
} else {
// If there's no previousProp there is a nextProp, since we've specialcased the 1 length case.
// Given the object below, and intending to remove the `a` property:
// "{\n \"a\": \"a\",\n \"m\": \"m\",\n \"z\": \"z\"\n}"
// ^---------------^
// Removing the range above results in:
// "{\n \"m\": \"m\",\n \"z\": \"z\"\n}"
start = targetProp.start;
end = nextProp.start;
}
recorder.remove(start.offset, end.offset - start.offset);
if (!nextProp) {
recorder.insertRight(start.offset, '\n');
}
}
export function appendValueInAstArray(
recorder: UpdateRecorder,
node: JsonAstArray,
value: JsonValue,
indent = 4,
) {
let indentStr = _buildIndent(indent);
let index = node.start.offset + 1;
let newNodes: any[] | undefined;
if (node.elements.length > 0) {
// Insert comma.
const { end } = node.elements[node.elements.length - 1];
const isClosingOnSameLine = node.end.offset - end.offset === 1;
if (isClosingOnSameLine && indent) {
// Reformat the entire array
recorder.remove(node.start.offset, node.end.offset - node.start.offset);
newNodes = [...node.elements.map(({ value }) => value), value];
index = node.start.offset;
// In case we are generating the entire node we need to reduce the spacing as
// otherwise we'd end up having incorrect double spacing
indent = indent - 2;
indentStr = _buildIndent(indent);
} else {
recorder.insertRight(end.offset, ',');
index = end.offset;
}
}
recorder.insertRight(
index,
(newNodes ? '' : indentStr) +
_stringifyContent(newNodes || value, indentStr) +
(node.elements.length === 0 && indent ? indentStr.substr(0, -indent) + '\n' : ''),
);
}
export function findPropertyInAstObject(
node: JsonAstObject,
propertyName: string,
): JsonAstNode | null {
let maybeNode: JsonAstNode | null = null;
for (const property of node.properties) {
if (property.key.value == propertyName) {
maybeNode = property.value;
}
}
return maybeNode;
}
function _buildIndent(count: number): string {
return count ? '\n' + ' '.repeat(count) : '';
}
function _stringifyContent(value: JsonValue, indentStr: string): string {
// TODO: Add snapshot tests
// The 'space' value is 2, because we want to add 2 additional
// indents from the 'key' node.
// If we use the indent provided we will have double indents:
// "budgets": [
// {
// "type": "initial",
// "maximumWarning": "2mb",
// "maximumError": "5mb"
// },
// {
// "type": "anyComponentStyle",
// 'maximumWarning": "5kb"
// }
// ]
return JSON.stringify(value, null, 2).replace(/\n/g, indentStr);
}

26
npm/ng-packs/packages/schematics/src/utils/angular/latest-versions.ts

@ -1,26 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export const latestVersions = {
// These versions should be kept up to date with latest Angular peer dependencies.
Angular: '~10.0.0-rc.0',
RxJs: '~6.6.0',
ZoneJs: '~0.10.2',
TypeScript: '~3.9.5',
TsLib: '^2.0.0',
// The versions below must be manually updated when making a new devkit release.
// For our e2e tests, these versions must match the latest tag present on the branch.
// During RC periods they will not match the latest RC until there's a new git tag, and
// should not be updated.
DevkitBuildAngular: '~0.1000.0-rc.0',
DevkitBuildNgPackagr: '~0.1000.0-rc.0',
DevkitBuildWebpack: '~0.1000.0-rc.0',
ngPackagr: '^10.0.0',
};

20
npm/ng-packs/packages/schematics/src/utils/angular/latest-versions/package.json

@ -0,0 +1,20 @@
{
"description": "Package versions used by schematics in @schematics/angular.",
"comment": "This file is needed so that depedencies are synced by Renovate.",
"private": true,
"dependencies": {
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"jasmine-core": "~4.0.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.1.0",
"karma-jasmine-html-reporter": "~1.7.0",
"karma-jasmine": "~4.0.0",
"karma": "~6.3.0",
"ng-packagr": "^13.0.0",
"rxjs": "~6.6.7",
"tslib": "^2.3.0",
"typescript": "~4.6.2",
"zone.js": "~0.11.4"
}
}

54
npm/ng-packs/packages/schematics/src/utils/angular/lint-fix.ts

@ -1,54 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
DirEntry,
Rule,
SchematicContext,
SchematicsException,
Tree,
} from '@angular-devkit/schematics';
import { TslintFixTask } from '@angular-devkit/schematics/tasks';
export function applyLintFix(path = '/'): Rule {
return (tree: Tree, context: SchematicContext) => {
// Find the closest tslint.json or tslint.yaml
let dir: DirEntry | null = tree.getDir(path.substr(0, path.lastIndexOf('/')));
do {
if ((dir.subfiles as string[]).some(f => f === 'tslint.json' || f === 'tslint.yaml')) {
break;
}
dir = dir.parent;
} while (dir !== null);
if (dir === null) {
throw new SchematicsException(
'Asked to run lint fixes, but could not find a tslint.json or tslint.yaml config file.',
);
}
// Only include files that have been touched.
const files = tree.actions.reduce((acc: Set<string>, action) => {
const path = action.path.substr(1); // Remove the starting '/'.
if (path.endsWith('.ts') && dir && action.path.startsWith(dir.path)) {
acc.add(path);
}
return acc;
}, new Set<string>());
context.addTask(
new TslintFixTask({
ignoreErrors: true,
tsConfigPath: 'tsconfig.json',
files: [...files],
}),
);
};
}

9
npm/ng-packs/packages/schematics/src/utils/angular/ng-ast-utils.ts

@ -1,10 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { normalize } from '@angular-devkit/core';
import { SchematicsException, Tree } from '@angular-devkit/schematics';
import { dirname } from 'path';
@ -59,17 +60,17 @@ export function findBootstrapModulePath(host: Tree, mainPath: string): string {
const mainBuffer = host.read(mainPath);
if (!mainBuffer) {
throw new SchematicsException(`Client app main file (${mainPath}) not found`);
throw new SchematicsException(`Client application main file (${mainPath}) not found`);
}
const mainText = mainBuffer.toString('utf-8');
const source = ts.createSourceFile(mainPath, mainText, ts.ScriptTarget.Latest, true);
const allNodes = getSourceNodes(source);
const bootstrapModuleRelativePath = allNodes
.filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
.filter(ts.isImportDeclaration)
.filter(imp => {
return findNode(imp, ts.SyntaxKind.Identifier, bootstrapModule.getText());
})
.map((imp: ts.ImportDeclaration) => {
.map(imp => {
const modulePathStringLiteral = imp.moduleSpecifier as ts.StringLiteral;
return modulePathStringLiteral.text;

5
npm/ng-packs/packages/schematics/src/utils/angular/parse-name.ts

@ -1,10 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// import { relative, Path } from "../../../angular_devkit/core/src/virtual-fs";
import { Path, basename, dirname, join, normalize } from '@angular-devkit/core';
@ -15,7 +16,7 @@ export interface Location {
export function parseName(path: string, name: string): Location {
const nameWithoutPath = basename(normalize(name));
const namePath = dirname(join(normalize(path), name) as Path);
const namePath = dirname(join(normalize(path), name));
return {
name: nameWithoutPath,

2
npm/ng-packs/packages/schematics/src/utils/angular/paths.ts

@ -1,6 +1,6 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license

2
npm/ng-packs/packages/schematics/src/utils/angular/project-targets.ts

@ -1,6 +1,6 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license

76
npm/ng-packs/packages/schematics/src/utils/angular/tsconfig.ts

@ -1,76 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { JsonParseMode, parseJsonAst } from '@angular-devkit/core';
import { Rule, SchematicsException, Tree } from '@angular-devkit/schematics';
import { appendValueInAstArray, findPropertyInAstObject } from './json-utils';
const SOLUTION_TSCONFIG_PATH = 'tsconfig.json';
/**
* Add project references in "Solution Style" tsconfig.
*/
export function addTsConfigProjectReferences(paths: string[]): Rule {
return (host, context) => {
const logger = context.logger;
// We need to read after each write to avoid missing `,` when appending multiple items.
for (const path of paths) {
const source = host.read(SOLUTION_TSCONFIG_PATH);
if (!source) {
// Solution tsconfig doesn't exist.
logger.warn(
`Cannot add reference '${path}' in '${SOLUTION_TSCONFIG_PATH}'. File doesn't exists.`,
);
return;
}
const jsonAst = parseJsonAst(source.toString(), JsonParseMode.Loose);
if (jsonAst?.kind !== 'object') {
// Invalid JSON
throw new SchematicsException(`Invalid JSON AST Object '${SOLUTION_TSCONFIG_PATH}'.`);
}
// Solutions style tsconfig can contain 2 properties:
// - 'files' with a value of empty array
// - 'references'
const filesAst = findPropertyInAstObject(jsonAst, 'files');
const referencesAst = findPropertyInAstObject(jsonAst, 'references');
if (
filesAst?.kind !== 'array' ||
filesAst.elements.length !== 0 ||
referencesAst?.kind !== 'array'
) {
logger.warn(
`Cannot add reference '${path}' in '${SOLUTION_TSCONFIG_PATH}'. It appears to be an invalid solution style tsconfig.`,
);
return;
}
// Append new paths
const recorder = host.beginUpdate(SOLUTION_TSCONFIG_PATH);
appendValueInAstArray(recorder, referencesAst, { path: `./${path}` }, 4);
host.commitUpdate(recorder);
}
};
}
/**
* Throws an exception when the base tsconfig doesn't exists.
*/
export function verifyBaseTsConfigExists(host: Tree): void {
if (host.exists('tsconfig.json')) {
return;
}
throw new SchematicsException(
`Cannot find base TypeScript configuration file 'tsconfig.json'.`,
);
}

60
npm/ng-packs/packages/schematics/src/utils/angular/validation.ts

@ -1,20 +1,14 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { tags } from '@angular-devkit/core';
import { SchematicsException } from '@angular-devkit/schematics';
export function validateName(name: string): void {
if (name && /^\d/.test(name)) {
throw new SchematicsException(tags.oneLine`name (${name})
can not start with a digit.`);
}
}
// Must start with a letter, and must contain only alphanumeric characters or dashes.
// When adding a dash the segment after the dash must also start with a letter.
export const htmlSelectorRe = /^[a-zA-Z][.0-9a-zA-Z]*(:?-[a-zA-Z][.0-9a-zA-Z]*)*$/;
@ -25,53 +19,3 @@ export function validateHtmlSelector(selector: string): void {
is invalid.`);
}
}
export function validateProjectName(projectName: string) {
const errorIndex = getRegExpFailPosition(projectName);
const unsupportedProjectNames: string[] = [];
const packageNameRegex = /^(?:@[a-zA-Z0-9_-]+\/)?[a-zA-Z0-9_-]+$/;
if (errorIndex !== null) {
const firstMessage = tags.oneLine`
Project name "${projectName}" is not valid. New project names must
start with a letter, and must contain only alphanumeric characters or dashes.
When adding a dash the segment after the dash must also start with a letter.
`;
const msg = tags.stripIndent`
${firstMessage}
${projectName}
${Array(errorIndex + 1).join(' ') + '^'}
`;
throw new SchematicsException(msg);
} else if (unsupportedProjectNames.indexOf(projectName) !== -1) {
throw new SchematicsException(
`Project name ${JSON.stringify(projectName)} is not a supported name.`,
);
} else if (!packageNameRegex.test(projectName)) {
throw new SchematicsException(`Project name ${JSON.stringify(projectName)} is invalid.`);
}
}
function getRegExpFailPosition(str: string): number | null {
const isScope = /^@.*\/.*/.test(str);
if (isScope) {
// Remove starting @
str = str.replace(/^@/, '');
// Change / to - for validation
str = str.replace(/\//g, '-');
}
const parts = str.indexOf('-') >= 0 ? str.split('-') : [str];
const matched: string[] = [];
const projectNameRegexp = /^[a-zA-Z][.0-9a-zA-Z]*(-[.0-9a-zA-Z]*)*$/;
parts.forEach(part => {
if (part.match(projectNameRegexp)) {
matched.push(part);
}
});
const compare = matched.join('-');
return str !== compare ? compare.length : null;
}

23
npm/ng-packs/packages/schematics/src/utils/angular/workspace-models.ts

@ -1,11 +1,11 @@
/* eslint-disable @typescript-eslint/ban-types */
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export enum ProjectType {
Application = 'application',
Library = 'library',
@ -49,7 +49,6 @@ export interface BrowserBuilderOptions extends BrowserBuilderBaseOptions {
optimization?: boolean;
outputHashing?: OutputHashing;
resourcesOutputPath?: string;
extractCss?: boolean;
namedChunks?: boolean;
aot?: boolean;
extractLicenses?: boolean;
@ -77,10 +76,12 @@ export interface ServerBuilderOptions {
tsConfig: string;
main: string;
fileReplacements?: FileReplacements[];
optimization?: {
scripts?: boolean;
styles?: boolean;
};
optimization?:
| boolean
| {
scripts?: boolean;
styles?: boolean;
};
sourceMap?:
| boolean
| {
@ -101,11 +102,6 @@ export interface TestBuilderOptions extends Partial<BrowserBuilderBaseOptions> {
karmaConfig: string;
}
export interface LintBuilderOptions {
tsConfig: string[] | string;
exclude?: string[];
}
export interface ExtractI18nOptions {
browserTarget: string;
}
@ -128,7 +124,6 @@ export type LibraryBuilderTarget = BuilderTarget<Builders.NgPackagr, LibraryBuil
export type BrowserBuilderTarget = BuilderTarget<Builders.Browser, BrowserBuilderOptions>;
export type ServerBuilderTarget = BuilderTarget<Builders.Server, ServerBuilderOptions>;
export type AppShellBuilderTarget = BuilderTarget<Builders.AppShell, AppShellBuilderOptions>;
export type LintBuilderTarget = BuilderTarget<Builders.TsLint, LintBuilderOptions>;
export type TestBuilderTarget = BuilderTarget<Builders.Karma, TestBuilderOptions>;
export type ServeBuilderTarget = BuilderTarget<Builders.DevServer, ServeBuilderOptions>;
export type ExtractI18nBuilderTarget = BuilderTarget<Builders.ExtractI18n, ExtractI18nOptions>;
@ -168,12 +163,12 @@ export interface WorkspaceProject<TProjectType extends ProjectType = ProjectType
export interface WorkspaceTargets<TProjectType extends ProjectType = ProjectType.Application> {
build?: TProjectType extends ProjectType.Library ? LibraryBuilderTarget : BrowserBuilderTarget;
server?: ServerBuilderTarget;
lint?: LintBuilderTarget;
test?: TestBuilderTarget;
serve?: ServeBuilderTarget;
e2e?: E2EBuilderTarget;
'app-shell'?: AppShellBuilderTarget;
'extract-i18n'?: ExtractI18nBuilderTarget;
// TODO(hans): change this any to unknown when google3 supports TypeScript 3.0.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}

51
npm/ng-packs/packages/schematics/src/utils/angular/workspace.ts

@ -1,12 +1,13 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { virtualFs, workspaces } from '@angular-devkit/core';
import { Rule, Tree } from '@angular-devkit/schematics';
import { json, virtualFs, workspaces } from '@angular-devkit/core';
import { noop, Rule, Tree } from '@angular-devkit/schematics';
import { ProjectType } from './workspace-models';
function createHost(tree: Tree): workspaces.WorkspaceHost {
@ -33,13 +34,13 @@ function createHost(tree: Tree): workspaces.WorkspaceHost {
}
export function updateWorkspace(
updater: (workspace: workspaces.WorkspaceDefinition) => void | PromiseLike<void>,
updater: (workspace: workspaces.WorkspaceDefinition) => void | Rule | PromiseLike<void | Rule>,
): Rule;
export function updateWorkspace(workspace: workspaces.WorkspaceDefinition): Rule;
export function updateWorkspace(
updaterOrWorkspace:
| workspaces.WorkspaceDefinition
| ((workspace: workspaces.WorkspaceDefinition) => void | PromiseLike<void>),
| ((workspace: workspaces.WorkspaceDefinition) => void | Rule | PromiseLike<void | Rule>),
): Rule {
return async (tree: Tree) => {
const host = createHost(tree);
@ -47,14 +48,15 @@ export function updateWorkspace(
if (typeof updaterOrWorkspace === 'function') {
const { workspace } = await workspaces.readWorkspace('/', host);
const result = updaterOrWorkspace(workspace);
if (result !== undefined) {
await result;
}
const result = await updaterOrWorkspace(workspace);
await workspaces.writeWorkspace(workspace, host);
return result || noop;
} else {
await workspaces.writeWorkspace(updaterOrWorkspace, host);
return noop;
}
};
}
@ -83,8 +85,37 @@ export async function createDefaultPath(tree: Tree, projectName: string): Promis
const workspace = await getWorkspace(tree);
const project = workspace.projects.get(projectName);
if (!project) {
throw new Error('Specified project does not exist.');
throw new Error(`Project "${projectName}" does not exist.`);
}
return buildDefaultPath(project);
}
export function* allWorkspaceTargets(
workspace: workspaces.WorkspaceDefinition,
): Iterable<[string, workspaces.TargetDefinition, string, workspaces.ProjectDefinition]> {
for (const [projectName, project] of workspace.projects) {
for (const [targetName, target] of project.targets) {
yield [targetName, target, projectName, project];
}
}
}
export function* allTargetOptions(
target: workspaces.TargetDefinition,
skipBaseOptions = false,
): Iterable<[string | undefined, Record<string, json.JsonValue | undefined>]> {
if (!skipBaseOptions && target.options) {
yield [undefined, target.options];
}
if (!target.configurations) {
return;
}
for (const [name, options] of Object.entries(target.configurations)) {
if (options !== undefined) {
yield [name, options];
}
}
}

1
npm/ng-packs/packages/schematics/src/utils/index.ts

@ -7,6 +7,7 @@ export * from './enum';
export * from './file';
export * from './generics';
export * from './import';
export * from './lib';
export * from './methods';
export * from './model';
export * from './namespace';

9
npm/ng-packs/packages/schematics/src/utils/lib.ts

@ -0,0 +1,9 @@
import { Tree } from '@angular-devkit/schematics';
import { resolveProject } from "./workspace";
export async function createTargetLibIfNotExist(tree: Tree, target: string) {
const lib = await resolveProject(tree, target, null);
if (!lib) {
}
}

2
npm/ng-packs/packages/schematics/src/utils/source.ts

@ -23,7 +23,7 @@ export function createApiDefinitionGetter(params: GenerateProxySchema) {
if (!sourceUrl) {
sourceUrl = getSourceUrl(host, source, apiName);
}
return await getApiDefinition(sourceUrl);
return await getApiDefinition(sourceUrl!);
};
}

49
npm/ng-packs/packages/schematics/src/utils/workspace.ts

@ -3,9 +3,11 @@ import { strings, workspaces } from '@angular-devkit/core';
import { SchematicsException, Tree } from '@angular-devkit/schematics';
import { Exception } from '../enums';
import { Project } from '../models';
import { getWorkspace, getWorkspaceSchema, ProjectType, WorkspaceSchema } from './angular';
import { buildDefaultPath, getWorkspace, ProjectType, WorkspaceSchema } from './angular';
import { findEnvironmentExpression } from './ast';
import { readFileInTree } from './common';
import { NOT_FOUND_VALUE } from '../constants/symbols';
import { parseJson } from '@angular/cli/utilities/json-file';
export function isLibrary(project: workspaces.ProjectDefinition): boolean {
return project.extensions['projectType'] === ProjectType.Library;
@ -33,8 +35,11 @@ export function readWorkspaceSchema(tree: Tree) {
return workspaceSchema;
}
export async function resolveProject(tree: Tree, name: string): Promise<Project> {
export async function resolveProject<T = any>(
tree: Tree,
name: string,
notFoundValue: T = NOT_FOUND_VALUE as unknown as any,
): Promise<Project | T> {
name = name || readWorkspaceSchema(tree).defaultProject!;
const workspace = await getWorkspace(tree);
let definition: Project['definition'] | undefined;
@ -61,7 +66,45 @@ export async function resolveProject(tree: Tree, name: string): Promise<Project>
definition = workspace.projects.get(name);
} catch (_) {}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (!definition && notFoundValue !== NOT_FOUND_VALUE) {
return notFoundValue;
}
if (!definition) throw new SchematicsException(Exception.NoProject);
return { name, definition };
}
export function getWorkspaceSchema(host: Tree): WorkspaceSchema {
const path = getWorkspacePath(host);
const configBuffer = host.read(path);
if (configBuffer === null) {
throw new SchematicsException(`Could not find (${path})`);
}
const content = configBuffer.toString();
return parseJson(content) as Record<string, any> as WorkspaceSchema;
}
export function getWorkspacePath(host: Tree): string {
const possibleFiles = ['/angular.json', '/.angular.json'];
const path = possibleFiles.filter(path => host.exists(path))[0];
return path;
}
/**
* Build a default project path for generating.
* @param project The project which will have its default path generated.
* @param entryPoint The secondary-entry-point.
*/
export function buildTargetPath(
project: workspaces.ProjectDefinition,
entryPoint?: string,
): string {
if (entryPoint) {
return `${project.root}/${entryPoint}/src`;
}
return buildDefaultPath(project);
}

6
npm/ng-packs/scripts/build-schematics.ts

@ -20,6 +20,12 @@ class FileCopy {
const PACKAGE_TO_BUILD = 'schematics';
const FILES_TO_COPY_AFTER_BUILD: (FileCopy | string)[] = [
{ src: 'src/commands/create-lib/schema.json', dest: 'commands/create-lib/schema.json' },
{ src: 'src/commands/create-lib/files-package', dest: 'commands/create-lib/files-package' },
{
src: 'src/commands/create-lib/files-secondary-entrypoint',
dest: 'commands/create-lib/files-secondary-entrypoint',
},
{ src: 'src/commands/proxy-add/schema.json', dest: 'commands/proxy-add/schema.json' },
{ src: 'src/commands/proxy-index/schema.json', dest: 'commands/proxy-index/schema.json' },
{ src: 'src/commands/proxy-refresh/schema.json', dest: 'commands/proxy-refresh/schema.json' },

Loading…
Cancel
Save