Skip to content

Commit

Permalink
chore(get-platform): Add package
Browse files Browse the repository at this point in the history
  • Loading branch information
medz committed Dec 22, 2022
1 parent 4b9392b commit 93f9255
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 0 deletions.
1 change: 1 addition & 0 deletions .pubignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ prisma/
lib/prisma_*
example/*
!example/README.md
packages/
10 changes: 10 additions & 0 deletions packages/prisma_get_platform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Files and directories created by pub.
.dart_tool/
.packages

# Conventional directory for build outputs.
build/

# Omit committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock
3 changes: 3 additions & 0 deletions packages/prisma_get_platform/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.0.1

- Initial version.
13 changes: 13 additions & 0 deletions packages/prisma_get_platform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Prisma get platform

This package is used to detect the platform of the Prisma binary engines.

## Usage

```dart
import 'package:prisma_get_platform/prisma_get_platform.dart';
void main() {
print(getBinaryPlatform());
}
```
30 changes: 30 additions & 0 deletions packages/prisma_get_platform/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml

# Uncomment the following section to specify additional rules.

# linter:
# rules:
# - camel_case_types

# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
7 changes: 7 additions & 0 deletions packages/prisma_get_platform/example/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:prisma_get_platform/prisma_get_platform.dart';

void main() {
final String version = getBinaryPlatform();

print(version);
}
3 changes: 3 additions & 0 deletions packages/prisma_get_platform/lib/prisma_get_platform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
library prisma.get_platform;

export 'src/get_binary_platform.dart' show getBinaryPlatform;
82 changes: 82 additions & 0 deletions packages/prisma_get_platform/lib/src/get_binary_platform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 'darwin',
// 'darwin-arm64',
// 'debian-openssl-1.0.x',
// 'debian-openssl-1.1.x',
// 'debian-openssl-3.0.x',
// 'rhel-openssl-1.0.x',
// 'rhel-openssl-1.1.x',
// 'rhel-openssl-3.0.x',
// 'linux-arm64-openssl-1.1.x',
// 'linux-arm64-openssl-1.0.x',
// 'linux-arm64-openssl-3.0.x',
// 'linux-arm-openssl-1.1.x',
// 'linux-arm-openssl-1.0.x',
// 'linux-arm-openssl-3.0.x',
// 'linux-musl',
// 'linux-musl-openssl-3.0.x',
// 'linux-nixos',
// 'windows',
// 'freebsd11',
// 'freebsd12',
// 'freebsd13',
// 'openbsd',
// 'netbsd',
// 'arm',
// https://github.com/prisma/prisma/blob/main/packages/get-platform/src/platforms.ts

import 'dart:io';

import 'get_openssl_version.dart';
import 'linux_os_distro.dart';

/// Get prisma binary engine platform.
String getBinaryPlatform() {
final String dartSdkVersion = Platform.version.toLowerCase();

if (Platform.isWindows) {
return 'windows';
} else if (Platform.isMacOS) {
return dartSdkVersion.contains('arm') ? 'darwin-arm64' : 'darwin';
} else if (!Platform.isLinux) {
throw UnsupportedError('Unsupported operating system');
}

final LinuxOperatingSystemDistro distro = LinuxOperatingSystemDistro.current;

// NixOS
if (distro == LinuxOperatingSystemDistro.nixos) {
return 'linux-nixos';
}

final String opensslVersion = getOpenSSLVersion();

// ARM architecture
if (dartSdkVersion.contains('arm')) {
return 'linux-arm${dartSdkVersion.contains('arm64') ? '64' : ''}-openssl-$opensslVersion';
}

// Debian
if (distro == LinuxOperatingSystemDistro.debian) {
return 'debian-openssl-$opensslVersion';
}

// RHEL(Red Hat Enterprise Linux)
if (distro == LinuxOperatingSystemDistro.rhel) {
return 'rhel-openssl-$opensslVersion';
}

// Musl
if (distro == LinuxOperatingSystemDistro.musl) {
final String musl = 'linux-musl';
if (opensslVersion == '3.0.x') {
return '$musl-openssl-$opensslVersion';
}
}

// Raspbian
if (distro == LinuxOperatingSystemDistro.arm) {
return 'arm';
}

throw UnsupportedError('Unsupported operating system');
}
88 changes: 88 additions & 0 deletions packages/prisma_get_platform/lib/src/get_openssl_version.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import 'dart:convert';
import 'dart:io';

/// Get OpenSSL version.
///
/// Returns format:
/// - 1.0.x
/// - 1.1.x
/// - 3.0.x
///
/// If OpenSSL version is not found, throws [UnsupportedError].
///
/// If OpenSSL version > 3.0, returns 3.0.x.
String getOpenSSLVersion() {
final Iterable<List<String>> libsslCommands = [
'ls -l /lib/libssl.so.3',
'ls -l /lib/libssl.so.1.1',
'ls -l /lib64',
'ls -l /usr/lib64',
].map((e) => e.split(' '));
final String? libssl = _getFirstSuccessCommandResult(libsslCommands);
if (libssl != null) {
final RegExp regex = RegExp(r'libssl\.so\.(\d)(\.\d)?',
multiLine: true, caseSensitive: false);
final Iterable<String> lines = LineSplitter.split(libssl);

for (final String line in lines) {
if (!line.contains('ssl')) {
continue;
}

final Match? match = regex.firstMatch(line);
if (match != null) {
final String major = match.group(1)!.trim();
final String? minor = match.group(2)?.trim();
final String version = '$major${minor ?? '.0'}.x';

return _senitseOpensslVersion(version);
}
}
}

final Iterable<List<String>> opensslCommands = [
'openssl version -v',
].map((e) => e.split(' '));
final String? openssl = _getFirstSuccessCommandResult(opensslCommands);
if (openssl != null) {
final RegExp regex =
RegExp(r'.*?(\d+)\.(\d+)\.\d+', multiLine: true, caseSensitive: false);
final Match? match = regex.firstMatch(openssl);

if (match != null) {
final String major = match.group(1)!.trim();
final String minor = match.group(2)!.trim();
final String version = '$major.$minor.x';

return _senitseOpensslVersion(version);
}
}

throw UnsupportedError('OpenSSL not found');
}

/// Get first success command result.
String? _getFirstSuccessCommandResult(Iterable<Iterable<String>> commands) {
for (final Iterable<String> command in commands) {
final String executable = command.first;
final List<String> arguments = command.skip(1).toList();

final ProcessResult result = Process.runSync(executable, arguments,
stdoutEncoding: utf8, stderrEncoding: utf8);
if (result.exitCode == 0) {
return result.stdout.toString().trim();
}
}
return null;
}

/// Senitse OpenSSL/LibSSL version
///
/// OpenSSL 3+, E.g: `3.1.x` -> `3.0.x`
String _senitseOpensslVersion(String version) {
if (version.startsWith('3.')) {
return '3.0.x';
}

return version;
}
75 changes: 75 additions & 0 deletions packages/prisma_get_platform/lib/src/linux_os_distro.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'dart:io';

const _osReleaseFile = '/etc/os-release';
const _alpineReleaseFile = '/etc/alpine-release';

/// Operating system distro.
enum LinuxOperatingSystemDistro {
rhel,
debian,
nixos,
arm,
musl;

/// Lookup the current operating system distro.
static LinuxOperatingSystemDistro get current {
assert(Platform.isLinux,
'Unsupported operating system distro, only Linux is supported');

// If alpine release file exists, return musl.
if (File(_alpineReleaseFile).existsSync()) {
return LinuxOperatingSystemDistro.musl;
}

// If os-release file exists, parse it and return distro.
final File osReleaseFile = File(_osReleaseFile);
if (osReleaseFile.existsSync()) {
return _parseOsReleaseDistro(osReleaseFile.readAsStringSync());
}

// Throw unsupported error.
throw UnsupportedError('Unsupported operating system distro');
}

/// Parse os-release file and return distro.
static LinuxOperatingSystemDistro _parseOsReleaseDistro(String osRelease) {
final RegExp idRegex =
RegExp(r'^ID="?([^"\n]*)"?$', multiLine: true, caseSensitive: false);

final Iterable<RegExpMatch> idMatchs = idRegex.allMatches(osRelease);
for (final RegExpMatch match in idMatchs) {
switch (match.group(1)?.toLowerCase()) {
case 'raspbian':
return LinuxOperatingSystemDistro.arm;
case 'nixos':
return LinuxOperatingSystemDistro.nixos;
case 'fedora':
return LinuxOperatingSystemDistro.rhel;
case 'debian':
return LinuxOperatingSystemDistro.debian;
}
}

final RegExp idLikeRegex = RegExp(r'^ID_LIKE="?([^"\n]*)"?$',
multiLine: true, caseSensitive: false);
final Iterable<RegExpMatch> idLikeMatchs =
idLikeRegex.allMatches(osRelease);
const List<String> rehlDistro = ['centos', 'fedora', 'rhel'];
const List<String> debianDistro = ['debian', 'ubuntu'];
for (final RegExpMatch match in idLikeMatchs) {
final String? idLike = match.group(1)?.toLowerCase();
for (final String rhelDistro in rehlDistro) {
if (idLike?.contains(rhelDistro) == true) {
return LinuxOperatingSystemDistro.rhel;
}
}
for (final String debianDistro in debianDistro) {
if (idLike?.contains(debianDistro) == true) {
return LinuxOperatingSystemDistro.debian;
}
}
}

throw UnsupportedError('Unsupported operating system distro');
}
}
12 changes: 12 additions & 0 deletions packages/prisma_get_platform/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: prisma_get_platform
description: Prisma ORM for Dart Gets the platform names supported by the Prisma binary engines.
version: 0.0.1
homepage: https://prisma.pub
repository: https://github.com/odroe/prisma-dart

environment:
sdk: '>=2.18.6 <3.0.0'

dev_dependencies:
lints: ^2.0.0
test: ^1.16.0
15 changes: 15 additions & 0 deletions packages/prisma_get_platform/test/get_openssl_version_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:prisma_get_platform/src/get_openssl_version.dart';
import 'package:test/test.dart';

void main() {
test('openssl version', () async {
final String version = getOpenSSLVersion();
final Iterable<String> supportedVersions = [
'1.0.x',
'1.1.x',
'3.0.x',
];

expect(supportedVersions.contains(version), isTrue);
});
}

1 comment on commit 93f9255

@vercel
Copy link

@vercel vercel bot commented on 93f9255 Dec 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.