diff --git a/.editorconfig b/.editorconfig index 61ea5dd7..f100c09b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,3 @@ indent_size = 2 [*.php] indent_size = 4 - -[Makefile] -indent_style = tab diff --git a/.gitattributes b/.gitattributes index cadd4117..641e8a3b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,25 @@ src/Resources/*.php linguist-generated src/Routes/*.php linguist-generated src/SeamClient.php linguist-generated + +# Keep development files out of the published package. +# GitHub builds the archives Composer downloads as dist with git archive, +# which honours these rules. +/.devcontainer export-ignore +/.editorconfig export-ignore +/.env.example export-ignore +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/.npmrc export-ignore +/.prettierignore export-ignore +/.prettierrc.json export-ignore +/.releaserc.json export-ignore +/codegen export-ignore +/eslint.config.ts export-ignore +/package-lock.json export-ignore +/package.json export-ignore +/phpunit.xml.dist export-ignore +/tests export-ignore +/tsconfig.json export-ignore +/version.ts export-ignore diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b1dab4d9..c3d9f4b0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @rchodava @andrii-balitskyi @seveibar +* @seamapi/sdk diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml new file mode 100644 index 00000000..d52103d3 --- /dev/null +++ b/.github/actions/setup-node/action.yml @@ -0,0 +1,46 @@ +--- +name: Setup Node.js +description: Setup Node.js and install dependencies. + +inputs: + node_version: + description: The Node.js version. + required: false + default: '24' + registry_url: + description: The Node.js package registry URL. + required: false + default: https://registry.npmjs.org + install_dependencies: + description: Install dependencies. + required: false + default: 'true' + +runs: + using: composite + steps: + - name: Setup Node.js + uses: actions/setup-node@v7 + if: inputs.install_dependencies == 'true' + with: + node-version: ${{ inputs.node_version }} + registry-url: ${{ inputs.registry_url }} + - name: Setup Node.js without cache + uses: actions/setup-node@v7 + if: inputs.install_dependencies == 'false' + with: + node-version: ${{ inputs.node_version }} + registry-url: ${{ inputs.registry_url }} + - name: Install dependencies + if: inputs.install_dependencies == 'true' + shell: bash + run: npm ci --ignore-scripts + - name: Rebuild Node.js modules + shell: bash + run: npm rebuild + - name: Run postinstall script + shell: bash + run: npm run postinstall --if-present + - name: Run prepare script + shell: bash + run: npm run prepare --if-present diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index e0b54475..fd9fcf70 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -1,15 +1,12 @@ --- name: Setup -description: Setup Node.js and install dependencies. +description: Setup PHP and install dependencies. + inputs: - node_version: - description: The Node.js version. - required: false - default: '24' - registry_url: - description: The Node.js package registry URL. + php_version: + description: The PHP version. required: false - default: https://registry.npmjs.org + default: '8.5' install_dependencies: description: Install dependencies. required: false @@ -18,28 +15,30 @@ inputs: runs: using: composite steps: - - name: Setup Node.js - uses: actions/setup-node@v7 - if: inputs.install_dependencies == 'true' + - name: Setup PHP + uses: shivammathur/setup-php@v2 with: - node-version: ${{ inputs.node_version }} - registry-url: ${{ inputs.registry_url }} - - name: Setup Node.js without cache - uses: actions/setup-node@v7 - if: inputs.install_dependencies == 'false' - with: - node-version: ${{ inputs.node_version }} - registry-url: ${{ inputs.registry_url }} - - name: Install dependencies + php-version: ${{ inputs.php_version }} + tools: composer:v2 + coverage: none + - name: Check lockfile if: inputs.install_dependencies == 'true' shell: bash - run: npm ci --ignore-scripts - - name: Rebuild Node.js modules - shell: bash - run: npm rebuild - - name: Run postinstall script + run: composer validate --strict + - name: Get Composer cache directory + id: composer_cache + if: inputs.install_dependencies == 'true' shell: bash - run: npm run postinstall --if-present - - name: Run prepare script + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Setup Composer cache + uses: actions/cache@v4 + if: inputs.install_dependencies == 'true' + with: + key: composer-${{ inputs.php_version }}-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('composer.lock') }} + restore-keys: | + composer-${{ inputs.php_version }}-${{ runner.os }}-${{ runner.arch }}- + path: ${{ steps.composer_cache.outputs.dir }} + - name: Install dependencies + if: inputs.install_dependencies == 'true' shell: bash - run: npm run prepare --if-present + run: composer install --no-interaction --no-progress diff --git a/.github/workflows/_build.yml b/.github/workflows/_build.yml new file mode 100644 index 00000000..63aea632 --- /dev/null +++ b/.github/workflows/_build.yml @@ -0,0 +1,36 @@ +--- +name: _build + +on: + workflow_call: + inputs: + php_version: + description: The PHP version. + type: string + required: false + default: '8.5' + outputs: + artifact_name: + description: The artifact name. + value: build-${{ github.sha }} + +jobs: + build: + name: Package + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Setup + uses: ./.github/actions/setup + with: + php_version: ${{ inputs.php_version }} + - name: Build + run: composer build + - name: Upload artifact + uses: actions/upload-artifact@v7 + with: + name: build-${{ github.sha }} + if-no-files-found: error + path: pkg/ diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 00000000..95ca05d1 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,124 @@ +--- +name: Check + +on: + push: + branches: + - main + pull_request: + branches: + - '**' + +jobs: + test: + name: Test (PHP ${{ matrix.php }} on ${{ matrix.os_name }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + php: + - '8.0' + - '8.5' + include: + - os: ubuntu-latest + os_name: Linux + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Setup + uses: ./.github/actions/setup + with: + php_version: ${{ matrix.php }} + - name: Setup Node.js + uses: ./.github/actions/setup-node + - name: Test + run: composer test + lint: + name: Lint (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + php: + - '8.0' + - '8.5' + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Setup + uses: ./.github/actions/setup + with: + php_version: ${{ matrix.php }} + - name: Setup Node.js + uses: ./.github/actions/setup-node + - name: Lint + run: composer lint + - name: Lint with ESLint and Prettier + run: npm run lint + build: + name: Build + uses: ./.github/workflows/_build.yml + install: + name: Install (PHP ${{ matrix.php }} on ${{ matrix.os_name }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + needs: build + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + php: + - '8.0' + - '8.5' + include: + - os: ubuntu-latest + os_name: Linux + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: none + - name: Download artifact + uses: actions/download-artifact@v8 + with: + name: ${{ needs.build.outputs.artifact_name }} + path: pkg/ + - name: Extract package + run: unzip -q pkg/seam.zip -d package + - name: Create composer.json + uses: DamianReeves/write-file-action@v1.3 + with: + write-mode: overwrite + path: composer.json + contents: | + { + "repositories": [ + { + "type": "path", + "url": "./package", + "options": { "symlink": false } + } + ], + "require": { "seamapi/seam": "*" }, + "minimum-stability": "dev" + } + - name: Create main.php + uses: DamianReeves/write-file-action@v1.3 + with: + write-mode: overwrite + path: main.php + contents: | + diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml index dd5e1472..f163e526 100644 --- a/.github/workflows/generate.yml +++ b/.github/workflows/generate.yml @@ -27,8 +27,8 @@ jobs: git_committer_email: ${{ secrets.GIT_USER_EMAIL }} gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.GPG_PASSPHRASE }} - - name: Setup - uses: ./.github/actions/setup + - name: Setup Node.js + uses: ./.github/actions/setup-node with: install_dependencies: 'false' - name: Normalize package-lock.json diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 42ac2323..506ee053 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,3 +1,4 @@ +--- name: Publish run-name: Publish ${{ github.ref_name }} @@ -8,16 +9,24 @@ on: - v* jobs: + build: + name: Build + uses: ./.github/workflows/_build.yml release: name: GitHub Releases runs-on: ubuntu-latest timeout-minutes: 30 + needs: build steps: - name: Checkout uses: actions/checkout@v7 with: fetch-depth: 0 - + - name: Download artifact + uses: actions/download-artifact@v8 + with: + name: ${{ needs.build.outputs.artifact_name }} + path: pkg/ - name: Generate release notes id: changelog run: | @@ -26,11 +35,11 @@ jobs: echo "outfile=${outfile}" >> $GITHUB_OUTPUT npx standard-changelog@^5.0.0 --release-count 2 --infile $outfile.tmp --outfile $outfile.tmp sed '1,3d' $outfile.tmp > $outfile - - name: Create GitHub release uses: softprops/action-gh-release@v3 with: token: ${{ secrets.GH_TOKEN }} + fail_on_unmatched_files: true prerelease: ${{ contains(github.ref_name, '-') }} - files: '' + files: pkg/* body_path: ${{ github.workspace }}/${{ steps.changelog.outputs.outfile }} diff --git a/.github/workflows/semantic-release.yml b/.github/workflows/semantic-release.yml index 88a1dfc1..b2e3aab9 100644 --- a/.github/workflows/semantic-release.yml +++ b/.github/workflows/semantic-release.yml @@ -6,7 +6,7 @@ run-name: Semantic Release from ${{ github.ref_name }} on: push: branches: - - main + - '**' concurrency: group: ${{ github.workflow }}-${{ github.ref_name }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 7f897d7d..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: PHP Test -on: ['pull_request'] -jobs: - test: - if: "!contains(github.event.head_commit.message, 'skip ci')" - name: Run PHP Tests - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.0' - - run: composer install - - run: composer exec phpunit tests - env: - SEAM_API_KEY: ${{ secrets.SEAM_API_KEY }} diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 7435c6d2..3d9a72f8 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -29,7 +29,7 @@ jobs: git_committer_email: ${{ secrets.GIT_USER_EMAIL }} gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.GPG_PASSPHRASE }} - - name: Setup - uses: ./.github/actions/setup + - name: Setup Node.js + uses: ./.github/actions/setup-node - name: Cut ${{ github.event.inputs.version }} version run: npm version --sign-git-tag=true ${{ github.event.inputs.version }} diff --git a/.gitignore b/.gitignore index 56327be0..78aaf436 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,12 @@ CODEGEN.md vendor tmp +# PHPUnit result cache +.phpunit.result.cache + # Build directories package +/pkg/ # Environment versions file .versions diff --git a/.prettierrc.json b/.prettierrc.json index 4e3a60e5..66ce34de 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,15 +1,22 @@ { "plugins": ["@prettier/plugin-php"], - "parser": "php", - + "semi": false, + "singleQuote": true, + "jsxSingleQuote": true, + "endOfLine": "lf", "overrides": [ { - "files": "**/*.{js,ts,json,yml,md}", + "files": "**/*.php", "options": { - "semi": false, - "singleQuote": true, - "jsxSingleQuote": true, - "endOfLine": "lf" + "parser": "php", + "semi": true, + "singleQuote": false + } + }, + { + "files": "**/*.md", + "options": { + "embeddedLanguageFormatting": "off" } } ] diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..ebaae486 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2021-2024 Seam Labs, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 2ca38f9f..567a864c 100644 --- a/README.md +++ b/README.md @@ -163,15 +163,96 @@ If you want to install our previous handwritten version, run: `composer require seamapi/seam:1.1` -## Development Setup +## Development and Testing -1. Run `yarn install` to get prettier installed for formatting -2. Install [composer](https://getcomposer.org/). -3. Run `composer install` in this directory -4. Run `composer exec phpunit tests` +### Quickstart -> To run a specific test file, do `composer exec phpunit tests/MyTest.php` +Install [PHP](https://www.php.net/) 8.0 or later, +[Composer](https://getcomposer.org/) and [Node.js](https://nodejs.org/), +then run + +``` +$ git clone git@github.com:seamapi/php.git +$ cd php +$ composer install +$ npm install +``` + +Primary development tasks are defined as [Composer scripts](https://getcomposer.org/doc/articles/scripts.md) +in `composer.json` and available via `composer`. +View them with + +``` +$ composer run-script --list +``` + +| Task | Command | +| ----------------- | ------------------ | +| Run the tests | `composer test` | +| Lint | `composer lint` | +| Format | `npm run format` | +| Build the package | `composer build` | +| Generate the SDK | `npm run generate` | + +Formatting is handled by [Prettier](https://prettier.io/) via +[@prettier/plugin-php](https://github.com/prettier/plugin-php), +so PHP, TypeScript, JSON, YAML and Markdown are all formatted by +`npm run format`. ### Running Tests -You'll need to export `SEAM_API_KEY` to a sandbox workspace API key. \ No newline at end of file +Run the full suite with + +``` +$ composer test +``` + +To run a specific test file, pass it as an argument + +``` +$ composer test -- tests/MyTest.php +``` + +PHPUnit is configured in `phpunit.xml.dist`. + +### Requirements + +This package supports PHP 8.0 and later. +Continuous integration exercises both ends of that range, PHP 8.0 and 8.5. + +### Publishing + +#### Automatic + +New versions are released automatically from `main` by the +[Semantic Release](.github/workflows/semantic-release.yml) workflow, +which reads [Conventional Commits](https://www.conventionalcommits.org/) +and dispatches the [Version](.github/workflows/version.yml) workflow. + +#### Manual + +Run the [Version](.github/workflows/version.yml) workflow with the +version to cut. +It runs `npm version`, which bumps the `version` field in `package.json`, +injects that version into `Seam\Utils\PackageVersion`, creates a signed `v*` +git tag and pushes it. +Pushing the tag triggers the [Publish](.github/workflows/publish.yml) +workflow, and [Packagist](https://packagist.org/packages/seamapi/seam) +picks up the new tag from its GitHub webhook. + +> Composer has no canonical place to store a package version, since Packagist +> derives it from the git tag, and it publishes the tag as-is with no build +> step in between. +> This repository therefore keeps the version in `package.json`, which is a +> development manifest that is not published, and injects it into the +> `Seam\Utils\PackageVersion::VERSION` constant used for the +> `seam-sdk-version` header. +> +> The injection runs from `version.ts`, wired to the `version` lifecycle +> script, which npm runs after the bump but before the commit, so the +> updated constant is part of the tagged commit. +> Never edit that constant by hand; a test asserts it matches `package.json`. + +Development files are kept out of the published package with `export-ignore` +rules in `.gitattributes`, which `git archive` honours when GitHub builds the +archives Composer downloads as `dist`. diff --git a/codegen/lib/handlebars-helpers.ts b/codegen/lib/handlebars-helpers.ts index 41238d38..263be9ce 100644 --- a/codegen/lib/handlebars-helpers.ts +++ b/codegen/lib/handlebars-helpers.ts @@ -52,10 +52,14 @@ const createPhpDoc = ( .split(/\r?\n/) .map(sanitizePhpDocLine) const populatedDescription = description.trim() === '' ? [] : descriptionLines - const populatedTags = tags.filter((tag) => tag.trim() !== '').map(sanitizePhpDocLine) + const populatedTags = tags + .filter((tag) => tag.trim() !== '') + .map(sanitizePhpDocLine) const lines = [ ...populatedDescription, - ...(populatedDescription.length > 0 && populatedTags.length > 0 ? [''] : []), + ...(populatedDescription.length > 0 && populatedTags.length > 0 + ? [''] + : []), ...populatedTags, ] diff --git a/codegen/lib/resource-model.ts b/codegen/lib/resource-model.ts index 0289112e..e29a192f 100644 --- a/codegen/lib/resource-model.ts +++ b/codegen/lib/resource-model.ts @@ -16,8 +16,14 @@ import { getPhpType } from './map-php-type.js' export type ResourceClassProperty = | ({ kind: 'value'; phpType: string } & ResourceClassPropertyMetadata) - | ({ kind: 'objectReference'; referenceName: string } & ResourceClassPropertyMetadata) - | ({ kind: 'listReference'; referenceName: string } & ResourceClassPropertyMetadata) + | ({ + kind: 'objectReference' + referenceName: string + } & ResourceClassPropertyMetadata) + | ({ + kind: 'listReference' + referenceName: string + } & ResourceClassPropertyMetadata) interface ResourceClassPropertyMetadata { name: string @@ -109,8 +115,12 @@ export const createResourceModel = (blueprint: Blueprint): ResourceModel => { currentResourceName = name localClassNames.set(name, []) const sourceResource = - blueprint.resources.find((resource) => resource.resourceType === resourceType) ?? - (resourceType === 'event' ? blueprint.events[0] : blueprint.actionAttempts[0]) + blueprint.resources.find( + (resource) => resource.resourceType === resourceType, + ) ?? + (resourceType === 'event' + ? blueprint.events[0] + : blueprint.actionAttempts[0]) addClass( name, baseResources.get(resourceType) ?? [], diff --git a/codegen/lib/routes.ts b/codegen/lib/routes.ts index 974a6ecf..f18f155a 100644 --- a/codegen/lib/routes.ts +++ b/codegen/lib/routes.ts @@ -102,7 +102,8 @@ export const routes = ( const createClientMethod = (endpoint: Endpoint): PhpClientMethod => { const { response } = endpoint - const responseKey = response.responseType === 'void' ? '' : response.responseKey + const responseKey = + response.responseType === 'void' ? '' : response.responseKey // Batch responses have no single resource type; they deserialize into the // Batch resource. A response whose resource type the blueprint cannot @@ -126,17 +127,17 @@ const createClientMethod = (endpoint: Endpoint): PhpClientMethod => { isDeprecated: endpoint.isDeprecated, deprecationMessage: endpoint.deprecationMessage, parameters: endpoint.request.parameters.map((parameter) => ({ - name: parameter.name, - type: getPhpType(parameter), - description: parameter.description, - required: parameter.isRequired, - // The primary identifier of a get endpoint always sorts first in the - // method signature. - position: - endpoint.name === 'get' && parameter.name === `${responseKey}_id` - ? 0 - : undefined, - })), + name: parameter.name, + type: getPhpType(parameter), + description: parameter.description, + required: parameter.isRequired, + // The primary identifier of a get endpoint always sorts first in the + // method signature. + position: + endpoint.name === 'get' && parameter.name === `${responseKey}_id` + ? 0 + : undefined, + })), returnPath: responseKey, returnResource: resourceType === '' ? '' : pascalCase(resourceType), isArrayResponse: diff --git a/composer.json b/composer.json index b8d0b9b4..6827b5ce 100644 --- a/composer.json +++ b/composer.json @@ -1,24 +1,96 @@ { "name": "seamapi/seam", + "description": "SDK for the Seam API written in PHP.", "type": "library", + "keywords": [ + "seam", + "sdk", + "api", + "iot", + "smart-lock", + "access-control" + ], + "homepage": "https://github.com/seamapi/php", + "license": "MIT", + "authors": [ + { + "name": "Seam Labs, Inc.", + "email": "engineering@getseam.com", + "homepage": "https://www.seam.co" + } + ], + "support": { + "docs": "https://docs.seam.co", + "issues": "https://github.com/seamapi/php/issues", + "source": "https://github.com/seamapi/php" + }, "require": { + "php": "^8.0", "guzzlehttp/guzzle": "^7.5" }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7" + }, "autoload": { "psr-4": { - "Seam\\": ["src/", "src/Exceptions/"], - "Tests\\": "tests/" + "Seam\\": [ + "src/", + "src/Exceptions/" + ] }, - "classmap": ["src/Resources/"] + "classmap": [ + "src/Resources/" + ] }, - "authors": [ - { - "name": "seveibar", - "email": "seveibar@gmail.com" + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" } - ], - "require-dev": { - "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "^3.7" + }, + "config": { + "sort-packages": true + }, + "archive": { + "exclude": [ + "/.devcontainer", + "/.editorconfig", + "/.env.example", + "/.github", + "/.npmrc", + "/.phpunit.result.cache", + "/.prettierignore", + "/.prettierrc.json", + "/.releaserc.json", + "/codegen", + "/eslint.config.ts", + "/node_modules", + "/package-lock.json", + "/package.json", + "/phpunit.xml.dist", + "/pkg", + "/tests", + "/tmp", + "/tsconfig.json", + "/vendor", + "/version.ts" + ] + }, + "scripts": { + "build": "@composer archive --format=zip --dir=pkg --file=seam", + "test": "phpunit", + "lint": [ + "@lint:composer", + "@lint:syntax" + ], + "lint:composer": "@composer validate --strict", + "lint:syntax": "! find src tests -name '*.php' -exec php -l {} \\; | grep -v '^No syntax errors detected'" + }, + "scripts-descriptions": { + "build": "Build a distributable archive of this package into pkg/.", + "test": "Run the test suite.", + "lint": "Run all lint checks.", + "lint:composer": "Validate composer.json and composer.lock.", + "lint:syntax": "Check every PHP source file for syntax errors." } } diff --git a/composer.lock b/composer.lock index 55187fba..bc6794ae 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dbef2f8bca9faca558cad1eb1b7a1771", + "content-hash": "47b28c106be0ff4f75680c1fe23e931a", "packages": [ { "name": "guzzlehttp/guzzle", @@ -54,13 +54,17 @@ } }, "autoload": { - "files": ["src/functions_include.php"], + "files": [ + "src/functions_include.php" + ], "psr-4": { "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "Graham Campbell", @@ -157,13 +161,17 @@ } }, "autoload": { - "files": ["src/functions_include.php"], + "files": [ + "src/functions_include.php" + ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "Graham Campbell", @@ -187,7 +195,9 @@ } ], "description": "Guzzle promises library", - "keywords": ["promise"], + "keywords": [ + "promise" + ], "support": { "issues": "https://github.com/guzzle/promises/issues", "source": "https://github.com/guzzle/promises/tree/1.5.2" @@ -256,7 +266,9 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "Graham Campbell", @@ -355,7 +367,9 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "PHP-FIG", @@ -364,7 +378,12 @@ ], "description": "Common interface for HTTP clients", "homepage": "https://github.com/php-fig/http-client", - "keywords": ["http", "http-client", "psr", "psr-18"], + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], "support": { "source": "https://github.com/php-fig/http-client/tree/master" }, @@ -400,7 +419,9 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "PHP-FIG", @@ -452,7 +473,9 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "PHP-FIG", @@ -497,10 +520,14 @@ }, "type": "library", "autoload": { - "files": ["src/getallheaders.php"] + "files": [ + "src/getallheaders.php" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "Ralph Khattar", @@ -542,10 +569,14 @@ } }, "autoload": { - "files": ["function.php"] + "files": [ + "function.php" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "Nicolas Grekas", @@ -613,7 +644,9 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "authors": [ { "name": "Marco Pivetta", @@ -623,7 +656,10 @@ ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": ["constructor", "instantiate"], + "keywords": [ + "constructor", + "instantiate" + ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", "source": "https://github.com/doctrine/instantiator/tree/1.4.1" @@ -672,15 +708,25 @@ }, "type": "library", "autoload": { - "files": ["src/DeepCopy/deep_copy.php"], + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", - "license": ["MIT"], + "license": [ + "MIT" + ], "description": "Create deep copies (clones) of your objects", - "keywords": ["clone", "copy", "duplicate", "object", "object graph"], + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" @@ -715,7 +761,9 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, - "bin": ["bin/php-parse"], + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { @@ -728,14 +776,19 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", - "keywords": ["parser", "php"], + "keywords": [ + "parser", + "php" + ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" @@ -770,10 +823,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Arne Blankerts", @@ -817,10 +874,14 @@ }, "type": "library", "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Arne Blankerts", @@ -888,10 +949,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -901,7 +966,11 @@ ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": ["coverage", "testing", "xunit"], + "keywords": [ + "coverage", + "testing", + "xunit" + ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17" @@ -941,10 +1010,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -954,7 +1027,10 @@ ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": ["filesystem", "iterator"], + "keywords": [ + "filesystem", + "iterator" + ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" @@ -998,10 +1074,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1011,7 +1091,9 @@ ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": ["process"], + "keywords": [ + "process" + ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" @@ -1051,10 +1133,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1064,7 +1150,9 @@ ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": ["template"], + "keywords": [ + "template" + ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" @@ -1104,10 +1192,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1117,7 +1209,9 @@ ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": ["timer"], + "keywords": [ + "timer" + ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" @@ -1177,7 +1271,9 @@ "ext-soap": "*", "ext-xdebug": "*" }, - "bin": ["phpunit"], + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { @@ -1185,11 +1281,17 @@ } }, "autoload": { - "files": ["src/Framework/Assert/Functions.php"], - "classmap": ["src/"] + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1199,7 +1301,11 @@ ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", - "keywords": ["phpunit", "testing", "xunit"], + "keywords": [ + "phpunit", + "testing", + "xunit" + ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24" @@ -1243,10 +1349,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1295,10 +1405,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1347,10 +1461,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1400,10 +1518,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1424,7 +1546,11 @@ ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": ["comparator", "compare", "equality"], + "keywords": [ + "comparator", + "compare", + "equality" + ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" @@ -1465,10 +1591,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1518,10 +1648,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1534,7 +1668,12 @@ ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": ["diff", "udiff", "unidiff", "unified diff"], + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" @@ -1577,10 +1716,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1589,7 +1732,11 @@ ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": ["Xdebug", "environment", "hhvm"], + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" @@ -1631,10 +1778,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1659,7 +1810,10 @@ ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": ["export", "exporter"], + "keywords": [ + "export", + "exporter" + ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" @@ -1705,10 +1859,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1717,7 +1875,9 @@ ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": ["global state"], + "keywords": [ + "global state" + ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" @@ -1758,10 +1918,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1812,10 +1976,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1863,10 +2031,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1914,10 +2086,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -1973,10 +2149,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -2024,10 +2204,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -2073,10 +2257,14 @@ } }, "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Sebastian Bergmann", @@ -2103,12 +2291,12 @@ "version": "3.7.1", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", "shasum": "" }, @@ -2121,7 +2309,10 @@ "require-dev": { "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, - "bin": ["bin/phpcs", "bin/phpcbf"], + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], "type": "library", "extra": { "branch-alias": { @@ -2129,7 +2320,9 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Greg Sherwood", @@ -2138,7 +2331,10 @@ ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": ["phpcs", "standards"], + "keywords": [ + "phpcs", + "standards" + ], "support": { "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", "source": "https://github.com/squizlabs/PHP_CodeSniffer", @@ -2168,10 +2364,14 @@ }, "type": "library", "autoload": { - "classmap": ["src/"] + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": ["BSD-3-Clause"], + "license": [ + "BSD-3-Clause" + ], "authors": [ { "name": "Arne Blankerts", @@ -2195,10 +2395,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform": { + "php": "^8.0" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/package.json b/package.json index d220fa7c..e2b1f75c 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "private": true, "license": "MIT", "scripts": { + "version": "tsx ./version.ts && git add src/Utils/PackageVersion.php", "postversion": "git push --follow-tags", "generate": "tsx codegen/smith.ts", "postgenerate": "npm run format", diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 00000000..e953736f --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,22 @@ + + + + + tests + + + + + src + + + diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 431586d4..00000000 --- a/renovate.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:base"], - "commitMessagePrefix": "autorelease:", - "packageRules": [ - { - "packagePatterns": ["*"], - "excludePackagePatterns": ["@seamapi/types"], - "enabled": false - }, - { - "matchUpdateTypes": ["major", "minor", "patch"], - "automerge": true - } - ] -} diff --git a/src/Utils/PackageVersion.php b/src/Utils/PackageVersion.php index 0dc8a6a3..4aa2fb50 100644 --- a/src/Utils/PackageVersion.php +++ b/src/Utils/PackageVersion.php @@ -2,41 +2,18 @@ namespace Seam\Utils; -class PackageVersionException extends \Exception {} - class PackageVersion { - public static function get() + /** + * The version of this package. + * + * Injected from package.json when a version is cut, by the version + * lifecycle script in package.json. Do not edit by hand. + */ + public const VERSION = "3.5.0"; + + public static function get(): string { - $filePath = __DIR__ . "/../../package.json"; - - if (!file_exists($filePath)) { - throw new PackageVersionException( - "Can't get package version. File package.json does not exist.", - ); - } - - $content = file_get_contents($filePath); - if ($content === false) { - throw new PackageVersionException( - "Unable to read package.json file to get package version.", - ); - } - - $json = json_decode($content, true); - if (json_last_error() !== JSON_ERROR_NONE) { - throw new PackageVersionException( - "JSON decode error occurred when decoding package.json: " . - json_last_error_msg(), - ); - } - - if (!isset($json["version"])) { - throw new PackageVersionException( - "Version not set in package.json", - ); - } - - return $json["version"]; + return self::VERSION; } } diff --git a/tests/PackageVersionTest.php b/tests/PackageVersionTest.php new file mode 100644 index 00000000..d45e970d --- /dev/null +++ b/tests/PackageVersionTest.php @@ -0,0 +1,36 @@ +assertIsString($contents, "Could not read $path"); + + $package = json_decode($contents, true); + $this->assertIsArray($package, "Could not decode $path"); + $this->assertArrayHasKey("version", $package); + + $this->assertSame( + $package["version"], + PackageVersion::get(), + "Seam\\Utils\\PackageVersion is out of date with package.json. " . + "It is injected by the version lifecycle script when a " . + "version is cut and should not be edited by hand.", + ); + } + + public function testVersionIsUsedAsTheSdkVersionHeader(): void + { + $seam = new \Seam\SeamClient("seam_apikey1_token"); + $headers = $seam->client->getConfig("headers"); + + $this->assertSame(PackageVersion::get(), $headers["seam-sdk-version"]); + } +} diff --git a/tsconfig.json b/tsconfig.json index 6190bfbf..c3d380f1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,5 +2,5 @@ "$schema": "https://json.schemastore.org/tsconfig.json", "extends": "./node_modules/@seamapi/smith/tsconfig.base.json", "files": ["codegen/index.ts"], - "include": ["codegen/**/*", "eslint.config.ts"] + "include": ["codegen/**/*", "eslint.config.ts", "version.ts"] } diff --git a/version.ts b/version.ts new file mode 100644 index 00000000..697bea44 --- /dev/null +++ b/version.ts @@ -0,0 +1,44 @@ +import { readFile, writeFile } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' + +const versionFile = './src/Utils/PackageVersion.php' + +const versionPattern = /public const VERSION = "[^"]*";/ + +const main = async (): Promise => { + const version = await injectVersion( + fileURLToPath(new URL(versionFile, import.meta.url)), + ) + // eslint-disable-next-line no-console + console.log(`✓ Version ${version} injected into ${versionFile}`) +} + +const injectVersion = async (path: string): Promise => { + const { version } = await readPackageJson() + + if (version == null) { + throw new Error('Missing version in package.json') + } + + const data = (await readFile(path)).toString() + + if (!versionPattern.test(data)) { + throw new Error(`Could not find the version constant in ${versionFile}`) + } + + await writeFile( + path, + data.replace(versionPattern, `public const VERSION = "${version}";`), + ) + + return version +} + +const readPackageJson = async (): Promise<{ version?: string }> => { + const pkgBuff = await readFile( + fileURLToPath(new URL('package.json', import.meta.url)), + ) + return JSON.parse(pkgBuff.toString()) +} + +await main()