From be0da83b16c82c6ab67f4d4bbe46a25655c06266 Mon Sep 17 00:00:00 2001 From: Palm Civet Date: Wed, 3 Apr 2024 00:12:34 +0800 Subject: [PATCH] feat: use @getspectra/spectra-typings --- .github/workflows/release.yml | 7 ++----- .github/workflows/test.yml | 15 ++++++++------- README.md | 4 ++-- package.json | 14 +++++++++++--- pnpm-lock.yaml | 9 +++++++++ src/expressions/and.ts | 5 +++-- src/expressions/binary.ts | 9 ++++----- src/expressions/factory.ts | 17 +++++++---------- src/expressions/not.ts | 5 +++-- src/expressions/or.ts | 5 +++-- src/types/expression.ts | 4 ++-- src/types/index.ts | 1 - src/types/literal.ts | 29 ---------------------------- src/types/operation.ts | 6 ------ src/utils/compare.ts | 3 ++- src/utils/evaluate.ts | 21 ++++++++++++++++++++ src/utils/expression.ts | 36 ++++++++++++++++++++++------------- src/utils/index.ts | 1 + src/utils/policy.ts | 35 +--------------------------------- 19 files changed, 102 insertions(+), 124 deletions(-) delete mode 100644 src/types/literal.ts create mode 100644 src/utils/evaluate.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 42ac592..9b94af4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,3 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - name: Release on: @@ -37,7 +34,7 @@ jobs: registry-url: https://npm.pkg.github.com/ - run: pnpm publish env: - NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} publish-npm: needs: build @@ -53,4 +50,4 @@ jobs: registry-url: https://npm.pkg.github.com/ - run: pnpm publish env: - NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f03465..5d64d49 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,3 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - name: CI on: [push, pull_request] @@ -9,14 +6,18 @@ jobs: build: runs-on: ubuntu-latest permissions: - contents: write + pages: write steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 with: node-version: 20 - - uses: pnpm/action-setup@v3 + - name: Set up pnpm + uses: pnpm/action-setup@v3 with: version: 8 run_install: | diff --git a/README.md b/README.md index d33f2e3..4df0aba 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Inspired by [《How we built a custom permissions DSL at Figma》](https://www.f ## Installing ```bash -pnpm install spectra-js +pnpm install @getspectra/spectra-js ``` ## Usage @@ -33,7 +33,7 @@ import { parseDependences, ResourceInterface, DataInterface, - } from 'spectra-js'; + } from '@getspectra/spectra-js'; function loadDataFromDatabase(resources: ResourceInterface): DataInterface { return { diff --git a/package.json b/package.json index 2ad7b9d..9245edd 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "spectra-js", + "name": "@getspectra/spectra-js", "version": "0.0.0", "license": "MIT", "publishConfig": { @@ -14,8 +14,13 @@ "type": "git", "url": "https://github.com/getspectra/spectra-js" }, - "description": "", - "keywords": [], + "description": "JavaScript implementation of the Spectra DSL.", + "keywords": [ + "DSL", + "permissions", + "spectra", + "figma" + ], "type": "module", "scripts": { "dev": "jest --watchAll", @@ -29,5 +34,8 @@ "rimraf": "^5.0.5", "ts-jest": "^29.1.2", "typescript": "^5.2.2" + }, + "dependencies": { + "@getspectra/spectra-typings": "^0.0.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3ec566..d391860 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,11 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +dependencies: + '@getspectra/spectra-typings': + specifier: ^0.0.5 + version: 0.0.5 + devDependencies: '@jest/globals': specifier: ^29.7.0 @@ -361,6 +366,10 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true + /@getspectra/spectra-typings@0.0.5: + resolution: {integrity: sha512-AzhWVj/An8MwEyO1R1RlDozG1PC1uJA4ljggnCZYIzV7wTmFy4uz88msttOE76DdlIhyBqKGSxXOhYOrT1xwiA==} + dev: false + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} diff --git a/src/expressions/and.ts b/src/expressions/and.ts index 150c0f3..1c020a0 100644 --- a/src/expressions/and.ts +++ b/src/expressions/and.ts @@ -1,4 +1,5 @@ -import { ExpressionInterface, AndExpressionDefine, FieldName } from '@/types'; +import { AndExpressionDefinition, FieldName } from '@getspectra/spectra-typings'; +import { ExpressionInterface } from '@/types'; export class AndExpression implements ExpressionInterface { private expressions: Array; @@ -11,7 +12,7 @@ export class AndExpression implements ExpressionInterface { return 'AND'; } - public getExpression(): AndExpressionDefine { + public getExpression(): AndExpressionDefinition { return { and: this.expressions.map((expression) => expression.getExpression()), }; diff --git a/src/expressions/binary.ts b/src/expressions/binary.ts index 7836220..877e5a8 100644 --- a/src/expressions/binary.ts +++ b/src/expressions/binary.ts @@ -1,11 +1,10 @@ import { - ExpressionInterface, - BinaryExpressionDefine, + BinaryExpressionDefinition, FieldName, FieldValue, Operation, - DataInterface, -} from '@/types'; +} from '@getspectra/spectra-typings'; +import { ExpressionInterface, DataInterface } from '@/types'; import { compareValue, getValueFromKey, isArgumentRef } from '@/utils'; export class BinaryExpression implements ExpressionInterface { @@ -23,7 +22,7 @@ export class BinaryExpression implements ExpressionInterface { return this.operation; } - public getExpression(): BinaryExpressionDefine { + public getExpression(): BinaryExpressionDefinition { return [this.left, this.operation, this.right]; } diff --git a/src/expressions/factory.ts b/src/expressions/factory.ts index 93b98ac..9250976 100644 --- a/src/expressions/factory.ts +++ b/src/expressions/factory.ts @@ -1,10 +1,5 @@ -import { - ExpressionDefine, - ExpressionInterface, - OperationEnum, - FieldName, - FieldValue, -} from '@/types'; +import { ExpressionDefinition, FieldName, FieldValue } from '@getspectra/spectra-typings'; +import { ExpressionInterface, OperationEnum } from '@/types'; import { normalizeExpression } from '@/utils'; import { BinaryExpression } from './binary'; import { AndExpression } from './and'; @@ -12,7 +7,7 @@ import { NotExpression } from './not'; import { OrExpression } from './or'; export function and( - expressions: Array + expressions: Array ): AndExpression { const normalizedExpressions = expressions.map((expression) => normalizeExpression(expression) @@ -21,7 +16,7 @@ export function and( } export function or( - expressions: Array + expressions: Array ): OrExpression { const normalizedExpressions = expressions.map((expression) => normalizeExpression(expression) @@ -29,7 +24,9 @@ export function or( return new OrExpression(normalizedExpressions); } -export function not(expression: ExpressionInterface | ExpressionDefine): NotExpression { +export function not( + expression: ExpressionInterface | ExpressionDefinition +): NotExpression { const normalizedExpression = normalizeExpression(expression); return new NotExpression(normalizedExpression); } diff --git a/src/expressions/not.ts b/src/expressions/not.ts index c3923a3..ad7dbd2 100644 --- a/src/expressions/not.ts +++ b/src/expressions/not.ts @@ -1,4 +1,5 @@ -import { ExpressionInterface, FieldName, NotExpressionDefine } from '@/types'; +import { FieldName, NotExpressionDefinition } from '@getspectra/spectra-typings'; +import { ExpressionInterface } from '@/types'; export class NotExpression implements ExpressionInterface { private expression: ExpressionInterface; @@ -11,7 +12,7 @@ export class NotExpression implements ExpressionInterface { return 'NOT'; } - public getExpression(): NotExpressionDefine { + public getExpression(): NotExpressionDefinition { return { not: this.expression.getExpression(), }; diff --git a/src/expressions/or.ts b/src/expressions/or.ts index 6d1144f..a1b67fe 100644 --- a/src/expressions/or.ts +++ b/src/expressions/or.ts @@ -1,4 +1,5 @@ -import { ExpressionInterface, FieldName, OrExpressionDefine } from '@/types'; +import { FieldName, OrExpressionDefinition } from '@getspectra/spectra-typings'; +import { ExpressionInterface } from '@/types'; export class OrExpression implements ExpressionInterface { private expressions: Array; @@ -11,7 +12,7 @@ export class OrExpression implements ExpressionInterface { return 'OR'; } - public getExpression(): OrExpressionDefine { + public getExpression(): OrExpressionDefinition { return { or: this.expressions.map((expression) => expression.getExpression()), }; diff --git a/src/types/expression.ts b/src/types/expression.ts index e0843ed..ce6d4a9 100644 --- a/src/types/expression.ts +++ b/src/types/expression.ts @@ -1,9 +1,9 @@ +import { ExpressionDefinition, FieldName } from '@getspectra/spectra-typings'; import { DataInterface } from './data-loader'; -import { ExpressionDefine, FieldName } from './literal'; export type ExpressionInterface = { getOperation(): string; - getExpression(): ExpressionDefine; + getExpression(): ExpressionDefinition; getFields(): Array; evaluate(data: DataInterface): boolean; jsonSerialize(): string; diff --git a/src/types/index.ts b/src/types/index.ts index f2c4314..84fca97 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -2,4 +2,3 @@ export * from './data-loader'; export * from './expression'; export * from './operation'; export * from './policy'; -export * from './literal'; diff --git a/src/types/literal.ts b/src/types/literal.ts deleted file mode 100644 index 62b57c4..0000000 --- a/src/types/literal.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Operation } from './operation'; - -export type FieldName = `${string}.${string}`; - -export type FieldValue = ArgumentValue | ArgumentRef; - -export type ArgumentValue = string | boolean | number | Date | null; - -export type ArgumentRef = { type: 'field'; ref: FieldName }; - -export type ExpressionDefine = - | BinaryExpressionDefine - | OrExpressionDefine - | AndExpressionDefine - | NotExpressionDefine; - -export type BinaryExpressionDefine = [FieldName, Operation, FieldValue]; - -export type OrExpressionDefine = { - or: Array; -}; - -export type AndExpressionDefine = { - and: Array; -}; - -export type NotExpressionDefine = { - not: ExpressionDefine; -}; diff --git a/src/types/operation.ts b/src/types/operation.ts index f4be023..fce5863 100644 --- a/src/types/operation.ts +++ b/src/types/operation.ts @@ -1,9 +1,3 @@ -export type NumberOperation = '=' | '!=' | '<>' | '>' | '>=' | '<' | '<='; - -export type ArrayOperation = 'in' | 'nin' | 'not_in'; - -export type Operation = NumberOperation | ArrayOperation; - export enum OperationEnum { EQ = '=', NEQ = '!=', diff --git a/src/utils/compare.ts b/src/utils/compare.ts index 3640732..bb49c77 100644 --- a/src/utils/compare.ts +++ b/src/utils/compare.ts @@ -1,4 +1,5 @@ -import { ArrayOperation, Operation, OperationEnum } from '@/types'; +import { ArrayOperation, Operation } from '@getspectra/spectra-typings'; +import { OperationEnum } from '@/types'; /** * @description Compare an array with a value based on an operation. diff --git a/src/utils/evaluate.ts b/src/utils/evaluate.ts new file mode 100644 index 0000000..b91a5f9 --- /dev/null +++ b/src/utils/evaluate.ts @@ -0,0 +1,21 @@ +import { ArgumentValue, FieldName, FieldValue } from '@getspectra/spectra-typings'; +import { DataInterface } from '@/types'; +import { isArgumentRef } from './expression'; + +/** + * @description Get the value from the key. + */ +export function getValueFromKey( + data: DataInterface, + key: FieldName | FieldValue +): ArgumentValue { + if (typeof key === 'string') { + return data[key]; + } + + if (key !== null && isArgumentRef(key)) { + return data[key.ref]; + } + + return key; +} diff --git a/src/utils/expression.ts b/src/utils/expression.ts index 3b39f0a..bf566d7 100644 --- a/src/utils/expression.ts +++ b/src/utils/expression.ts @@ -1,17 +1,25 @@ +import { + ExpressionDefinition, + BinaryExpressionDefinition, + AndExpressionDefinition, + OrExpressionDefinition, + NotExpressionDefinition, + ArgumentRef, +} from '@getspectra/spectra-typings'; import { BinaryExpression, AndExpression, OrExpression, NotExpression, } from '@/expressions'; -import { - ExpressionDefine, - ExpressionInterface, - BinaryExpressionDefine, - AndExpressionDefine, - OrExpressionDefine, - NotExpressionDefine, -} from '@/types'; +import { ExpressionInterface } from '@/types'; + +/** + * @description Check if the key is an ArgumentRef. + */ +export function isArgumentRef(key: any): key is ArgumentRef { + return typeof key === 'object' && 'ref' in key && 'type' in key; +} /** * @description Check if an expression is a valid expression interface. @@ -32,7 +40,7 @@ export function isValidExpressionInterface( */ export function isValidBinaryExpressionDefine( expression: any -): expression is BinaryExpressionDefine { +): expression is BinaryExpressionDefinition { if (!Array.isArray(expression)) { return false; } @@ -77,7 +85,7 @@ export function isValidBinaryExpressionDefine( */ export function isValidAndExpressionDefine( expression: any -): expression is AndExpressionDefine { +): expression is AndExpressionDefinition { if (typeof expression !== 'object') { return false; } @@ -94,7 +102,7 @@ export function isValidAndExpressionDefine( */ export function isValidOrExpressionDefine( expression: any -): expression is OrExpressionDefine { +): expression is OrExpressionDefinition { if (typeof expression !== 'object') { return false; } @@ -111,14 +119,16 @@ export function isValidOrExpressionDefine( */ export function isValidNotExpressionDefine( expression: any -): expression is NotExpressionDefine { +): expression is NotExpressionDefinition { return typeof expression === 'object' && expression.not !== undefined; } /** * @description Check if an expression is a valid expression definition. */ -export function isValidExpressionDefine(expression: any): expression is ExpressionDefine { +export function isValidExpressionDefine( + expression: any +): expression is ExpressionDefinition { return ( isValidBinaryExpressionDefine(expression) || isValidAndExpressionDefine(expression) || diff --git a/src/utils/index.ts b/src/utils/index.ts index 384fe4f..04a8da2 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,4 @@ export * from './expression'; export * from './compare'; export * from './policy'; +export * from './evaluate'; diff --git a/src/utils/policy.ts b/src/utils/policy.ts index 1df26d9..c97bbf6 100644 --- a/src/utils/policy.ts +++ b/src/utils/policy.ts @@ -1,12 +1,4 @@ -import { - ExpressionInterface, - ResourceInterface, - DataInterface, - ArgumentValue, - FieldName, - FieldValue, - ArgumentRef, -} from '@/types'; +import { ExpressionInterface, ResourceInterface } from '@/types'; /** * @description Bisect an array into two arrays based on a callback. @@ -48,28 +40,3 @@ export function parseDependences(expression: ExpressionInterface): ResourceInter return dependences; } - -/** - * @description Check if the key is an ArgumentRef. - */ -export function isArgumentRef(key: any): key is ArgumentRef { - return typeof key === 'object' && 'ref' in key && 'type' in key; -} - -/** - * @description Get the value from the key. - */ -export function getValueFromKey( - data: DataInterface, - key: FieldName | FieldValue -): ArgumentValue { - if (typeof key === 'string') { - return data[key]; - } - - if (key !== null && isArgumentRef(key)) { - return data[key.ref]; - } - - return key; -}