osr - tasks v1

This commit is contained in:
babayaga 2026-01-29 15:31:09 +01:00
parent 3fa0bfb9f9
commit c8d84b64cd
98 changed files with 2699 additions and 2622 deletions

View File

@ -178,6 +178,7 @@
"integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~6.20.0" "undici-types": "~6.20.0"
} }
@ -934,6 +935,7 @@
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"

View File

@ -1,12 +0,0 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

View File

@ -1,19 +0,0 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
build
/captures
.externalNativeBuild
.cxx
local.properties
key.properties
/.tauri
/tauri.settings.gradle

View File

@ -1,6 +0,0 @@
/src/main/java/com/tauri/api/generated
/src/main/jniLibs/**/*.so
/src/main/assets/tauri.conf.json
/tauri.build.gradle.kts
/proguard-tauri.pro
/tauri.properties

View File

@ -1,69 +0,0 @@
import java.util.Properties
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("rust")
}
val tauriProperties = Properties().apply {
val propFile = file("tauri.properties")
if (propFile.exists()) {
propFile.inputStream().use { load(it) }
}
}
android {
compileSdk = 34
namespace = "com.tauri.api"
defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.tauri.api"
minSdk = 24
targetSdk = 34
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
}
buildTypes {
getByName("debug") {
manifestPlaceholders["usesCleartextTraffic"] = "true"
isDebuggable = true
isJniDebuggable = true
isMinifyEnabled = false
packaging { jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
jniLibs.keepDebugSymbols.add("*/x86/*.so")
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
}
}
getByName("release") {
isMinifyEnabled = true
proguardFiles(
*fileTree(".") { include("**/*.pro") }
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
.toList().toTypedArray()
)
}
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
buildConfig = true
}
}
rust {
rootDirRel = "../../../"
}
dependencies {
implementation("androidx.webkit:webkit:1.6.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
}
apply(from = "tauri.build.gradle.kts")

View File

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<!-- AndroidTV support -->
<uses-feature android:name="android.software.leanback" android:required="false" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.api"
android:usesCleartextTraffic="${usesCleartextTraffic}">
<activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
android:launchMode="singleTask"
android:label="@string/main_activity_title"
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- AndroidTV support -->
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<!-- NFC PLUGIN. AUTO-GENERATED. DO NOT REMOVE. -->
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
<!-- NFC PLUGIN. AUTO-GENERATED. DO NOT REMOVE. -->
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@ -1,3 +0,0 @@
package com.tauri.api
class MainActivity : TauriActivity()

View File

@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.api" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@ -1,4 +0,0 @@
<resources>
<string name="app_name">Tauri API</string>
<string name="main_activity_title">Tauri API</string>
</resources>

View File

@ -1,6 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.api" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="." />
<cache-path name="my_cache_images" path="." />
</paths>

View File

@ -1,22 +0,0 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.5.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
tasks.register("clean").configure {
delete("build")
}

View File

@ -1,23 +0,0 @@
plugins {
`kotlin-dsl`
}
gradlePlugin {
plugins {
create("pluginsForCoolKids") {
id = "rust"
implementationClass = "RustPlugin"
}
}
}
repositories {
google()
mavenCentral()
}
dependencies {
compileOnly(gradleApi())
implementation("com.android.tools.build:gradle:8.5.1")
}

View File

@ -1,52 +0,0 @@
import java.io.File
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.logging.LogLevel
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
open class BuildTask : DefaultTask() {
@Input
var rootDirRel: String? = null
@Input
var target: String? = null
@Input
var release: Boolean? = null
@TaskAction
fun assemble() {
val executable = """pnpm""";
try {
runTauriCli(executable)
} catch (e: Exception) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
runTauriCli("$executable.cmd")
} else {
throw e;
}
}
}
fun runTauriCli(executable: String) {
val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
val target = target ?: throw GradleException("target cannot be null")
val release = release ?: throw GradleException("release cannot be null")
val args = listOf("tauri", "android", "android-studio-script");
project.exec {
workingDir(File(project.projectDir, rootDirRel))
executable(executable)
args(args)
if (project.logger.isEnabled(LogLevel.DEBUG)) {
args("-vv")
} else if (project.logger.isEnabled(LogLevel.INFO)) {
args("-v")
}
if (release) {
args("--release")
}
args(listOf("--target", target))
}.assertNormalExitValue()
}
}

View File

@ -1,85 +0,0 @@
import com.android.build.api.dsl.ApplicationExtension
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
const val TASK_GROUP = "rust"
open class Config {
lateinit var rootDirRel: String
}
open class RustPlugin : Plugin<Project> {
private lateinit var config: Config
override fun apply(project: Project) = with(project) {
config = extensions.create("rust", Config::class.java)
val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64");
val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList
val defaultArchList = listOf("arm64", "arm", "x86", "x86_64");
val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList
val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64")
extensions.configure<ApplicationExtension> {
@Suppress("UnstableApiUsage")
flavorDimensions.add("abi")
productFlavors {
create("universal") {
dimension = "abi"
ndk {
abiFilters += abiList
}
}
defaultArchList.forEachIndexed { index, arch ->
create(arch) {
dimension = "abi"
ndk {
abiFilters.add(defaultAbiList[index])
}
}
}
}
}
afterEvaluate {
for (profile in listOf("debug", "release")) {
val profileCapitalized = profile.replaceFirstChar { it.uppercase() }
val buildTask = tasks.maybeCreate(
"rustBuildUniversal$profileCapitalized",
DefaultTask::class.java
).apply {
group = TASK_GROUP
description = "Build dynamic library in $profile mode for all targets"
}
tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask)
for (targetPair in targetsList.withIndex()) {
val targetName = targetPair.value
val targetArch = archList[targetPair.index]
val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() }
val targetBuildTask = project.tasks.maybeCreate(
"rustBuild$targetArchCapitalized$profileCapitalized",
BuildTask::class.java
).apply {
group = TASK_GROUP
description = "Build dynamic library in $profile mode for $targetArch"
rootDirRel = config.rootDirRel
target = targetName
release = profile == "release"
}
buildTask.dependsOn(targetBuildTask)
tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn(
targetBuildTask
)
}
}
}
}
}

View File

@ -1,24 +0,0 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonFinalResIds=false

View File

@ -1,6 +0,0 @@
#Tue May 10 19:22:52 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View File

@ -1,185 +0,0 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

View File

@ -1,89 +0,0 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,3 +0,0 @@
include ':app'
apply from: 'tauri.settings.gradle'

View File

@ -1,3 +0,0 @@
xcuserdata/
build/
Externals/

View File

@ -1,116 +0,0 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "AppIcon-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "AppIcon-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29x29@2x-1.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "AppIcon-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "AppIcon-20x20@2x-1.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "AppIcon-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "AppIcon-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "AppIcon-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "AppIcon-40x40@2x-1.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "AppIcon-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "AppIcon-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "AppIcon-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "AppIcon-512@2x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>debugging</string>
</dict>
</plist>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17150" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17122"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View File

@ -1,21 +0,0 @@
# Uncomment the next line to define a global platform for your project
target 'api_iOS' do
platform :ios, '14.0'
# Pods for api_iOS
end
target 'api_macOS' do
platform :osx, '11.0'
# Pods for api_macOS
end
# Delete the deployment target for iOS and macOS, causing it to be inherited from the Podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
config.build_settings.delete 'MACOSX_DEPLOYMENT_TARGET'
end
end
end

View File

@ -1,8 +0,0 @@
#pragma once
namespace ffi {
extern "C" {
void start_app();
}
}

View File

@ -1,6 +0,0 @@
#include "bindings/bindings.h"
int main(int argc, char * argv[]) {
ffi::start_app();
return 0;
}

View File

