diff --git a/apple/OmnivoreKit/Sources/App/Views/AI/DigestView.swift b/apple/OmnivoreKit/Sources/App/Views/AI/DigestView.swift deleted file mode 100644 index 437bccf77..000000000 --- a/apple/OmnivoreKit/Sources/App/Views/AI/DigestView.swift +++ /dev/null @@ -1,290 +0,0 @@ -import SwiftUI -import Models -import Services -import Views - -public class DigestViewModel: ObservableObject { - @Published var isLoading = false - @Published var digest: DigestResult? - - func load(dataService: DataService) async { - isLoading = true - - -// if digest == nil { -// do { -// digest = try await dataService.getLatestDigest(timeoutInterval: 10) -// } catch { -// print("ERROR WITH DIGEST: ", error) -// } -// } - isLoading = false - } -} - -@available(iOS 17.0, *) -@MainActor -struct DigestView: View { - let viewModel: DigestViewModel = DigestViewModel() - let dataService: DataService - - // @State private var currentIndex = 0 - @State private var items: [DigestItem] - // @State private var preloadedItems: [Int: String] = [:] - @Environment(\.dismiss) private var dismiss - - // let itemCount = 10 // Number of items to initially load - // let prefetchCount = 2 // Number of items to prefetch - - public init(dataService: DataService) { - self.dataService = dataService - self.items = [ - DigestItem( - id: "1468AFAA-88sdfsdfC-4546-BE02-EACF385288FC", - site: "CNBC.com", - siteIcon: URL(string: "https://www.cnbc.com/favicon.ico"), - author: "Kif Leswing", - title: "Apple shares just had their best day since last May", - summaryText: "In a significant political turn, the SOTU response faces unexpected collapse, marking a stark contrast to Trump's latest" + - " downturn, alongside an unprecedented surge in Biden's fundraising efforts as of 3/11/24, according to the TDPS Podcast. " + - "The analysis provides insights into the shifting dynamics of political support and the potential implications for future " + - "electoral strategies. ", - keyPointsText: "Key points from the article:", - highlightsText: "Highlights from the article:" - ), - DigestItem( - id: "1468AFAA-8sdfsdffsdf-4546-BE02-EACF385288FC", - site: "CNBC.com", - siteIcon: URL(string: "https://www.cnbc.com/favicon.ico"), - author: "Kif Leswing", - title: "Apple shares just had their best day since last May", - summaryText: "In a significant political turn, the SOTU response faces unexpected collapse, marking a stark contrast to Trump's latest" + - " downturn, alongside an unprecedented surge in Biden's fundraising efforts as of 3/11/24, according to the TDPS Podcast. " + - "The analysis provides insights into the shifting dynamics of political support and the potential implications for future " + - "electoral strategies. ", - keyPointsText: "Key points from the article:", - highlightsText: "Highlights from the article:" - ), - DigestItem( - id: "1468AFAA-882C-asdadfsa85288FC", - site: "CNBC.com", - siteIcon: URL(string: "https://www.cnbc.com/favicon.ico"), - author: "Kif Leswing", - title: "Apple shares just had their best day since last May", - summaryText: "In a significant political turn, the SOTU response faces unexpected collapse, marking a stark contrast to Trump's latest" + - " downturn, alongside an unprecedented surge in Biden's fundraising efforts as of 3/11/24, according to the TDPS Podcast. " + - "The analysis provides insights into the shifting dynamics of political support and the potential implications for future " + - "electoral strategies. ", - keyPointsText: "Key points from the article:", - highlightsText: "Highlights from the article:" - ) - ] - // currentIndex = 0 - // _preloadedItems = [Int:String] - } - - var body: some View { - if viewModel.isLoading { - ProgressView() - } else { - itemBody - .task { - await viewModel.load(dataService: dataService) - } - } - } - - @available(iOS 17.0, *) - var itemBody: some View { - ScrollView(.vertical) { - LazyVStack(spacing: 0) { - ForEach(Array(self.items.enumerated()), id: \.1.id) { idx, item in - PreviewItemView( - viewModel: PreviewItemViewModel(dataService: dataService, item: item, showSwipeHint: idx == 0) - ) - .containerRelativeFrame([.horizontal, .vertical]) - } - RatingView() - .containerRelativeFrame([.horizontal, .vertical]) - } - .scrollTargetLayout() - } - .scrollTargetBehavior(.paging) - .ignoresSafeArea() - } -} - -//@MainActor -//public class PreviewItemViewModel: ObservableObject { -// let dataService: DataService -// @Published var item: DigestItem -// let showSwipeHint: Bool -// -// @Published var isLoading = false -// @Published var resultText: String? -// @Published var promptDisplayText: String? -// -// init(dataService: DataService, item: DigestItem, showSwipeHint: Bool) { -// self.dataService = dataService -// self.item = item -// self.showSwipeHint = showSwipeHint -// } -// -// func loadResult() async { -//// isLoading = true -//// let taskId = try? await dataService.createAITask( -//// extraText: extraText, -//// libraryItemId: item?.id ?? "", -//// promptName: "summarize-001" -//// ) -//// -//// if let taskId = taskId { -//// do { -//// let fetchedText = try await dataService.pollAITask(jobId: taskId, timeoutInterval: 30) -//// resultText = fetchedText -//// } catch { -//// print("ERROR WITH RESULT TEXT: ", error) -//// } -//// } else { -//// print("NO TASK ID: ", taskId) -//// } -//// isLoading = false -// } -//} -// -//@MainActor -//struct PreviewItemView: View { -// @StateObject var viewModel: PreviewItemViewModel -// -// var body: some View { -// VStack(spacing: 10) { -// HStack { -// AsyncImage(url: viewModel.item.siteIcon) { phase in -// if let image = phase.image { -// image -// .resizable() -// .aspectRatio(contentMode: .fill) -// .frame(width: 20, height: 20, alignment: .center) -// } else { -// Color.appButtonBackground -// .frame(width: 20, height: 20, alignment: .center) -// } -// } -// Text(viewModel.item.site) -// .font(Font.system(size: 14)) -// .frame(maxWidth: .infinity, alignment: .topLeading) -// } -// .padding(.top, 10) -// Text(viewModel.item.title) -// // .font(.body) -// // .fontWeight(.semibold) -// .font(Font.system(size: 18, weight: .semibold)) -// .frame(maxWidth: .infinity, alignment: .topLeading) -// -// Text(viewModel.item.author) -// .font(Font.system(size: 14)) -// .foregroundColor(Color(hex: "898989")) -// .frame(maxWidth: .infinity, alignment: .topLeading) -// -// Color(hex: "2A2A2A") -// .frame(height: 1) -// .frame(maxWidth: .infinity, alignment: .center) -// .padding(.vertical, 20) -// -// if viewModel.isLoading { -// ProgressView() -// .task { -// await viewModel.loadResult() -// } -// .frame(maxWidth: .infinity, maxHeight: .infinity) -// } else { -// Text(viewModel.item.summaryText) -// .font(Font.system(size: 16)) -// // .font(.body) -// .lineSpacing(12.0) -// .frame(maxWidth: .infinity, alignment: .topLeading) -// HStack { -// Button(action: {}, label: { -// HStack(alignment: .center) { -// Text("Start listening") -// .font(Font.system(size: 14)) -// .frame(height: 42, alignment: .center) -// Image(systemName: "play.fill") -// .resizable() -// .frame(width: 10, height: 10) -// } -// .padding(.horizontal, 15) -// .background(Color.blue) -// .foregroundColor(.white) -// .cornerRadius(18) -// }) -// Spacer() -// } -// .padding(.top, 20) -// } -// Spacer() -// if viewModel.showSwipeHint { -// VStack { -// Image.doubleChevronUp -// Text("Swipe up for next article") -// .foregroundColor(Color(hex: "898989")) -// } -// .padding(.bottom, 50) -// } -// }.frame(maxWidth: .infinity, maxHeight: .infinity) -// .padding(.top, 100) -// .padding(.horizontal, 15) -// -// } -//} -// -//struct RatingView: View { -// @State private var rating: Int = 0 -// -// var body: some View { -// VStack(spacing: 30) { -// Text("Rate today's digest") -// .font(.title) -// .padding(.vertical, 40) -// Text("I liked the stories picked for today's digest") -// RatingWidget() -// -// Text("The stories were interesting") -// RatingWidget() -// -// Text("The voices sounded good") -// RatingWidget() -// -// Text("I liked the music") -// RatingWidget() -// Spacer() -// }.padding(.top, 60) -// } -//} -// -// -//struct StarView: View { -// var isFilled: Bool -// var body: some View { -// Image(systemName: isFilled ? "star.fill" : "star") -// .foregroundColor(isFilled ? Color.yellow : Color.gray) -// } -//} -// -//struct RatingWidget: View { -// @State private var rating: Int = 0 -// var body: some View { -// HStack { -// ForEach(1...5, id: \.self) { index in -// StarView(isFilled: index <= rating) -// .onTapGesture { -// rating = index -// } -// } -// } -// .padding() -// .background(Color(hex: "313131")) -// .cornerRadius(8) -// // .shadow(radius: 3) -// } -//} diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index a9ce0c56f..430b16d26 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -181,7 +181,7 @@ struct AnimatingCellHeight: AnimatableModifier { // swiftlint:disable file_length #if os(iOS) - private let enableGrid = UIDevice.isIPad || FeatureFlag.enableGridCardsOnPhone + private let enableGrid = UIDevice.isIPad @MainActor struct HomeFeedContainerView: View { @@ -204,8 +204,6 @@ struct AnimatingCellHeight: AnimatableModifier { @ObservedObject var viewModel: HomeFeedViewModel @State private var selection = Set() - @AppStorage("LibraryList::digestEnabled") var digestEnabled = false - init(viewModel: HomeFeedViewModel, isEditMode: Binding) { _viewModel = ObservedObject(wrappedValue: viewModel) _isEditMode = isEditMode @@ -354,25 +352,6 @@ struct AnimatingCellHeight: AnimatableModifier { viewModel.stopUsingFollowingPrimer = true } } - .task { - do { - // If the user doesn't have digest enabled, try updating their features - // to see if they have it. - if !digestEnabled { - if let viewer = try await dataService.fetchViewer() { - digestEnabled = viewer.hasFeatureGranted("ai-digest") - } - } - if digestEnabled { - Task { - await viewModel.checkForDigestUpdate(dataService: dataService) - } - } - } catch { - print("ERROR FETCHING VIEWER: ", error) - print("") - } - } .environment(\.editMode, self.$isEditMode) .navigationBarTitleDisplayMode(.inline) } @@ -417,7 +396,7 @@ struct AnimatingCellHeight: AnimatableModifier { if isEditMode == .active { Button(action: { isEditMode = .inactive }, label: { Text("Cancel") }) } else { - if #available(iOS 17.0, *), digestEnabled { + if #available(iOS 17.0, *), dataService.featureFlags.digestEnabled { Button( action: { showLibraryDigest = true }, label: { viewModel.digestIsUnread ? Image.tabDigestSelected : Image.tabDigest } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechVoiceSelectionView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechVoiceSelectionView.swift index 46389bfbe..4b6fd3fdd 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechVoiceSelectionView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechVoiceSelectionView.swift @@ -23,7 +23,7 @@ var body: some View { Group { Form { - if FeatureFlag.enableUltraRealisticVoices, language.key == "en" { + if language.key == "en" { if viewModel.waitingForRealisticVoices { HStack { Text(LocalText.texttospeechBetaSignupInProcess) diff --git a/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift b/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift index 7260e6bab..3822faa1e 100644 --- a/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift @@ -37,6 +37,8 @@ public struct RootView: View { Services.scheduleBackgroundFetch() #endif } + }.task { + await viewModel.services.dataService.tryUpdateFeatureFlags() } } } diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/HighlightViewer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/HighlightViewer.swift deleted file mode 100644 index ef90a7f3f..000000000 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/HighlightViewer.swift +++ /dev/null @@ -1,93 +0,0 @@ -import Models -import SwiftUI -import Utils -import Views -import WebKit - -#if os(iOS) - struct HighlightViewer: PlatformViewRepresentable { - let highlightData: HighlightData - - func makeCoordinator() -> WebReaderCoordinator { - WebReaderCoordinator() - } - - private func makePlatformView(context: Context) -> WKWebView { - let webView = WebViewManager.shared() - let contentController = WKUserContentController() - - webView.navigationDelegate = context.coordinator - webView.configuration.userContentController = contentController - webView.configuration.userContentController.removeAllScriptMessageHandlers() - - #if os(iOS) - webView.isOpaque = false - webView.backgroundColor = .clear - webView.scrollView.delegate = context.coordinator - webView.scrollView.contentInset.top = readerViewNavBarHeight - webView.scrollView.verticalScrollIndicatorInsets.top = readerViewNavBarHeight - webView.configuration.userContentController.add(webView, name: "viewerAction") - #else - webView.setValue(false, forKey: "drawsBackground") - #endif - - for action in WebViewAction.allCases { - webView.configuration.userContentController.add(context.coordinator, name: action.rawValue) - } - - webView.configuration.userContentController.addScriptMessageHandler( - context.coordinator, contentWorld: .page, name: "articleAction" - ) - - loadContent(webView: webView) - - return webView - } - - private func updatePlatformView(_: WKWebView, context _: Context) { - // If the webview had been terminated `needsReload` will have been set to true - // Or if the articleContent value has changed then it's id will be different from the coordinator's -// if context.coordinator.needsReload { -// loadContent(webView: webView) -// context.coordinator.needsReload = false -// return -// } - } - - private func loadContent(webView: WKWebView) { - // swiftlint:disable line_length - let themeKey = ThemeManager.currentThemeName - let content = """ - - - - - - - - -
-
- \(highlightData.highlightHTML) -
- - - """ - // swiftlint:enable line_length - - webView.loadHTMLString(content, baseURL: ViewsPackage.resourceURL) - } - } - - extension HighlightViewer { - func makeUIView(context: Context) -> WKWebView { - makePlatformView(context: context) - } - - func updateUIView(_ webView: WKWebView, context: Context) { - updatePlatformView(webView, context: context) - } - } -#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index 9ea666087..e1b6e5653 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -400,7 +400,7 @@ struct WebReaderContainerView: View { #endif }, tapHandler: tapHandler, - explainHandler: explainHandler, + explainHandler: dataService.featureFlags.explainEnabled ? explainHandler : nil, scrollPercentHandler: scrollPercentHandler, webViewActionHandler: webViewActionHandler, navBarVisibilityUpdater: { visible in diff --git a/apple/OmnivoreKit/Sources/Models/DataModels/Feature.swift b/apple/OmnivoreKit/Sources/Models/DataModels/Feature.swift index 2bccfc724..bf5b6e5a0 100644 --- a/apple/OmnivoreKit/Sources/Models/DataModels/Feature.swift +++ b/apple/OmnivoreKit/Sources/Models/DataModels/Feature.swift @@ -1,3 +1,4 @@ +import SwiftUI public struct FeatureInternal { public let name: String diff --git a/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift b/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift index 11062d9ea..0b131f3c7 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift @@ -33,6 +33,8 @@ public final class DataService: ObservableObject { persistentContainer.viewContext } + public var featureFlags = FeatureFlags() + public var lastItemSyncTime: Date { get { guard @@ -298,4 +300,11 @@ public final class DataService: ObservableObject { } return objectID } + + public func tryUpdateFeatureFlags() async { + if let features = (try? await fetchViewer())?.enabledFeatures { + featureFlags.digestEnabled = features.contains("ai-digest") + featureFlags.explainEnabled = features.contains("ai-explain") + } + } } diff --git a/apple/OmnivoreKit/Sources/Utils/FeatureFlags.swift b/apple/OmnivoreKit/Sources/Utils/FeatureFlags.swift index 9f0d5f898..24b11cd7d 100644 --- a/apple/OmnivoreKit/Sources/Utils/FeatureFlags.swift +++ b/apple/OmnivoreKit/Sources/Utils/FeatureFlags.swift @@ -1,4 +1,5 @@ import Foundation +import SwiftUI #if DEBUG public let isDebug = true @@ -6,11 +7,13 @@ import Foundation public let isDebug = false #endif -public enum FeatureFlag { - public static let enableSnoozeFromShareExtension = false - public static let enableRemindersFromShareExtension = false - public static let enableShareButton = false - public static let enableSnooze = false - public static let enableGridCardsOnPhone = false - public static let enableUltraRealisticVoices = true +public struct FeatureFlags { + @AppStorage("FeatureFlag::digestEnabled") + public var digestEnabled = false + + @AppStorage("FeatureFlag::explainEnabled") + public var explainEnabled = false + + public init() { + } } diff --git a/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift b/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift index 57b3e4199..93ddf7910 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift @@ -27,6 +27,8 @@ public final class OmnivoreWebView: WKWebView { private var currentMenu: ContextMenu = .defaultMenu + private var explainEnabled = false + override init(frame: CGRect, configuration: WKWebViewConfiguration) { super.init(frame: frame, configuration: configuration) @@ -399,8 +401,12 @@ public final class OmnivoreWebView: WKWebView { return } let highlight = UICommand(title: LocalText.genericHighlight, action: #selector(highlightSelection)) - let explain = UICommand(title: "Explain", action: #selector(explainSelection)) - items = [highlight, explain, annotate] + if explainHandler != nil { + let explain = UICommand(title: "Explain", action: #selector(explainSelection)) + items = [highlight, explain, annotate] + } else { + items = [highlight, annotate] + } } else { let remove = UICommand(title: "Remove", action: #selector(removeSelection)) let setLabels = UICommand(title: LocalText.labelsGeneric, action: #selector(setLabels)) diff --git a/packages/api/src/routers/explain_router.ts b/packages/api/src/routers/explain_router.ts index 9f2aebee1..347807889 100644 --- a/packages/api/src/routers/explain_router.ts +++ b/packages/api/src/routers/explain_router.ts @@ -27,7 +27,7 @@ export function explainRouter() { return res.status(400).send('Bad Request') } - if (!(await findGrantedFeatureByName(FeatureName.Explain, user.id))) { + if (!(await findGrantedFeatureByName(FeatureName.AIExplain, user.id))) { return res.status(403).send('Not granted') } diff --git a/packages/api/src/services/features.ts b/packages/api/src/services/features.ts index c34a86322..709615e18 100644 --- a/packages/api/src/services/features.ts +++ b/packages/api/src/services/features.ts @@ -17,7 +17,7 @@ export enum FeatureName { UltraRealisticVoice = 'ultra-realistic-voice', Notion = 'notion', AIDigest = 'ai-digest', - Explain = 'explain', + AIExplain = 'ai-explain', } export const getFeatureName = (name: string): FeatureName | undefined => { diff --git a/yarn.lock b/yarn.lock index 9c651f55f..7b354c30f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6493,6 +6493,11 @@ resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.3.tgz#1185726610acc37317ddab11c3c7f9066966bd20" integrity sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg== +"@sqltools/formatter@^1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" + integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw== + "@stitches/react@^1.2.5": version "1.2.8" resolved "https://registry.yarnpkg.com/@stitches/react/-/react-1.2.8.tgz#954f8008be8d9c65c4e58efa0937f32388ce3a38" @@ -8348,6 +8353,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@^20.11.0": + version "20.12.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" + integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== + dependencies: + undici-types "~5.26.4" + "@types/node@^20.8.4": version "20.11.30" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f" @@ -9916,6 +9928,11 @@ app-root-path@^3.0.0: resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== +app-root-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.1.0.tgz#5971a2fc12ba170369a7a1ef018c71e6e47c2e86" + integrity sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA== + apparatus@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/apparatus/-/apparatus-0.0.10.tgz#81ea756772ada77863db54ceee8202c109bdca3e" @@ -13380,7 +13397,7 @@ dateformat@^3.0.0, dateformat@^3.0.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dayjs@1.x, dayjs@^1.10.4, dayjs@^1.11.7: +dayjs@1.x, dayjs@^1.10.4, dayjs@^1.11.7, dayjs@^1.11.9: version "1.11.10" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== @@ -14116,7 +14133,7 @@ dotenv@^16.0.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== -dotenv@^16.3.1: +dotenv@^16.0.3, dotenv@^16.3.1: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== @@ -16811,6 +16828,17 @@ glob@^10.2.2: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" +glob@^10.3.10: + version "10.3.12" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" + integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.6" + minimatch "^9.0.1" + minipass "^7.0.4" + path-scurry "^1.10.2" + glob@^8.0.0: version "8.0.3" resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" @@ -19264,7 +19292,7 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jackspeak@^2.3.5: +jackspeak@^2.3.5, jackspeak@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== @@ -21256,6 +21284,11 @@ lowlight@^1.14.0: fault "^1.0.0" highlight.js "~10.7.0" +lru-cache@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -22481,7 +22514,7 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3, minipass@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== @@ -22569,6 +22602,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@^2.1.3: + version "2.1.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" + integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== + mkdirp@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" @@ -24892,6 +24930,14 @@ path-scurry@^1.10.1, path-scurry@^1.6.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-scurry@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" + integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -26961,6 +27007,14 @@ read-pkg@^7.1.0: parse-json "^5.2.0" type-fest "^2.0.0" +read-yaml-file@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read-yaml-file/-/read-yaml-file-2.1.0.tgz#c5866712db9ef5343b4d02c2413bada53c41c4a9" + integrity sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ== + dependencies: + js-yaml "^4.0.0" + strip-bom "^4.0.0" + read@1, read@^1.0.7, read@~1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" @@ -27105,6 +27159,11 @@ reflect-metadata@^0.1.13: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== +reflect-metadata@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" + integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== + reflect.getprototypeof@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" @@ -30171,7 +30230,7 @@ tslib@^1.0.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2: +tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -30387,6 +30446,27 @@ typeorm-naming-strategies@^4.1.0: resolved "https://registry.yarnpkg.com/typeorm-naming-strategies/-/typeorm-naming-strategies-4.1.0.tgz#1ec6eb296c8d7b69bb06764d5b9083ff80e814a9" integrity sha512-vPekJXzZOTZrdDvTl1YoM+w+sUIfQHG4kZTpbFYoTsufyv9NIBRe4Q+PdzhEAFA2std3D9LZHEb1EjE9zhRpiQ== +typeorm@^0.3.19: + version "0.3.20" + resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.20.tgz#4b61d737c6fed4e9f63006f88d58a5e54816b7ab" + integrity sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q== + dependencies: + "@sqltools/formatter" "^1.2.5" + app-root-path "^3.1.0" + buffer "^6.0.3" + chalk "^4.1.2" + cli-highlight "^2.1.11" + dayjs "^1.11.9" + debug "^4.3.4" + dotenv "^16.0.3" + glob "^10.3.10" + mkdirp "^2.1.3" + reflect-metadata "^0.2.1" + sha.js "^2.4.11" + tslib "^2.5.0" + uuid "^9.0.0" + yargs "^17.6.2" + typeorm@^0.3.4: version "0.3.7" resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.7.tgz#5776ed5058f0acb75d64723b39ff458d21de64c1" @@ -30425,6 +30505,11 @@ typescript@^4.4.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.3.3: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + ua-parser-js@^0.7.30: version "0.7.33" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532"