Initial public release of Warp.
Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
NSString *get_default_app_bundle_for_file(id);
|
||||
@@ -0,0 +1,15 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
NSString *get_default_app_bundle_for_file(NSString *file_path) {
|
||||
NSURL *fileUrl = [NSURL fileURLWithPath:file_path];
|
||||
NSURL *appUrl = [[NSWorkspace sharedWorkspace] URLForApplicationToOpenURL:fileUrl];
|
||||
if (!appUrl) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSBundle *appBundle = [NSBundle bundleWithURL:appUrl];
|
||||
if (!appBundle) {
|
||||
return nil;
|
||||
}
|
||||
return [appBundle bundleIdentifier];
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#import <Sentry/Sentry.h>
|
||||
|
||||
void start(id, id, id, bool);
|
||||
void setUser(id);
|
||||
void recordBreadcrumb(id, id, id, double);
|
||||
|
||||
@interface SentryLevelMapper : NSObject
|
||||
|
||||
/**
|
||||
* Maps a string to a SentryLevel. If the passed string doesn't match any level this defaults to
|
||||
* the 'error' level. See https://develop.sentry.dev/sdk/event-payloads/#optional-attributes
|
||||
*/
|
||||
+ (SentryLevel)levelWithString:(NSString *)string;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,95 @@
|
||||
#import "crash_reporting.h"
|
||||
#import <MetricKit/MetricKit.h>
|
||||
#import <Sentry/Sentry-Swift.h>
|
||||
#import <Sentry/Sentry.h>
|
||||
|
||||
void startSentry(id sentryUrl, id environment, id version, bool isDogfood) {
|
||||
[SentrySDK startWithConfigureOptions:^(SentryOptions *options) {
|
||||
options.dsn = sentryUrl;
|
||||
options.debug = NO;
|
||||
options.environment = environment;
|
||||
options.releaseName = version;
|
||||
options.enableAppHangTracking = isDogfood;
|
||||
}];
|
||||
}
|
||||
|
||||
void stopSentry() { [SentrySDK close]; }
|
||||
|
||||
void crashSentry() { [SentrySDK crash]; }
|
||||
|
||||
void setUser(id userId) {
|
||||
SentryUser *user = [[SentryUser alloc] init];
|
||||
user.userId = userId;
|
||||
[SentrySDK setUser:user];
|
||||
// `SentrySDK setUser:` retains its own copy (per the ObjC `copy` property
|
||||
// contract on `SentryUser.userId` / `SentryScope.user`), so balance the
|
||||
// `alloc]/init]` here. Mirrors `recordBreadcrumb` below, which releases its
|
||||
// allocated `SentryBreadcrumb` after `[SentrySDK addBreadcrumb:]`.
|
||||
[user release];
|
||||
}
|
||||
|
||||
// Define constants for the integer representations of the SentryLevel Swift
|
||||
// enum.
|
||||
//
|
||||
// We intentionally use a different prefix (kLevel instead of kSentryLevel) to
|
||||
// ensure there are no symbol name conflicts with Sentry's own code.
|
||||
//
|
||||
// SentryLevel is defined here:
|
||||
// https://github.com/getsentry/sentry-cocoa/blob/b8ac05036d8cf7b5aa6bda6a108d7827f286ca04/Sources/Swift/Helper/Log/SentryLevel.swift#L4-L26
|
||||
NSUInteger kLevelNone = 0;
|
||||
NSUInteger kLevelDebug = 1;
|
||||
NSUInteger kLevelInfo = 2;
|
||||
NSUInteger kLevelWarning = 3;
|
||||
NSUInteger kLevelError = 4;
|
||||
NSUInteger kLevelFatal = 5;
|
||||
|
||||
// Maps the string representation of a breadcrumb level to the corresponding
|
||||
// SentryLevel enum value.
|
||||
//
|
||||
// See Sentry-internal mapping function here:
|
||||
// https://github.com/getsentry/sentry-cocoa/blob/854478ce6e1b9349d9a30c2adb59a49e80867991/Sources/Sentry/SentryLevelMapper.m
|
||||
SentryLevel levelFromString(NSString *string) {
|
||||
if ([string isEqualToString:@"none"]) {
|
||||
return kLevelNone;
|
||||
}
|
||||
if ([string isEqualToString:@"debug"]) {
|
||||
return kLevelDebug;
|
||||
}
|
||||
if ([string isEqualToString:@"info"]) {
|
||||
return kLevelInfo;
|
||||
}
|
||||
if ([string isEqualToString:@"warning"]) {
|
||||
return kLevelWarning;
|
||||
}
|
||||
if ([string isEqualToString:@"error"]) {
|
||||
return kLevelError;
|
||||
}
|
||||
if ([string isEqualToString:@"fatal"]) {
|
||||
return kLevelFatal;
|
||||
}
|
||||
|
||||
// Default is error, see https://develop.sentry.dev/sdk/event-payloads/#optional-attributes
|
||||
return kLevelError;
|
||||
}
|
||||
|
||||
void recordBreadcrumb(id message, id category, id level, double seconds_since_epoch) {
|
||||
// The Rust logger may be initialized before the Sentry Cocoa SDK is enabled.
|
||||
if (![SentrySDK isEnabled]) {
|
||||
return;
|
||||
}
|
||||
|
||||
SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc] init];
|
||||
crumb.level = levelFromString(level);
|
||||
crumb.category = category;
|
||||
crumb.message = message;
|
||||
crumb.timestamp = [NSDate dateWithTimeIntervalSince1970:seconds_since_epoch];
|
||||
[SentrySDK addBreadcrumb:crumb];
|
||||
[crumb release];
|
||||
}
|
||||
|
||||
void setTag(id key, id value) {
|
||||
// Set a tag on the current scope using the sentry-cocoa SDK.
|
||||
[SentrySDK configureScope:^(SentryScope *_Nonnull scope) {
|
||||
[scope setTagValue:value forKey:key];
|
||||
}];
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Our class for handling NSServices messages.
|
||||
@interface WarpServicesProvider : NSObject
|
||||
@end
|
||||
|
||||
// Functions implemented in Rust.
|
||||
id warp_services_provider_custom_url_scheme();
|
||||
void warp_app_open_urls(id app, id urls);
|
||||
@@ -0,0 +1,65 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#import "services.h"
|
||||
|
||||
@implementation WarpServicesProvider
|
||||
|
||||
// Opens a new tab for each file URL in the pasteboard, with the initial
|
||||
// directory set to the provided path (or parent directory, if the path
|
||||
// is to a file).
|
||||
//
|
||||
// This is registered as a service endpoint in the embedded Info.plist.
|
||||
- (void)openTab:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error {
|
||||
[self forFilesFromPasteboard:pboard performAction:@"/new_tab"];
|
||||
}
|
||||
|
||||
// Opens a new window for each file URL in the pasteboard, with the initial
|
||||
// directory set to the provided path (or parent directory, if the path
|
||||
// is to a file).
|
||||
//
|
||||
// This is registered as a service endpoint in the embedded Info.plist.
|
||||
- (void)openWindow:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error {
|
||||
[self forFilesFromPasteboard:pboard performAction:@"/new_window"];
|
||||
}
|
||||
|
||||
// Parses file URLs from the provided pasteboard and makes an intent into
|
||||
// the application to perform the provided action for each path.
|
||||
- (void)forFilesFromPasteboard:(NSPasteboard *)pboard performAction:(NSString *)action {
|
||||
@autoreleasepool {
|
||||
NSArray<NSURL *> *urls = [pboard readObjectsForClasses:@[ [NSURL class] ] options:0];
|
||||
NSMutableArray<NSString *> *filePaths = [NSMutableArray array];
|
||||
for (NSURL *url in urls) {
|
||||
[filePaths addObject:url.path];
|
||||
}
|
||||
|
||||
NSMutableArray<NSURL *> *warpUrls = [NSMutableArray array];
|
||||
for (NSString *path in filePaths) {
|
||||
NSURLComponents *components = [[[NSURLComponents alloc] init] autorelease];
|
||||
NSString *scheme = warp_services_provider_custom_url_scheme();
|
||||
[components setScheme:scheme];
|
||||
[components setHost:@"action"];
|
||||
[components setPath:action];
|
||||
NSMutableArray *queryItems = [NSMutableArray array];
|
||||
[queryItems addObject:[NSURLQueryItem queryItemWithName:@"path" value:path]];
|
||||
[components setQueryItems:queryItems];
|
||||
[warpUrls addObject:components.URL];
|
||||
};
|
||||
|
||||
NSApplication *app = [NSApplication sharedApplication];
|
||||
warp_app_open_urls(app, warpUrls);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Creates a new WarpServicesProvider and registers it as the global services
|
||||
// provider for the application
|
||||
void warp_register_services_provider() {
|
||||
WarpServicesProvider *provider = [[WarpServicesProvider alloc] init];
|
||||
|
||||
// Set the global NSServices provider for the application. This holds a
|
||||
// strong reference to the provider, so we don't have to worry about it
|
||||
// being prematurely cleaned up while the application exist.
|
||||
[NSApp setServicesProvider:provider];
|
||||
[provider release];
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#[cfg(target_family = "wasm")]
|
||||
pub mod wasm;
|
||||
|
||||
pub fn init() {
|
||||
#[cfg(target_family = "wasm")]
|
||||
wasm::init();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
use js_sys::ReferenceError;
|
||||
use thiserror::Error;
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
|
||||
pub use warp_web_event_bus::{emit_event, WarpEvent};
|
||||
|
||||
/// This function should be called early in application initialization to ensure that
|
||||
/// static variables are initialized.
|
||||
pub(super) fn init() {
|
||||
unsafe {
|
||||
extern "C" {
|
||||
/// __wasm_call_ctors is a function defined by the `wasm-ld` linker, and is used to
|
||||
/// initialize static variables.
|
||||
///
|
||||
/// It should be called once at runtime before other code is executed.
|
||||
fn __wasm_call_ctors();
|
||||
}
|
||||
|
||||
__wasm_call_ctors();
|
||||
}
|
||||
}
|
||||
|
||||
mod ffi {
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name = "warpUserHandoff", catch)]
|
||||
pub fn user_handoff() -> Result<Option<String>, JsValue>;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
pub enum AuthHandoffError {
|
||||
#[error("The host page doesn't support user handoff")]
|
||||
Unsupported,
|
||||
#[error("Unexpected handoff error: {0:?}")]
|
||||
Unexpected(JsValue),
|
||||
}
|
||||
|
||||
/// Fetch the user's Firebase refresh token from the host React app.
|
||||
pub fn user_handoff() -> Result<Option<String>, AuthHandoffError> {
|
||||
ffi::user_handoff().map_err(|err| {
|
||||
if ReferenceError::instanceof(&err) {
|
||||
AuthHandoffError::Unsupported
|
||||
} else {
|
||||
AuthHandoffError::Unexpected(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user