@ -1,469 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
3043432501C9BC2DB6B4CB95 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */; };
328B4ADB3700C1873BEB7B10 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 90D3B673AFAB8D8AB561F616 /* main.mm */; };
6F379F15DA085785BA2624D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B7E79E23E646BA7968B457C /* Assets.xcassets */; };
832F9A55FEDEF3D807D8C40A /* libapp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 248286BAA086BB1A5F98B2B2 /* libapp.a */; };
9AADB041D25772D04E543F15 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62601E25FA39E62BE119B74D /* Metal.framework */; };
9DDA3BE70DD0E4013973FE38 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6082E363D51372A7658C351 /* UIKit.framework */; };
AC8BDC2C7A63FA3FDC5967F4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */; };
AFA0CA286325FD7A34968CA2 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 384966E551417F94A02D2706 /* Security.framework */; };
B60763BD194DFACA215EC7DA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC377692DC31A070A0188C9D /* QuartzCore.framework */; };
C6D80743F168BDF017B7769E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */; };
DFFF888045C8D9D9FB69E8FD /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 338E66700FD330B99D434DD7 /* MetalKit.framework */; };
F86717F05E27C72C9FA1FB27 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 74A8FDFB350B966F5AAD4A24 /* assets */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0E96CE07CD20273DD46BF325 /* main.rs */ = {isa = PBXFileReference; path = main.rs; sourceTree = "<group>"; };
1C1AB1B414CA2795AFBEDDB9 /* tray.rs */ = {isa = PBXFileReference; path = tray.rs; sourceTree = "<group>"; };
248286BAA086BB1A5F98B2B2 /* libapp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapp.a; sourceTree = "<group>"; };
2F63E2AA460089BB58D40C79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
338E66700FD330B99D434DD7 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
384966E551417F94A02D2706 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
5AC703CEBA41A121596066F3 /* api_iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = api_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
62601E25FA39E62BE119B74D /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
6B7E79E23E646BA7968B457C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
74A8FDFB350B966F5AAD4A24 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = SOURCE_ROOT; };
785D025E9542F7E098BF22B5 /* lib.rs */ = {isa = PBXFileReference; path = lib.rs; sourceTree = "<group>"; };
879941AE3DAA14534BBC6391 /* api_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = api_iOS.entitlements; sourceTree = "<group>"; };
90D3B673AFAB8D8AB561F616 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
B6082E363D51372A7658C351 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
DC377692DC31A070A0188C9D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
EC8C7948C50C3C9B5D96CB61 /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = "<group>"; };
F835F52713CE8F029D5D252C /* cmd.rs */ = {isa = PBXFileReference; path = cmd.rs; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
11E18DCDB3ADFE87C18915EF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
832F9A55FEDEF3D807D8C40A /* libapp.a in Frameworks */,
3043432501C9BC2DB6B4CB95 /* CoreGraphics.framework in Frameworks */,
9AADB041D25772D04E543F15 /* Metal.framework in Frameworks */,
DFFF888045C8D9D9FB69E8FD /* MetalKit.framework in Frameworks */,
B60763BD194DFACA215EC7DA /* QuartzCore.framework in Frameworks */,
AFA0CA286325FD7A34968CA2 /* Security.framework in Frameworks */,
9DDA3BE70DD0E4013973FE38 /* UIKit.framework in Frameworks */,
C6D80743F168BDF017B7769E /* WebKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0677CEAF1F282F38CBA0F140 = {
isa = PBXGroup;
children = (
74A8FDFB350B966F5AAD4A24 /* assets */,
6B7E79E23E646BA7968B457C /* Assets.xcassets */,
4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */,
F2116A6428EED18BE2A07E2B /* api_iOS */,
86D903732E10FAC4D300E8DF /* Externals */,
7A9A7AC155D9E22E54D6D847 /* Sources */,
CF9AA87D2F6E9C389B7AB70B /* src */,
10C9FC3FA3E12D6A4A67999D /* Frameworks */,
4AC51E67B71E27F15B02C5CD /* Products */,
);
sourceTree = "<group>";
};
07051859D6E2D8109C8FB128 /* bindings */ = {
isa = PBXGroup;
children = (
EC8C7948C50C3C9B5D96CB61 /* bindings.h */,
);
path = bindings;
sourceTree = "<group>";
};
10C9FC3FA3E12D6A4A67999D /* Frameworks */ = {
isa = PBXGroup;
children = (
71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */,
248286BAA086BB1A5F98B2B2 /* libapp.a */,
62601E25FA39E62BE119B74D /* Metal.framework */,
338E66700FD330B99D434DD7 /* MetalKit.framework */,
DC377692DC31A070A0188C9D /* QuartzCore.framework */,
384966E551417F94A02D2706 /* Security.framework */,
B6082E363D51372A7658C351 /* UIKit.framework */,
59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
4AC51E67B71E27F15B02C5CD /* Products */ = {
isa = PBXGroup;
children = (
5AC703CEBA41A121596066F3 /* api_iOS.app */,
);
name = Products;
sourceTree = "<group>";
};
7A9A7AC155D9E22E54D6D847 /* Sources */ = {
isa = PBXGroup;
children = (
A3574F52DBC5463B9C3D043D /* api */,
);
path = Sources;
sourceTree = "<group>";
};
86D903732E10FAC4D300E8DF /* Externals */ = {
isa = PBXGroup;
children = (
);
path = Externals;
sourceTree = "<group>";
};
A3574F52DBC5463B9C3D043D /* api */ = {
isa = PBXGroup;
children = (
90D3B673AFAB8D8AB561F616 /* main.mm */,
07051859D6E2D8109C8FB128 /* bindings */,
);
path = api;
sourceTree = "<group>";
};
CF9AA87D2F6E9C389B7AB70B /* src */ = {
isa = PBXGroup;
children = (
F835F52713CE8F029D5D252C /* cmd.rs */,
785D025E9542F7E098BF22B5 /* lib.rs */,
0E96CE07CD20273DD46BF325 /* main.rs */,
1C1AB1B414CA2795AFBEDDB9 /* tray.rs */,
);
name = src;
path = ../../src;
sourceTree = "<group>";
};
F2116A6428EED18BE2A07E2B /* api_iOS */ = {
isa = PBXGroup;
children = (
879941AE3DAA14534BBC6391 /* api_iOS.entitlements */,
2F63E2AA460089BB58D40C79 /* Info.plist */,
);
path = api_iOS;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
54DC6E273C78071F3BA12EF3 /* api_iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 01CBC40275452376830D79B1 /* Build configuration list for PBXNativeTarget "api_iOS" */;
buildPhases = (
FF948951157DE71465B5BD5F /* Build Rust Code */,
71E73CC9AB5F1323EC1F6365 /* Sources */,
CA2BEC44B6EDA1F21B6155CD /* Resources */,
11E18DCDB3ADFE87C18915EF /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = api_iOS;
packageProductDependencies = (
);
productName = api_iOS;
productReference = 5AC703CEBA41A121596066F3 /* api_iOS.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9BC88C3717DA5D4B78A51C15 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1430;
TargetAttributes = {
54DC6E273C78071F3BA12EF3 = {
DevelopmentTeam = Q93MBH6S2F;
};
};
};
buildConfigurationList = 8FA67D0F928A09CD639137D1 /* Build configuration list for PBXProject "api" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
Base,
en,
);
mainGroup = 0677CEAF1F282F38CBA0F140;
minimizedProjectReferenceProxies = 1;
preferredProjectObjectVersion = 54;
projectDirPath = "";
projectRoot = "";
targets = (
54DC6E273C78071F3BA12EF3 /* api_iOS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
CA2BEC44B6EDA1F21B6155CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6F379F15DA085785BA2624D4 /* Assets.xcassets in Resources */,
AC8BDC2C7A63FA3FDC5967F4 /* LaunchScreen.storyboard in Resources */,
F86717F05E27C72C9FA1FB27 /* assets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
FF948951157DE71465B5BD5F /* Build Rust Code */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Build Rust Code";
outputFileListPaths = (
);
outputPaths = (
"$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a",
"$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "pnpm tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths \"${FRAMEWORK_SEARCH_PATHS:?}\" --header-search-paths \"${HEADER_SEARCH_PATHS:?}\" --gcc-preprocessor-definitions \"${GCC_PREPROCESSOR_DEFINITIONS:-}\" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
71E73CC9AB5F1323EC1F6365 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
328B4ADB3700C1873BEB7B10 /* main.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
A83F70B4C02DD0222038C7F1 /* release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
};
name = release;
};
B6AD77E490F315562F75D3D7 /* debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"DEBUG=1",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = debug;
};
BF284FE6E7AE0C8DDCCE398B /* debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = (
arm64,
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = api_iOS/api_iOS.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "Q93MBH6S2F";
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\".\"",
);
INFOPLIST_FILE = api_iOS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
"LIBRARY_SEARCH_PATHS[arch=arm64]" = "$(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)";
"LIBRARY_SEARCH_PATHS[arch=x86_64]" = "$(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = com.tauri.api;
PRODUCT_NAME = "Tauri API";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64;
};
name = debug;
};
DB0E254D0FD84970B57F6410 /* release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = (
arm64,
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = api_iOS/api_iOS.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "Q93MBH6S2F";
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\".\"",
);
INFOPLIST_FILE = api_iOS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
"LIBRARY_SEARCH_PATHS[arch=arm64]" = "$(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)";
"LIBRARY_SEARCH_PATHS[arch=x86_64]" = "$(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = com.tauri.api;
PRODUCT_NAME = "Tauri API";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64;
};
name = release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
01CBC40275452376830D79B1 /* Build configuration list for PBXNativeTarget "api_iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
BF284FE6E7AE0C8DDCCE398B /* debug */,
DB0E254D0FD84970B57F6410 /* release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = debug;
};
8FA67D0F928A09CD639137D1 /* Build configuration list for PBXProject "api" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B6AD77E490F315562F75D3D7 /* debug */,
A83F70B4C02DD0222038C7F1 /* release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = debug;
};
/* End XCConfigurationList section */
};
rootObject = 9BC88C3717DA5D4B78A51C15 /* Project object */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
<key>DisableBuildSystemDeprecationDiagnostic</key>
<true/>
</dict>
</plist>

View File

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "54DC6E273C78071F3BA12EF3"
BuildableName = "Tauri API.app"
BlueprintName = "api_iOS"
ReferencedContainer = "container:api.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "NO">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "54DC6E273C78071F3BA12EF3"
BuildableName = "Tauri API.app"
BlueprintName = "api_iOS"
ReferencedContainer = "container:api.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "RUST_BACKTRACE"
value = "full"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "RUST_LOG"
value = "info"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "54DC6E273C78071F3BA12EF3"
BuildableName = "Tauri API.app"
BlueprintName = "api_iOS"
ReferencedContainer = "container:api.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "RUST_BACKTRACE"
value = "full"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "RUST_LOG"
value = "info"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "release"
shouldUseLaunchSchemeArgsEnv = "NO"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "54DC6E273C78071F3BA12EF3"
BuildableName = "Tauri API.app"
BlueprintName = "api_iOS"
ReferencedContainer = "container:api.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "RUST_BACKTRACE"
value = "full"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "RUST_LOG"
value = "info"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<key>CFBundleVersion</key>
<string>2.0.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
<string>metal</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSCameraUsageDescription</key>
<string>Request camera access for WebRTC</string>
<key>NSMicrophoneUsageDescription</key>
<string>Request microphone access for WebRTC</string>
<key>NSFaceIDUsageDescription</key>
<string>Authenticate with biometrics</string>
<key>NFCReaderUsageDescription</key>
<string>Read and write to NFC tags for testing</string>
</dict>
</plist>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

View File

@ -1,89 +0,0 @@
name: api
options:
bundleIdPrefix: com.tauri.api
deploymentTarget:
iOS: 14.0
fileGroups: [../../src]
configs:
debug: debug
release: release
settingGroups:
app:
base:
PRODUCT_NAME: Tauri API
PRODUCT_BUNDLE_IDENTIFIER: com.tauri.api
DEVELOPMENT_TEAM: Q93MBH6S2F
targetTemplates:
app:
type: application
sources:
- path: Sources
scheme:
environmentVariables:
RUST_BACKTRACE: full
RUST_LOG: info
settings:
groups: [app]
targets:
api_iOS:
type: application
platform: iOS
sources:
- path: Sources
- path: Assets.xcassets
- path: Externals
- path: api_iOS
- path: assets
buildPhase: resources
type: folder
- path: LaunchScreen.storyboard
info:
path: api_iOS/Info.plist
properties:
LSRequiresIPhoneOS: true
UILaunchStoryboardName: LaunchScreen
UIRequiredDeviceCapabilities: [arm64, metal]
UISupportedInterfaceOrientations:
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad:
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
CFBundleShortVersionString: 2.0.0
CFBundleVersion: 2.0.0
entitlements:
path: api_iOS/api_iOS.entitlements
scheme:
environmentVariables:
RUST_BACKTRACE: full
RUST_LOG: info
settings:
base:
ENABLE_BITCODE: false
ARCHS: [arm64]
VALID_ARCHS: arm64
LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)
LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true
EXCLUDED_ARCHS[sdk=iphoneos*]: x86_64
groups: [app]
dependencies:
- framework: libapp.a
embed: false
- sdk: CoreGraphics.framework
- sdk: Metal.framework
- sdk: MetalKit.framework
- sdk: QuartzCore.framework
- sdk: Security.framework
- sdk: UIKit.framework
- sdk: WebKit.framework
preBuildScripts:
- script: pnpm tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths "${FRAMEWORK_SEARCH_PATHS:?}" --header-search-paths "${HEADER_SEARCH_PATHS:?}" --gcc-preprocessor-definitions "${GCC_PREPROCESSOR_DEFINITIONS:-}" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}
name: Build Rust Code
basedOnDependencyAnalysis: false
outputFiles:
- $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a
- $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a

View File

@ -155,6 +155,7 @@
"@polymech/fs": "file:../fs", "@polymech/fs": "file:../fs",
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@ -332,40 +333,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@bundled-es-modules/cookie": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz",
"integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==",
"dev": true,
"license": "ISC",
"optional": true,
"dependencies": {
"cookie": "^0.7.2"
}
},
"node_modules/@bundled-es-modules/statuses": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz",
"integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==",
"dev": true,
"license": "ISC",
"optional": true,
"dependencies": {
"statuses": "^2.0.1"
}
},
"node_modules/@bundled-es-modules/tough-cookie": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz",
"integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==",
"dev": true,
"license": "ISC",
"optional": true,
"dependencies": {
"@types/tough-cookie": "^4.0.5",
"tough-cookie": "^4.1.4"
}
},
"node_modules/@calebboyd/semaphore": { "node_modules/@calebboyd/semaphore": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@calebboyd/semaphore/-/semaphore-1.3.1.tgz", "resolved": "https://registry.npmjs.org/@calebboyd/semaphore/-/semaphore-1.3.1.tgz",
@ -994,159 +961,6 @@
"dev": true, "dev": true,
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/@inquirer/confirm": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.6.tgz",
"integrity": "sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@inquirer/core": "^10.1.7",
"@inquirer/type": "^3.0.4"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@types/node": ">=18"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
}
}
},
"node_modules/@inquirer/core": {
"version": "10.1.7",
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.7.tgz",
"integrity": "sha512-AA9CQhlrt6ZgiSy6qoAigiA1izOa751ugX6ioSjqgJ+/Gd+tEN/TORk5sUYNjXuHWfW0r1n/a6ak4u/NqHHrtA==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@inquirer/figures": "^1.0.10",
"@inquirer/type": "^3.0.4",
"ansi-escapes": "^4.3.2",
"cli-width": "^4.1.0",
"mute-stream": "^2.0.0",
"signal-exit": "^4.1.0",
"wrap-ansi": "^6.2.0",
"yoctocolors-cjs": "^2.1.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@types/node": ">=18"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
}
}
},
"node_modules/@inquirer/core/node_modules/ansi-escapes": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"type-fest": "^0.21.3"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@inquirer/core/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/@inquirer/core/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@inquirer/core/node_modules/type-fest": {
"version": "0.21.3",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"optional": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@inquirer/core/node_modules/wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@inquirer/figures": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.10.tgz",
"integrity": "sha512-Ey6176gZmeqZuY/W/nZiUyvmb1/qInjcpiZjXWi6nON+nxJpD1bxtSoBxNliGISae32n6OwbY+TSXPZ1CfS4bw==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=18"
}
},
"node_modules/@inquirer/type": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.4.tgz",
"integrity": "sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@types/node": ">=18"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
}
}
},
"node_modules/@ioredis/commands": { "node_modules/@ioredis/commands": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
@ -1341,25 +1155,6 @@
"integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/@mswjs/interceptors": {
"version": "0.37.6",
"resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.6.tgz",
"integrity": "sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@open-draft/deferred-promise": "^2.2.0",
"@open-draft/logger": "^0.3.0",
"@open-draft/until": "^2.0.0",
"is-node-process": "^1.2.0",
"outvariant": "^1.4.3",
"strict-event-emitter": "^0.5.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -1398,34 +1193,6 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@open-draft/deferred-promise": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
"integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/@open-draft/logger": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz",
"integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"is-node-process": "^1.2.0",
"outvariant": "^1.4.0"
}
},
"node_modules/@open-draft/until": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz",
"integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/@pkgjs/parseargs": { "node_modules/@pkgjs/parseargs": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -1823,14 +1590,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/@types/debug": { "node_modules/@types/debug": {
"version": "4.1.12", "version": "4.1.12",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
@ -1930,14 +1689,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/statuses": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz",
"integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/@types/tapable": { "node_modules/@types/tapable": {
"version": "1.0.12", "version": "1.0.12",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.12.tgz", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.12.tgz",
@ -1945,14 +1696,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/tough-cookie": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/@types/turndown": { "node_modules/@types/turndown": {
"version": "5.0.5", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.5.tgz",
@ -3638,17 +3381,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/cli-width": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
"dev": true,
"license": "ISC",
"optional": true,
"engines": {
"node": ">= 12"
}
},
"node_modules/cliui": { "node_modules/cliui": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@ -3854,17 +3586,6 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/core-util-is": { "node_modules/core-util-is": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@ -5850,17 +5571,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/graphql": {
"version": "16.10.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz",
"integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/gtoken": { "node_modules/gtoken": {
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz",
@ -5958,14 +5668,6 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/headers-polyfill": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz",
"integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/highlight.js": { "node_modules/highlight.js": {
"version": "10.7.3", "version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
@ -6242,14 +5944,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/is-node-process": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz",
"integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/is-number": { "node_modules/is-number": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@ -7705,17 +7399,6 @@
"readable-stream": "^3.6.0" "readable-stream": "^3.6.0"
} }
}, },
"node_modules/mute-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
"integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
"dev": true,
"license": "ISC",
"optional": true,
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/mz": { "node_modules/mz": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@ -7965,18 +7648,6 @@
} }
} }
}, },
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
"license": "MIT",
"optional": true,
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.19", "version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
@ -8221,14 +7892,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/outvariant": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz",
"integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/p-cancelable": { "node_modules/p-cancelable": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
@ -8475,14 +8138,6 @@
"node": "20 || >=22" "node": "20 || >=22"
} }
}, },
"node_modules/path-to-regexp": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/path-type": { "node_modules/path-type": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@ -8715,20 +8370,6 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"punycode": "^2.3.1"
},
"funding": {
"url": "https://github.com/sponsors/lupomontero"
}
},
"node_modules/pump": { "node_modules/pump": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
@ -8765,14 +8406,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -8986,14 +8619,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "1.22.10", "version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@ -9549,17 +9174,6 @@
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/std-env": { "node_modules/std-env": {
"version": "3.8.0", "version": "3.8.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz",
@ -9567,14 +9181,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/strict-event-emitter": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
"integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/strict-uri-encode": { "node_modules/strict-uri-encode": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@ -10220,23 +9826,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/tough-cookie": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
"integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
"dev": true,
"license": "BSD-3-Clause",
"optional": true,
"dependencies": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.2.0",
"url-parse": "^1.5.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/tr46": { "node_modules/tr46": {
"version": "0.0.3", "version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@ -10993,20 +10582,6 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/type-fest": {
"version": "4.35.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.35.0.tgz",
"integrity": "sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"optional": true,
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typed-array-buffer": { "node_modules/typed-array-buffer": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
@ -11138,17 +10713,6 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/universalify": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
@ -11190,18 +10754,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/url-parse": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
}
},
"node_modules/url-parse-lax": { "node_modules/url-parse-lax": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
@ -11912,20 +11464,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/yoctocolors-cjs": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz",
"integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zip-stream": { "node_modules/zip-stream": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz",

View File

@ -43,16 +43,6 @@ export async function getMessagesFromInboxWithFilter(imapConfig, fromAddress, to
throw err; throw err;
} }
} }
// Configuration for IMAP
const imapConfig = {
host: 'imap.example.com',
port: 993,
auth: {
user: 'your_email@example.com',
pass: 'your_password'
},
secure: true
};
// Create a draft email // Create a draft email
export const draft = async (subject, html, options) => { export const draft = async (subject, html, options) => {
const client = new ImapFlow(options); const client = new ImapFlow(options);
@ -81,4 +71,4 @@ export const draft = async (subject, html, options) => {
console.log('Connection ended.'); console.log('Connection ended.');
} }
}; };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2ltYXAvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQVVuQyxNQUFNLENBQUMsS0FBSyxVQUFVLDhCQUE4QixDQUFDLFVBQXVCLEVBQUUsV0FBb0IsRUFBRSxTQUFrQixFQUFFLE9BQWdCO0lBQ3RJLE1BQU0sTUFBTSxHQUFHLElBQUksUUFBUSxDQUFDO1FBQzFCLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtRQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUk7UUFDckIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxHQUFHO1FBQ3RCLElBQUksRUFBRTtZQUNKLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtZQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVE7U0FDMUI7S0FDRixDQUFDLENBQUM7SUFFSCxNQUFNLE9BQU8sR0FBVSxFQUFFLENBQUM7SUFFMUIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFdkIsSUFBSSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWhELElBQUksQ0FBQztZQUNILE1BQU0sY0FBYyxHQUFRLEVBQUUsQ0FBQztZQUMvQixJQUFJLFdBQVc7Z0JBQUUsY0FBYyxDQUFDLElBQUksR0FBRyxXQUFXLENBQUM7WUFDbkQsSUFBSSxTQUFTO2dCQUFFLGNBQWMsQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDO1lBQzdDLElBQUksT0FBTztnQkFBRSxjQUFjLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztZQUU5QywwR0FBMEc7WUFDMUcsMkRBQTJEO1lBRTNELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUVoRixJQUFJLEtBQUssRUFBRSxJQUFJLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDbkMsT0FBTyxDQUFDLElBQUksQ0FBQztvQkFDWCxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBQ2hCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtvQkFDMUIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO2lCQUNsQyxDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLENBQUM7UUFFRCxNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN0QixPQUFPLE9BQU8sQ0FBQztJQUVqQixDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDL0MsTUFBTSxHQUFHLENBQUM7SUFDWixDQUFDO0FBQ0gsQ0FBQztBQUVELHlCQUF5QjtBQUN6QixNQUFNLFVBQVUsR0FBRztJQUNqQixJQUFJLEVBQUUsa0JBQWtCO0lBQ3hCLElBQUksRUFBRSxHQUFHO0lBQ1QsSUFBSSxFQUFFO1FBQ0osSUFBSSxFQUFFLHdCQUF3QjtRQUM5QixJQUFJLEVBQUUsZUFBZTtLQUN0QjtJQUNELE1BQU0sRUFBRSxJQUFJO0NBQ2IsQ0FBQztBQUVGLHVCQUF1QjtBQUN2QixNQUFNLENBQUMsTUFBTSxLQUFLLEdBQUcsS0FBSyxFQUFFLE9BQWUsRUFBRSxJQUFZLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDcEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUE7SUFFcEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUE7UUFFdEIsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBRWxDLE1BQU0sWUFBWSxHQUFHO1lBQ25CLFFBQVEsRUFBRTtnQkFDUixJQUFJLEVBQUUsb0NBQW9DO2dCQUMxQyxPQUFPLEVBQUUsT0FBTzthQUNqQjtZQUNELE9BQU8sRUFBRSxJQUFJO1lBQ2IsR0FBRyxPQUFPO1NBQ1gsQ0FBQTtRQUVELDBDQUEwQztRQUMxQyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDekQsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDN0IsTUFBTSxHQUFHLENBQUE7SUFDWCxDQUFDO1lBQVMsQ0FBQztRQUNULHVCQUF1QjtRQUN2QixNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkMsQ0FBQztBQUNILENBQUMsQ0FBQSJ9 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2ltYXAvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQVVuQyxNQUFNLENBQUMsS0FBSyxVQUFVLDhCQUE4QixDQUFDLFVBQXVCLEVBQUUsV0FBb0IsRUFBRSxTQUFrQixFQUFFLE9BQWdCO0lBQ3RJLE1BQU0sTUFBTSxHQUFHLElBQUksUUFBUSxDQUFDO1FBQzFCLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtRQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUk7UUFDckIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxHQUFHO1FBQ3RCLElBQUksRUFBRTtZQUNKLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtZQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVE7U0FDMUI7S0FDRixDQUFDLENBQUM7SUFFSCxNQUFNLE9BQU8sR0FBVSxFQUFFLENBQUM7SUFFMUIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFdkIsSUFBSSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWhELElBQUksQ0FBQztZQUNILE1BQU0sY0FBYyxHQUFRLEVBQUUsQ0FBQztZQUMvQixJQUFJLFdBQVc7Z0JBQUUsY0FBYyxDQUFDLElBQUksR0FBRyxXQUFXLENBQUM7WUFDbkQsSUFBSSxTQUFTO2dCQUFFLGNBQWMsQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDO1lBQzdDLElBQUksT0FBTztnQkFBRSxjQUFjLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztZQUU5QywwR0FBMEc7WUFDMUcsMkRBQTJEO1lBRTNELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUVoRixJQUFJLEtBQUssRUFBRSxJQUFJLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDbkMsT0FBTyxDQUFDLElBQUksQ0FBQztvQkFDWCxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBQ2hCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtvQkFDMUIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO2lCQUNsQyxDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLENBQUM7UUFFRCxNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN0QixPQUFPLE9BQU8sQ0FBQztJQUVqQixDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDL0MsTUFBTSxHQUFHLENBQUM7SUFDWixDQUFDO0FBQ0gsQ0FBQztBQUVELHVCQUF1QjtBQUN2QixNQUFNLENBQUMsTUFBTSxLQUFLLEdBQUcsS0FBSyxFQUFFLE9BQWUsRUFBRSxJQUFZLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDcEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUE7SUFFcEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUE7UUFFdEIsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBRWxDLE1BQU0sWUFBWSxHQUFHO1lBQ25CLFFBQVEsRUFBRTtnQkFDUixJQUFJLEVBQUUsb0NBQW9DO2dCQUMxQyxPQUFPLEVBQUUsT0FBTzthQUNqQjtZQUNELE9BQU8sRUFBRSxJQUFJO1lBQ2IsR0FBRyxPQUFPO1NBQ1gsQ0FBQTtRQUVELDBDQUEwQztRQUMxQyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDekQsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDN0IsTUFBTSxHQUFHLENBQUE7SUFDWCxDQUFDO1lBQVMsQ0FBQztRQUNULHVCQUF1QjtRQUN2QixNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkMsQ0FBQztBQUNILENBQUMsQ0FBQSJ9

View File

@ -25,7 +25,6 @@
"pm-mail": "dist-in/main.js" "pm-mail": "dist-in/main.js"
}, },
"devDependencies": { "devDependencies": {
"@vitest/coverage-v8": "^4.0.18",
"vitest": "^4.0.18" "vitest": "^4.0.18"
}, },
"engines": { "engines": {
@ -132,66 +131,6 @@
"typescript-eslint": "^8.20.0" "typescript-eslint": "^8.20.0"
} }
}, },
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
"integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.28.6"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/types": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
"integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@bcoe/v8-coverage": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
"integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.27.2", "version": "0.27.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
@ -634,16 +573,6 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
@ -651,17 +580,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@pinojs/redact": { "node_modules/@pinojs/redact": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
@ -1099,37 +1017,6 @@
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vitest/coverage-v8": {
"version": "4.0.18",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz",
"integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^1.0.2",
"@vitest/utils": "4.0.18",
"ast-v8-to-istanbul": "^0.3.10",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.2.0",
"magicast": "^0.5.1",
"obug": "^2.1.1",
"std-env": "^3.10.0",
"tinyrainbow": "^3.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@vitest/browser": "4.0.18",
"vitest": "4.0.18"
},
"peerDependenciesMeta": {
"@vitest/browser": {
"optional": true
}
}
},
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "4.0.18", "version": "4.0.18",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz",
@ -1286,18 +1173,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/ast-v8-to-istanbul": {
"version": "0.3.10",
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz",
"integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.31",
"estree-walker": "^3.0.3",
"js-tokens": "^9.0.1"
}
},
"node_modules/atomic-sleep": { "node_modules/atomic-sleep": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
@ -1478,23 +1353,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true,
"license": "MIT"
},
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.7.2", "version": "0.7.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
@ -1546,52 +1404,6 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/istanbul-lib-coverage": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=8"
}
},
"node_modules/istanbul-lib-report": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"istanbul-lib-coverage": "^3.0.0",
"make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/istanbul-reports": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
"integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"html-escaper": "^2.0.0",
"istanbul-lib-report": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/js-tokens": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
"dev": true,
"license": "MIT"
},
"node_modules/libbase64": { "node_modules/libbase64": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz",
@ -1638,34 +1450,6 @@
"@jridgewell/sourcemap-codec": "^1.5.5" "@jridgewell/sourcemap-codec": "^1.5.5"
} }
}, },
"node_modules/magicast": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz",
"integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.5",
"@babel/types": "^7.28.5",
"source-map-js": "^1.2.1"
}
},
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
"license": "MIT",
"dependencies": {
"semver": "^7.5.3"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.11", "version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@ -1899,19 +1683,6 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/semver": {
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/siginfo": { "node_modules/siginfo": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
@ -2017,19 +1788,6 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1" "url": "https://github.com/chalk/strip-ansi?sponsor=1"
} }
}, },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/thread-stream": { "node_modules/thread-stream": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz",

69
packages/tasks/src/cad.ts Normal file
View File

@ -0,0 +1,69 @@
import * as pMap from 'p-map'
import * as path from 'path'
import { isArray } from '@plastichub/core/primitives'
import { convert as cadConvert } from '@plastichub/osr-cad/cad/sw-lib'
import { SolidworkOptions } from '@plastichub/osr-cad'
import { sanitize } from '@plastichub/osr-cad/sw_argv'
import { resolve } from '@plastichub/osr-commons'
import { logger } from '../src'
import { option } from '../library'
export interface ICadTask {
src: string | string[]
output: string
options: any
}
const create_cad_options = (src: string, dst: string, options: SolidworkOptions) => {
return { ...options, src, dst }
}
const convert = async (src, options, output) => {
const args = create_cad_options(src, output, options);
const syncArgs = sanitize({
...args,
...options
})
return cadConvert(syncArgs)
}
const convertFiles = async (items, options, output) => {
return (pMap as any)(items, async (s) => {
return convert(s, options, output)
}, {
concurrency: 1
})
}
export const register = (grunt) => {
grunt.registerMultiTask('cad', 'converts CAD files', function () {
const done = this.async()
const task_options = this.data.options || {}
const options: SolidworkOptions = {
...this.data.options,
root: option('root', task_options, grunt, path.resolve('./')),
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
sw: option('sw', task_options, grunt),
swv: option('swv', task_options, grunt),
args: option('args', task_options, grunt),
dry: option('dry', task_options, grunt),
onNode: option('onNode', task_options, grunt),
cache: option('cache', task_options, grunt, true),
report: option('report', task_options, grunt),
configuration: option('configuration', task_options, grunt),
hidden: option('hidden', task_options, grunt),
quality: option('quality', task_options, grunt),
renderer: option('renderer', task_options, grunt),
view: option('view', task_options, grunt),
close: option('close', task_options, grunt, true),
logLevel: option('logLevel', task_options, grunt, 'warn')
}
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
src = src.map(f => (resolve(f)))
try {
convertFiles(src, options, this.data.output).then(done)
} catch (e) {
logger.error('Error converting files', e)
}
})
}

View File

@ -0,0 +1,385 @@
import * as path from 'path'
import * as md5 from 'md5'
import * as pMap from 'p-map'
import { IOptions, ICompileOptions, compilerOptions } from '@plastichub/osrl/types'
import { Engine as engine } from '@plastichub/osrl/Engine'
import { parse } from '@plastichub/osrl/options'
import { get_cached, set_cached } from '@plastichub/osr-cache/lib'
import { OSR_CACHE, OSR_ROOT } from '@plastichub/osr-commons/config'
import { isFile, resolve, substitute, pathInfo, pathInfoEx } from '@plastichub/osr-commons'
import { sync as exists } from '@plastichub/fs/exists'
import { sync as read } from '@plastichub/fs/read'
import { sync as write } from '@plastichub/fs/write'
import { sync as rm } from '@plastichub/fs/remove'
import { taskOptions } from '../src/zod_schema'
import { ICompileTaskOptions } from '../src/zod_types'
import { logger } from '../src'
import { option, gruntOptions } from '../library'
import {
MODULE_NAME
} from '../src/constants'
import { TLogLevelName } from 'tslog'
import { I18N_STORE } from '../src/config'
const chokidar = require("chokidar")
const lockMap = {}
const fileAsBuffer = (path: string) => read(path, 'buffer') as Buffer || Buffer.from("-")
export type onCompileDone = (source: string, target: string, options: IOptions, content: string) => Promise<void>
export type ICompileTaskOptions2 = IOptions & {
watchContent?: boolean
debugWatch?: boolean
clear?: boolean
onCompile?: (options: IOptions) => Promise<IOptions | null>
onCompiled?: (source: string, target: string, content: string) => Promise<string | null>
onCompileDone?: (source: string, target: string, options: IOptions, content: string) => Promise<void>
}
export interface ICompileTaskData {
options: ICompileTaskOptions
src: string[]
}
export const createContent = async (file: string, _options: any) => {
if (!exists(file)) {
logger.error(`Source file ${file} not found`)
return false
}
const parts = path.parse(file)
const rel = path.relative(_options.root, file)
let output = _options.output
let outputInfo = pathInfo(_options.output)
const variables = {
root: _options.root || '.',
cwd: _options.cwd || path.resolve('.'),
..._options.variables
}
if (!outputInfo.FILE_EXT) {
output = path.resolve(`${_options.output}/${path.parse(rel).dir}/${parts.name}.md`)
} else {
output = path.resolve(resolve(output, false, variables));
}
const defaults: any = {
language: _options.language,
debug: _options.debug,
profile: _options.profile,
output: output,
plugins: _options.plugins,
env: _options.env || 'library',
cwd: _options.cwd || path.resolve('.'),
source: file,
variables,
user: _options.user,
template: _options.template,
targetLanguage: _options.targetLanguage,
sourceLanguage: _options.sourceLanguage
}
const options = parse(defaults, defaults)
debugger
let eOptions = {
...options,
root: [
...options.profile.includes,
path.parse(file).dir
],
toHTML: false,
cache: false,
keepOutputType: true,
trimTagRight: false,
trimTagLeft: false,
trimOutputRight: false,
trimOutputLeft: false,
greedy: false
} as IOptions
const Engine = new engine(eOptions)
if (_options.onCompile) {
const newOpts = await _options.onCompile(options)
if (newOpts) {
eOptions = newOpts
}
}
options.source = path.resolve(options.source)
const osr_cache = OSR_CACHE()
let dst = path.resolve(resolve(output, false, options.variables))
const cache_key = {
file,
dst,
targetLanguage: eOptions.targetLanguage,
sourceLanguage: eOptions.sourceLanguage,
language: eOptions.language,
format: eOptions.format
}
const done = async (content) => {
const contentCompiled = await _options.onCompiled(options.source, output, content)
if(contentCompiled) {
content = contentCompiled
}else{
logger.warn(`onCompiled returned nothing : ${options.source}`)
}
if (_options.onCompileDone) {
await _options.onCompileDone(options.source, dst, options, content)
}
}
let cached = await get_cached(options.source, cache_key, _options.module || MODULE_NAME)
if (osr_cache && cached && _options.cache !== false) {
let md5Src = md5(Buffer.from(cached));
let md5Dst = md5(fileAsBuffer(options.output));
if (!exists(options.output) || md5Src !== md5Dst) {
write(options.output, cached);
}
logger.debug(`Compile file ${file} : serving from cache`)
lockMap[file] = false
cached = await done(cached)
return cached
}
let content = await Engine.render(options.source, options.variables)
if (!content) {
logger.error(`Error compiling ${options.source} to ${options.output}`)
lockMap[file] = false
return false
}
if (_options.onCompiled) {
const contentCompiled = await _options.onCompiled(options.source, output, content)
if(contentCompiled) {
content = contentCompiled
}else{
logger.warn(`onCompiled returned nothing : ${options.source}`)
}
}
if (osr_cache && _options.cache !== false) {
logger.debug('Write output to cache', output)
await set_cached(options.source, cache_key, _options.module || MODULE_NAME, content)
}
dst && content && write(dst, content)
if (_options.onCompileDone) {
await _options.onCompileDone(options.source, dst, options, content)
}
lockMap[file] = false
logger.info(`Compiled ${file} to: ${dst} `)
return content
}
const watch = async (src, options) => {
const dInfo = pathInfo(src, false, options.cwd)
src = path.resolve(src)
const dir = dInfo.IS_GLOB ? dInfo.DIR : src
const watcher = chokidar.watch(`${dir}`, {
ignored: /(^|[\/\\])\../,
persistent: true,
ignoreInitial: false,
followSymlinks: true,
disableGlobbing: false,
usePolling: false,
interval: 1000,
binaryInterval: 300,
alwaysStat: false,
depth: 99,
awaitWriteFinish: {
stabilityThreshold: 2500,
pollInterval: 2000
},
ignorePermissionErrors: false,
atomic: 2000
})
watcher.on('addDir', path => logger.debug(`Directory ${path} has been added`))
.on('unlinkDir', path => logger.debug(`Directory ${path} has been removed`))
.on('error', error => logger.debug(`Watcher error: ${error}`))
.on('raw', (event, _path, details) => {
if (!_path.endsWith(dInfo.FILE_EXT)) {
return
}
switch (event) {
case 'rename': {
const rel = path.relative(dir, path.parse(details.watchedPath).dir)
const dst = path.resolve(`${options.output}/${rel}/${_path}`)
if (exists(dst)) {
rm(dst)
}
const _src = path.resolve(`${details.watchedPath}`)
if (lockMap[_src]) {
return
}
if (exists(_src) && isFile(_src)) {
lockMap[_src] = true
createContent(_src, { ...options })
}
break
}
case 'change': {
let _src = ''
if (isFile(details.watchedPath)) {
_src = `${details.watchedPath}`
} else {
_src = path.resolve(`${details.watchedPath}/${_path}`)
}
if (!exists(details.watchedPath)) {
return
}
if (lockMap[_src]) {
return
}
if (exists(_src) && isFile(_src)) {
lockMap[_src] = true
createContent(_src, { ...options })
setTimeout(() => { lockMap[_src] = false }, 3000)
}
break;
}
}
})
return watcher
}
const compileAllEx = async (files, options) => await pMap(files, (f: string) => createContent(f, options), { concurrency: 1 })
export const register = (grunt) => {
grunt.registerMultiTask('compile', 'Compile ', async function () {
const done = this.async()
const task_options = this.data.options
const cwd = path.resolve(option('cwd', task_options, grunt, process.cwd()))
const options: ICompileTaskOptions2 = {
...this.data.options,
cache: option('cache', task_options, grunt, true),
clear: option('clear', task_options, grunt, false),
debug: option('debug', task_options, grunt),
debugWatch: option('debugWatch', task_options, grunt),
env: option('env', task_options, grunt),
format: option('format', task_options, grunt, 'html'),
lang: option('lang', task_options, grunt, 'osr'),
language: option('language', task_options, grunt, 'en'),
sourceLanguage: option('sourceLanguage', task_options, grunt, 'en'),
targetLanguage: option('targetLanguage', task_options, grunt, 'en'),
logLevel: option('logLevel', task_options, grunt, 'warn'),
module: option('module', task_options, grunt),
onCompiled: option('onCompiled', task_options, grunt),
onCompileDone: option('onCompileDone', task_options, grunt),
onCompile: option('onCompile', task_options, grunt),
plugins: option('plugins', task_options, grunt, ['${root}/osr/plugins']),
profile: option('profile', task_options, grunt, '${OSR_ROOT}/.osrl.json'),
root: option('root', task_options, grunt, path.resolve('./')),
template: option('template', task_options, grunt),
variables: option('variables', task_options, grunt, {}),
watchContent: option('watchContent', task_options, grunt, false)
}
logger.setSettings({ minLevel: options.logLevel as TLogLevelName })
if (task_options.watchContent) {
this.data.src.map(f => watch(f, options))
}
let _files = []
this.data.src.map(f => {
const fInfo = pathInfoEx(f, false, { cwd: cwd, absolute: true })
_files = _files.concat(fInfo.FILES)
})
if (!_files.length) {
logger.error(`Have no files or glob in ${cwd}`, this.data.src)
done()
return
}
logger.debug(`Compile - task data`, _files, this.data.options)
if (options.clear !== false) {
if (exists(options.output)) {
rm(options.output)
}
}
const all = await compileAllEx(_files, options)
grunt.event.emit('compile.done', { all, options })
if (!task_options.watchContent) {
logger.info('Done compiling all!')
done()
}
return new Promise((resolve) => {
if (!task_options.watchContent) {
resolve(true)
done()
}
})
})
}
export const contentTasks = (
grunt: IGrunt,
taskOpts: ICompileTaskOptions,
compilerOpts: ICompileOptions) => {
taskOpts =
{
...taskOptions().parse({
...taskOpts,
...gruntOptions(grunt)
})
}
compilerOpts = compilerOptions().parse(compilerOpts as any) as ICompileOptions
logger.setSettings({ minLevel: taskOpts.logLevel, prefix: [MODULE_NAME] })
// logger.warn(`Registering content tasks for ${taskOpts.taskPrefix}`,taskOpts)
const tasks = {}
const taskLanguages = taskOpts.languages as string[]
const taskLanguage = (lang) => {
const taskName = `${taskOpts.taskPrefix}-${lang}`
const config = {}
const taskVariables =
{
...compilerOpts.variables,
...gruntOptions(grunt),
targetLanguage: lang,
sourceLanguage: taskOpts.sourceLanguage,
i18n: I18N_STORE(OSR_ROOT(), lang)
}
config[taskName] = {
src: taskOpts.src,
options:
{
...compilerOpts as any,
variables: { ...taskVariables },
output: path.resolve(resolve(compilerOpts.output, false, taskVariables)),
...taskOpts,
...gruntOptions(grunt)
}
};
(grunt as any).extendConfig({ compile: config })
const substituteTask = (task: string) => substitute(false, task, {
...config[taskName].options.variables,
taskSuffix: taskOpts.taskSuffix,
taskPrefix: taskOpts.taskPrefix,
task
})
const tasksBefore = taskOpts.tasksBefore.map(substituteTask)
const tasksAfter = taskOpts.tasksAfter.map(substituteTask)
const languageTasks = [
...tasksBefore,
`compile:${taskName}`,
...tasksAfter,
]
grunt.registerTask(taskName, languageTasks)
tasks[lang] = {
taskName,
tasks: languageTasks
}
}
taskLanguages.forEach(taskLanguage)
return tasks
}
export * from '../src/zod_types'

View File

@ -3,8 +3,9 @@ import { resolve } from '@plastichub/osr-commons'
export const OSR_ROOT = () => path.resolve(resolve("${OSR_ROOT}")) export const OSR_ROOT = () => path.resolve(resolve("${OSR_ROOT}"))
// Grunt Commons
export const LOG_LEVEL_GRUNT = 'info'
// Supported languages // Supported languages
export const TRANSLATE_CONTENT = true // translate regular pages
export const LANGUAGES = ['de'] export const LANGUAGES = ['de']
// i18n constants // i18n constants
@ -12,36 +13,119 @@ export const I18N_STORE = (root, lang) => `${root}/i18n-store/store-${lang}.json
export const I18N_SOURCE_LANGUAGE = 'en' export const I18N_SOURCE_LANGUAGE = 'en'
// Product compiler // Product compiler
export const PRODUCT_BODY = `templates/shared/body.md`
export const PRODUCT_ROOT = () => path.resolve(resolve("${OSR_ROOT}/products")) export const PRODUCT_ROOT = () => path.resolve(resolve("${OSR_ROOT}/products"))
export const PRODUCT_CONFIG = (product) => export const PRODUCT_CONFIG = (product) =>
path.resolve(resolve("${OSR_ROOT}/products/${product}/config.json", false, path.resolve(resolve("${OSR_ROOT}/products/${product}/config.json", false, { product }))
{
product
}))
export const PRODUCT_DIR = (product) => export const PRODUCT_DIR = (product) =>
path.resolve(resolve("${OSR_ROOT}/products/${product}", false, path.resolve(resolve("${OSR_ROOT}/products/${product}", false, { product }))
{
product
}))
export const IS_DEV = true export const IS_DEV = true
export const OSRL_ENV = 'bazar-release' export const OSRL_ENV = 'bazar-release'
export const OSRL_ENV_DEV = 'hugo-debug' export const OSRL_ENV_DEV = 'hugo-debug'
export const OSRL_ENVIRONMENT = IS_DEV ? OSRL_ENV_DEV : OSRL_ENV export const OSRL_ENVIRONMENT = IS_DEV ? OSRL_ENV_DEV : OSRL_ENV
export const PRODUCT_HUGO_TEMPLATE = './osr/hugo/root.html'
export const PRODUCTS_TARGET_SRC = './src/content/en/retail'
// OSRL - Language // OSRL - Language
export const OSRL_MODULE_NAME = 'osr-site' export const OSRL_MODULE_NAME = 'osr-site'
export const OSRL_PRODUCT_PROFILE = '${root}/.osrl.json'
export const OSRL_LANG_FLAVOR = 'osr'
export const OSRL_FORMAT = 'html'
// Tasks
export const TASK_CONFIG_LOG_DIRECTORY = './config/'
// Task: compile:content
export const TASK_COMPILE_CONTENT = true
export const TASK_COMPILE_CONTENT_CACHE = true
export const TASK_COMPILE_DEFAULT_PROFILE = '${OSR_ROOT}/osr-templates/osrl/.osrl.json'
export const TASK_COMPILE_DEFAULT_PLUGINS = '${root}/osr/plugins'
// Task - Logging // Task - Logging
export const TASK_LOG_DIRECTORY = './logs/' export const TASK_LOG_DIRECTORY = './logs/'
// Task - Retail Config
export const RETAIL_DEFAULT_BRANCH = 'dev'
export const RETAIL_MEDIA_CACHE = true
export const RETAIL_LOG_LEVEL_I18N_PRODUCT_ASSETS = 'info'
export const ConvertProductMedia = true
export const TranslateProductAssets = true
export const PopulateProductDefaults = true
export const PRODUCT_TEMPLATE = './osr/bazar/root.html'
export const HTML_DEFAULT_PATH = 'resources/edrawings.html'
export const DEFAULT_CAD_CAM_EXPORT = '${SRC_DIR}/${SRC_NAME}.+(step)'
export const DEFAULT_CAD_EXPORT = '${SRC_DIR}/${SRC_NAME}.+(json|html|step|x_t)'
export const DEFAULT_CAD_EXPORT_CONFIGURATION = '${SRC_DIR}/${SRC_NAME}-${CONFIGURATION}.+(json|html|step|x_t)'
export const DEFAULT_CAD_EXPORT_MIN = '${SRC_DIR}/${SRC_NAME}.+(json)'
export const DEFAULT_CAD_EXPORT_MIN_CONFIGURATION = '${SRC_DIR}/${SRC_NAME}-${CONFIGURATION}.+(json)'
export const SYNC_PROFILE = '${OSR_ROOT}/osr-commons/profiles/.osr-sync-public.json'
export const PRODUCT_ROOT_REL = '${PRODUCT_ROOT}/products'
export const SYNC_TARGET = '${OSR_ROOT}/osr-machines/'
export const CAD_MAIN_MATCH = (product) => `${product}/cad*/**/*Global*.+(SLDASM)`
export const CAD_CAM_MAIN_MATCH = (product) => `${product}/cad*/**/*-CNC*.+(SLDASM)`
export const CAD_CACHE = false
export const CAD_EXPORT_CONFIGURATIONS = false
export const CAD_EXPORT_SUB_COMPONENTS = false
export const CAD_MODEL_FILE_PATH = (SOURCE, CONFIGURATION = '') =>
SOURCE.replace('.json', `${CONFIGURATION ? '-' + CONFIGURATION : ''}.tree.json`)
export const CAD_DEFAULT_CONFIGURATION = 'Default'
export const CAD_RENDERER = 'solidworks'
export const CAD_RENDERER_VIEW = 'Render'
export const CAD_RENDERER_QUALITY = 1
////////////////////////////////////////////////////////////
//
// Content Tasks
export const ENABLE_NEWSLETTER = true
export const ENABLE_MAIL = false
// newsletter
export const NEWSLETTER_ROOT = `company/new sletter/2024/08`
export const NEWSLETTER_LOG_LEVEL = 'debug'
export const NEWSLETTER_LANGUAGES = ['en']
export const NEWSLETTER_TEMPLATE_FILE = 'root.osr'
export const NEWSLETTER_SRC_FILE = 'mail.html'
export const NEWSLETTER_DST_DIR = '${OSR_ROOT}/products/products/assets/newsletter/'
export const NEWSLETTER_DST_FILE = '${prefix}_newsletter_${YYYY}-${MM}_${targetLanguage}.html'
export const NEWSLETTER_DEFAULT_ENV = 'hugo-release'
export const NEWSLETTER_DEBUG_PROFILE = 'hugo-debug'
export const NEWSLETTER_RELEASE_PROFILE = 'hugo-release'
export const NEWSLETTER_COMPILE_CACHE = false
// mail
export const MAIL_ROOT = `company/mail/2024/08`
export const MAIL_LOG_LEVEL = 'debug'
export const MAIL_CONTACTS_ROOT = () => `${PRODUCT_ROOT()}/company/campaign/contacts`
export const MAIL_ASSETS_ROOT = () => `${PRODUCT_ROOT()}/company/campaign/data`
export const MAIL_OUTPUT_DIR = '/products/assets/newsletter/mail/'
export const MAIL_OUTPUT_FILE_NAME = 'mail_2024_09'
export const MAIL_OUTPUT_FILE_NAME_PROD = `${MAIL_OUTPUT_FILE_NAME}_public`
export const MAIL_OUTPUT_FILE_EXT = '.html'
export const MAIL_PROFILE = "${OSR_ROOT}/osr-templates/osrl/.osrl.json"
export const MAIL_SRC_LANGUAGE = 'en'
export const MAIL_LANGUAGES = ['en', 'es']
export const MAIL_LANGUAGES_RELEASE = ['en', 'es', 'de', 'fr']
export const MAIL_ENV_DEV = 'hugo-debug'
export const MAIL_ENV_PROD = 'hugo-release'
export const MAIL_TEMPLATE = "./root.osr"
export const MAIL_SOURCE_FILE = "mail.html"
export const MAIL_COMPILE_CACHE = false
export const MAIL_I18N_CACHE = true
export const MAIL_SEND_INTERVAL = 1000
export const MAIL_DEFAULT_OUTPUT_PATH = "${SRC_DIR}/${SRC_NAME-0}-${DST_LANG}${SRC_EXT}"
//////////////////////////////////////////////////////
//
// Store query templates
export const buildQuery = (typeFilter, emailRequired = true, geoFilter = {}, params = "", additionalFilter = "") => {
const types = typeFilter || [
"Carpenter",
"Woodworker",
"Furniture maker",
"Cabinet maker",
"Furniture manufacturer"
]
const typeCondition = types.map(type => `@.type == "${type}"`).join(" || ")
const emailCondition = emailRequired ? "&& @.email != null" : ""
const geoConditions = Object.entries(geoFilter).map(([key, value]) => `&& @.geo.${key} == "${value}"`).join(" ")
return `$[?(((${typeCondition}) ${emailCondition} ${geoConditions} ${additionalFilter}) ${params})]`
}
export const QUERY_TEMPLATES = {
}

View File

@ -0,0 +1,51 @@
import * as path from 'path'
import { JSONPath } from 'jsonpath-plus'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { resolve } from '@plastichub/osr-commons'
import {
MAIL_CONTACTS_ROOT,
QUERY_TEMPLATES
} from './config'
import { logger } from '../src'
import { cleanArray } from './utils'
export const resolveContactsPath = (mailerOptions) => {
if (!mailerOptions.contacts) {
return false
}
let contactFiles = path.resolve(resolve(mailerOptions.contacts))
if (!exists(contactFiles)) {
contactFiles = path.join(MAIL_CONTACTS_ROOT(), mailerOptions.contacts)
}
return contactFiles
}
export const getContacts = (mailerOptions) => {
let contactFiles = resolveContactsPath(mailerOptions)
if (!contactFiles) {
return []
}
logger.debug(`Reading Contact File : ${contactFiles}`)
let contacts = read(contactFiles, 'json') as any[]
if (!contacts) {
logger.error(`Cannot read contacts file ${contactFiles}`)
return []
}
return contacts
}
export const filterContacts = (grunt, contacts, mailerOptions) => {
if (!mailerOptions.query) {
return contacts
}
if (QUERY_TEMPLATES[mailerOptions.query]) {
mailerOptions.query = QUERY_TEMPLATES[mailerOptions.query](grunt.option('queryExtra'))
}
let queryResult = JSONPath({ path: mailerOptions.query, json: contacts })
logger.debug(`Query Result : ${queryResult.length} contacts : \n\t ${mailerOptions.query}`)
queryResult = cleanArray(queryResult)
return queryResult
}

View File

@ -0,0 +1,30 @@
import { logger } from '../src'
import { option } from '../library'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons/config'
import { resolve } from '@plastichub/osr-commons'
import { IOSRConfig } from '@plastichub/osr-commons'
export const register = (grunt) => {
grunt.registerMultiTask('cscart', 'Deploy product to CSCart', async function () {
const done = this.async();
const task_options = this.data.options || {}
const config = CONFIG_DEFAULT() as IOSRConfig
const options = {
...this.data.options,
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
vendor: option('vendor', task_options, grunt)
}
const src = this.data.src.map(f => (resolve(f)))
options.debug && logger.info('Compile - task data ', process.cwd(), this.data, src)
// let ret = await updateProducts(src, config.cscart, options.vendor)
debugger;
});
};

63
packages/tasks/src/git.ts Normal file
View File

@ -0,0 +1,63 @@
import { simpleGit } from 'simple-git'
import { resolve } from '@plastichub/osr-commons'
import { logger } from '../src/index'
import { option } from '../library'
const GIT_MESSAGE_PREFIX = (rel: string) => `Updating - ${rel}`
export async function git_update(options) {
const { cwd, rel, message, debug } = options
const git = simpleGit(cwd)
let commit: any = null
let push: any = null
try {
debug && logger.debug("commit " + rel + " in " + cwd)
commit = await git.add(rel)
}
catch (e) {
logger.error('Error Git Commit', e)
}
try {
debug && logger.debug("commit " + rel + " in " + cwd)
commit = await git.commit(message || GIT_MESSAGE_PREFIX(rel), rel)
}
catch (e) {
logger.error('Error Git Commit', e)
}
try {
push = await git.push()
}
catch (e) {
logger.error('Error Git Push', e)
}
return { commit, push }
}
export const register = (grunt) => {
grunt.registerMultiTask('git', 'Adds, commits and pushes folders', async function () {
const done = this.async()
const task_options = this.data || {}
const logLevel = option('logLevel', task_options, grunt, 'warn')
logger.setSettings({ minLevel: logLevel })
let rel: string = this.data.rel
const variables = {
...task_options.variables || {}
}
const options = {
rel: resolve(rel, false, variables),
cwd: resolve(option('cwd', task_options, grunt), false),
message: option('message', task_options, grunt),
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
logLevel
}
logger.info('Git - task data ', this.data)
await git_update(options)
done()
})
}

View File

@ -0,0 +1,55 @@
import * as path from 'path'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
import { resolve } from '@plastichub/osr-commons'
import { IOptions } from '@plastichub/osr-i18n/types'
import { translate } from '@plastichub/osr-i18n/lib/translate'
import { sanitize } from '@plastichub/osr-i18n/_cli'
import { isArray } from '@plastichub/core/primitives'
import { logger } from '../src'
import { option } from '../library'
import * as pMap from 'p-map'
const _translate = async (src, dst, options) => {
const i18nOptions = sanitize(
{
...options,
src: src,
dst: dst,
debug: options.debug,
verbose: options.verbose,
dry: options.dry
}
) as IOptions
if (!i18nOptions) {
logger.error('Invalid i18n options')
return
}
return await translate(i18nOptions)
}
const translateAll = async (files, options, dst: string) => {
return pMap(files, async (f) => _translate(f, dst, options), { concurrency: 1 })
}
export const register = (grunt) => {
grunt.registerMultiTask('i18n', 'translate files via osr-i18n', async function () {
const done = this.async();
const task_options = this.data.options || {}
const config: any = CONFIG_DEFAULT()
const options = {
...this.data.options,
root: option('root', task_options, grunt, path.resolve('./')),
debug: option('debug', task_options, grunt , false),
logLevel: option('logLevel', task_options, grunt , 'warn'),
api_key: config.deepl.auth_key
}
logger.setSettings({ minLevel: options.logLevel })
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
src = src.map(f => (resolve(f)))
logger.debug('Translate - task data ', this.data)
await translateAll(src, options, this.data.options.dst)
logger.info(`Translate - task done : \n\t ${src.join('\n\t')}`)
done()
})
}

View File

@ -0,0 +1,55 @@
import { Promise as BPromise } from 'bluebird'
import { isArray } from '@plastichub/core/primitives'
import { resolve } from '@plastichub/osr-commons'
import { IOptions as IResizeOptions } from '@plastichub/osr-media/types'
import { sanitize } from '@plastichub/osr-media/_cli'
import { resize } from '@plastichub/osr-media/lib/media/images'
import { logger } from '../src'
import { option } from '../library'
const convert = async (src, dst, options) => {
const resizeOptions = sanitize(
{
src: src,
dst: dst,
debug: options.debug,
verbose: options.verbose,
dry: options.dry
}
) as IResizeOptions
return await resize(resizeOptions)
}
const resizeFiles = async (items, dst, options) => {
return BPromise.resolve(items).map((s) => {
return convert(s, options, dst)
}, {
concurrency: 1
})
}
export const register = (grunt) => {
grunt.registerMultiTask('images-resize', 'resizes images', function () {
const done = this.async()
const task_options = this.data.options || {}
const options = {
...this.data.options,
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
dry: option('dry', task_options, grunt)
}
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
src = src.map(f => (resolve(f)))
options.debug && logger.info('Images-Resize : Task data ', process.cwd(), this.data, src)
resizeFiles(src, options, this.data.dst).then(done)
})
}

View File

@ -1,4 +1,17 @@
/**
* Callback prototype signature when content has been compiled
* @param {string} src The path of the source file
* @param {string} dst The path of the destination file
* @param {string} content The content
* @returns {boolean}
*/
export type OnCompiled = (src: string, dst: string, content: string) => Promise<string>
import { MODULE_NAME } from './constants' /**
import { logger as _logger } from '@plastichub/core/debug' * Callback prototype signature when 'compile' task is finish
export const logger = _logger(MODULE_NAME) * @param {string} src The path of the source file
* @param {string} dst The path of the destination file
* @param {string} content The content
* @returns {boolean}
*/
export type OnCompileDone = (src: string, dst: string, options: any, content: string) => Promise<void>

213
packages/tasks/src/laser.ts Normal file
View File

@ -0,0 +1,213 @@
import * as path from 'path'
import * as pMap from 'p-map'
import { resolve, isFolder } from '@plastichub/osr-commons'
import { isArray } from '@plastichub/core/primitives'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { sync } from '@plastichub/osr-sync'
import { IAssemblyData } from '@plastichub/osr-cad/cad/sw-types'
import {
CAD_MAIN_PATTERN,
MainAssembly,
file_path_with_ext_ex,
forward_slash,
unique_by,
option
} from '../library'
import { logger } from '../src'
export const regexLaserFile = /^(\d+)_([a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+)*)_x(\d+)_(\d+)mm_(\w+)$/;
export const laserDetails = (input: string) => {
if(!input) {
return false
}
const match = (path.parse(input).name).match(regexLaserFile)
if (!match) {
const idMatch = input.match(/^(\d+)_/)
const nameMatch = input.match(/_(\w+)_/)
const quantityMatch = input.match(/_x\d+_/)
const thicknessMatch = input.match(/_\d+mm_/)
const materialMatch = input.match(/_\w+$/)
let errorMessage = 'Invalid input format:'
if (!idMatch) {
errorMessage += '\n- Leading ID (digits) is missing or invalid';
}
if (!nameMatch) {
errorMessage += '\n- Name (letters) is missing or invalid';
}
if (!quantityMatch) {
errorMessage += '\n- Quantity (x followed by digits) is missing or invalid';
}
if (!thicknessMatch) {
errorMessage += '\n- Thickness (digits followed by "mm") is missing or invalid';
}
if (!materialMatch) {
errorMessage += '\n- Material (alphanumeric characters) is missing or invalid';
}
logger.error(errorMessage)
return
}
const [_, id, name, quantity, thickness, material] = match
return {
id: parseInt(id),
name,
quantity: parseInt(quantity),
thickness: parseInt(thickness),
material
}
}
const parts_with_laser = (model) => {
let parts = [...model.filter((f) => f.IsLaser === "1"), ...model]
return parts.filter((f) => {
const _path = path.resolve(resolve(f['File Path']))
if (_path && exists(_path)) {
const dir = path.parse(_path).dir
const laser = path.resolve(path.join(dir, 'laser'))
if (exists(laser)) {
return f
}
}
})
}
const createLaserFiles = async (root, product, options, grunt) => {
if (!exists(root)) {
options.debug && logger.info("Create Laser Files : Root doesnt exists" + root)
}
const PRODUCT_ROOT = path.resolve(path.join(root, product))
if (!exists(PRODUCT_ROOT)) {
logger.warn(`Invalid product root : ${PRODUCT_ROOT}`)
return false
}
const main = MainAssembly(PRODUCT_ROOT, options.filePattern)
if (!main) {
logger.warn("Have no main assembly at " + PRODUCT_ROOT);
return false
}
const modelFilePath = file_path_with_ext_ex(main, 'json')
if (!modelFilePath || !exists(modelFilePath)) {
logger.warn("Have no model at " + modelFilePath)
return false
}
const model = read(modelFilePath, 'json')
let tree : IAssemblyData = null
const treeFilePath = file_path_with_ext_ex(main, 'tree.json')
if (!treeFilePath || !exists(treeFilePath)) {
logger.warn("Have no tree at " + treeFilePath)
}else{
tree = read(treeFilePath, 'json') as IAssemblyData
}
const laserParts = parts_with_laser(model)
let laserDirectories: any[] = [
...new Set(laserParts.map((f) => {
const _path = path.resolve(resolve(f['File Path']))
const dir = path.parse(_path).dir
const ret = {
target: forward_slash(path.relative(PRODUCT_ROOT, dir)).
replace('../components/', '').
replace('components', '').
replace('cad', '').
replace('../', ''),
path: dir + '/laser'
}
return ret
}))
]
const config: any = read(path.join(PRODUCT_ROOT, 'config.json'), 'json')
if (!config) {
return []
}
laserDirectories = unique_by(laserDirectories, 'path')
logger.debug('Create laser files for ', laserDirectories)
return (pMap as any)(laserDirectories, async (item) => {
return (pMap as any)(['en','es'], async (lCode) => {
const renamer = (from, to) => {
if (isFolder(from)) { return }
const lParts = laserDetails(from)
if(!lParts){
logger.warn(`Invalid laser file in ${PRODUCT_ROOT} : ${from}`)
}
const fromParts = path.parse('' + from)
const toParts = path.parse('' + to)
const pCode = config.code || ''
const toFileParts = ('' + toParts.name).split('_')
const fromFileParts = ('' + fromParts.name).split('_')
const thickness = fromFileParts[3]
let qty = fromFileParts[2]
let material = fromFileParts[4]
if (!material) {
logger.error('logger.error : invalid material ', from + ' : ' + ' to : ' + to, toFileParts)
return to
}
if (lCode === 'en') {
material = material.toLowerCase().replace("ferro", "Steel").replace("inox", "Stainless")
}
const newName = path.resolve(
toParts.dir + '/' +
material + '/' +
thickness + '/' +
pCode + '-' +
toFileParts[0] + '_' +
toFileParts[1] + '_' +
qty +
toParts.ext)
return newName
}
return sync({
renamer: renamer,
clear: options.clear,
source: path.resolve(item.path),
target: `${PRODUCT_ROOT}/laser/${lCode}/${item.target}`,
debug: options.debug,
verbose: options.verbose,
profile: options.profile
})
}, {concurrency: 1})
},{concurrency: 1})
}
const create = async (item, options, grunt) => {
try {
return createLaserFiles(options.cwd || '.', item, options, grunt);
} catch (e) {
logger.error(e)
return []
}
}
export const register = (grunt) => {
grunt.registerMultiTask('laser', 'Create laser files', function () {
const done = this.async()
const task_options = this.data.options || {};
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
logger.setSettings({ minLevel: option('logLevel', task_options, grunt, 'warn') })
let p
src.forEach((item) => {
try {
p = create(item, {
verbose: option('verbose', task_options, grunt, false),
clear: option('clear', task_options, grunt, true),
debug: option('debug', task_options, grunt, true),
filePattern: option('filePattern', task_options, grunt, CAD_MAIN_PATTERN),
profile: option('profile', task_options, grunt, {
"matching": ["*"]
}),
module: option('module', task_options, grunt, 'osr-tasks'),
cwd: option('cwd', task_options, grunt, process.cwd())
}, grunt)
} catch (e) {
logger.error(e)
}
})
if (p) {
p.then((result) => {
done(true)
})
}
})
}

View File

@ -0,0 +1,278 @@
import * as path from 'path'
import * as pMap from 'p-map'
import { resolve, isFolder } from '@plastichub/osr-commons'
import { isArray } from '@plastichub/core/primitives'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { sync } from '@plastichub/osr-sync'
import {
CAD_MAIN_PATTERN,
MainAssembly,
file_path_with_ext_ex,
forward_slash,
unique_by,
option
} from '../library'
import { logger } from '../src'
import { IAssemblyData, ITreeNode } from '@plastichub/osr-cad/cad/sw-types'
export const regexLaserFile = /^(\d+)_([a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+)*)_x(\d+)_(\d+)mm_(\w+)$/;
export const laserDetails = (input: string) => {
if (!input) {
return false
}
const fileName = (path.parse(input).name)
const match = fileName.match(regexLaserFile)
if (!match) {
const idMatch = input.match(/^(\d+)_/)
const nameMatch = input.match(/_(\w+)_/)
const quantityMatch = input.match(/_x\d+_/)
const thicknessMatch = input.match(/_\d+mm_/)
const materialMatch = input.match(/_\w+$/)
let errorMessage = 'Invalid input format:'
if (!idMatch) {
errorMessage += `\n- Leading ID (digits) is missing or invalid : ${fileName}`
}
if (!nameMatch) {
errorMessage += `\n- Name (letters) is missing or invalid ${fileName}`
}
if (!quantityMatch) {
errorMessage += `\n- Quantity (x followed by digits) is missing or invalid ${fileName}`
}
if (!thicknessMatch) {
errorMessage += `\n- Thickness (digits followed by "mm") is missing or invalid ${fileName}`
}
if (!materialMatch) {
errorMessage += `\n- Material (alphanumeric characters) is missing or invalid ${fileName}`
}
logger.error(errorMessage)
return
}
const [_, id, name, quantity, thickness, material] = match
return {
id: parseInt(id),
name,
quantity: parseInt(quantity),
thickness: parseInt(thickness),
material
}
}
const parts_with_laser = (model) => {
if(!model){
return []
}
let parts = [...model.filter((f) => f.IsLaser === "1"), ...model]
return parts.filter((f) => {
const _path = path.resolve(resolve(f['File Path']))
if (_path && exists(_path)) {
const dir = path.parse(_path).dir
const laser = path.resolve(path.join(dir, 'laser'))
if (exists(laser)) {
return f
}
}
})
}
export const createLaserFiles = async (root, product, options, grunt) => {
if (!exists(root)) {
options.debug && logger.info("Create Laser Files : Root doesnt exists" + root)
}
const PRODUCT_ROOT = path.resolve(path.join(root, product))
if (!exists(PRODUCT_ROOT)) {
logger.warn(`Invalid product root : ${PRODUCT_ROOT}`)
return false
}
const main = MainAssembly(PRODUCT_ROOT, options.filePattern)
if (!main) {
logger.warn("Have no main assembly at " + PRODUCT_ROOT);
return false
}
const modelFilePath = file_path_with_ext_ex(main, 'json')
if (!modelFilePath || !exists(modelFilePath)) {
logger.warn("Have no model at " + modelFilePath)
return false
}
const model = read(modelFilePath, 'json')
let tree: IAssemblyData = null
const treeFilePath = file_path_with_ext_ex(main, 'tree.json')
if (!treeFilePath || !exists(treeFilePath)) {
logger.warn("Have no tree at " + treeFilePath)
} else {
tree = read(treeFilePath, 'json') as IAssemblyData
}
const laserParts = parts_with_laser(model)
let laserDirectories: any[] = [
...new Set(laserParts.map((f) => {
const _path = path.resolve(resolve(f['File Path']))
const dir = path.parse(_path).dir
const ret = {
target: forward_slash(path.relative(PRODUCT_ROOT, dir)).
replace('../components/', '').
replace('components', '').
replace('cad', '').
replace('../', ''),
path: path.resolve(dir + '/laser')
}
return ret
}))
]
const config: any = read(path.join(PRODUCT_ROOT, 'config.json'), 'json')
if (!config) {
logger.warn("Have no config at " + PRODUCT_ROOT)
return []
}
laserDirectories = unique_by(laserDirectories, 'path')
logger.debug('Create laser files for ', laserDirectories)
const qtyTotal = (qty, filePath) => {
if (tree) {
const { Components } = tree.assembly
if (!Components) {
return qty
}
const c = Components.filter((c) => {
const partPath = path.parse(c.Path).name.toLowerCase()
const laserFilePath = path.parse(filePath).name.toLowerCase()
return partPath === laserFilePath && !c.IsSuppressed
}).length
if (c){
return c
}else{
debugger
logger.warn(`Cant find instances of file : ${path.parse(filePath).name} : \n\t${filePath} in tree : \n\t${treeFilePath}`)
}
}
return qty
}
const qtyTotal2 = (qty, filePath) => {
if (tree) {
const { Components } = tree.assembly
if (!Components) {
return qty
}
if(filePath.includes('7_Side_x2_6mm_FERRO')){
debugger
}
let count = 1;
const chlidren = tree.root.Children;
if(chlidren){
const items = chlidren.filter((c: ITreeNode) => {
const partPath = path.parse(c.Path).name.toLowerCase()
const laserFilePath = path.parse(filePath).name.toLowerCase()
return partPath === laserFilePath && !c.IsSuppressed
})
count = items.length;
}
if (count){
return count
}else{
logger.warn(`Cant find instances of file : ${path.parse(filePath).name} : \n\t${filePath} in tree : \n\t${treeFilePath}`)
}
}
return qty
}
return (pMap as any)(laserDirectories, async (item) => {
return (pMap as any)(['en', 'es'], async (lCode) => {
const renamer = (from, to) => {
if (isFolder(from)) {
return
}
const lParts: any = laserDetails(from) || {}
if (!lParts) {
logger.warn(`Invalid laser file in ${PRODUCT_ROOT} : ${from}`)
}
const fromParts = path.parse('' + from)
const toParts = path.parse('' + to)
const pCode = config.code || ''
const toFileParts = ('' + toParts.name).split('_')
const fromFileParts = ('' + fromParts.name).split('_')
let qty = qtyTotal2(lParts.quantity, from)
let material = fromFileParts[4]
if (!material) {
logger.error('logger.error : invalid material ', from + ' : ' + ' to : ' + to, toFileParts)
return to
}
if (lCode === 'en') {
material = material.toLowerCase().replace("ferro", "Steel").replace("inox", "Stainless")
}
const newName = path.resolve(
toParts.dir + '/' +
material + '/' +
`${lParts.thickness}mm` + '/' +
pCode + '-' +
toFileParts[0] + '_' +
toFileParts[1] + '_' +
`x${qty}` +
toParts.ext.toLowerCase())
return newName
}
const target = `${PRODUCT_ROOT}/laser/${lCode}/${item.target}`
logger.debug(`Create laser files for ${item.path} ${lCode} : to ${target}`)
return sync({
renamer: renamer,
clear: options.clear,
source: path.resolve(item.path),
target,
debug: options.debug,
verbose: options.verbose,
profile: options.profile,
logLevel: options.logLevel || 'warn'
})
}, { concurrency: 1 })
}, { concurrency: 1 })
}
const create = async (item, options, grunt) => {
try {
return createLaserFiles(options.cwd || '.', item, options, grunt);
} catch (e) {
logger.error(e)
return []
}
}
export const register = (grunt) => {
grunt.registerMultiTask('laser2', 'Create laser files', function () {
const done = this.async()
const task_options = this.data.options || {};
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
logger.setSettings({ minLevel: option('logLevel', task_options, grunt, 'warn') })
let p
src.forEach((item) => {
try {
p = create(item, {
verbose: option('verbose', task_options, grunt, false),
clear: option('clear', task_options, grunt, true),
debug: option('debug', task_options, grunt, true),
filePattern: option('filePattern', task_options, grunt, CAD_MAIN_PATTERN),
profile: option('profile', task_options, grunt, {
"matching": ["*"]
}),
module: option('module', task_options, grunt, 'osr-tasks'),
cwd: option('cwd', task_options, grunt, process.cwd())
}, grunt)
} catch (e) {
logger.error(e)
}
})
if (p) {
p.then((result) => {
done(true)
})
}
})
}

View File

@ -0,0 +1,221 @@
import * as path from 'path'
import * as sharp from 'sharp'
import { sync as dir } from '@plastichub/fs/dir'
import { sync as exists } from '@plastichub/fs/exists'
import { files as _glob } from '@plastichub/osr-commons'
import { logger } from '../src'
const fg = require('fast-glob')
export const getFormats = (product, folder) => {
return [{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/webp`,
format: 'webp',
}];
}
/*
const updateImages = async (root, product_root, content) => {
// Feed the content into JSDOM
const dom = new JSDOM(content);
const document = dom.window.document;
// Find the image elements via `querySelectorAll`, replace this selector with your own custom one
const imageElems = document.querySelectorAll('img');
// If there are no matching elements, just return the original content :)
if (imageElems.length === 0) {
return content;
}
for (const imgElem of imageElems) {
// Get the `src` of the image element
const imgSrc = imgElem.getAttribute('src');
// Only add this transform for internal images
if (imgSrc.startsWith('https') || imgSrc.startsWith('http')) {
let srcSet = [];
// Replace all of the image sources with a new one that matches the results of the Sharp build
if (imgSrc.indexOf('.png') !== -1) {
continue;
}
if (imgSrc.indexOf('.png') !== -1) {
continue;
}
const parsed = URI.parse(decodeURIComponent(imgSrc));
const pParsed = path.parse(parsed.path);
const imageName = (url) => {
return decodeURIComponent(pParsed.base);
}
// const parts = url.parse(imgSrc);
// Get the metadata for the file and add it as the `${width}w` needed in defining a `srcset` in HTML for `<img>`
const name = imageName(imgSrc);
const _path = decodeURIComponent(parsed.path).replace('//', '');
const imageSrcPath = `${root}/${_path}`;
if (!exists(imageSrcPath)) {
console.log('image doesnt exists : ' + imageSrcPath + ' \n\t' + imgSrc);
return;
}
const imageSrcPathParts = path.parse(imageSrcPath);
const imgSrc80 = imgSrc.replace(name, '80/' + name);
const imgSrc60 = imgSrc.replace(name, '60/' + name);
const imgSrc40 = imgSrc.replace(name, '40/' + name);
const imgSrc20 = imgSrc.replace(name, '20/' + name);
const _set = (res) => {
return path.resolve(imageSrcPathParts.dir + '/' + res + '/' + name);
}
if (!exists(_set(80))) {
console.error('doesnt exists ', _set(80), imgSrc);
continue;
}
if (!exists(_set(60))) {
console.error('doesnt exists ', _set(60), imgSrc);
continue;
}
if (!exists(_set(40))) {
console.error('doesnt exists ', _set(40), imgSrc);
continue;
}
if (!exists(_set(20))) {
console.error('doesnt exists ', _set(20), imgSrc);
continue;
}
const img80 = await sharp(_set(80));
const md80 = await img80.metadata();
srcSet.push(`${imgSrc80.replace(/\s/g,'%20')} ${md80.width}w`);
// Repeat
const img60 = await sharp(_set(60));
const md60 = await img60.metadata();
srcSet.push(`${imgSrc60.replace(/\s/g,'%20')} ${md60.width}w`);
// Repeat
const img40 = await sharp(_set(40));
const md40 = await img40.metadata();
srcSet.push(`${imgSrc40.replace(/\s/g,'%20')} ${md40.width}w`);
// Repeat
const img20 = await sharp(_set(20));
const md20 = await img20.metadata();
srcSet.push(`${imgSrc20.replace(/\s/g,'%20')} ${md20.width}w`);
// Join the `srcset` into a string. that can be added to the `<img>` tag
srcSet = srcSet.join(', ');
// Set the `srcset` attribute
imgElem.setAttribute('srcset', srcSet);
// Find the new `src` for the WebP image
let webpSrc = imgSrc.replace(name, 'webp/' + encodeURIComponent(name)).replace('.png', '.webp').replace('.jpg', '.webp');
// const webpSrc = imgSrc
// .replace('/images/', '/images/webp/')
// .replace('.png', '.webp');
// Create a separate `source` element for the WebP with feature detection via `type`
const webpElement = document.createElement('source');
webpElement.setAttribute('srcset', webpSrc);
webpElement.setAttribute('type', 'image/webp');
// Wrap the `<img>` and the `<source>` into one `<picture>` tag in order for it to work
const pictureElement = document.createElement('picture');
pictureElement.appendChild(webpElement);
pictureElement.appendChild(imgElem.cloneNode());
// Replace the `<img>` with the `<picture>`
imgElem.replaceWith(pictureElement);
}
}
return document.documentElement.outerHTML;
}
*/
export const format = (formats) => {
return formats.forEach((format) => {
if (!exists(format.dist)) {
dir(format.dist)
}
// Find all files matching the glob patterns specified in `src`
let _files = fg.sync(format.src)
_files.forEach((file) => {
let filename = path.basename(file);
if (exists(path.resolve(`${format.dist}/${filename.replace('jpg', format.format)}`))) {
return;
}
const image = sharp(file);
// Convert to WebP via Sharp's inferencing automatically of extensions
image
.toFile(`${format.dist}/${filename.replace('jpg', format.format)}`)
.catch((err) => {
console.log(err);
});
});
});
}
export const getResizePatterns = (product, folder) => {
return [{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/80`,
percent: 80,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/60`,
percent: 60,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/40`,
percent: 40,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/20`,
percent: 20,
},
];
}
const resize = (patterns) => {
return patterns.forEach((resize) => {
if (!exists(resize.dist)) {
dir(resize.dist)
}
let _files = fg.sync(resize.src)
_files.forEach((file) => {
let filename = path.basename(file)
const image = sharp(file)
if (exists(`${resize.dist}/${filename}`)) {
return
}
image
.metadata()
.then((metadata) => {
return image
.resize(Math.round(metadata.width * (resize.percent / 100)))
.png()
.toFile(`${resize.dist}/${filename}`)
.catch(logger.error);
})
.catch(logger.error)
})
})
}

