From 898c283697b4c0a9b3f1f42a0fdcae817ceb7dcd Mon Sep 17 00:00:00 2001 From: Didier Garcia Date: Fri, 28 Jul 2023 18:06:04 -0400 Subject: [PATCH 1/9] Make changes required for OSS. Add a LICENSE.md file, Add CONTRIBUTING.md file, and add copyright to main file (main.swift). (#7) --- CONTRIBUTING.md | 5 +++++ LICENSE.md | 21 +++++++++++++++++++++ Sources/segmentcli/main.swift | 2 ++ 3 files changed, 28 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f376ca6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,5 @@ +*Contributing* + +**All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. ** + + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..908a220 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Twilio inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Sources/segmentcli/main.swift b/Sources/segmentcli/main.swift index a297cb8..474b5bd 100644 --- a/Sources/segmentcli/main.swift +++ b/Sources/segmentcli/main.swift @@ -1,3 +1,5 @@ +// Copyright 2021 Twilio Inc. + import Foundation import SwiftCLI From e6014a76a527722358b71bd9f77c1356dcd34ae7 Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Fri, 28 Jul 2023 15:34:37 -0700 Subject: [PATCH 2/9] Dependency changes for analytics live. (#8) * Dependency changes for analytics live. * Added makefile --- Makefile | 35 ++++++++++++++++++++++ Package.resolved | 34 ++++++++++----------- Package.swift | 8 ++--- Sources/segmentcli/Utilities/Runtime.swift | 2 +- 4 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b052e91 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +SHELL = /bin/bash + +prefix ?= /usr/local +bindir ?= $(prefix)/bin +libdir ?= $(prefix)/lib +srcdir = Sources + +REPODIR = $(shell pwd) +BUILDDIR = $(REPODIR)/.build +SOURCES = $(wildcard $(srcdir)/**/*.swift) + +.DEFAULT_GOAL = all + +segmentcli: $(SOURCES) + @swift build \ + -c release \ + --disable-sandbox \ + --build-path "$(BUILDDIR)" + +.PHONY: install +install: segmentcli + @install -d "$(bindir)" + @install "$(wildcard $(BUILDDIR)/**/release/segmentcli)" "$(bindir)" + +.PHONY: uninstall +uninstall: + @rm -rf "$(bindir)/segmentcli" + +.PHONY: clean +distclean: + @rm -f $(BUILDDIR)/release + +.PHONY: clean +clean: distclean + @rm -rf $(BUILDDIR) diff --git a/Package.resolved b/Package.resolved index 6f927d8..f071e93 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,9 +5,18 @@ "package": "Segment", "repositoryURL": "https://github.com/segmentio/analytics-swift.git", "state": { - "branch": "bsneed/cli_additions", - "revision": "f778e2e9c19f4e3052317c5af26a4897ef77cc86", - "version": null + "branch": null, + "revision": "c8fd5fdf59299f00b3e4303a1b12a6d88893bf56", + "version": "1.4.7" + } + }, + { + "package": "AnalyticsLive", + "repositoryURL": "git@github.com:segment-integrations/analytics-swift-live.git", + "state": { + "branch": null, + "revision": "3b07681d498595aa8e06cd814003db53661abb88", + "version": "0.2.3" } }, { @@ -28,15 +37,6 @@ "version": "1.6.0" } }, - { - "package": "EdgeFn", - "repositoryURL": "git@github.com:segmentio/EdgeFn-Swift.git", - "state": { - "branch": "main", - "revision": "9e7fe14e458148a8e86ac56e85d52bc13d595288", - "version": null - } - }, { "package": "mustache", "repositoryURL": "https://github.com/AlwaysRightInstitute/Mustache", @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/segmentio/Sovran-Swift.git", "state": { "branch": null, - "revision": "944c17d7c46bd95fc37f09136cabd172be5b413b", - "version": "1.0.3" + "revision": "64f3b5150c282a34af4578188dce2fd597e600e3", + "version": "1.1.0" } }, { @@ -95,9 +95,9 @@ "package": "Substrata", "repositoryURL": "git@github.com:segmentio/substrata-swift.git", "state": { - "branch": "main", - "revision": "079da728865b9933d41466c588bbc3079ee1ee66", - "version": null + "branch": null, + "revision": "a673d773d0a6dab86a31cadcb771b45022e0c5ac", + "version": "0.0.2" } }, { diff --git a/Package.swift b/Package.swift index 078d52b..f8a770c 100644 --- a/Package.swift +++ b/Package.swift @@ -12,12 +12,12 @@ let package = Package( .package(url: "https://github.com/jakeheis/SwiftCLI", from: "6.0.0"), .package(url: "https://github.com/dominicegginton/Spinner", from: "1.1.4"), .package(url: "https://github.com/mtynior/ColorizeSwift.git", from: "1.5.0"), - .package(url: "https://github.com/segmentio/analytics-swift.git", branch: "bsneed/cli_additions"), + .package(url: "https://github.com/segmentio/analytics-swift.git", from: "1.4.7"), .package(url: "https://github.com/swiftcsv/SwiftCSV.git", from: "0.6.1"), .package(url: "https://github.com/AlwaysRightInstitute/Mustache", from: "1.0.0"), .package(url: "https://github.com/antitypical/Result.git", from: "5.0.0"), - .package(url: "git@github.com:segmentio/EdgeFn-Swift.git", branch: "main"), - .package(url: "git@github.com:segmentio/substrata-swift.git", branch: "main") + .package(url: "git@github.com:segment-integrations/analytics-swift-live.git", from: "0.2.3"), + .package(url: "git@github.com:segmentio/substrata-swift.git", from: "0.0.2") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. @@ -30,7 +30,7 @@ let package = Package( "SwiftCSV", "Result", .product(name: "Substrata", package: "substrata-swift"), - .product(name: "EdgeFn", package: "EdgeFn-Swift"), + .product(name: "AnalyticsLive", package: "analytics-swift-live"), .product(name: "mustache", package: "Mustache"), .product(name: "Segment", package: "analytics-swift")]), .testTarget( diff --git a/Sources/segmentcli/Utilities/Runtime.swift b/Sources/segmentcli/Utilities/Runtime.swift index a75a5f1..0291272 100644 --- a/Sources/segmentcli/Utilities/Runtime.swift +++ b/Sources/segmentcli/Utilities/Runtime.swift @@ -9,7 +9,7 @@ import Foundation import Segment import Substrata import SwiftCLI -import EdgeFn +import AnalyticsLive var engine = JSEngine() From 935a2ec4984bcfed83ec0a036319e5b614e8062c Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Fri, 28 Jul 2023 15:42:06 -0700 Subject: [PATCH 3/9] EdgeFn to LivePlugin refactor --- .../{EdgeFn.swift => LivePlugins.swift} | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) rename Sources/segmentcli/Commands/{EdgeFn.swift => LivePlugins.swift} (90%) diff --git a/Sources/segmentcli/Commands/EdgeFn.swift b/Sources/segmentcli/Commands/LivePlugins.swift similarity index 90% rename from Sources/segmentcli/Commands/EdgeFn.swift rename to Sources/segmentcli/Commands/LivePlugins.swift index c833176..0e56bcd 100644 --- a/Sources/segmentcli/Commands/EdgeFn.swift +++ b/Sources/segmentcli/Commands/LivePlugins.swift @@ -12,22 +12,22 @@ import ColorizeSwift import Segment class EdgeFnGroup: CommandGroup { - let name = "edgefn" - let shortDescription = "Work with and develop edge functions" + let name = "liveplugins" + let shortDescription = "Work with and develop analytics live plugins" let children: [Routable] = [EdgeFnLatestCommand(), EdgeFnUpload(), EdgeFnDisable()] init() {} } class EdgeFnDisable: Command { let name = "disable" - let shortDescription = "Disable edge functions for a given source ID" + let shortDescription = "Disable Live Plugins for a given source ID" @Param var sourceId: String func execute() throws { guard let workspace = currentWorkspace else { exitWithError(code: .commandFailed, message: "No authentication tokens found."); return } executeAndWait { semaphore in - let spinner = Spinner(.dots, "Uploading edge function ...") + let spinner = Spinner(.dots, "Uploading live plugin ...") spinner.start() PAPI.shared.edgeFunctions.disable(token: workspace.token, sourceId: sourceId) { data, response, error in @@ -42,14 +42,14 @@ class EdgeFnDisable: Command { switch statusCode { case .ok: // success! - print("Edge functions disabled for \(self.sourceId.italic.bold).") + print("Live plugins disabled for \(self.sourceId.italic.bold).") case .unauthorized: fallthrough case .unauthorized2: exitWithError(code: .commandFailed, message: "Supplied token is not authorized.") case .notFound: - exitWithError(code: .commandFailed, message: "No edge functions were found.") + exitWithError(code: .commandFailed, message: "No live plugins were found.") default: exitWithError("An unknown error occurred.") } @@ -62,7 +62,7 @@ class EdgeFnDisable: Command { class EdgeFnUpload: Command { let name = "upload" - let shortDescription = "Upload an edge function" + let shortDescription = "Upload a Live Plugin" @Param var sourceId: String @Param var filePath: String @@ -102,7 +102,7 @@ class EdgeFnUpload: Command { case .unauthorized2: exitWithError(code: .commandFailed, message: "Supplied token is not authorized.") case .notFound: - exitWithError(code: .commandFailed, message: "No edge functions were found.") + exitWithError(code: .commandFailed, message: "No live plugins were found.") default: exitWithError("An unknown error occurred.") } @@ -134,7 +134,7 @@ class EdgeFnUpload: Command { case .unauthorized2: exitWithError(code: .commandFailed, message: "Supplied token is not authorized.") case .notFound: - exitWithError(code: .commandFailed, message: "No edge functions were found.") + exitWithError(code: .commandFailed, message: "No live plugins were found.") default: exitWithError("An unknown error occurred.") } @@ -144,7 +144,7 @@ class EdgeFnUpload: Command { // call create to make a new connection to the version we just posted. executeAndWait { semaphore in - let spinner = Spinner(.dots, "Creating new edge function version ...") + let spinner = Spinner(.dots, "Creating new live plugin version ...") spinner.start() PAPI.shared.edgeFunctions.createNewVersion(token: workspace.token, sourceId: sourceId, uploadURL: uploadURL) { data, response, error in @@ -170,7 +170,7 @@ class EdgeFnUpload: Command { case .unauthorized2: exitWithError(code: .commandFailed, message: "Supplied token is not authorized.") case .notFound: - exitWithError(code: .commandFailed, message: "No edge functions were found.") + exitWithError(code: .commandFailed, message: "No live plugins were found.") default: exitWithError("An unknown error occurred.") } @@ -183,7 +183,7 @@ class EdgeFnUpload: Command { class EdgeFnLatestCommand: Command { let name = "latest" - let shortDescription = "Get info about the latest Edge Function in use" + let shortDescription = "Get info about the latest Live Plugin in use" @Param var sourceId: String @@ -191,7 +191,7 @@ class EdgeFnLatestCommand: Command { guard let workspace = currentWorkspace else { exitWithError(code: .commandFailed, message: "No authentication tokens found."); return } executeAndWait { semaphore in - let spinner = Spinner(.dots, "Retrieving latest Edge Functino info ...") + let spinner = Spinner(.dots, "Retrieving latest Live Plugin info ...") spinner.start() PAPI.shared.edgeFunctions.latest(token: workspace.token, sourceId: sourceId) { data, response, error in @@ -217,7 +217,7 @@ class EdgeFnLatestCommand: Command { case .unauthorized2: exitWithError(code: .commandFailed, message: "Supplied token is not authorized.") case .notFound: - exitWithError(code: .commandFailed, message: "No edge functions were found.") + exitWithError(code: .commandFailed, message: "No live plugins were found.") default: exitWithError("An unknown error occurred.") } From e3a9bb49850ecee504fa5a1548cbd4e0c1a3e0ff Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Mon, 14 Aug 2023 10:42:26 -0700 Subject: [PATCH 4/9] Adding JIRA action yml --- .github/workflows/create_jira.yml | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/create_jira.yml diff --git a/.github/workflows/create_jira.yml b/.github/workflows/create_jira.yml new file mode 100644 index 0000000..8180ac0 --- /dev/null +++ b/.github/workflows/create_jira.yml @@ -0,0 +1,39 @@ +name: Create Jira Ticket + +on: + issues: + types: + - opened + +jobs: + create_jira: + name: Create Jira Ticket + runs-on: ubuntu-latest + environment: IssueTracker + steps: + - name: Checkout + uses: actions/checkout@master + - name: Login + uses: atlassian/gajira-login@master + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_TOKEN }} + JIRA_EPIC_KEY: ${{ secrets.JIRA_EPIC_KEY }} + JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }} + + - name: Create + id: create + uses: atlassian/gajira-create@master + with: + project: ${{ secrets.JIRA_PROJECT }} + issuetype: Bug + summary: | + [${{ github.event.repository.name }}] (${{ github.event.issue.number }}): ${{ github.event.issue.title }} + description: | + Github Link: ${{ github.event.issue.html_url }} + ${{ github.event.issue.body }} + fields: '{"parent": {"key": "${{ secrets.JIRA_EPIC_KEY }}"}}' + + - name: Log created issue + run: echo "Issue ${{ steps.create.outputs.issue }} was created" \ No newline at end of file From 536d57668b51a6edf4740dbeacba5b57531207b6 Mon Sep 17 00:00:00 2001 From: Didier Garcia Date: Mon, 22 Jan 2024 18:03:15 -0500 Subject: [PATCH 5/9] Updating README. (#9) --- README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fac97b7..ef0cbd8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,81 @@ -# segmentcli +# Segment CLI + +The Segment CLI (segmentcli) is a command line utility used to work with Analytics +Live Plugins in your Segment work space. + +```bash +Usage: segmentcli [options] + +A command line utility to interact with and drive Segment + +Groups: + profile Work with stored profiles on this device + analytics Send custom crafted events to Segment + liveplugins Work with and develop analytics live plugins + sources View and edit workspace sources + +Commands: + auth Authenticate with Segment.com and assign a profile name + import Import CSV data into Segment from + scaffold Create baseline implementation of a given code artifact + repl Segment virtual development environment + help Prints help information + version Prints the current version of this app +``` + +## Getting Started + +In order to use the segmentcli to work with your workspace you must have the +Analytics Live Plugins featured enabled in your workspace and you must +authenticate with that workspace. + +### Enabling the Analytics Live Plugins feature + +Reach out to your Customer Support Engineer (CSE) or Customer Success Manager (CSM) +to have them add this feature to your account. + +The command to authenticate is as follows: + +```bash +$ segmentcli auth +``` + +`ProfileName` - is the name you give to this workspace so you can distinguish +between various local profiles. + +`AuthToken` - is the AuthToken associated with your workspace. You must create +an Auth token in your Segment workspace. + +### Creating an Auth Token + +1. Log into https://app.segment.com +1. Navigate to Settings > Workspace Settings > Access Management > Tokens +1. Generate a new token using the "Create token" button with the Workspace Owner role. + +## Uploading Your Analytics Live Plugins to Your Workspace + +In order to upload your Analytics Live Plugins you'll need the following command: + +```bash +$ segmentcli upload +``` + +`SourceId` - This is listed next your Write Key in the Segment app. +`FileName` - The name of the JavaScript file containing your code. + +Note: It will take a few minutes for your Source's setting payload to be update +with the Analytics Live Plugin file URL. + +### Finding Your SourceID + +1. Log into https://app.segment.com +1. Navigate to Connections > Sources +1. Choose the source for which we're adding Analytics Live Plugins +1. Navigate to Settings > API Keys +1. You'll find the "Source ID" at the top of the page. + + +## References + +Learn more about Analytics Live Plugins for [Swift](https://github.com/segment-integrations/analytics-swift-live) and [Kotlin](https://github.com/segment-integrations/analytics-swift-live). -A description of this package. From f4e3655cb32af6366bab339c5664680d8d343506 Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Wed, 3 Apr 2024 15:45:02 -0700 Subject: [PATCH 6/9] Added support for staging. --- Sources/segmentcli/Commands/Profile.swift | 1 - Sources/segmentcli/PAPI/PAPI.swift | 17 ++++++++++++++++- Sources/segmentcli/main.swift | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Sources/segmentcli/Commands/Profile.swift b/Sources/segmentcli/Commands/Profile.swift index 03db41b..bb4baa3 100644 --- a/Sources/segmentcli/Commands/Profile.swift +++ b/Sources/segmentcli/Commands/Profile.swift @@ -77,7 +77,6 @@ class ProfileSetCommand: Command { } // MARK: - Global option for profile - let specifiedProfileKey = Key("-p", "--profile", description: "Specify a profile name to use for this operation") extension Command { var specifiedProfile: String? { diff --git a/Sources/segmentcli/PAPI/PAPI.swift b/Sources/segmentcli/PAPI/PAPI.swift index 21ad07f..2275b80 100644 --- a/Sources/segmentcli/PAPI/PAPI.swift +++ b/Sources/segmentcli/PAPI/PAPI.swift @@ -6,8 +6,15 @@ // import Foundation +import SwiftCLI -let PAPIEndpoint: String = "https://api.segmentapis.com/" +var PAPIEndpoint: String { + if useStagingKey.value { + return "https://api.segmentapis.build/" + } else { + return "https://api.segmentapis.com/" + } +} protocol PAPISection { static var pathEntry: String { get } @@ -53,3 +60,11 @@ class PAPI { } } + +// MARK: - Global option to support staging +let useStagingKey = Flag("--staging", description: "Use Segment staging for operations") +extension Command { + var isStaging: Bool { + return useStagingKey.value + } +} diff --git a/Sources/segmentcli/main.swift b/Sources/segmentcli/main.swift index 474b5bd..0d36ddd 100644 --- a/Sources/segmentcli/main.swift +++ b/Sources/segmentcli/main.swift @@ -18,6 +18,7 @@ func main() { SourcesGroup() ]) + segment.globalOptions.append(useStagingKey) segment.globalOptions.append(specifiedProfileKey) segment.go() From 951f19473747bed8a9049d75226fd8fe6c56b915 Mon Sep 17 00:00:00 2001 From: dsjackins Date: Thu, 25 Jul 2024 11:54:50 -0600 Subject: [PATCH 7/9] Update README.md (#10) * Update README.md * Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef0cbd8..48c8bc4 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,18 @@ In order to use the segmentcli to work with your workspace you must have the Analytics Live Plugins featured enabled in your workspace and you must authenticate with that workspace. +### Installation + +Run this command to install segmentcli locally from the repo: +```bash +$ sudo make install +``` + +or, using brew: +```bash +$ brew install segment-integrations/formulae/segmentcli +``` + ### Enabling the Analytics Live Plugins feature Reach out to your Customer Support Engineer (CSE) or Customer Success Manager (CSM) @@ -57,7 +69,7 @@ an Auth token in your Segment workspace. In order to upload your Analytics Live Plugins you'll need the following command: ```bash -$ segmentcli upload +$ segmentcli liveplugins upload ``` `SourceId` - This is listed next your Write Key in the Segment app. From c6f6614e0ca6a1f41ac54f5900cfd6c093813ca3 Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Fri, 9 May 2025 16:05:01 -0700 Subject: [PATCH 8/9] Updated to latest Analytics Live + Substrata. --- .github/workflows/build.yml | 0 .github/workflows/create_jira.yml | 0 .github/workflows/release.yml | 0 .gitignore | 0 .../xcschemes/segmentcli.xcscheme | 0 CONTRIBUTING.md | 0 LICENSE.md | 0 Makefile | 0 Package.resolved | 29 +++++++---- Package.swift | 8 ++-- README.md | 28 ++++++++--- Sources/segmentcli/Commands/Analytics.swift | 0 Sources/segmentcli/Commands/Auth.swift | 0 Sources/segmentcli/Commands/Import.swift | 0 Sources/segmentcli/Commands/LivePlugins.swift | 0 Sources/segmentcli/Commands/Profile.swift | 0 Sources/segmentcli/Commands/REPL.swift | 0 Sources/segmentcli/Commands/Scaffold.swift | 0 Sources/segmentcli/Commands/Sources.swift | 0 Sources/segmentcli/JS Additions/csvJS.swift | 48 ++++++++----------- Sources/segmentcli/PAPI/PAPI.swift | 0 .../segmentcli/PAPI/PAPIEdgeFunctions.swift | 0 Sources/segmentcli/PAPI/PAPISources.swift | 0 .../segmentcli/Templates/CSVImporterJS.swift | 0 .../segmentcli/Templates/PluginSwift.swift | 0 Sources/segmentcli/Utilities/Misc.swift | 2 + Sources/segmentcli/Utilities/Runtime.swift | 35 +++----------- Sources/segmentcli/Utilities/Settings.swift | 0 Sources/segmentcli/main.swift | 0 Tests/segmentcliTests/segmentcliTests.swift | 0 30 files changed, 73 insertions(+), 77 deletions(-) mode change 100644 => 100755 .github/workflows/build.yml mode change 100644 => 100755 .github/workflows/create_jira.yml mode change 100644 => 100755 .github/workflows/release.yml mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .swiftpm/xcode/xcshareddata/xcschemes/segmentcli.xcscheme mode change 100644 => 100755 CONTRIBUTING.md mode change 100644 => 100755 LICENSE.md mode change 100644 => 100755 Makefile mode change 100644 => 100755 Package.resolved mode change 100644 => 100755 Package.swift mode change 100644 => 100755 README.md mode change 100644 => 100755 Sources/segmentcli/Commands/Analytics.swift mode change 100644 => 100755 Sources/segmentcli/Commands/Auth.swift mode change 100644 => 100755 Sources/segmentcli/Commands/Import.swift mode change 100644 => 100755 Sources/segmentcli/Commands/LivePlugins.swift mode change 100644 => 100755 Sources/segmentcli/Commands/Profile.swift mode change 100644 => 100755 Sources/segmentcli/Commands/REPL.swift mode change 100644 => 100755 Sources/segmentcli/Commands/Scaffold.swift mode change 100644 => 100755 Sources/segmentcli/Commands/Sources.swift mode change 100644 => 100755 Sources/segmentcli/JS Additions/csvJS.swift mode change 100644 => 100755 Sources/segmentcli/PAPI/PAPI.swift mode change 100644 => 100755 Sources/segmentcli/PAPI/PAPIEdgeFunctions.swift mode change 100644 => 100755 Sources/segmentcli/PAPI/PAPISources.swift mode change 100644 => 100755 Sources/segmentcli/Templates/CSVImporterJS.swift mode change 100644 => 100755 Sources/segmentcli/Templates/PluginSwift.swift mode change 100644 => 100755 Sources/segmentcli/Utilities/Misc.swift mode change 100644 => 100755 Sources/segmentcli/Utilities/Runtime.swift mode change 100644 => 100755 Sources/segmentcli/Utilities/Settings.swift mode change 100644 => 100755 Sources/segmentcli/main.swift mode change 100644 => 100755 Tests/segmentcliTests/segmentcliTests.swift diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/create_jira.yml b/.github/workflows/create_jira.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/segmentcli.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/segmentcli.xcscheme old mode 100644 new mode 100755 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md old mode 100644 new mode 100755 diff --git a/LICENSE.md b/LICENSE.md old mode 100644 new mode 100755 diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 diff --git a/Package.resolved b/Package.resolved old mode 100644 new mode 100755 index f071e93..e5a73ef --- a/Package.resolved +++ b/Package.resolved @@ -6,17 +6,17 @@ "repositoryURL": "https://github.com/segmentio/analytics-swift.git", "state": { "branch": null, - "revision": "c8fd5fdf59299f00b3e4303a1b12a6d88893bf56", - "version": "1.4.7" + "revision": "7d47f4b42e6d74fe2de73b8e3c3fc2eeae4a3efd", + "version": "1.7.3" } }, { "package": "AnalyticsLive", - "repositoryURL": "git@github.com:segment-integrations/analytics-swift-live.git", + "repositoryURL": "https://github.com/segment-integrations/analytics-swift-live.git", "state": { "branch": null, - "revision": "3b07681d498595aa8e06cd814003db53661abb88", - "version": "0.2.3" + "revision": "fa1f3f75ee439544ce3bf69cf99f01a5cdb36bb7", + "version": "3.1.7" } }, { @@ -37,6 +37,15 @@ "version": "1.6.0" } }, + { + "package": "JSONSafeEncoding", + "repositoryURL": "https://github.com/segmentio/jsonsafeencoding-swift.git", + "state": { + "branch": null, + "revision": "af6a8b360984085e36c6341b21ecb35c12f47ebd", + "version": "2.0.0" + } + }, { "package": "mustache", "repositoryURL": "https://github.com/AlwaysRightInstitute/Mustache", @@ -78,8 +87,8 @@ "repositoryURL": "https://github.com/segmentio/Sovran-Swift.git", "state": { "branch": null, - "revision": "64f3b5150c282a34af4578188dce2fd597e600e3", - "version": "1.1.0" + "revision": "24867f3e4ac62027db9827112135e6531b6f4051", + "version": "1.1.2" } }, { @@ -93,11 +102,11 @@ }, { "package": "Substrata", - "repositoryURL": "git@github.com:segmentio/substrata-swift.git", + "repositoryURL": "https://github.com/segmentio/substrata-swift.git", "state": { "branch": null, - "revision": "a673d773d0a6dab86a31cadcb771b45022e0c5ac", - "version": "0.0.2" + "revision": "293df9d9ad5339bf24abaf9525518c5019a061b7", + "version": "2.1.0" } }, { diff --git a/Package.swift b/Package.swift old mode 100644 new mode 100755 index f8a770c..2bb85dd --- a/Package.swift +++ b/Package.swift @@ -6,18 +6,18 @@ import PackageDescription let package = Package( name: "segmentcli", platforms: [ - .macOS(.v10_15) + .macOS(.v11) ], dependencies: [ .package(url: "https://github.com/jakeheis/SwiftCLI", from: "6.0.0"), .package(url: "https://github.com/dominicegginton/Spinner", from: "1.1.4"), .package(url: "https://github.com/mtynior/ColorizeSwift.git", from: "1.5.0"), - .package(url: "https://github.com/segmentio/analytics-swift.git", from: "1.4.7"), + .package(url: "https://github.com/segmentio/analytics-swift.git", from: "1.7.3"), .package(url: "https://github.com/swiftcsv/SwiftCSV.git", from: "0.6.1"), .package(url: "https://github.com/AlwaysRightInstitute/Mustache", from: "1.0.0"), .package(url: "https://github.com/antitypical/Result.git", from: "5.0.0"), - .package(url: "git@github.com:segment-integrations/analytics-swift-live.git", from: "0.2.3"), - .package(url: "git@github.com:segmentio/substrata-swift.git", from: "0.0.2") + .package(url: "https://github.com/segment-integrations/analytics-swift-live.git", from: "3.1.7"), + .package(url: "https://github.com/segmentio/substrata-swift.git", from: "2.1.0") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/README.md b/README.md old mode 100644 new mode 100755 index ef0cbd8..2f96002 --- a/README.md +++ b/README.md @@ -25,14 +25,21 @@ Commands: ## Getting Started +### Installing `segmentcli`. + +``` +git clone https://github.com/segment-integrations/segmentcli.git +cd segmentcli +sudo make install +``` + +A binary `segmentcli` will be installed to `/usr/local/bin`. + In order to use the segmentcli to work with your workspace you must have the -Analytics Live Plugins featured enabled in your workspace and you must +Analytics Live Plugins feature enabled in your workspace and you must authenticate with that workspace. -### Enabling the Analytics Live Plugins feature - -Reach out to your Customer Support Engineer (CSE) or Customer Success Manager (CSM) -to have them add this feature to your account. +## Authenticating The command to authenticate is as follows: @@ -52,7 +59,14 @@ an Auth token in your Segment workspace. 1. Navigate to Settings > Workspace Settings > Access Management > Tokens 1. Generate a new token using the "Create token" button with the Workspace Owner role. -## Uploading Your Analytics Live Plugins to Your Workspace +## Using `segmentcli` with Analytics Live. + +### Enabling the Analytics Live Plugins feature + +Reach out to your Customer Support Engineer (CSE) or Customer Success Manager (CSM) +to have them add this feature to your account. Once that is completed, you may continue. + +### Uploading Your Analytics Live Plugins to Your Workspace In order to upload your Analytics Live Plugins you'll need the following command: @@ -66,7 +80,7 @@ $ segmentcli upload Note: It will take a few minutes for your Source's setting payload to be update with the Analytics Live Plugin file URL. -### Finding Your SourceID +## Finding Your SourceID 1. Log into https://app.segment.com 1. Navigate to Connections > Sources diff --git a/Sources/segmentcli/Commands/Analytics.swift b/Sources/segmentcli/Commands/Analytics.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/Auth.swift b/Sources/segmentcli/Commands/Auth.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/Import.swift b/Sources/segmentcli/Commands/Import.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/LivePlugins.swift b/Sources/segmentcli/Commands/LivePlugins.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/Profile.swift b/Sources/segmentcli/Commands/Profile.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/REPL.swift b/Sources/segmentcli/Commands/REPL.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/Scaffold.swift b/Sources/segmentcli/Commands/Scaffold.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Commands/Sources.swift b/Sources/segmentcli/Commands/Sources.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/JS Additions/csvJS.swift b/Sources/segmentcli/JS Additions/csvJS.swift old mode 100644 new mode 100755 index 2057a38..c5c3838 --- a/Sources/segmentcli/JS Additions/csvJS.swift +++ b/Sources/segmentcli/JS Additions/csvJS.swift @@ -43,37 +43,31 @@ import Substrata } */ -class CSVJS: JavascriptClass, JSConvertible { - internal let csv: CSV? - - static var className = "CSV" - - static var staticProperties = [String: JavascriptProperty]() - static var staticMethods = [String: JavascriptMethod]() - var instanceProperties: [String: JavascriptProperty] = [ - "rows": JavascriptProperty(get: { weakSelf, this in - guard let self = weakSelf as? CSVJS else { return nil } - return self.csv?.namedRows.count - }) - ] - - var instanceMethods: [String : JavascriptMethod] = [ - "value": JavascriptMethod { weakSelf, this, params in - guard let self = weakSelf as? CSVJS else { return nil } - guard let row = params[0]?.typed(Int.self) else { return nil } - guard let columnName = params[1]?.typed(String.self) else { return nil } - let result = self.csv?.namedRows[row][columnName] - return result +class CSVJS: JSExport { + internal var csv: CSV? = nil + + required init() { + super.init() + + exportProperty(named: "rows") { + guard let csv = self.csv else { throw "No CSV file loaded." } + return csv.namedRows.count + } + + exportMethod(named: "value") { args in + guard let csv = self.csv else { throw "No CSV file loaded." } + guard let row = args.typed(as: Int.self, index: 0) else { return nil } + guard let columnName = args.typed(as: String.self, index: 1) else { return nil } + return csv.namedRows[row][columnName] } - ] + } - public required init(context: JSContext, params: JSConvertible?...) throws { - guard let csvPath = params[0]?.typed(String.self) else { throw "Unable to load specified CSV file." } - let delimiter = params[1]?.typed(String.self) ?? "|" - let loadColumns = params[2]?.typed(Bool.self) ?? true + override func construct(args: [JSConvertible?]) throws { + guard let csvPath = args.typed(as: String.self, index: 0) else { throw "Unable to load specified CSV file." } + let delimiter = args.typed(as: String.self, index: 1) ?? "|" + let loadColumns = args.typed(as: Bool.self, index: 2) ?? true let url = URL(fileURLWithPath: csvPath) self.csv = try CSV(url: url, delimiter: delimiter.first ?? "|", encoding: .utf8, loadColumns: loadColumns) } - } diff --git a/Sources/segmentcli/PAPI/PAPI.swift b/Sources/segmentcli/PAPI/PAPI.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/PAPI/PAPIEdgeFunctions.swift b/Sources/segmentcli/PAPI/PAPIEdgeFunctions.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/PAPI/PAPISources.swift b/Sources/segmentcli/PAPI/PAPISources.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Templates/CSVImporterJS.swift b/Sources/segmentcli/Templates/CSVImporterJS.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Templates/PluginSwift.swift b/Sources/segmentcli/Templates/PluginSwift.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/Utilities/Misc.swift b/Sources/segmentcli/Utilities/Misc.swift old mode 100644 new mode 100755 index ef2738e..aeaf6b9 --- a/Sources/segmentcli/Utilities/Misc.swift +++ b/Sources/segmentcli/Utilities/Misc.swift @@ -20,6 +20,8 @@ func executeAndWait(_ closure: (DispatchSemaphore) -> Void) { // MARK: - Exits & Errors +extension String: @retroactive Error { } + enum ErrorCode: Int { case success = 0 case unknown = 1 diff --git a/Sources/segmentcli/Utilities/Runtime.swift b/Sources/segmentcli/Utilities/Runtime.swift old mode 100644 new mode 100755 index 0291272..ef8aec6 --- a/Sources/segmentcli/Utilities/Runtime.swift +++ b/Sources/segmentcli/Utilities/Runtime.swift @@ -41,7 +41,7 @@ func runJSInteractive() { case _ where input.hasPrefix(":print"): let variable = input.replacingOccurrences(of: ":print ", with: "") - if let value = engine.object(key: variable) { + if let value = engine.value(for: variable) { print("\(variable) = \(String(describing: value))") } else { print("\(variable) = nil") @@ -75,16 +75,7 @@ func runJSFile(path scriptFile: String) { do { let url = URL(fileURLWithPath: scriptFile) let code = try String(contentsOf: url) - let readQueue = DispatchQueue(label: "segmentcli.js.execution") - @Atomic var done = false - readQueue.async { - engine.evaluate(script: code) - done = true - } - // don't have a good solution to knowing when async stuff is complete yet. - while done == false { - RunLoop.main.run(until: Date(timeIntervalSinceNow: 10)) - } + engine.evaluate(script: code) } catch { exitWithError(error.localizedDescription) } @@ -95,31 +86,17 @@ func runJSFile(path scriptFile: String) { func runJS(script: String) { configureEngine() - let readQueue = DispatchQueue(label: "segmentcli.js.execution") - @Atomic var done = false - readQueue.async { - engine.evaluate(script: script) - done = true - } - // TODO: don't have a good solution to knowing when async stuff is complete yet. - while done == false { - RunLoop.main.run(until: Date(timeIntervalSinceNow: 10)) - } + engine.evaluate(script: script) } func configureEngine() { - engine.errorHandler = { error in - switch error { - case .evaluationError(let s): - print(s) - default: - print(error) - } + engine.exceptionHandler = { error in + print(error) } // expose our classes - try? engine.expose(name: "Analytics", classType: AnalyticsJS.self) + engine.export(type: AnalyticsJS.self, className: "Analytics") // set the system analytics object. //engine.setObject(key: "analytics", value: AnalyticsJS(wrapping: self.analytics, engine: engine)) diff --git a/Sources/segmentcli/Utilities/Settings.swift b/Sources/segmentcli/Utilities/Settings.swift old mode 100644 new mode 100755 diff --git a/Sources/segmentcli/main.swift b/Sources/segmentcli/main.swift old mode 100644 new mode 100755 diff --git a/Tests/segmentcliTests/segmentcliTests.swift b/Tests/segmentcliTests/segmentcliTests.swift old mode 100644 new mode 100755 From df611ec129c1f820035bf22c6fe74d2c432cd90c Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Fri, 9 May 2025 16:07:45 -0700 Subject: [PATCH 9/9] Updated readme. --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index d621769..637aafa 100755 --- a/README.md +++ b/README.md @@ -35,10 +35,6 @@ sudo make install A binary `segmentcli` will be installed to `/usr/local/bin`. -In order to use the segmentcli to work with your workspace you must have the -Analytics Live Plugins feature enabled in your workspace and you must -authenticate with that workspace. - ## Authenticating The command to authenticate is as follows: