feat: update dependencies

This commit is contained in:
Kevin Franklin Kim
2026-03-17 16:56:54 +01:00
parent 61d671341c
commit f4eae472a6
112 changed files with 993 additions and 555 deletions

View File

@@ -1,21 +0,0 @@
# Contributing
If you want to submit a pull request to fix a bug or enhance an existing
feature, please first open an issue and link to that issue when you
submit your pull request.
If you have any questions about a possible submission, feel free to open
an issue too.
### Pull request process
1. Fork this repository
2. Create a branch in your fork to implement the changes. We recommend using
the issue number as part of your branch name, e.g. `1234-fixes`
3. Ensure that any documentation is updated with the changes that are required
by your fix.
4. Ensure that any samples are updated if the base image has been changed.
5. Submit the pull request. *Do not leave the pull request blank*. Explain exactly
what your changes are meant to do and provide simple steps on how to validate
your changes. Ensure that you reference the issue you created as well.
The pull request will be review before it is merged.

View File

@@ -1,17 +0,0 @@
---
name: Bug Report
about: Report a bug you encountered
labels: bug
---
**What happened**:
**What you expected to happen**:
**How to reproduce it (as minimally and precisely as possible)**:
**Anything else we need to know?**:
**Environment**:
- Affected Version:
- OS (e.g: `cat /etc/os-release`):
- Others:

88
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: 🐛 Bug Report
description: Report a bug or unexpected behavior
title: "[Bug]: "
labels: ["bug", "needs-triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report this issue! Please fill out the information below to help us understand and resolve the problem.
- type: checkboxes
id: prerequisites
attributes:
label: Prerequisites
description: Please confirm the following before submitting
options:
- label: I have searched existing issues to ensure this bug hasn't been reported
required: true
- label: I have checked the documentation
required: true
- label: I am using the latest version
required: false
- type: input
id: version
attributes:
label: Version
description: What version are you using?
placeholder: e.g., 1.2.3
validations:
required: true
- type: textarea
id: description
attributes:
label: Bug Description
description: A clear and concise description of what the bug is
placeholder: What went wrong?
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to Reproduce
description: Detailed steps to reproduce the behavior
placeholder: |
1. Import '...'
2. Call function with '...'
3. See error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: What did you expect to happen?
placeholder: What should have happened instead?
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Behavior
description: What actually happened?
placeholder: Include error messages, screenshots, or logs
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional Context
description: Any other context, environment, code, screenshots, or information about the problem
placeholder: Add any other relevant details here
validations:
required: false
- type: textarea
id: solution
attributes:
label: Possible Solution
description: If you have suggestions on how to fix this, please share
placeholder: Optional - your ideas for fixing this issue
validations:
required: false

View File

@@ -1,8 +0,0 @@
---
name: Enhancement Request
about: Suggest an enhancement
labels: enhancement
---
**What would you like to be added**:
**Why is this needed**:

View File

@@ -0,0 +1,76 @@
name: ✨ Feature Request
description: Suggest a new feature or enhancement
title: "[Feature]: "
labels: ["enhancement", "needs-triage"]
body:
- type: markdown
attributes:
value: |
Thanks for your interest in improving this project! Please describe your feature request in detail.
- type: checkboxes
id: prerequisites
attributes:
label: Prerequisites
description: Please confirm the following before submitting
options:
- label: I have searched existing issues to ensure this hasn't been requested
required: true
- label: I have checked the documentation to ensure this feature doesn't exist
required: true
- type: textarea
id: problem
attributes:
label: Problem Statement
description: Is your feature request related to a problem? Please describe.
placeholder: I'm frustrated when... / It would be helpful if...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: Describe the solution you'd like
placeholder: A clear and concise description of what you want to happen
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: Describe alternatives you've considered
placeholder: What other approaches have you thought about?
validations:
required: false
- type: textarea
id: additional
attributes:
label: Additional Context
description: Add any other context, code, mockups, or screenshots
placeholder: Links to similar features in other libraries, mockups, etc.
validations:
required: false
- type: dropdown
id: priority
attributes:
label: Priority
description: How important is this feature to you?
options:
- Low - Nice to have
- Medium - Would significantly improve my workflow
- High - Blocking my usage of this library
validations:
required: false
- type: checkboxes
id: contribution
attributes:
label: Contribution
description: Would you be willing to contribute this feature?
options:
- label: I'm willing to submit a PR to implement this feature

55
.github/ISSUE_TEMPLATE/question.yaml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: ❓ Question
description: Ask a question about usage or clarification
title: "[Question]: "
labels: ["question"]
body:
- type: markdown
attributes:
value: |
Thanks for your question! Please provide as much detail as possible so we can help you effectively.
- type: checkboxes
id: prerequisites
attributes:
label: Prerequisites
description: Please confirm the following before submitting
options:
- label: I have checked the documentation
required: true
- label: I have searched existing issues for similar questions
required: true
- type: textarea
id: question
attributes:
label: Your Question
description: What would you like to know?
placeholder: Please be as specific as possible
validations:
required: true
- type: textarea
id: context
attributes:
label: Context
description: What are you trying to accomplish?
placeholder: Describe your use case or what you're building
validations:
required: false
- type: textarea
id: attempted
attributes:
label: What I've Tried
description: What have you already attempted?
placeholder: Describe any solutions you've already explored
validations:
required: false
- type: textarea
id: additional
attributes:
label: Additional Information
description: Any other details or code that might be helpful
validations:
required: false

View File

@@ -1,19 +1,36 @@
### Type of Change
- [ ] New feature
- [ ] Bug fix
- [ ] Documentation update
- [ ] Refactoring
- [ ] Hotfix
- [ ] Security patch
### Description
_[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]_
### Related Issues
_[If this pull request addresses an issue, please link to it here (e.g., Fixes #123).]_
<!-- Briefly describe what this PR does -->
### Type of Change
<!-- Check the relevant option -->
- [ ] 🐛 Bug fix
- [ ] ✨ New feature
- [ ] 💥 Breaking change
- [ ] 📝 Documentation
- [ ] ♻️ Refactoring
- [ ] ⚡ Performance
- [ ] ✅ Tests
- [ ] 🔧 Build/CI
### Related Issue
<!-- Link related issues: Fixes #123, Closes #456 -->
## Changes
<!-- List key changes -->
-
### Checklist
- [ ] My code adheres to the coding and style guidelines of the project.
- [ ] I have performed a self-review of my own code.
- [ ] I have commented my code, particularly in hard-to-understand areas.
- [ ] I have commented on my code, particularly in hard-to-understand areas.
- [ ] I have made corresponding changes to the documentation.
#### Notes
<!-- Optional: Add additional context -->

View File

@@ -13,11 +13,12 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: jdx/mise-action@v3
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
check-latest: true
go-version-file: go.mod
@@ -35,7 +36,7 @@ jobs:
- name: Login to docker.io
run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
- uses: goreleaser/goreleaser-action@v6
- uses: goreleaser/goreleaser-action@v7
with:
version: '~> v2'
args: release --clean

View File

@@ -19,24 +19,31 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: actions/setup-go@v5
- uses: jdx/mise-action@v3
- uses: actions/setup-go@v6
with:
check-latest: true
go-version-file: 'go.mod'
go-version-file: go.mod
- uses: gotesttools/gotestfmt-action@v2
- name: Setup golangci-lint cache
uses: actions/cache@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
path: ~/.cache/golangci-lint
key: golangci-lint-${{ runner.os }}-${{ hashFiles('**/go.mod') }}
restore-keys: |
golangci-lint-${{ runner.os }}--
- uses: golangci/golangci-lint-action@v8
with:
version: latest
- name: Run tidy
run: make tidy && git diff --exit-code
- name: Run generate
run: make generate && git diff --exit-code
- name: Run lint
run: make lint.branch
- name: Run tests
run: make test
- uses: coverallsapp/github-action@v2
with:
file: coverage.out

47
.gitignore vendored
View File

@@ -1,33 +1,50 @@
.*
*.zip
*.tar
*.tgz
*.pem
*.out
*.log
/bin/
/tmp/
bin/
dist/
tmp/
## Git
!.gitkeep
!.gitignore
!.gitkeep
## GitHub
!.github/
## Mise
!.mise.toml
## Lefthook
!.lefthook.yaml
## VSCode
!.vscode/
.vscode/*
!.vscode/extensions.json
!.vscode/settings.default.json
## Editorconfig
!.editorconfig
## Docker
!.dockerignore
## Node ##
**/node_modules/
## Husky
!.husky/
!.husky.yaml
### Golang
/go.work
/go.work.sum
!.golangci.yaml
!.goreleaser.yaml
## Golang
go.work
go.work.sum
!.golangci.yml
!.goreleaser.yml
## Node
**/node_modules/
## Ownbrew
!.ownbrew.yaml
## Vitepress
!docs/.vitepress
docs/.vitepress/*
!docs/.vitepress/theme/
!docs/.vitepress/config.mts

83
.golangci.yaml Normal file
View File

@@ -0,0 +1,83 @@
# yaml-language-server: $schema=https://golangci-lint.run/jsonschema/golangci.jsonschema.json
version: "2"
run:
build-tags: [ safe ]
modules-download-mode: readonly
linters:
default: all
disable:
# Project specific linters
- paralleltest
# Discouraged linters
- noinlineerr # Disallows inline error handling (`if err := ...; err != nil {`).
- embeddedstructfieldcheck # Embedded types should be at the top of the field list of a struct, and there must be an empty line separating embedded fields from regular fields. [fast]
- cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false]
- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
- dupl # Tool for code clone detection [fast: true, auto-fix: false]
- dupword # checks for duplicate words in the source code [fast: true, auto-fix: false]
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
- err113 # Go linter to check the errors handling expressions [fast: false, auto-fix: false]
- exhaustruct # Checks if all structure fields are initialized [fast: false, auto-fix: false]
- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
- ginkgolinter # enforces standards of using ginkgo and gomega [fast: false, auto-fix: false]
- gochecknoglobals # Check that no global variables exist. [fast: false, auto-fix: false]
- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
- godot # Check if comments end in a period [fast: true, auto-fix: true]
- godox # Tool for detection of comment keywords [fast: true, auto-fix: false]
- interfacebloat # A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false]
- intrange # (go >= 1.22) intrange is a linter to find places where for loops could make use of an integer range. [fast: true, auto-fix: false]
- ireturn # Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false]
- lll # Reports long lines [fast: true, auto-fix: false]
- maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false]
- nestif # Reports deeply nested if statements [fast: true, auto-fix: false]
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
- mnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. [fast: false, auto-fix: false]
- prealloc # Finds slice declarations that could potentially be pre-allocated [fast: true, auto-fix: false]
- protogetter # Reports direct reads from proto message fields when getters should be used [fast: false, auto-fix: true]
- sloglint # ensure consistent code style when using log/slog [fast: false, auto-fix: false]
- tagalign # check that struct tags are well aligned [fast: true, auto-fix: true]
- tagliatelle # Checks the struct tags. [fast: true, auto-fix: false]
- unparam # Reports unused function parameters [fast: false, auto-fix: false]
- varnamelen # checks that the length of a variable's name matches its scope [fast: false, auto-fix: false]
- wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
- zerologlint # Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg` [fast: false, auto-fix: false]
# Deprected linters
- wsl
# https://golangci-lint.run/docs/linters/
settings:
# https://golangci-lint.run/docs/linters/configuration/#exhaustive
exhaustive:
default-signifies-exhaustive: true
# https://golangci-lint.run/docs/linters/configuration/#gosec
gosec:
severity: medium
confidence: medium
# https://golangci-lint.run/docs/linters/configuration/#revive
revive:
rules:
- name: package-comments
disabled: true
exclusions:
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- path: _test\.go
linters:
- forbidigo
paths:
- docs
- tmp
formatters:
enable:
- gofmt
- goimports

View File

@@ -1,221 +0,0 @@
version: "2"
run:
go: 1.24.3
build-tags: [safe]
modules-download-mode: readonly
linters:
default: none
enable:
## Default linters
- errcheck # errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]
- govet # (vet, vetshadow) Vet examines Go source code and reports suspicious constructs. It is roughly the same as 'go vet' and uses its passes. [fast: false, auto-fix: false]
- ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
- staticcheck # (megacheck) It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. [fast: false, auto-fix: false]
- unused # (megacheck) Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
## Recommended linters
- asasalint # check for pass []any as any in variadic func(...any) [fast: false, auto-fix: false]
- asciicheck # checks that all code identifiers does not have non-ASCII symbols in the name [fast: true, auto-fix: false]
- bidichk # Checks for dangerous unicode character sequences [fast: true, auto-fix: false]
- bodyclose # checks whether HTTP response body is closed successfully [fast: false, auto-fix: false]
- canonicalheader # checks whether net/http.Header uses canonical header [fast: false, auto-fix: false]
- containedctx # containedctx is a linter that detects struct contained context.Context field [fast: false, auto-fix: false]
- contextcheck # check whether the function uses a non-inherited context [fast: false, auto-fix: false]
- copyloopvar # (go >= 1.22) copyloopvar is a linter detects places where loop variables are copied [fast: true, auto-fix: false]
- decorder # check declaration order and count of types, constants, variables and functions [fast: true, auto-fix: false]
- durationcheck # check for two durations multiplied together [fast: false, auto-fix: false]
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omitted. [fast: false, auto-fix: false]
- errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. [fast: false, auto-fix: false]
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
- exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false]
- exptostd # Detects functions from golang.org/x/exp/ that can be replaced by std functions. [auto-fix]
- fatcontext # detects nested contexts in loops and function literals [fast: false, auto-fix: false]
#- forbidigo # Forbids identifiers [fast: false, auto-fix: false]
- forcetypeassert # finds forced type assertions [fast: true, auto-fix: false]
- gocheckcompilerdirectives # Checks that go compiler directive comments (//go:) are valid. [fast: true, auto-fix: false]
- gochecksumtype # Run exhaustiveness checks on Go "sum types" [fast: false, auto-fix: false]
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
- gocritic # Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: true]
- goheader # Checks is file header matches to pattern [fast: true, auto-fix: true]
- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
- goprintffuncname # Checks that printf-like functions are named with `f` at the end. [fast: true, auto-fix: false]
- gosec # (gas) Inspects source code for security problems [fast: false, auto-fix: false]
- gosmopolitan # Report certain i18n/l10n anti-patterns in your Go codebase [fast: false, auto-fix: false]
- grouper # Analyze expression groups. [fast: true, auto-fix: false]
- iface # Detect the incorrect use of interfaces, helping developers avoid interface pollution. [fast: false, auto-fix: false]
- importas # Enforces consistent import aliases [fast: false, auto-fix: false]
- inamedparam # reports interfaces with unnamed method parameters [fast: true, auto-fix: false]
- intrange # (go >= 1.22) intrange is a linter to find places where for loops could make use of an integer range. [fast: true, auto-fix: false]
- loggercheck # (logrlint) Checks key value pairs for common logger libraries (kitlog,klog,logr,zap). [fast: false, auto-fix: false]
- makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
- mirror # reports wrong mirror patterns of bytes/strings usage [fast: false, auto-fix: true]
- misspell # Finds commonly misspelled English words [fast: true, auto-fix: true]
- musttag # enforce field tags in (un)marshaled structs [fast: false, auto-fix: false]
- nakedret # Checks that functions with naked returns are not longer than a maximum size (can be zero). [fast: true, auto-fix: false]
- nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
- nilnesserr # Reports constructs that checks for err != nil, but returns a different nil value error.
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false]
- noctx # Finds sending http request without context.Context [fast: false, auto-fix: false]
- nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: true]
- nonamedreturns # Reports all named returns [fast: false, auto-fix: false]
- nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL. [fast: true, auto-fix: false]
#- paralleltest # Detects missing usage of t.Parallel() method in your Go test [fast: false, auto-fix: false]
- predeclared # find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false]
- promlinter # Check Prometheus metrics naming via promlint [fast: true, auto-fix: false]
- reassign # Checks that package variables are not reassigned [fast: false, auto-fix: false]
- recvcheck # checks for receiver type consistency [fast: false, auto-fix: false]
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]
- rowserrcheck # checks whether Rows.Err of rows is checked successfully [fast: false, auto-fix: false]
- spancheck # Checks for mistakes with OpenTelemetry/Census spans. [fast: false, auto-fix: false]
- sqlclosecheck # Checks that sql.Rows, sql.Stmt, sqlx.NamedStmt, pgx.Query are closed. [fast: false, auto-fix: false]
- testableexamples # linter checks if examples are testable (have an expected output) [fast: true, auto-fix: false]
- testifylint # Checks usage of github.com/stretchr/testify. [fast: false, auto-fix: false]
- testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false]
- thelper # thelper detects tests helpers which is not start with t.Helper() method. [fast: false, auto-fix: false]
- tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes. [fast: false, auto-fix: false]
- unconvert # Remove unnecessary type conversions [fast: false, auto-fix: false]
- usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library. [fast: true, auto-fix: false]
- usetesting # Reports uses of functions with replacement inside the testing package. [auto-fix]
- wastedassign # Finds wasted assignment statements [fast: false, auto-fix: false]
- whitespace # Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc. [fast: true, auto-fix: true]
## Discouraged linters
#- cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false]
#- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
#- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
#- dupl # Tool for code clone detection [fast: true, auto-fix: false]
#- dupword # checks for duplicate words in the source code [fast: true, auto-fix: false]
#- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
#- err113 # Go linter to check the errors handling expressions [fast: false, auto-fix: false]
#- exhaustruct # Checks if all structure fields are initialized [fast: false, auto-fix: false]
#- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
#- ginkgolinter # enforces standards of using ginkgo and gomega [fast: false, auto-fix: false]
#- gochecknoglobals # Check that no global variables exist. [fast: false, auto-fix: false]
#- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
#- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
#- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
#- godot # Check if comments end in a period [fast: true, auto-fix: true]
#- godox # Tool for detection of comment keywords [fast: true, auto-fix: false]
#- interfacebloat # A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false]
#- intrange # (go >= 1.22) intrange is a linter to find places where for loops could make use of an integer range. [fast: true, auto-fix: false]
#- ireturn # Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false]
#- lll # Reports long lines [fast: true, auto-fix: false]
#- maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false]
#- nestif # Reports deeply nested if statements [fast: true, auto-fix: false]
#- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
#- mnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
#- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. [fast: false, auto-fix: false]
#- prealloc # Finds slice declarations that could potentially be pre-allocated [fast: true, auto-fix: false]
#- protogetter # Reports direct reads from proto message fields when getters should be used [fast: false, auto-fix: true]
#- sloglint # ensure consistent code style when using log/slog [fast: false, auto-fix: false]
#- tagalign # check that struct tags are well aligned [fast: true, auto-fix: true]
#- tagliatelle # Checks the struct tags. [fast: true, auto-fix: false]
#- unparam # Reports unused function parameters [fast: false, auto-fix: false]
#- varnamelen # checks that the length of a variable's name matches its scope [fast: false, auto-fix: false]
#- wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
#- wsl # add or remove empty lines [fast: true, auto-fix: false]
#- zerologlint # Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg` [fast: false, auto-fix: false]
settings:
exhaustive:
default-signifies-exhaustive: true
gocritic:
disabled-checks:
- ifElseChain
- commentFormatting
gomoddirectives:
replace-local: true
gosec:
confidence: medium
importas:
no-unaliased: true
misspell:
mode: restricted
predeclared:
ignore:
- new
- error
revive:
enable-all-rules: true
rules:
- name: line-length-limit
disabled: true
- name: cognitive-complexity
disabled: true
- name: unused-parameter
disabled: true
- name: add-constant
disabled: true
- name: cyclomatic
disabled: true
- name: function-length
disabled: true
- name: function-result-limit
disabled: true
- name: flag-parameter
disabled: true
- name: unused-receiver
disabled: true
- name: argument-limit
disabled: true
- name: max-control-nesting
disabled: true
- name: comment-spacings
disabled: true
- name: max-public-structs
disabled: true
- name: struct-tag
arguments:
- json,inline
- yaml,squash
- name: unhandled-error
arguments:
- fmt.Println
- viper.BindPFlag
- strings.Builder.WriteString
- name: deep-exit
disabled: true
- name: if-return
disabled: true
- name: empty-block
disabled: true
- name: indent-error-flow
disabled: true
- name: var-naming
disabled: true
testifylint:
disable:
- float-compare
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- forbidigo
- forcetypeassert
path: _test\.go
- linters:
- asasalint
path: (.+)_test\.go
paths:
- bin
- tmp
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- goimports
exclusions:
generated: lax
paths:
- bin
- tmp
- third_party$
- builtin$
- examples$

View File

@@ -1,15 +0,0 @@
hooks:
pre-commit:
- golangci-lint run --fast-only
- husky lint-staged
commit-msg:
# only execute if not in a merge
- if [[ -z $(git rev-parse -q --verify MERGE_HEAD) ]]; then husky lint-commit; fi
lint-staged:
'*.go':
- golangci-lint fmt
lint-commit:
types: '^(feat|fix|build|chore|docs|perf|refactor|revert|style|test|wip)$'
header: '^(?P<type>\w+)(\((?P<scope>[\w/.-]+)\))?(?P<breaking>!)?:( +)?(?P<header>.+)'

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

View File

@@ -1,3 +0,0 @@
#!/bin/sh
husky hook $(basename "$0") $*

44
.lefthook.yaml Normal file
View File

@@ -0,0 +1,44 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/evilmartians/lefthook/refs/heads/master/schema.json
# https://lefthook.dev/configuration/
output: [ summary ]
pre-commit:
skip: [ merge, rebase ]
parallel: true
commands:
branch-name:
run: |
branch_name=$(git rev-parse --abbrev-ref HEAD)
if ! [[ "$branch_name" =~ ^(feature|fix)/ ]]; then
echo "Error: Branch name must start with 'feature/' or 'fix/'. Your branch: $branch_name"
exit 1
fi
golangci-fmt:
glob: "*.go"
run: golangci-lint fmt {staged_files}
stage_fixed: true
golangci-lint:
glob: "*.go"
run: golangci-lint run --new --fast-only
stage_fixed: false
commit-msg:
skip: [ merge, rebase ]
commands:
commit:
run: |
commit_msg_file={1}
commit_msg=$(cat "$commit_msg_file")
# Regex for conventional commits (type(scope?): subject)
regex="^(build|chore|ci|docs|feat|fix|perf|refactor|style|test|sec|wip|revert)(\([a-z0-9\-]+\))?(!)?: .{1,50}"
if ! echo "$commit_msg" | grep -qE "$regex"; then
echo "Error: Commit message does not follow Conventional Commits format."
echo "Format: type(scope?): subject"
echo "Example: feat(login): add remember me option"
exit 1
fi
post-checkout:
commands:
mise:
run: mise -q install

5
.mise.toml Normal file
View File

@@ -0,0 +1,5 @@
[tools]
# https://mise-tools.jdx.dev/tools/lefthook
lefthook = "2.1.4"
# https://mise-tools.jdx.dev/tools/golangci-lint
golangci-lint = "2.11.3"

View File

@@ -1,16 +0,0 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/foomo/ownbrew/refs/tags/v0.2.3/ownbrew.schema.json
version: '1.1'
binDir: "bin"
tapDir: ".ownbrew/tap"
tempDir: ".ownbrew/tmp"
cellarDir: ".ownbrew/bin"
packages:
## https://github.com/golangci/golangci-lint/releases
- name: golangci-lint
tap: foomo/tap/golangci/golangci-lint
version: 2.1.6
## https://github.com/go-courier/husky/releases
- name: husky
tap: foomo/tap/go-courier/husky
version: 1.8.1

112
Makefile
View File

@@ -1,55 +1,95 @@
.DEFAULT_GOAL := help
.DEFAULT_GOAL:=help
-include .makerc
PATH:=bin:$(PATH)
# --- Config -----------------------------------------------------------------
# Newline hack for error output
define br
endef
# --- Targets -----------------------------------------------------------------
# This allows us to accept extra arguments
%: .husky
%: .mise .lefthook
@:
.PHONY: .husky
# Configure git hooks for husky
.husky:
@if ! command -v husky &> /dev/null; then \
echo "ERROR: missing executeable 'husky', please run:"; \
echo "\n$ make brew\n"; \
fi
@git config core.hooksPath .husky
.PHONY: .mise
# Install dependencies
.mise:
ifeq (, $(shell command -v mise))
$(error $(br)$(br)Please ensure you have 'mise' installed and activated!$(br)$(br) $$ brew update$(br) $$ brew install mise$(br)$(br)See the documentation: https://mise.jdx.dev/getting-started.html)
endif
@mise install
.PHONY: .lefthook
# Configure git hooks for lefthook
.lefthook:
@lefthook install --reset-hooks-path
### Tasks
.PHONY: doc
## Open go docs
doc:
@open "http://localhost:6060/pkg/github.com/foomo/sesamy-cli/"
@godoc -http=localhost:6060 -play
.PHONY: check
## Run lint & test
check: tidy generate lint test
.PHONY: test
## Run tests
test:
@GO_TEST_TAGS=-skip go test -tags=safe -coverprofile=coverage.out -race -json -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
.PHONY: tidy
## Run go mod tidy
tidy:
@echo "〉go mod tidy"
@go mod tidy
.PHONY: lint
## Run linter
lint:
@echo "〉golangci-lint run"
@golangci-lint run
.PHONY: lint.fix
## Fix lint violations
lint.fix:
@echo "〉golangci-lint run fix"
@golangci-lint run --fix
.PHONY: tidy
## Run go mod tidy
tidy:
@go mod tidy
.PHONY: lint.branch
## Run linter with --new-from-rev=origin/main
lint.branch:
@echo "〉golangci-lint run with --new-from-rev=origin/main"
@golangci-lint run --new-from-rev=origin/main
.PHONY: test
## Run tests
test:
@echo "〉go test"
@GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -tags=safe ./...
.PHONY: test.race
## Run tests with -race
test.race:
@echo "〉go test -race"
@GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -tags=safe -race ./...
.PHONY: test.nocache
## Run tests with -count=1
test.nocache:
@echo "〉go test -count=1"
@GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -tags=safe -count=1 ./...
.PHONY: outdated
## Show outdated direct dependencies
outdated:
@echo "〉go mod outdated"
@go list -u -m -json all | go-mod-outdated -update -direct
.PHONY: generate
## Run go generate
generate:
@echo "〉go generate"
@go generate ./...
### Build
.PHONY: build
## Build binary
build:
@@ -68,24 +108,30 @@ install:
install.debug:
@go build -tags=safe -gclags="all=-N -l" -o ${GOPATH}/bin/sesamy main.go
### Utils
### Documentation
.PHONY: brew
## Install project binaries
brew:
@ownbrew install
.PHONY: godocs
## Open go docs
godocs:
@echo "〉starting go docs"
@go doc -http
### Utils
.PHONY: help
## Show help text
help:
@echo "\033[1;36mSesamy CLI\033[0m"
@echo ""
@echo "SESAMY CLI"
@echo ""
@echo "Usage:\n make [task]"
@awk '{ \
if($$0 ~ /^### /){ \
if(help) printf "\033[36m%-23s\033[0m %s\n\n", cmd, help; help=""; \
printf "\n\033[1;36m%s\033[0m\n", substr($$0,5); \
if(help) printf "%-23s %s\n\n", cmd, help; help=""; \
printf "\n%s:\n", substr($$0,5); \
} else if($$0 ~ /^[a-zA-Z0-9._-]+:/){ \
cmd = substr($$0, 1, index($$0, ":")-1); \
if(help) printf " \033[36m%-23s\033[0m %s\n", cmd, help; help=""; \
if(help) printf " %-23s %s\n", cmd, help; help=""; \
} else if($$0 ~ /^##/){ \
help = help ? help "\n " substr($$0,3) : substr($$0,3); \
} else if(help){ \

View File

@@ -4,7 +4,7 @@
[![goreleaser](https://github.com/foomo/sesamy-cli/actions/workflows/release.yml/badge.svg)](https://github.com/foomo/sesamy-cli/actions)
<p align="center">
<img alt="sesamy" src=".github/assets/sesamy.png"/>
<img alt="sesamy" src="docs/public/logo.png" width="400" height="400"/>
</p>
# Sesamy CLI
@@ -532,10 +532,12 @@ You might need to increase your Google Tag Manager API quotas, since they are li
## How to Contribute
Please refer to the [CONTRIBUTING](.github/CONTRIBUTING.md) details and follow the [CODE_OF_CONDUCT](.github/CODE_OF_CONDUCT.md) and [SECURITY](.github/SECURITY.md) guidelines.
Contributions are welcome! Please read the [contributing guide](docs/CONTRIBUTING.md).
![Contributors](https://contributors-table.vercel.app/image?repo=foomo/sesamy-cli&width=50&columns=15)
## License
Distributed under MIT License, please see license file within the code for more details.
Distributed under MIT License, please see the [license](LICENSE) file within the code for more details.
_Made with ♥ [foomo](https://www.foomo.org) by [bestbytes](https://www.bestbytes.com)_

View File

@@ -15,6 +15,7 @@ const ChangeStatusDeleted = "deleted"
func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (string, error) {
l.Info("└ ⬇︎ Loading status")
s, err := tm.Service().Accounts.Containers.Workspaces.GetStatus(tm.WorkspacePath()).Context(ctx).Do()
if err != nil {
return "", err
@@ -23,12 +24,14 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
l.Info("└ ⬇︎ Loading live version")
live, err := tm.Service().Accounts.Containers.Versions.Live(tm.ContainerPath()).Do()
if err != nil {
return "", err
}
var res []string
for _, entity := range s.WorkspaceChange {
switch {
case entity.Tag != nil:
@@ -49,6 +52,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.Tag {
if value.Name == entity.Tag.Name {
// unset props
@@ -58,6 +62,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -66,6 +71,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.Folder != nil:
res = append(res, " # Folder: "+entity.Folder.Name+" ("+entity.ChangeStatus+")")
@@ -85,6 +91,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.Folder {
if value.Name == entity.Folder.Name {
// unset props
@@ -94,6 +101,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -102,6 +110,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.Trigger != nil:
res = append(res, " # Trigger: "+entity.Trigger.Name+" ("+entity.ChangeStatus+")")
@@ -121,6 +130,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.Trigger {
if value.Name == entity.Trigger.Name {
// unset props
@@ -130,6 +140,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -138,6 +149,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.Variable != nil:
res = append(res, " # Variable: "+entity.Variable.Name+" ("+entity.ChangeStatus+")")
@@ -157,6 +169,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.Variable {
if value.Name == entity.Variable.Name {
// unset props
@@ -166,6 +179,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -174,6 +188,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.Client != nil:
res = append(res, " # Client: "+entity.Client.Name+" ("+entity.ChangeStatus+")")
@@ -193,6 +208,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.Client {
if value.Name == entity.Client.Name {
// unset props
@@ -202,6 +218,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -210,6 +227,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.GtagConfig != nil:
res = append(res, " # GtagConfig: "+entity.GtagConfig.AccountId+" ("+entity.ChangeStatus+")")
@@ -229,6 +247,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.GtagConfig {
if value.AccountId == entity.GtagConfig.AccountId {
// unset props
@@ -238,6 +257,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -246,6 +266,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.BuiltInVariable != nil:
res = append(res, " # BuiltInVariable: "+entity.BuiltInVariable.Name+" ("+entity.ChangeStatus+")")
@@ -263,12 +284,14 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.BuiltInVariable {
if value.Name == entity.BuiltInVariable.Name {
original, err = ToYalm(value)
if err != nil {
return "", err
}
break
}
}
@@ -277,6 +300,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.CustomTemplate != nil:
res = append(res, " # CustomTemplate: "+entity.CustomTemplate.Name+" ("+entity.ChangeStatus+")")
@@ -296,6 +320,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.CustomTemplate {
if value.Name == entity.CustomTemplate.Name {
// unset props
@@ -305,6 +330,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -313,6 +339,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
case entity.Transformation != nil:
res = append(res, " # Transformation: "+entity.Transformation.Name+" ("+entity.ChangeStatus+")")
@@ -332,6 +359,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
}
var original string
for _, value := range live.Transformation {
if value.Name == entity.Transformation.Name {
// unset props
@@ -341,6 +369,7 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
break
}
}
@@ -349,11 +378,13 @@ func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (strin
if err != nil {
return "", err
}
res = append(res, d...)
default:
l.Warn("unknown entity type", "entity", entity)
}
}
return strings.Join(res, " ---\n"), nil
}
@@ -373,11 +404,13 @@ func ToDiff(original, changed string) ([]string, error) {
}
var ret []string
for _, d := range yamldiff.Do(yamls1, yamls2) {
if value := d.Dump(); len(value) > 4 {
ret = append(ret, value)
}
}
return ret, nil
}

View File

@@ -51,7 +51,9 @@ func NewServer(l *slog.Logger) *cobra.Command {
if !c.GetBool("raw") {
out = utils.Highlight(out)
}
_, err = fmt.Println(out)
return err
},
}

View File

@@ -51,7 +51,9 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if !c.GetBool("raw") {
out = utils.Highlight(out)
}
_, err = fmt.Println(out)
return err
},
}

View File

@@ -15,6 +15,7 @@ func dump(i interface{ MarshalJSON() ([]byte, error) }, err error) (string, erro
if err != nil {
return "", err
}
out, err := i.MarshalJSON()
if err != nil {
return "", err
@@ -24,6 +25,7 @@ func dump(i interface{ MarshalJSON() ([]byte, error) }, err error) (string, erro
if err := json2yaml.Convert(&output, bytes.NewBuffer(out)); err != nil {
return "", err
}
return output.String(), nil
}
@@ -50,11 +52,13 @@ func list(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, resour
if err != nil {
return "", err
}
var ret strings.Builder
for _, template := range r.Template {
ret.WriteString("---- Template data: " + template.Name + " ----------------------\n")
ret.WriteString(template.TemplateData + "\n")
}
return ret.String(), nil
case "gtag-config":
return dump(tm.Service().Accounts.Containers.Workspaces.GtagConfig.List(tm.WorkspacePath()).Context(ctx).Do())

View File

@@ -68,7 +68,9 @@ func NewServer(l *slog.Logger) *cobra.Command {
if !c.GetBool("raw") {
out = utils.Highlight(out)
}
_, err = fmt.Println(out)
return err
},
}

View File

@@ -67,7 +67,9 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if !c.GetBool("raw") {
out = utils.Highlight(out)
}
_, err = fmt.Println(out)
return err
},
}

View File

@@ -31,11 +31,13 @@ func NewOpen(l *slog.Logger) *cobra.Command {
}
var url string
switch args[0] {
case "ga":
if cfg.GoogleAnalytics.PropertyID == "" {
return errors.New("missing Google Analytics Property ID")
}
url = fmt.Sprintf(
"https://analytics.google.com/analytics/web/#/p%s/",
cfg.GoogleAnalytics.PropertyID,

View File

@@ -77,6 +77,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.GoogleAnalytics.Enabled && utils.Tag(googleanalyticsprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", googleanalyticsprovider.Name, "tag", googleanalyticsprovider.Tag)
if err := googleanalyticsprovider.Server(cmd.Context(), tm, cfg.GoogleAnalytics, cfg.RedactVisitorIP, cfg.EnableGeoResolution); err != nil {
return errors.Wrap(err, "failed to provision google analytics")
}
@@ -84,6 +85,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.ConversionLinker.Enabled && utils.Tag(conversionlinkerprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", conversionlinkerprovider.Name, "tag", conversionlinkerprovider.Tag)
if err := conversionlinkerprovider.Server(cmd.Context(), tm, cfg.ConversionLinker); err != nil {
return errors.Wrap(err, "failed to provision conversion linker")
}
@@ -91,6 +93,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Umami.Enabled && utils.Tag(umamiprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", umamiprovider.Name, "tag", umamiprovider.Tag)
if err := umamiprovider.Server(cmd.Context(), tm, cfg.Umami); err != nil {
return errors.Wrap(err, "failed to provision umami")
}
@@ -98,6 +101,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Facebook.Enabled && utils.Tag(facebookprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", facebookprovider.Name, "tag", facebookprovider.Tag)
if err := facebookprovider.Server(cmd.Context(), l, tm, cfg.Facebook); err != nil {
return errors.Wrap(err, "failed to provision facebook")
}
@@ -105,6 +109,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.GoogleAds.Enabled && utils.Tag(googleadsprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", googleadsprovider.Name, "tag", googleadsprovider.Tag)
if err := googleadsprovider.Server(cmd.Context(), l, tm, cfg.GoogleAds); err != nil {
return errors.Wrap(err, "failed to provision google ads")
}
@@ -112,6 +117,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Emarsys.Enabled && utils.Tag(emarsysprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", emarsysprovider.Name, "tag", emarsysprovider.Tag)
if err := emarsysprovider.Server(cmd.Context(), l, tm, cfg.Emarsys); err != nil {
return errors.Wrap(err, "failed to provision emarsys")
}
@@ -119,6 +125,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Tracify.Enabled && utils.Tag(tracifyprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", tracifyprovider.Name, "tag", tracifyprovider.Tag)
if err := tracifyprovider.Server(cmd.Context(), l, tm, cfg.Tracify); err != nil {
return errors.Wrap(err, "failed to provision tracify")
}
@@ -126,6 +133,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Criteo.Enabled && utils.Tag(criteoprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", criteoprovider.Name, "tag", criteoprovider.Tag)
if err := criteoprovider.Server(cmd.Context(), l, tm, cfg.Criteo); err != nil {
return errors.Wrap(err, "failed to provision criteo")
}
@@ -133,6 +141,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.MicrosoftAds.Enabled && utils.Tag(microsoftadsprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", microsoftadsprovider.Name, "tag", microsoftadsprovider.Tag)
if err := microsoftadsprovider.Server(cmd.Context(), l, tm, cfg.MicrosoftAds); err != nil {
return errors.Wrap(err, "failed to provision microsoftads")
}
@@ -140,6 +149,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Mixpanel.Enabled && utils.Tag(mixpanelprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", mixpanelprovider.Name, "tag", mixpanelprovider.Tag)
if err := mixpanelprovider.Server(cmd.Context(), l, tm, cfg.Mixpanel); err != nil {
return errors.Wrap(err, "failed to provision mixpanel")
}
@@ -147,6 +157,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
if cfg.Pinterest.Enabled && utils.Tag(pinterestprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", pinterestprovider.Name, "tag", pinterestprovider.Tag)
if err := pinterestprovider.Server(cmd.Context(), l, tm, cfg.Pinterest); err != nil {
return errors.Wrap(err, "failed to provision mixpanel")
}
@@ -163,6 +174,7 @@ func NewServer(l *slog.Logger) *cobra.Command {
for _, s := range i {
child.Children = append(child.Children, pterm.TreeNode{Text: s})
}
tree.Children = append(tree.Children, child)
}

View File

@@ -59,6 +59,7 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if utils.Tag(googletagprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", googletagprovider.Name, "tag", googletagprovider.Tag)
if err := googletagprovider.Web(cmd.Context(), tm, cfg.GoogleTag); err != nil {
return errors.Wrap(err, "failed to provision google tag provider")
}
@@ -72,6 +73,7 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if cfg.GoogleAnalytics.Enabled && utils.Tag(googleanaylticsprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", googleanaylticsprovider.Name, "tag", googleanaylticsprovider.Tag)
if err := googleanaylticsprovider.Web(cmd.Context(), tm, cfg.GoogleAnalytics); err != nil {
return errors.Wrap(err, "failed to provision google analytics provider")
}
@@ -79,6 +81,7 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if cfg.Emarsys.Enabled && utils.Tag(emarsysprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", emarsysprovider.Name, "tag", emarsysprovider.Tag)
if err := emarsysprovider.Web(cmd.Context(), tm, cfg.Emarsys); err != nil {
return errors.Wrap(err, "failed to provision emarsys provider")
}
@@ -86,6 +89,7 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if cfg.Hotjar.Enabled && utils.Tag(hotjarprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", hotjarprovider.Name, "tag", hotjarprovider.Tag)
if err := hotjarprovider.Web(cmd.Context(), tm, cfg.Hotjar); err != nil {
return errors.Wrap(err, "failed to provision hotjar provider")
}
@@ -93,6 +97,7 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if cfg.Criteo.Enabled && utils.Tag(criteoprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", criteoprovider.Name, "tag", criteoprovider.Tag)
if err := criteoprovider.Web(cmd.Context(), l, tm, cfg.Criteo); err != nil {
return errors.Wrap(err, "failed to provision criteo provider")
}
@@ -100,6 +105,7 @@ func NewWeb(l *slog.Logger) *cobra.Command {
if cfg.Cookiebot.Enabled && utils.Tag(cookiebotprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", cookiebotprovider.Name, "tag", cookiebotprovider.Tag)
if err := cookiebotprovider.Web(cmd.Context(), tm, cfg.Cookiebot); err != nil {
return errors.Wrap(err, "failed to provision cookiebot provider")
}
@@ -116,8 +122,10 @@ func NewWeb(l *slog.Logger) *cobra.Command {
for _, s := range i {
child.Children = append(child.Children, pterm.TreeNode{Text: s})
}
tree.Children = append(tree.Children, child)
}
if err := pterm.DefaultTree.WithRoot(tree).WithWriter(ptermx.NewWriter(pterm.Warning)).Render(); err != nil {
l.Warn("failed to render missed resources", "error", err)
}

View File

@@ -54,6 +54,7 @@ func NewTags(l *slog.Logger) *cobra.Command {
for _, name := range slices.Sorted(maps.Keys(tags)) {
data = append(data, []string{name, tags[name]})
}
return pterm.DefaultTable.WithHasHeader().WithData(data).Render()
},
}

View File

@@ -51,6 +51,7 @@ func NewTypeScript(l *slog.Logger) *cobra.Command {
}
l.InfoContext(cmd.Context(), "generated typescript code", "dir", outPath, "files", slices.AppendSeq(make([]string, 0, len(files)), maps.Keys(files)))
for filename, file := range files {
if err = os.WriteFile(path.Join(outPath, filename), []byte(file.String()), 0600); err != nil {
return errors.Wrap(err, "failed to write typescript code")

43
docs/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,43 @@
# Contributing
Thank you for your interest in contributing to our project! This guide will help you get started with the development process.
## Development Workflow
1. Fork this repository
2. Create a new branch: `git checkout -b feature/your-feature-name`
3. Make your changes
4. Check and fix code style and formatting issues: `make lint`
5. Run checks: `make test`
6. Build the project: `make build`
7. Commit your changes using the conventions below
8. Push your branch to your fork
9. Open a pull request
## Commit Message Conventions
We follow [Conventional Commits](https://www.conventionalcommits.org/) for clear and structured commit messages:
- `feat:` New features
- `fix:` Bug fixes
- `docs:` Documentation changes
- `style:` Code style changes (formatting, etc.)
- `refactor:` Code changes that neither fix bugs nor add features
- `perf:` Performance improvements
- `test:` Adding or updating tests
- `chore:` Maintenance tasks, dependencies, etc.
## Pull Request Guidelines
1. Update documentation if needed
2. Ensure all tests pass
3. Address any feedback from code reviews
4. Once approved, your PR will be merged
## Code of Conduct & Security
Please be respectful and constructive in all interactions within our community and follow the [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) and [SECURITY](SECURITY.md) guidelines.
## Questions?
If you have any questions, please [open an issue](https://github.com/foomo/sesamy-cli/issues/new) for discussion.

View File

Before

Width:  |  Height:  |  Size: 177 KiB

After

Width:  |  Height:  |  Size: 177 KiB

77
go.mod
View File

@@ -1,95 +1,94 @@
module github.com/foomo/sesamy-cli
go 1.25.1
go 1.26
require (
github.com/Code-Hex/Neo-cowsay/v2 v2.0.4
github.com/alecthomas/chroma v0.10.0
github.com/fatih/structtag v1.2.0
github.com/foomo/go v0.0.3
github.com/foomo/go v0.4.0
github.com/foomo/gocontemplate v0.2.0
github.com/foomo/sesamy-go v0.11.2
github.com/foomo/sesamy-go v0.12.1
github.com/invopop/jsonschema v0.13.0
github.com/itchyny/json2yaml v0.1.4
github.com/itchyny/json2yaml v0.1.5
github.com/joho/godotenv v1.5.1
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/file v1.2.0
github.com/knadh/koanf/providers/file v1.2.1
github.com/knadh/koanf/providers/rawbytes v1.0.0
github.com/knadh/koanf/v2 v2.2.2
github.com/knadh/koanf/v2 v2.3.3
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.81
github.com/spf13/cobra v1.10.1
github.com/pterm/pterm v0.12.83
github.com/spf13/cobra v1.10.2
github.com/spf13/viper v1.21.0
github.com/sters/yaml-diff v1.4.1
github.com/stoewer/go-strcase v1.3.1
github.com/stretchr/testify v1.11.1
github.com/wissance/stringFormatter v1.5.0
google.golang.org/api v0.249.0
github.com/wissance/stringFormatter v1.6.1
google.golang.org/api v0.272.0
)
require (
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
cloud.google.com/go/auth v0.16.5 // indirect
cloud.google.com/go/auth v0.18.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.8.0 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
github.com/Code-Hex/go-wordwrap v1.0.0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/containerd/console v1.0.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/foomo/gostandards v0.2.0 // indirect
github.com/foomo/gostandards v0.3.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/goccy/go-yaml v1.15.6 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
github.com/googleapis/gax-go/v2 v2.18.0 // indirect
github.com/gookit/color v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/knadh/koanf/maps v0.1.2 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mailru/easyjson v0.9.2 // indirect
github.com/mattn/go-runewidth v0.0.21 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 // indirect
go.opentelemetry.io/otel v1.42.0 // indirect
go.opentelemetry.io/otel/metric v1.42.0 // indirect
go.opentelemetry.io/otel/trace v1.42.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/tools v0.36.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
google.golang.org/grpc v1.75.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/mod v0.33.0 // indirect
golang.org/x/net v0.52.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/term v0.41.0 // indirect
golang.org/x/text v0.35.0 // indirect
golang.org/x/tools v0.42.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 // indirect
google.golang.org/grpc v1.79.2 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

172
go.sum
View File

@@ -6,12 +6,12 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=
cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ=
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 h1:y80Hd9hmB+rsEH/p4c5ti5PbO0PhBmxw4NgbpFZvoHg=
github.com/Code-Hex/Neo-cowsay/v2 v2.0.4/go.mod h1:6k40Pwrc2FazLf1BUbmAC36E9LvT+DErjZr30isbXhg=
github.com/Code-Hex/go-wordwrap v1.0.0 h1:yl5fLyZEz3+hPGbpTRlTQ8mQJ1HXWcTq1FCNR1ch6zM=
@@ -32,6 +32,10 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
@@ -47,14 +51,14 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/foomo/go v0.0.3 h1:5pGzcPC78dImuBTT7nsZZnH+GIQUylbCtMkFEH26uZk=
github.com/foomo/go v0.0.3/go.mod h1:x6g64wiQusqaFElnh5rlk9unCgLKmfUWy0YFLejJxio=
github.com/foomo/go v0.4.0 h1:9Qo5DLdoTI965sj6pDHm990Wzqk1RpbcGu0TZ4r2RNw=
github.com/foomo/go v0.4.0/go.mod h1:bZ/DrRPjvjpsg093nIHuifyHLNcgjKppBXzBCwSTYrU=
github.com/foomo/gocontemplate v0.2.0 h1:YbgNUwZ9mK9Wj05cGVTPamCpMuxlaL4qegkbZv2eqOY=
github.com/foomo/gocontemplate v0.2.0/go.mod h1:VOYIvxPPAT7HxrderRexS0EttcT8pyfSRkCMvS8rtxA=
github.com/foomo/gostandards v0.2.0 h1:Ryd7TI9yV3Xk5B84DcUDB7KcL3LzQ8NS+TVOrFxTYfA=
github.com/foomo/gostandards v0.2.0/go.mod h1:XQx7Ur6vyvxaIe2cQvAthuhPYDe+d2soibqVcXDXOh4=
github.com/foomo/sesamy-go v0.11.2 h1:P405IMMDzW/4hMKbAbvCVBaFjOARb26/PdG1wTBAxBM=
github.com/foomo/sesamy-go v0.11.2/go.mod h1:yORAeN0fDaZ0irXx4QdMp61wuDBAeEBHD0bTN4JjKxA=
github.com/foomo/gostandards v0.3.0 h1:Ev88Tdu0+52UH/d0l2KcAWx542A13o42d++LSTG0DC4=
github.com/foomo/gostandards v0.3.0/go.mod h1:8hJ56tpyFAVwavs5FuUF3po7Bq7hOTkQ1+DzFi4GCWg=
github.com/foomo/sesamy-go v0.12.1 h1:Gk14r7IYB3vAA+Dc4LEq+6fR/OfBDyQSRkmqhWQachE=
github.com/foomo/sesamy-go v0.12.1/go.mod h1:SW0G8wQJQ8GXjw+POcXyhtdQoI6qCZlYv7I8YuBTU1w=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
@@ -64,8 +68,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-yaml v1.15.6 h1:gy5kf1yjMia3/c3wWD+u1z3lU5XlhpT8FZGaLJU9cOA=
github.com/goccy/go-yaml v1.15.6/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@@ -77,10 +81,10 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8=
github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
github.com/googleapis/gax-go/v2 v2.18.0 h1:jxP5Uuo3bxm3M6gGtV94P4lliVetoCB4Wk2x8QA86LI=
github.com/googleapis/gax-go/v2 v2.18.0/go.mod h1:uSzZN4a356eRG985CzJ3WfbFSpqkLTjsnhWGJR6EwrE=
github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0=
github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
@@ -91,8 +95,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/itchyny/json2yaml v0.1.4 h1:/pErVOXGG5iTyXHi/QKR4y3uzhLjGTEmmJIy97YT+k8=
github.com/itchyny/json2yaml v0.1.4/go.mod h1:6iudhBZdarpjLFRNj+clWLAkGft+9uCcjAZYXUH9eGI=
github.com/itchyny/json2yaml v0.1.5 h1:wKaepxwivjcn2ssiLu7v4KrLKSIILWtwD/8L054tTdI=
github.com/itchyny/json2yaml v0.1.5/go.mod h1:lBQ0JI7HugKRQy/c5/U3KRymvBNub/HTbSXHS9/4018=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -104,12 +108,12 @@ github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpb
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
github.com/knadh/koanf/parsers/yaml v1.1.0/go.mod h1:HHmcHXUrp9cOPcuC+2wrr44GTUB0EC+PyfN3HZD9tFg=
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/providers/file v1.2.1 h1:bEWbtQwYrA+W2DtdBrQWyXqJaJSG3KrP3AESOJYp9wM=
github.com/knadh/koanf/providers/file v1.2.1/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/providers/rawbytes v1.0.0 h1:MrKDh/HksJlKJmaZjgs4r8aVBb/zsJyc/8qaSnzcdNI=
github.com/knadh/koanf/providers/rawbytes v1.0.0/go.mod h1:KxwYJf1uezTKy6PBtfE+m725NGp4GPVA7XoNTJ/PtLo=
github.com/knadh/koanf/v2 v2.2.2 h1:ghbduIkpFui3L587wavneC9e3WIliCgiCgdxYO/wd7A=
github.com/knadh/koanf/v2 v2.2.2/go.mod h1:abWQc0cBXLSF/PSOMCB/SK+T13NXDsPvOksbpi5e/9Q=
github.com/knadh/koanf/v2 v2.3.3 h1:jLJC8XCRfLC7n4F+ZKKdBsbq1bfXTpuFhf4L7t94D94=
github.com/knadh/koanf/v2 v2.3.3/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -119,12 +123,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mailru/easyjson v0.9.2 h1:dX8U45hQsZpxd80nLvDGihsQ/OxlvTkVUXH2r/8cb2M=
github.com/mailru/easyjson v0.9.2/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY=
@@ -147,26 +151,22 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
github.com/pterm/pterm v0.12.81 h1:ju+j5I2++FO1jBKMmscgh5h5DPFDFMB7epEjSoKehKA=
github.com/pterm/pterm v0.12.81/go.mod h1:TyuyrPjnxfwP+ccJdBTeWHtd/e0ybQHkOS/TakajZCw=
github.com/pterm/pterm v0.12.83 h1:ie+YmGmA727VuhxBlyGr74Ks+7McV6kT99IB8EU80aA=
github.com/pterm/pterm v0.12.83/go.mod h1:xlgc6bFWyJIMtmLJvGim+L7jhSReilOlOnodeIYe4Tk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -189,53 +189,53 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/wissance/stringFormatter v1.5.0 h1:hiGpYEJS3B3H/6M03HecqW8nDO0OXgQ75REVTXp6reM=
github.com/wissance/stringFormatter v1.5.0/go.mod h1:H7Mz15+5i8ypmv6bLknM/uD+U1teUW99PlW0DNCNscA=
github.com/wissance/stringFormatter v1.6.1 h1:Pf5m2lMi1z256+SgWLj+u4SGqSzix0HP0Z0t4QgMM2I=
github.com/wissance/stringFormatter v1.6.1/go.mod h1:H7Mz15+5i8ypmv6bLknM/uD+U1teUW99PlW0DNCNscA=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 h1:PnV4kVnw0zOmwwFkAzCN5O07fw1YOIQor120zrh0AVo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0/go.mod h1:ofAwF4uinaf8SXdVzzbL4OsxJ3VfeEg3f/F6CeF49/Y=
go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho=
go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc=
go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4=
go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI=
go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8=
go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90=
go.opentelemetry.io/otel/sdk/metric v1.41.0 h1:siZQIYBAUd1rlIWQT2uCxWJxcCO7q3TriaMlf08rXw8=
go.opentelemetry.io/otel/sdk/metric v1.41.0/go.mod h1:HNBuSvT7ROaGtGI50ArdRLUnvRTRGniSUZbxiWxSO8Y=
go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY=
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -247,45 +247,45 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w=
google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/api v0.272.0 h1:eLUQZGnAS3OHn31URRf9sAmRk3w2JjMx37d2k8AjJmA=
google.golang.org/api v0.272.0/go.mod h1:wKjowi5LNJc5qarNvDCvNQBn3rVK8nSy6jg2SwRwzIA=
google.golang.org/genproto v0.0.0-20260217215200-42d3e9bedb6d h1:vsOm753cOAMkt76efriTCDKjpCbK18XGHMJHo0JUKhc=
google.golang.org/genproto v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:0oz9d7g9QLSdv9/lgbIjowW1JoxMbxmBVNe8i6tORJI=
google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d h1:EocjzKLywydp5uZ5tJ79iP6Q0UjDnyiHkGRWxuPBP8s=
google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:48U2I+QQUYhsFrg2SY6r+nJzeOtjey7j//WBESw+qyQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 h1:aJmi6DVGGIStN9Mobk/tZOOQUBbj0BPjZjjnOdoZKts=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

View File

@@ -31,23 +31,28 @@ func main() {
if say, cerr := cowsay.Say(msg, cowsay.BallonWidth(80)); cerr == nil {
msg = say
}
return msg
}
code := 0
defer func() {
if r := recover(); r != nil {
l.Error(say("It's time to panic"))
l.Error(fmt.Sprintf("%v", r))
l.Error(string(debug.Stack()))
code = 1
}
os.Exit(code)
}()
if err := root.Execute(); err != nil {
l.Error(say(strings.Split(errors.Cause(err).Error(), ":")[0]))
l.Error(err.Error())
code = 1
}
}

View File

@@ -29,6 +29,7 @@ func TestConfig(t *testing.T) {
if t.Name() == "" {
return t.String()
}
return strings.ReplaceAll(t.PkgPath(), "/", ".") + "." + t.Name()
}
require.NoError(t, reflector.AddGoComments("github.com/foomo/sesamy-cli", "./"))
@@ -37,6 +38,7 @@ func TestConfig(t *testing.T) {
require.NoError(t, err)
filename := path.Join(cwd, "sesamy.schema.json")
expected, err := os.ReadFile(filename)
if !errors.Is(err, os.ErrNotExist) {
require.NoError(t, err)

View File

@@ -22,8 +22,10 @@ func ReadConfig(l *slog.Logger, c *viper.Viper, cmd *cobra.Command) (*config.Con
for _, filename := range c.GetStringSlice("config") {
var p koanf.Provider
if filename == "-" {
pterm.Debug.Println("reading config from stdin")
if b, err := io.ReadAll(cmd.InOrStdin()); err != nil {
return nil, err
} else {
@@ -33,13 +35,16 @@ func ReadConfig(l *slog.Logger, c *viper.Viper, cmd *cobra.Command) (*config.Con
pterm.Debug.Println("reading config from filename: " + filename)
p = file.Provider(filename)
}
if err := k.Load(p, yaml.Parser()); err != nil {
return nil, errors.Wrap(err, "error loading config file: "+filename)
}
}
var cfg *config.Config
pterm.Debug.Println("unmarshalling config")
if err := k.UnmarshalWithConf("", &cfg, koanf.UnmarshalConf{
Tag: "yaml",
}); err != nil {

View File

@@ -68,6 +68,7 @@ func (f *File) String() string {
section := f.Sections[id]
sectionParts := section.Parts
slices.Sort(sectionParts)
for _, part := range sectionParts {
b.WriteString(part + "\n")
}

View File

@@ -26,5 +26,6 @@ func (s *FacebookServerContainer) Setting(eventName string) FacebookConversionAP
if value, ok := s.Settings[eventName]; ok {
return value
}
return FacebookConversionAPITag{}
}

View File

@@ -22,5 +22,6 @@ func (s *GoogleAdsConversionServerContainer) Setting(eventName string) []GoogleA
if value, ok := s.Settings[eventName]; ok {
return value
}
return nil
}

View File

@@ -13,9 +13,10 @@ type GoogleAPI struct {
func (c GoogleAPI) GetClientOption() googleapioption.ClientOption {
var ret googleapioption.ClientOption
if c.CredentialsFile != "" {
ret = googleapioption.WithCredentialsFile(c.CredentialsFile)
ret = googleapioption.WithAuthCredentialsFile(googleapioption.ServiceAccount, c.CredentialsFile)
} else {
ret = googleapioption.WithCredentialsJSON([]byte(c.Credentials))
ret = googleapioption.WithAuthCredentialsJSON(googleapioption.ServiceAccount, []byte(c.Credentials))
}
return ret
}

View File

@@ -25,5 +25,6 @@ func (s *MicrosoftAdsServerContainer) Setting(eventName string) MicrosoftAdsConv
if value, ok := s.Settings[eventName]; ok {
return value
}
return MicrosoftAdsConversionTag{}
}

View File

@@ -19,14 +19,17 @@ func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.Conversio
}
var eventTriggerOpts []trigger.ConversionLinkerEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.ConversionLinkerEventWithConsentMode(consentVariable))
}

View File

@@ -19,6 +19,7 @@ func ConversionLinkerEventWithConsentMode(mode *tagmanager.Variable) ConversionL
func NewConversionLinkerEvent(name string, opts ...ConversionLinkerEventOption) *tagmanager.Trigger {
o := &ConversionLinkerEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -105,6 +105,7 @@ func NewCookiebotInitialization(name string, cfg config.Cookiebot, template *tag
Type: "map",
})
}
parameter = append(parameter, param)
}

View File

@@ -26,6 +26,7 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
if errors.Is(err, tagmanager.ErrNotFound) {
l.Warn("Please install the 'Criteo Events API' Tag Template manually first")
}
return err
}
@@ -52,14 +53,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.CriteoEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.CriteoEventWithConsentMode(consentVariable))
}

View File

@@ -23,6 +23,7 @@ func CriteoEventWithConsentMode(mode *tagmanager.Variable) CriteoEventOption {
func NewCriteoEvent(name string, opts ...CriteoEventOption) *tagmanager.Trigger {
o := &CriteoEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -22,6 +22,7 @@ func Web(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg con
if errors.Is(err, tagmanager.ErrNotFound) {
l.Warn("Please install the 'Criteo User Identification' template manually first")
}
return err
}

View File

@@ -29,5 +29,6 @@ func NewUserIdentification(name string, callerID, partnerID *tagmanager.Variable
},
Type: utils.TemplateType(template),
}
return ret
}

View File

@@ -52,14 +52,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.EmarsysEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.EmarsysEventWithConsentMode(consentVariable))
}

View File

@@ -163,9 +163,9 @@ function mapEventData() {
}
case 'view_item_list': {
const prefix = createRegex('^/', 'i');
const seperator = createRegex('/', 'i');
const separator = createRegex('/', 'i');
mappedData.cart = serializeItems(eventData.items || []);
mappedData.category = eventData.item_list_id.replace(prefix,"").replace(seperator, " > ");
mappedData.category = eventData.item_list_id.replace(prefix,"").replace(separator, " > ");
break;
}
case 'purchase': {

View File

@@ -23,6 +23,7 @@ func EmarsysEventWithConsentMode(mode *tagmanager.Variable) EmarsysEventOption {
func NewEmarsysEvent(name string, opts ...EmarsysEventOption) *tagmanager.Trigger {
o := &EmarsysEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -13,5 +13,6 @@ func NewEmarsysInitialization(name string, template *tagmanager.CustomTemplate)
TagFiringOption: "oncePerEvent",
Type: utils.TemplateType(template),
}
return ret
}

View File

@@ -33,8 +33,10 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
}
var testEventToken *tagmanager2.Variable
if cfg.TestEventToken != "" {
var err error
testEventToken, err = tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameTestEventTokenConstant, cfg.TestEventToken))
if err != nil {
return err
@@ -57,14 +59,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.FacebookEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.FacebookEventWithConsentMode(consentVariable))
}

View File

@@ -23,6 +23,7 @@ func FacebookEventWithConsentMode(mode *tagmanager.Variable) FacebookEventOption
func NewFacebookEvent(name string, opts ...FacebookEventOption) *tagmanager.Trigger {
o := &FacebookEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -53,14 +53,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.GoogleAdsEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.GoogleAdsEventWithConsentMode(consentVariable))
}
@@ -80,14 +83,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
// remarketing
if cfg.Remarketing.Enabled {
var eventTriggerOpts []trigger.GoogleAdsRemarketingEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.GoogleAdsRemarketingEventWithConsentMode(consentVariable))
}

View File

@@ -13,6 +13,7 @@ func GoogleAdsConversionTrackingName(v string) string {
func NewGoogleAdsConversionTracking(name string, value, currency, conversionID *tagmanager.Variable, settings config.GoogleAdsConversionTracking, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
tagName := GoogleAdsConversionTrackingName(name)
tagConversionID := "{{" + conversionID.Name + "}}"
if settings.ConversionID != "" {
tagName += " (" + settings.ConversionID + ")"
tagConversionID = settings.ConversionID

View File

@@ -23,6 +23,7 @@ func GoogleAdsEventWithConsentMode(mode *tagmanager.Variable) GoogleAdsEventOpti
func NewGoogleAdsEvent(name string, opts ...GoogleAdsEventOption) *tagmanager.Trigger {
o := &GoogleAdsEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -19,6 +19,7 @@ func GoogleAdsRemarketingEventWithConsentMode(mode *tagmanager.Variable) GoogleA
func NewGoogleAdsRemarketingEvent(name string, opts ...GoogleAdsRemarketingEventOption) *tagmanager.Trigger {
o := &GoogleAdsRemarketingEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -55,6 +55,7 @@ func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleAna
if err != nil {
return err
}
if _, err = tm.UpsertTrigger(ctx, folder, servertrigger.NewClient(NameMeasurementProtocolGA4ClientTrigger, client)); err != nil {
return err
}
@@ -106,14 +107,17 @@ func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleAna
for event := range eventParameters {
var eventTriggerOpts []trigger.GoogleAnalyticsEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.GoogleAnalyticsEventWithConsentMode(consentVariable))
}

View File

@@ -23,6 +23,7 @@ func GoogleAnalyticsEventWithConsentMode(mode *tagmanager.Variable) GoogleAnalyt
func NewGoogleAnalyticsEvent(name string, opts ...GoogleAnalyticsEventOption) *tagmanager.Trigger {
o := &GoogleAnalyticsEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -19,9 +19,11 @@ func ServerEnsure(ctx context.Context, tm *tagmanager.TagManager) error {
if err != nil {
return err
}
if _, err = tm.UpsertVariable(ctx, folder, variable.NewGoogleConsentModeAdStorage(consentTemplate)); err != nil {
return err
}
if _, err = tm.UpsertVariable(ctx, folder, variable.NewGoogleConsentModeAnalyticsStorage(consentTemplate)); err != nil {
return err
}

View File

@@ -28,16 +28,19 @@ func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTag) e
if !cfg.SendPageView {
configSettings["send_page_view"] = "false"
}
if cfg.ServerContainerURL != "" {
configSettings["server_container_url"] = cfg.ServerContainerURL
}
eventSettings := map[string]*api.Variable{}
for k, v := range cfg.DataLayerVariables {
dlv, err := tm.UpsertVariable(ctx, folder, variable.NewDataLayer(v))
if err != nil {
return err
}
eventSettings[k] = dlv
}
@@ -50,6 +53,7 @@ func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTag) e
if err != nil {
return err
}
if _, err = tm.UpsertTag(ctx, folder, webtag.NewGoogleTag(NameGoogleTag, tagID, settingsVariable, eventSettings)); err != nil {
return err
}
@@ -99,5 +103,6 @@ func CreateWebDatalayerVariables(ctx context.Context, tm *tagmanager.TagManager,
return nil, err
}
}
return variables, nil
}

View File

@@ -47,5 +47,6 @@ func NewGoogleTag(name string, tagID *tagmanager.Variable, configSettings *tagma
},
Type: "googtag",
}
return ret
}

View File

@@ -15,6 +15,7 @@ func NewGoogleTagEventSettings(name string, variables map[string]*tagmanager.Var
for k := range variables {
parameters = append(parameters, k)
}
sort.Strings(parameters)
list := make([]*tagmanager.Parameter, len(parameters))

View File

@@ -40,6 +40,7 @@ func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTag
return err
}
}
for key, value := range cfg.ServerContaienrVariables.LookupTables {
if _, err := tm.UpsertVariable(ctx, folder, commonvariable.NewLookupTable(key, value)); err != nil {
return err

View File

@@ -21,6 +21,7 @@ func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTagMan
return err
}
}
for key, value := range cfg.WebContaienrVariables.LookupTables {
if _, err := tm.UpsertVariable(ctx, folder, commonvariable.NewLookupTable(key, value)); err != nil {
return err

View File

@@ -18,5 +18,6 @@ func NewHotjar(name string, siteID *tagmanager.Variable) *tagmanager.Tag {
},
Type: "hjtc",
}
return ret
}

View File

@@ -41,14 +41,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.ConversionEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.ConversionEventWithConsentMode(consentVariable))
}

View File

@@ -23,6 +23,7 @@ func ConversionEventWithConsentMode(mode *tagmanager.Variable) ConversionEventOp
func NewConversionEvent(name string, opts ...ConversionEventOption) *tagmanager.Trigger {
o := &ConversionEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -34,6 +34,7 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
if errors.Is(err, tagmanager.ErrNotFound) {
l.Warn("Please install the 'Mixpanel' by stape-io Tag Template manually first")
}
return err
}
@@ -50,18 +51,22 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event, params := range eventParameters {
var eventTriggerOpts []trigger.EventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
}
eventParams := map[string]*tagmanager2.Variable{}
for k := range params {
if value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData(k)); err != nil {
return err
@@ -89,18 +94,22 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event, params := range eventParameters {
var eventTriggerOpts []trigger.EventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
}
eventParams := map[string]*tagmanager2.Variable{}
for k := range params {
if value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData(k)); err != nil {
return err
@@ -128,14 +137,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.EventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
}
@@ -158,18 +170,22 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event, params := range eventParameters {
var eventTriggerOpts []trigger.EventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
}
eventParams := map[string]*tagmanager2.Variable{}
for k := range params {
if value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData(k)); err != nil {
return err
@@ -197,14 +213,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.EventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
}

View File

@@ -53,6 +53,7 @@ func NewSet(name string, projectToken *tagmanager.Variable, template *tagmanager
if len(params) > 0 {
var list []*tagmanager.Parameter
for _, key := range slices.Sorted(maps.Keys(params)) {
param := params[key]
list = append(list, &tagmanager.Parameter{
@@ -71,6 +72,7 @@ func NewSet(name string, projectToken *tagmanager.Variable, template *tagmanager
},
})
}
parameter = append(parameter, &tagmanager.Parameter{
Key: "userPropertiesTable",
Type: "list",

View File

@@ -53,6 +53,7 @@ func NewSetOnce(name string, projectToken *tagmanager.Variable, template *tagman
if len(params) > 0 {
var list []*tagmanager.Parameter
for _, key := range slices.Sorted(maps.Keys(params)) {
param := params[key]
list = append(list, &tagmanager.Parameter{
@@ -71,6 +72,7 @@ func NewSetOnce(name string, projectToken *tagmanager.Variable, template *tagman
},
})
}
parameter = append(parameter, &tagmanager.Parameter{
Key: "userPropertiesToSetOnce",
Type: "list",

View File

@@ -58,6 +58,7 @@ func NewTrack(name string, projectToken *tagmanager.Variable, template *tagmanag
if len(params) > 0 {
var list []*tagmanager.Parameter
for _, key := range slices.Sorted(maps.Keys(params)) {
param := params[key]
list = append(list, &tagmanager.Parameter{
@@ -76,6 +77,7 @@ func NewTrack(name string, projectToken *tagmanager.Variable, template *tagmanag
},
})
}
parameter = append(parameter, &tagmanager.Parameter{
Key: "trackParameters",
Type: "list",

View File

@@ -23,6 +23,7 @@ func EventWithConsentMode(mode *tagmanager.Variable) EventOption {
func NewEvent(name string, opts ...EventOption) *tagmanager.Trigger {
o := &EventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -25,6 +25,7 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
if errors.Is(err, tagmanager.ErrNotFound) {
l.Warn("Please install the 'Pinterest API for Conversions Ta' Tag Template manually first")
}
return err
}
@@ -36,14 +37,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.EventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.ConversionWithConsentMode(consentVariable))
}

View File

@@ -40,6 +40,7 @@ func NewConversion(name string, cfg config.Pinterest, template *tagmanager.Custo
if testMode {
return "log"
}
return "donotlog"
}(cfg.TestModeEnabled),
},

View File

@@ -31,6 +31,7 @@ func ConversionWithConsentMode(mode *tagmanager.Variable) EventOption {
func NewConversion(name string, opts ...EventOption) *tagmanager.Trigger {
o := &EventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -46,14 +46,17 @@ func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg
for event := range eventParameters {
var eventTriggerOpts []trigger.TracifyEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.TracifyEventWithConsentMode(consentVariable))
}

View File

@@ -23,6 +23,7 @@ func TracifyEventWithConsentMode(mode *tagmanager.Variable) TracifyEventOption {
func NewTracifyEvent(name string, opts ...TracifyEventOption) *tagmanager.Trigger {
o := &TracifyEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -33,14 +33,17 @@ func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.Umami) er
for event := range eventParameters {
var eventTriggerOpts []trigger.UmamiEventOption
if cfg.GoogleConsent.Enabled {
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
return err
}
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
if err != nil {
return err
}
eventTriggerOpts = append(eventTriggerOpts, trigger.UmamiEventWithConsentMode(consentVariable))
}

View File

@@ -23,6 +23,7 @@ func UmamiEventWithConsentMode(mode *tagmanager.Variable) UmamiEventOption {
func NewUmamiEvent(name string, opts ...UmamiEventOption) *tagmanager.Trigger {
o := &UmamiEventOptions{}
for _, opt := range opts {
if opt != nil {
opt(o)

View File

@@ -75,6 +75,7 @@ func (s *SlogHandler) Handle(ctx context.Context, record slog.Record) error {
func (s *SlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
newS := *s
newS.attrs = attrs
return &newS
}

View File

@@ -17,6 +17,7 @@ func NewLookupTable(name string, data config.LookupTable) *tagmanager.Variable {
{
keys := slices.AppendSeq(make([]string, 0, len(data.KeyTable)), maps.Keys(data.KeyTable))
slices.Sort(keys)
for _, k := range keys {
v := data.KeyTable[k]
list = append(list, &tagmanager.Parameter{
@@ -36,8 +37,10 @@ func NewLookupTable(name string, data config.LookupTable) *tagmanager.Variable {
})
}
}
keys := slices.AppendSeq(make([]string, 0, len(data.ValueTable)), maps.Keys(data.ValueTable))
slices.Sort(keys)
for _, k := range keys {
v := data.ValueTable[k]
list = append(list, &tagmanager.Parameter{
@@ -56,6 +59,7 @@ func NewLookupTable(name string, data config.LookupTable) *tagmanager.Variable {
},
})
}
return &tagmanager.Variable{
Name: LookupTableName(name),
Parameter: []*tagmanager.Parameter{

Some files were not shown because too many files have changed in this diff Show More