257
packages/tasks/src/mail.ts Normal file
View File

@ -0,0 +1,257 @@
import * as path from 'path'
import * as pMap from 'p-map'
import { sync as write } from '@plastichub/fs/write'
import { substitute } from '@plastichub/core'
import { isArray, isObject } from '@plastichub/core/primitives'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { resolve, filesEx } from '@plastichub/osr-commons'
import { test as send } from '@plastichub/osr-mail/lib/nodemailer'
import {
MAIL_LOG_LEVEL,
MAIL_ENV_DEV,
MAIL_LANGUAGES,
MAIL_PROFILE,
MAIL_SOURCE_FILE,
MAIL_SRC_LANGUAGE,
MAIL_TEMPLATE,
MAIL_COMPILE_CACHE,
MAIL_ASSETS_ROOT,
MAIL_I18N_CACHE,
MAIL_DEFAULT_OUTPUT_PATH as SHEET_TRANSLATION_PATH
} from './config'
import { sheetTranslationTask } from './sheets'
import { onCompiledMail } from './mail_utils'
import { gruntOptions } from '../library'
import { ICompileOptions } from './compile'
import { I18N_STORE, OSR_ROOT } from './config'
import { logger } from '../src'
import { getOutputFileName, prepMailQueue } from './mail_utils'
import { mailOptionSchema, enumerateHelpStrings, mailCompileSchema } from './utils'
import { resolveContactsPath, getContacts, filterContacts } from './contacts'
const getSubject = (language: string) => {
const subjectPath = path.resolve(resolve(`${OSR_ROOT()}/products/company/campaign/content/subject-${language}.md`))
if (!exists(subjectPath)) {
logger.error(`Cannot read subject file ${subjectPath}`)
return 'Default Subject'
}
return read(subjectPath) || 'Default Subject'
}
const sendOptions = (grunt, language: string = 'en') => {
const subject = getSubject(language)
return {
from: 'PlasticHub <newsletter@osr-plastic.org>',
transport: 'newsletter',
subject,
contacts: '',
filter: true,
query: null,
to: null,
source: `${OSR_ROOT()}/products/products/assets/newsletter/mail/mail_2024_09_public_${language}.html`,
...gruntOptions(grunt)
}
}
const sendMailQueue = async (grunt) => {
const mailerOptions = sendOptions(grunt, grunt.option('lang') || 'en')
const source = read(path.resolve(resolve(mailerOptions.source)))
if (!source) {
logger.error(`Cannot read source file ${mailerOptions.source}`)
return
}
let contacts = getContacts(mailerOptions)
if (!contacts) {
logger.error(`Invalid contacts: ${resolveContactsPath(mailerOptions)}`)
return
}
if (!isArray(contacts) && isObject(contacts)) {
contacts = Object.keys(contacts).map((k) => contacts[k])
}
const total = contacts.length
contacts = filterContacts(grunt, contacts, mailerOptions)
if (mailerOptions.filter !== false) {
contacts = contacts.filter((contact) => contact.email && contact.email.length > 0)
contacts = contacts.filter((contact) => contact.status !== 'sent')
}
const sendMail = async (contact, options) => {
const subject = getSubject(grunt.option('lang'))
if (!contact.email) {
logger.error(`Invalid contact : ${contact}`)
return
}
logger.info(`Sending mail to ${contact.email}`)
const opts = {
...options,
from: 'Lovebird <newsletter@osr-plastic.org>',
subject: subject,
transport: "newsletter",
to: contact.email,
html: substitute(source, {
unsubscribe_email: contact.email
})
}
const mail = await send(opts)
contact.mail = mail
contact.status = 'sent'
const contactsFile = resolveContactsPath(mailerOptions)
if (mailerOptions.contacts && contactsFile) {
const last = read(contactsFile, 'json')
last[contact.title] = contact
write(contactsFile, last)
}
logger.info(`Sent mail to ${contact.email}`)
return mail
}
if (contacts.length === 0 && mailerOptions.to) {
contacts = [{ email: mailerOptions.to }]
}
if (grunt.option('dry')) {
logger.info(`Dry : Sending ${contacts.length} mails in total, of ${total} contacts`)
return false
} else {
logger.debug(`Sending ${path.resolve(resolve(mailerOptions.source))} to ${contacts.length} mails`)
}
const mails = await pMap(contacts, async (contact) => {
return sendMail(contact, mailerOptions)
}, { concurrency: 1 })
logger.info(`Sent ${mails.length} mails`)
return mails
}
export const getOutputFile = (grunt, root, slug, options = {}, language: string = 'en') => {
const env = grunt.option('env') || MAIL_ENV_DEV
const isDebug = env === MAIL_ENV_DEV
const outFile = getOutputFileName(isDebug, slug, language)
const output = path.resolve(path.join(root, outFile))
return output
}
export const mailCompileOptions = (grunt: any, root, slug, options = {}, language: string = 'en') => {
const template = grunt.option('template') ?
path.resolve(resolve(grunt.option('template'))) : path.join(root, slug, MAIL_TEMPLATE)
const env = grunt.option('env') || MAIL_ENV_DEV
const isDebug = env === MAIL_ENV_DEV
const outFile = getOutputFileName(isDebug, slug, language)
const output = grunt.option('output') ?
path.resolve(resolve(grunt.option('output'))) : path.resolve(path.join(root, outFile))
root = path.join(root, slug)
const onCompiled = async (src, dst, content) => {
const ret = await onCompiledMail(src, dst, content)
if (grunt.option('send') && !grunt.option('contacts')) {
const opts = {
from: 'Lovebird <newsletter@osr-plastic.org>',
to: grunt.option('to') || 'cgoflyn@gmail.com',
html: substitute(ret, {
unsubscribe_email: 'cgoflyn@gmail.com'
}),
subject: `Test Mail : - ${language} : - ` + Math.random(),
transport: "newsletter",
...gruntOptions(grunt)
}
await send(opts)
}
return ret
}
const ret: ICompileOptions = {
cache: MAIL_COMPILE_CACHE,
root,
cwd: root,
env,
format: 'html',
language: 'osr',
logLevel: grunt.option('logLevel') || MAIL_LOG_LEVEL,
module: 'plastichub-mail',
profile: MAIL_PROFILE as any,
template,
output,
// onCompiled: !isDebug || grunt.option('send') ? onCompiled : undefined,
variables: {
cwd: root,
root,
targetLanguage: language as any,
sourceLanguage: MAIL_SRC_LANGUAGE,
i18n: I18N_STORE(OSR_ROOT(), language),
...gruntOptions(grunt)
},
...options,
...gruntOptions(grunt)
}
return ret
}
export const mailSendTask = (grunt, root, directory, options: any = {}, newsletter_tasks) => {
grunt.registerTask(`prepare-mail-contacts`, async () => {
prepMailQueue(grunt, root, directory, options)
})
grunt.registerTask(`send-mail-queue`, "help", async function () {
this.async()
try {
await sendMailQueue(grunt)
} catch (e) {
logger.error(`Error sending mail : ${e.message}`, e.stack)
}
})
if (grunt.option('describe')) {
grunt.registerTask(`send-mail`, () => {
logger.setSettings({
displayFunctionName: false,
displayInstanceName: false,
displayLogLevel: false,
displayLoggerName: false,
displayDateTime: false,
displayFilePath: "hidden"
})
logger.debug(`\nOptions : ${mailOptionSchema._def.description}`)
logger.info(`send mail options: Directory:${directory}`, enumerateHelpStrings(mailOptionSchema, [], logger))
logger.debug(`\nOptions : ${mailCompileSchema(grunt)._def.description}`)
logger.info(`send compile schema options:`, enumerateHelpStrings(mailCompileSchema(grunt), [], logger))
})
return
} else {
grunt.registerTask(`send-mail`, [`mail-tasks`, "send-mail-queue"])
}
}
export const mailTask = (grunt, root, directory, options: any = {}, newsletter_tasks) => {
const mailAssets = filesEx(MAIL_ASSETS_ROOT(), '*-en.xlsx')
const mailAssetTasks = []
const languages: string[] = grunt.option('languages') ? grunt.option('languages').split(',') : MAIL_LANGUAGES
sheetTranslationTask(grunt, 'mail-assets',
mailAssets, languages, mailAssetTasks,
{
dst: SHEET_TRANSLATION_PATH,
cache: MAIL_I18N_CACHE,
query: "$[*][0,1,2,3,4,5]"
})
////////////////////////////////
// Content Compile Tasks
const config = {}
const slug = directory.replace(/\//g, '-')
const extraOptions = {}
const source = grunt.option('source') ?
path.resolve(resolve(grunt.option('source'))) : path.join(root, directory, MAIL_SOURCE_FILE)
languages.forEach((lang) => {
config[`${slug}-${lang}`] = {
src: [source],
options: mailCompileOptions(grunt, root, directory, extraOptions, lang)
}
grunt.extendConfig({ compile: config })
write('./tmp/compile-mail/options.json', config)
grunt.registerTask(`${slug}-${lang}`, [`mail-assets-${lang}`, `compile:${slug}-${lang}`])
newsletter_tasks.push(`compile:${slug}-${lang}`)
})
grunt.registerTask(`mail-tasks`, newsletter_tasks)
}

View File

@ -0,0 +1,85 @@
import * as path from 'path'
import * as juice from 'juice'
import { minify } from 'html-minifier-terser'
import { filesEx } from '@plastichub/osr-commons/_glob'
import { sync as write } from '@plastichub/fs/write'
import * as XLSX from 'xlsx'
import { logger } from '../src'
import { gruntOptions } from '../library'
import {
MAIL_OUTPUT_DIR,
MAIL_OUTPUT_FILE_EXT,
MAIL_OUTPUT_FILE_NAME,
MAIL_OUTPUT_FILE_NAME_PROD,
PRODUCT_ROOT
} from './config'
type TableData = (string | null)[][]
export const prepMailQueue = async (grunt, root, directory, options: any = {},) => {
logger.info(`Sending mail queue from ${directory}`)
const mailRoot = path.join(root, directory)
const mailContentRoot = path.join(mailRoot, 'data')
const contactFiles = filesEx(mailContentRoot, '*.xlsx')
contactFiles.forEach((file) => {
const workbook = XLSX.readFile(file)
const worksheet = workbook.Sheets[workbook.SheetNames[0]]
const raw_data: any[] = XLSX.utils.sheet_to_json(worksheet, { header: 1, blankrows: false, raw: false, skipHidden: false })
const contacts = convertToJSON(raw_data)
const dst = path.join(mailContentRoot, path.parse(file).name + '.json')
logger.info(`Writing contacts from ${file} to ${dst}`)
write(dst, JSON.stringify(contacts, null, 2))
})
}
export const convertToJSON = (data: TableData): object[] => {
const [fields, ...rows] = data;
return rows.map(row => {
const jsonObject: any = {};
row.forEach((value, index) => {
let fieldName = fields[index];
if (fieldName?.toLowerCase().includes('mail')) {
fieldName = 'email';
} else if (fieldName?.toLowerCase().includes('name')) {
fieldName = 'name';
}
jsonObject[fieldName] = value;
});
return jsonObject;
});
}
export const sendOptions = (grunt, root, slug, options = {}, language: string = 'en', contacts) => {
return {
from: 'PlasticHub <newsletter@osr-plastic.org>',
transport: 'newsletter',
subject: 'New Sheetpresses, Extruders, Shredders and Injectors',
contacts,
source: `${PRODUCT_ROOT()}/${MAIL_OUTPUT_DIR}/${MAIL_OUTPUT_FILE_NAME}_public_${language}.html`,
...gruntOptions(grunt)
}
}
export const getOutputFileName = (isDebug: boolean, slug: string, lang: string = 'en') => {
return isDebug ?
`${MAIL_OUTPUT_DIR}/${MAIL_OUTPUT_FILE_NAME}_${lang}${MAIL_OUTPUT_FILE_EXT}` :
`${MAIL_OUTPUT_DIR}/${MAIL_OUTPUT_FILE_NAME_PROD}_${lang}${MAIL_OUTPUT_FILE_EXT}`
}
export const mailDefault = async (content) => {
const options: juice.Options = {}
content = juice(content, options)
content = await minify(content, {
collapseWhitespace: true,
removeComments: true,
minifyCSS: true,
minifyJS: true
})
return content
}
export const onCompiledMail = async (src, dst, content) =>
mailDefault(content)

View File

@ -0,0 +1,49 @@
import * as path from 'path'
import { contentTasks, ICompileOptions, ICompileTaskOptions } from './compile'
import { option } from '../library'
import { logger } from '../src/'
import {
I18N_SOURCE_LANGUAGE,
NEWSLETTER_COMPILE_CACHE,
NEWSLETTER_DEFAULT_ENV,
NEWSLETTER_LOG_LEVEL} from './config'
export const newsletterTasks = (
grunt,
taskPrefix = 'newsletter',
root,
template,
src,
dst,
taskOptions: ICompileTaskOptions = {},
compilerOptions: ICompileOptions = {}
) => {
logger.info(`Registering newsletter tasks for ${taskPrefix}`)
const env = option('env', {}, grunt, NEWSLETTER_DEFAULT_ENV)
const newsletter_tasks = contentTasks(grunt,
{
sourceLanguage: I18N_SOURCE_LANGUAGE,
src: [path.join(root, src)],
taskPrefix,
...taskOptions
},
{
cache: option('cache', {}, grunt, NEWSLETTER_COMPILE_CACHE),
root,
env,
logLevel: option('logLevel', {}, grunt, NEWSLETTER_LOG_LEVEL),
output: dst,
template:path.join(root, template),
variables: {
env,
prefix: env,
root,
targetLanguage: I18N_SOURCE_LANGUAGE,
sourceLanguage: I18N_SOURCE_LANGUAGE
},
...compilerOptions
})
grunt.registerTask(taskPrefix, Object.keys(newsletter_tasks).map((lang: any) => newsletter_tasks[lang].taskName))
return newsletter_tasks
}

290
packages/tasks/src/npm.ts Normal file
View File

@ -0,0 +1,290 @@
import * as semver from 'semver'
import * as child_process from 'child_process'
let DESC = 'Increment the version, commit, tag and push.'
export const register = (grunt) => {
grunt.registerTask('bump', DESC, function(versionType, incOrCommitOnly) {
const opts = this.options({
bumpVersion: true,
commit: true,
commitFiles: ['package.json'], // '-a' for all files
commitMessage: 'Release v%VERSION%',
createTag: true,
dryRun: false,
files: ['package.json'],
gitCommitOptions: '',
gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d',
globalReplace: false,
prereleaseName: false,
metadata: '',
push: true,
pushTo: 'upstream',
regExp: false,
setVersion: false,
tagMessage: 'Version %VERSION%',
tagName: 'v%VERSION%',
updateConfigs: [], // array of config properties to update (with files)
versionType: false
});
if (versionType === 'bump-only' || versionType === 'commit-only') {
incOrCommitOnly = versionType;
versionType = '';
}
versionType = versionType || opts.versionType;
const dryRun = grunt.option('dry-run') || opts.dryRun;
let setVersion = grunt.option('setversion') || opts.setVersion;
if (setVersion && !semver.valid(setVersion)) {
setVersion = false;
}
let globalVersion; // when bumping multiple files
let gitVersion; // when bumping using `git describe`
let VERSION_REGEXP = (typeof opts.regExp === 'function') ? opts.regExp(opts.prereleaseName) : opts.regExp || new RegExp(
'([\'|\"]?version[\'|\"]?[ ]*:[ ]*[\'|\"]?)(\\d+\\.\\d+\\.\\d+(-' +
opts.prereleaseName +
'\\.\\d+)?(-\\d+)?)[\\d||A-a|.|-]*([\'|\"]?)', 'i'
);
if (opts.globalReplace) {
VERSION_REGEXP = new RegExp(VERSION_REGEXP.source, 'gi');
}
const done = this.async();
const queue = [];
const next = function() {
if (!queue.length) {
grunt.config.set('bump.version', globalVersion);
return done();
}
queue.shift()();
};
const runIf = function(condition, behavior) {
if (condition) {
queue.push(behavior);
}
};
if (dryRun) {
grunt.log.writeln('Running grunt-bump in dry mode!');
}
if (incOrCommitOnly === 'bump-only') {
grunt.verbose.writeln('Only incrementing the version.');
opts.commit = false;
opts.createTag = false;
opts.push = false;
}
if (incOrCommitOnly === 'commit-only') {
grunt.verbose.writeln('Only committing/tagging/pushing.');
opts.bumpVersion = false;
}
// GET VERSION FROM GIT
runIf(opts.bumpVersion && versionType === 'git', function() {
child_process.execFile('git describe ' + opts.gitDescribeOptions, function(err, stdout) {
if (err) {
grunt.fatal('Can not get a version number using `git describe`');
}
gitVersion = stdout.trim();
next();
});
});
// BUMP ALL FILES
runIf(opts.bumpVersion, function() {
grunt.file.expand(opts.files).forEach(function(file, idx) {
let version = null;
const content = grunt.file.read(file).replace(
VERSION_REGEXP,
function(match, prefix, parsedVersion, namedPre, noNamePre, suffix) {
const type = versionType === 'git' ? 'prerelease' : versionType;
version = setVersion || semver.inc(
parsedVersion, type || 'patch', gitVersion || opts.prereleaseName
);
if (opts.metadata) {
if (!/^([0-9a-zA-Z-]+\.{0,1})*$/.test(opts.metadata)) {
grunt.fatal(
'Metadata can only contain letters, numbers, dashes ' +
'(-) and dots (.)'
);
}
version += '+' + opts.metadata;
}
return prefix + version + (suffix || '');
}
);
if (!version) {
grunt.fatal('Can not find a version to bump in ' + file);
}
const logMsg = 'Version bumped to ' + version + ' (in ' + file + ')';
if (!dryRun) {
grunt.file.write(file, content);
grunt.log.ok(logMsg);
} else {
grunt.log.ok('bump-dry: ' + logMsg);
}
if (!globalVersion) {
globalVersion = version;
} else if (globalVersion !== version) {
grunt.warn('Bumping multiple files with different versions!');
}
const configProperty = opts.updateConfigs[idx];
if (!configProperty) {
return;
}
const cfg = grunt.config(configProperty);
if (!cfg) {
return grunt.warn(
'Can not update "' + configProperty + '" config, it does not exist!'
);
}
cfg.version = version;
grunt.config(configProperty, cfg);
grunt.log.ok(configProperty + '\'s version updated');
});
next();
});
// when only committing, read the version from package.json / pkg config
runIf(!opts.bumpVersion, function() {
const configVersion = grunt.config.get('bump.version');
if (configVersion) {
globalVersion = configVersion;
}
else if (opts.updateConfigs.length) {
globalVersion = grunt.config(opts.updateConfigs[0]).version;
} else {
globalVersion = grunt.file.readJSON(opts.files[0]).version;
}
next();
});
// COMMIT
runIf(opts.commit, function() {
const commitMessage = opts.commitMessage.replace(
'%VERSION%', globalVersion
);
let cmd = 'git commit ' + opts.gitCommitOptions + ' ' + opts.commitFiles.join(' ');
cmd += ' -m "' + commitMessage + '"';
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd, function(err, stdout, stderr) {
if (err) {
grunt.fatal('Can not create the commit:\n ' + stderr);
}
grunt.log.ok('Committed as "' + commitMessage + '"');
next();
});
}
});
// CREATE TAG
runIf(opts.createTag, function() {
const tagName = opts.tagName.replace('%VERSION%', globalVersion);
const tagMessage = opts.tagMessage.replace('%VERSION%', globalVersion);
const cmd = 'git tag -a ' + tagName + ' -m "' + tagMessage + '"';
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd , function(err, stdout, stderr) {
if (err) {
grunt.fatal('Can not create the tag:\n ' + stderr);
}
grunt.log.ok('Tagged as "' + tagName + '"');
next();
});
}
});
// PUSH CHANGES
runIf(opts.push, function() {
let cmd;
if (opts.push === 'git' && !opts.pushTo) {
cmd = 'git push';
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd, function(err, stdout, stderr) {
if (err) {
grunt.fatal(
'Can not push to the git default settings:\n ' + stderr
);
}
grunt.log.ok('Pushed to the git default settings');
next();
});
}
return;
}
child_process.execFile('git rev-parse --abbrev-ref HEAD', function(err, ref, stderr) {
if (err) {
grunt.fatal('Can not get ref for HEAD:\n' + stderr);
}
cmd = [];
if (opts.push === true || opts.push === 'branch') {
cmd.push('git push ' + opts.pushTo + ' ' + ref.trim());
}
if (opts.createTag && (opts.push === true || opts.push === 'tag')) {
const tagName = opts.tagName.replace('%VERSION%', globalVersion);
cmd.push('git push ' + opts.pushTo + ' ' + tagName);
}
cmd = cmd.join(' && ');
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd, function(err, stdout, stderr) {
if (err) {
grunt.fatal('Can not push to ' + opts.pushTo + ':\n ' + stderr);
}
grunt.log.ok('Pushed to ' + opts.pushTo);
next();
});
}
});
});
next();
});
// ALIASES
DESC = 'Increment the version only.';
grunt.registerTask('bump-only', DESC, function(versionType) {
grunt.task.run('bump:' + (versionType || '') + ':bump-only');
});
DESC = 'Commit, tag, push without incrementing the version.';
grunt.registerTask('bump-commit', DESC, 'bump::commit-only');
}

View File

@ -0,0 +1,93 @@
import { sanitize } from '@plastichub/osr-i18n/_cli'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
import { IOptions as IOptionsI18n } from '@plastichub/osr-i18n/types'
import { translate } from '@plastichub/osr-i18n/lib/translate'
import * as pMap from 'p-map'
import {
I18N_SOURCE_LANGUAGE, I18N_STORE,
MAIL_DEFAULT_OUTPUT_PATH,
OSR_ROOT
} from './config'
import { logger } from '../src'
export const defaultSheetOptions = (srcLang, dstLang, dst: string, logLevel: string, options: {} = {}) => {
const i18nOptions: IOptionsI18n = {
srcLang,
dstLang,
store: I18N_STORE(OSR_ROOT(), dstLang),
dst,
cache: true,
logLevel,
...options
}
return i18nOptions
}
export const translateSheets = async (
languages: string[],
files: string[],
srcLang: string,
dstLanguage: string,
query: string = "$[*][0,1,2,3,4]",
dst: string = MAIL_DEFAULT_OUTPUT_PATH,
logLevel = 'info',
options: any = {}) => {
const config: any = CONFIG_DEFAULT()
if (dstLanguage === I18N_SOURCE_LANGUAGE) {
return
}
return await pMap(languages, async (dstLanguage) => {
return await pMap(files, async (src) => {
const i18nOptions: IOptionsI18n = {
srcLang: srcLang,
dstLang: dstLanguage,
src: src,
store: I18N_STORE(OSR_ROOT(), dstLanguage),
dst: dst,
query: query,
cache: true,
api_key: config.deepl.auth_key,
logLevel: logLevel,
...options
}
logger.debug('Translate Sheet ' + src + ' ' + dstLanguage, i18nOptions)
const ret = await translate(sanitize(i18nOptions) as any)
return ret
})
})
}
export const sheetTranslationTask = (grunt, slug: string, files: string[], languages: string[], translationTasks: string[], options: {} = {}) => {
const config = {}
const key: any = (CONFIG_DEFAULT() as any).deepl.auth_key
languages.forEach((lang: string) => {
config[`${slug}-${lang}`] = {
src: files,
options: defaultSheetOptions(I18N_SOURCE_LANGUAGE, lang, `${OSR_ROOT()}/content/${lang}`, 'warn', { api_key: key, ...options })
}
grunt.extendConfig({ i18n: config })
grunt.registerTask(`${slug}-${lang}`, `i18n:${slug}-${lang}`)
translationTasks.push(`i18n:${slug}-${lang}`)
})
grunt.registerTask(`${slug}-tasks`, translationTasks)
}
export const register = (grunt) => {
grunt.registerMultiTask('sheets-i18n', 'Translate Sheets ', async function () {
const done = this.async()
const task_options = this.data.options
// const cwd = path.resolve(option('cwd', task_options, grunt, process.cwd()))
return new Promise((resolve) => {
if (!task_options.watchContent) {
resolve(true)
done()
}
})
})
}

View File

@ -0,0 +1,156 @@
import { Client } from 'ssh2'
import { isArray } from '@plastichub/core/primitives'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons/config'
import { logger } from '../src'
import { option } from '../library'
const parseConnectionOptions = function (options: any) {
const connectionOptions: any = {
host: options.host,
port: options.port,
username: options.user,
readyTimeout: options.readyTimeout,
agentForward: options.agentForward
}
if (options.privateKey) {
connectionOptions.privateKey = options.privateKey.trim();
if (options.passphrase) {
connectionOptions.passphrase = options.passphrase.trim();
}
}
else if (options.password) {
connectionOptions.password = options.password;
if (options.agent) {
connectionOptions.agent = options.agent;
}
} else {
connectionOptions.agent = options.agent;
}
return connectionOptions
}
const exce = async (commands: string[], options: any) => {
return new Promise((resolve, reject) => {
const c = new Client()
const { debug, verbose } = options
c.on('keyboard-interactive', function () {
const prompts = arguments[3]
const reply = arguments[4]
prompts.forEach(function (question) {
const msg = question.prompt.toLowerCase()
if (msg.indexOf('password') !== -1) {
reply([options.password])
}
})
})
c.on('connect', () => logger.info('Connection :: connect'))
c.on('ready', () => {
logger.info('Connection :: ready')
execCommand()
})
c.on('error', (err) => logger.error('Connection :: error :: ' + err) && resolve(false))
c.on('end', () => logger.info('Connection :: end') && resolve(false))
const execCommand = () => {
if (commands.length === 0) {
c.end()
} else {
const command = commands.shift()
logger.info('Executing :: ' + command)
c.exec(command, options, function (err, stream) {
if (err) {
reject(err)
}
let out
stream.on('data', (data, extended) => {
out = String(data);
if (extended === 'stderr') {
if (!options.suppressRemoteErrors) {
logger.warn(out);
}
else {
logger.warn(out);
}
} else {
logger.info(out)
}
})
stream.on('end', () => {
resolve(out)
})
stream.on('close', (code, signal) => {
debug && logger.info('Stream :: close :: code: ' + code + ', signal: ' + signal)
if (!options.ignoreErrors && code !== 0) {
logger.error('Error executing task ' + command, code, signal)
c.end()
reject({ signal, code })
} else {
execCommand()
}
})
})
}
}
const connectionOptions = parseConnectionOptions(options)
connectionOptions.tryKeyboard = true;
const proxyHost = (options.proxy || {}).host
if (proxyHost) {
const proxyConnectionOptions = parseConnectionOptions(options.proxy)
const proxyConnection = new Client()
proxyConnection.on('connect', function () {
logger.info('Proxy connection :: connect')
})
proxyConnection.on('error', function (err) {
logger.error('Proxy connection :: error :: ' + err)
})
proxyConnection.on('ready', function () {
logger.info('Proxy connection :: ready')
proxyConnection.exec('nc ' + connectionOptions.host + ' ' + connectionOptions.port, function (err, stream) {
if (err) {
proxyConnection.end()
reject(err)
}
connectionOptions.sock = stream;
c.connect(connectionOptions)
})
})
proxyConnection.connect(proxyConnectionOptions)
}
else {
c.connect(connectionOptions)
}
})
}
export const register = (grunt) => {
grunt.registerMultiTask('sshexec', 'Runs commands on SSH', async function () {
let done = this.async()
const task_options = this.data || {}
const sshConfig = (CONFIG_DEFAULT() as any || {}).ssh || {}
const opts = {
...sshConfig,
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
port: option('port', task_options, grunt, sshConfig.port),
host: option('host', task_options, grunt, sshConfig.host),
user: option('user', task_options, grunt, sshConfig.user),
password: option('password', task_options, grunt, sshConfig.password),
logLevel: option('logLevel', task_options, grunt,'warn')
}
logger.setSettings({ minLevel: opts.logLevel })
logger.info('Git - task data ', this.data)
let commands: string[] = isArray(this.data.commands) ? this.data.commands : [this.data.commands]
const ret = await exce(commands, opts)
logger.info(`Exce : ${[this.data.command].join('\n')} : `, ret)
done()
})
}

View File

@ -0,0 +1,37 @@
import { isArray } from '@plastichub/core/primitives'
import { sync } from '@plastichub/osr-sync/lib/sync'
import { resolve } from '@plastichub/osr-commons'
import { option } from '../library'
import { logger } from '../src'
export const register = (grunt) => {
grunt.registerMultiTask('sync', 'Synchronizes folders, using osr-sync', function () {
const done = this.async()
const task_options = this.data || {}
let source: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
const variables = { ...task_options.variables || {} }
logger.setSettings({ minLevel: option('logLevel', task_options, grunt, 'warn') })
source = source.map(f => resolve(f, false, variables))
const options = {
source,
target: resolve(option('target', task_options, grunt), variables),
root: option('root', task_options, grunt),
clear: option('clear', task_options, grunt),
debug: false,
verbose: false,
//debug: option('debug', task_options, grunt),
//verbose: option('verbose', task_options, grunt, false),
profile: option('profile', task_options, grunt),
logLevel: option('logLevel', task_options, grunt, 'warn'),
variables: variables
}
try {
sync(options)
} catch (e) {
logger.error(`Error while syncing : ${source.join('\n')} : ${e.messsage}`, e)
}
done()
return true
})
}

186
packages/tasks/src/utils.ts Normal file
View File

@ -0,0 +1,186 @@
import { z, ZodObject, ZodTypeAny } from "zod"
import { MAIL_SOURCE_FILE } from "./config"
export const cleanArray = (arr: any[]): any[] => {
// Use a Set to eliminate duplicates
const uniqueItems = Array.from(new Set(arr.map(item => JSON.stringify(item))))
.map(item => JSON.parse(item))
return uniqueItems.filter(item => {
if (Array.isArray(item)) {
return item.length > 0; // Exclude empty arrays
} else if (typeof item === 'object' && item !== null) {
return Object.keys(item).length > 0; // Exclude empty objects
} else if (typeof item === 'string') {
// Remove URL parameters from strings
return item
}
return true; // Keep other types (e.g., numbers, etc.)
}).map(item => {
// Apply the URL cleanup on strings if they haven't been filtered out
if (typeof item === 'string') {
return item
}
return item
})
}
export const mailOptionSchema = z.object({
from: z
.string()
.default("'PlasticHub-Barcelona <newsletter@osr-plastic.org>'")
.describe("The sender email address formatted as a string."),
transport: z
.string()
.default("newsletter")
.describe("The transport profile, e.g., 'newsletter'."),
subject: z
.string()
.default("Mejora tu Carpintería: Prensas de Planchas, Extrusoras e Inyectores para Procesamiento de Plástico")
.describe("The subject of the email being sent."),
contacts: z
.string()
.default("${OSR_ROOT}/osr-directory/meta/index.json")
.describe("Path to the contacts directory or file."),
filter: z
.boolean()
.default(true)
.describe("Indicates whether a filter should be applied: true filters out already sent emails."),
query: z
.string()
.default("QT_CARPENTERS_SPAIN_ALL_EMAIL")
.describe("The query string used to select recipients. From profile or string"),
to: z
.string()
.nullable()
.default(null)
.describe("Optional recipient address; can be null if not specified."),
send: z
.boolean()
.default(true)
.describe("Indicates whether the email should be sent."),
dry: z
.boolean()
.default(false)
.describe("For testing purposes"),
logLevel: z
.string()
.default("debug")
.describe("The level of logging detail, e.g., 'debug', 'info', 'error'.")
}, { description: "Options for sending an email." })
export const compileVariablesSchema = (grunt) => z.object({
cwd: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The current working directory for the process."),
root: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The root directory for the project."),
targetLanguage: z
.string()
.default("es")
.describe("The target language code for the output."),
sourceLanguage: z
.string()
.default("en")
.describe("The source language code for the input."),
i18n: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr/i18n-store/store-es.json")
.describe("The path to the internationalization (i18n) store file.")
});
export const mailCompileSchema = (grunt) => z.object({
cache: z
.boolean()
.default(false)
.describe("Indicates whether caching is enabled."),
cwd: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The current working directory for the process."),
env: z
.string()
.default("hugo-release")
.describe("The environment for the process, e.g., 'hugo-release'."),
format: z
.string()
.default("html")
.describe("The format of the output file."),
language: z
.string()
.default("osr")
.describe("The language code or identifier used for processing."),
logLevel: z
.string()
.default("debug")
.describe("The level of logging detail, e.g., 'debug', 'info', 'error'."),
module: z
.string()
.default("plastichub-mail")
.describe("The module being used for the process."),
profile: z
.string()
.default("${OSR_ROOT}/osr-templates/osrl/.osrl.json")
.describe("The path to the profile configuration file."),
root: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The root directory for the project."),
sourceLanguage: z
.string()
.default("en")
.describe("The source language code for the input."),
targetLanguage: z
.string()
.default("en")
.describe("The target language code for the output."),
template: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08\\root.osr")
.describe("The path to the template file being used."),
output: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\products\\assets\\newsletter\\mail\\mail_2024_09_public_es.html")
.describe("The path to the output file."),
source: z
.string()
.default(MAIL_SOURCE_FILE || grunt.option('source'))
.describe("The path to the source file."),
variables: compileVariablesSchema(grunt).describe("An object containing variable paths and language codes for processing.")
})
export const enumerateHelpStrings = (schema: ZodTypeAny, path: string[] = [], logger: any): void => {
if (schema instanceof ZodObject) {
for (const key in schema.shape) {
const nestedSchema = schema.shape[key];
enumerateHelpStrings(nestedSchema, [...path, key], logger)
}
} else {
const description = schema._def.description
const fieldDef = schema._def
const innerType = fieldDef.innerType
let type: 'string' | 'boolean' | 'number' | undefined
if (innerType._def.typeName === 'ZodString') {
type = 'string'
} else if (innerType._def.typeName === 'ZodBoolean') {
type = 'boolean'
} else if (innerType._def.typeName === 'ZodNumber') {
type = 'number'
}
let defaultValue = fieldDef.defaultValue
defaultValue = defaultValue !== undefined ? defaultValue() : undefined
if (type === 'boolean') {
defaultValue = defaultValue === 'true'
}
if (description) {
logger.debug(`\t ${path.join('.')}: ${description} \t Default: ${defaultValue}`)
}
}
}

View File

@ -14259,7 +14259,6 @@
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz",
"integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"orderedmap": "^2.0.0" "orderedmap": "^2.0.0"
} }
@ -14293,7 +14292,6 @@
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"prosemirror-model": "^1.0.0", "prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0", "prosemirror-transform": "^1.0.0",
@ -14327,7 +14325,6 @@
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.5.tgz", "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.5.tgz",
"integrity": "sha512-UDQbIPnDrjE8tqUBbPmCOZgtd75htE6W3r0JCmY9bL6W1iemDM37MZEKC49d+tdQ0v/CKx4gjxLoLsfkD2NiZA==", "integrity": "sha512-UDQbIPnDrjE8tqUBbPmCOZgtd75htE6W3r0JCmY9bL6W1iemDM37MZEKC49d+tdQ0v/CKx4gjxLoLsfkD2NiZA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"prosemirror-model": "^1.20.0", "prosemirror-model": "^1.20.0",
"prosemirror-state": "^1.0.0", "prosemirror-state": "^1.0.0",