Skip to content

Commit 4beab25

Browse files
emdashcodesemdashcodesgziolojustlevineMamaduka
authored
Add client-side package for Abilities API (#60)
* WordPress Abilities API Client * Fix: minor formatting issues and test fix for pagination headers * fix: correct return type of wp_abilities_register_client_assets * fix: auto-init assets & use class pattern for registration * Normalize paths for asset loading * fix: package structure, pull in rules from gutenberg for eslint and tsconfig, and unify deps where possible * docs: Remove NPM package mention for now * refactor: Rename listAbilities to getAbilities & update reducer naming * fix: Update AbilityInput type to accept any JSON value * fix: correct package.json after rebase with trunk * fix: Use per_page=-1 instead of recursion in resolver * update: use addQueryArgs to build GET requests * fix: wrap strings with @wordpress/i18n * fix: phpstan issues in register_assets * fix: additional phpstan error * Add client-only ability registration (#69) * Client only abilities * fix: Add proper server ability validation in registerAbility * feat: Add ClientAbility and ServerAbility types for better type safety * refactor: Remove location field, use callback presence for execution type * feat: add permissionCallback on the client * update: check if ability is already registered in registerAbility * fix: wrap client errors in i18n * Add client library tests and code quality infrastructure (#70) * Add testing & linting infa * Remove uncessary combined checks * Add client tests * test: Use proper TypeScript types instead of 'as any' in tests * Fix typescript check for extra server check * test: update tests for client-only abilities API changes * chore: add build:client and dev:client scripts to root package.json * fix: formatting * fix: prettier issues * fix: apply Prettier formatting to README and validation.ts * deps: remove @types/wordpress__api-fetch since types are already shipped * fix: move validation to the store * fix: validate ability name uses same format as server * tests: clean up CI checks * deps: fix dev dependencies and remove extra package-lock.json * fix: rename main dev and build commands * fix: better match server validation rules for schema * Fix remaining validation issues Co-authored-by: emdashcodes <emdashcodes@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: justlevine <justlevine@git.wordpress.org> Co-authored-by: jonathanbossenger <psykro@git.wordpress.org> --------- Co-authored-by: emdashcodes <emdashcodes@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: justlevine <justlevine@git.wordpress.org> Co-authored-by: jonathanbossenger <psykro@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> * Do not translate thrown developer errors * use rimraf for cleaning files, move to root package.json * Use correct versions for CI * fix: move scripts to main package.json and prefer wp-scripts * Simplify client readme by linking to CONTRIBUTING.md for dev and testing commands * align tsconfig with gutenberg * fix wp-scripts build command * Build JS assets for the plugin zip * allow asset class prefix * Optimize npm dependencies * Fix Prettier config and format files accordingly * Use correct ajv-draft-04 import. Remove unusued jest libs * Only store valid ability keys in the store --------- Co-authored-by: emdashcodes <emdashcodes@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: justlevine <justlevine@git.wordpress.org> Co-authored-by: jonathanbossenger <psykro@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: Grzegorz Ziolkowski <grzegorz@gziolo.pl> Co-authored-by: emdashcodes <emdashcodes@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org> Co-authored-by: justlevine <justlevine@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
1 parent 2f3cda7 commit 4beab25

36 files changed

+7555
-4083
lines changed

.eslintrc.cjs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
module.exports = {
2+
root: true,
3+
extends: [
4+
'plugin:@wordpress/eslint-plugin/recommended',
5+
'plugin:eslint-comments/recommended',
6+
],
7+
plugins: [ 'import' ],
8+
parserOptions: {
9+
ecmaVersion: 2021,
10+
sourceType: 'module',
11+
ecmaFeatures: {
12+
jsx: true,
13+
},
14+
project: './tsconfig.json',
15+
},
16+
settings: {
17+
'import/resolver': {
18+
typescript: {
19+
project: './tsconfig.json',
20+
},
21+
},
22+
},
23+
env: {
24+
browser: true,
25+
es6: true,
26+
node: true,
27+
},
28+
rules: {
29+
// React best practices
30+
'react/jsx-boolean-value': 'error',
31+
'react/jsx-curly-brace-presence': [
32+
'error',
33+
{ props: 'never', children: 'never' },
34+
],
35+
36+
// WordPress-specific rules, lifted from gutenberg
37+
'@wordpress/dependency-group': 'error',
38+
'@wordpress/data-no-store-string-literals': 'error',
39+
'@wordpress/wp-global-usage': 'error',
40+
'@wordpress/react-no-unsafe-timeout': 'error',
41+
'@wordpress/i18n-hyphenated-range': 'error',
42+
'@wordpress/i18n-no-flanking-whitespace': 'error',
43+
'@wordpress/i18n-text-domain': [
44+
'error',
45+
{
46+
allowedTextDomain: 'default',
47+
},
48+
],
49+
'@wordpress/no-unsafe-wp-apis': 'off',
50+
'import/default': 'error',
51+
'import/named': 'error',
52+
'import/no-extraneous-dependencies': [
53+
'error',
54+
{
55+
devDependencies: [
56+
'**/*.@(spec|test).@(j|t)s?(x)',
57+
'**/@(webpack|jest).config.@(j|t)s',
58+
'**/scripts/**',
59+
],
60+
},
61+
],
62+
'no-restricted-imports': [
63+
'error',
64+
{
65+
paths: [
66+
{
67+
name: 'lodash',
68+
message: 'Please use native functionality instead.',
69+
},
70+
{
71+
name: 'classnames',
72+
message: "Please use `clsx` instead. It's a lighter and faster drop-in replacement for `classnames`.",
73+
},
74+
{
75+
name: 'redux',
76+
importNames: [ 'combineReducers' ],
77+
message: 'Please use `combineReducers` from `@wordpress/data` instead.',
78+
},
79+
],
80+
},
81+
],
82+
'no-restricted-syntax': [
83+
'error',
84+
{
85+
selector: 'ImportDeclaration[source.value=/^@wordpress\\u002F.+\\u002F/]',
86+
message: 'Path access on WordPress dependencies is not allowed.',
87+
},
88+
{
89+
selector: 'JSXAttribute[name.name="id"][value.type="Literal"]',
90+
message: 'Do not use string literals for IDs; use withInstanceId instead.',
91+
},
92+
{
93+
selector: 'CallExpression[callee.object.name="Math"][callee.property.name="random"]',
94+
message: 'Do not use Math.random() to generate unique IDs; use withInstanceId instead. (If you\'re not generating unique IDs: ignore this message.)',
95+
},
96+
],
97+
},
98+
overrides: [
99+
{
100+
files: [ '**/*.ts?(x)' ],
101+
rules: {
102+
'@typescript-eslint/consistent-type-imports': [
103+
'error',
104+
{
105+
prefer: 'type-imports',
106+
disallowTypeAnnotations: false,
107+
},
108+
],
109+
'@typescript-eslint/no-shadow': 'error',
110+
'no-shadow': 'off',
111+
'jsdoc/require-param': 'off',
112+
'jsdoc/require-param-type': 'off',
113+
'jsdoc/require-returns-type': 'off',
114+
},
115+
},
116+
],
117+
};

.github/workflows/copilot-setup-steps.yml

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,50 @@ name: 'Copilot Setup Steps'
33
# Automatically run the setup steps when they are changed to allow for easy validation, and
44
# allow manual testing through the repository's "Actions" tab
55
on:
6-
workflow_dispatch:
7-
push:
8-
paths:
9-
- .github/workflows/copilot-setup-steps.yml
10-
pull_request:
11-
paths:
12-
- .github/workflows/copilot-setup-steps.yml
6+
workflow_dispatch:
7+
push:
8+
paths:
9+
- .github/workflows/copilot-setup-steps.yml
10+
pull_request:
11+
paths:
12+
- .github/workflows/copilot-setup-steps.yml
1313

1414
jobs:
15-
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
16-
copilot-setup-steps:
17-
runs-on: ubuntu-latest
18-
19-
permissions:
20-
contents: read
21-
22-
steps:
23-
- name: Checkout repository
24-
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
25-
with:
26-
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
27-
persist-credentials: false
28-
29-
##
30-
# This allows Composer dependencies to be installed using a single step.
31-
#
32-
# Since the tests are currently run within the Docker containers where the PHP version varies,
33-
# the same PHP version needs to be configured for the action runner machine so that the correct
34-
# dependency versions are installed and cached.
35-
##
36-
- name: Set up PHP
37-
uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # v2.35.4
38-
with:
39-
php-version: '8.3'
40-
coverage: none
41-
42-
- name: Install Composer dependencies
43-
uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1
44-
45-
- name: Setup Node
46-
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
47-
with:
48-
cache: 'npm'
49-
node-version-file: '.nvmrc'
50-
51-
- name: Install NPM dependencies
52-
run: npm ci
15+
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
16+
copilot-setup-steps:
17+
runs-on: ubuntu-latest
18+
19+
permissions:
20+
contents: read
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
25+
with:
26+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
27+
persist-credentials: false
28+
29+
##
30+
# This allows Composer dependencies to be installed using a single step.
31+
#
32+
# Since the tests are currently run within the Docker containers where the PHP version varies,
33+
# the same PHP version needs to be configured for the action runner machine so that the correct
34+
# dependency versions are installed and cached.
35+
##
36+
- name: Set up PHP
37+
uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # v2.35.4
38+
with:
39+
php-version: '8.3'
40+
coverage: none
41+
42+
- name: Install Composer dependencies
43+
uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1
44+
45+
- name: Setup Node
46+
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
47+
with:
48+
cache: 'npm'
49+
node-version-file: '.nvmrc'
50+
51+
- name: Install NPM dependencies
52+
run: npm ci

.github/workflows/props-bot.yml

Lines changed: 77 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,92 @@
11
name: Props Bot
22

33
on:
4-
# This event runs anytime a PR is (re)opened, updated, marked ready for review, or labeled.
5-
# GitHub does not allow filtering the `labeled` event by a specific label.
6-
# However, the logic below will short-circuit the workflow when the `props-bot` label is not the one being added.
7-
# Note: The pull_request_target event is used instead of pull_request because this workflow needs permission to comment
8-
# on the pull request. Because this event grants extra permissions to `GITHUB_TOKEN`, any code changes within the PR
9-
# should be considered untrusted. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
10-
pull_request_target:
11-
types:
12-
- opened
13-
- synchronize
14-
- reopened
15-
- labeled
16-
- ready_for_review
17-
# This event runs anytime a comment is added or deleted.
18-
# You cannot filter this event for PR comments only.
19-
# However, the logic below does short-circuit the workflow for issues.
20-
issue_comment:
21-
types:
22-
- created
23-
# This event will run everytime a new PR review is initially submitted.
24-
pull_request_review:
25-
types:
26-
- submitted
27-
# This event runs anytime a PR review comment is created or deleted.
28-
pull_request_review_comment:
29-
types:
30-
- created
4+
# This event runs anytime a PR is (re)opened, updated, marked ready for review, or labeled.
5+
# GitHub does not allow filtering the `labeled` event by a specific label.
6+
# However, the logic below will short-circuit the workflow when the `props-bot` label is not the one being added.
7+
# Note: The pull_request_target event is used instead of pull_request because this workflow needs permission to comment
8+
# on the pull request. Because this event grants extra permissions to `GITHUB_TOKEN`, any code changes within the PR
9+
# should be considered untrusted. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
10+
pull_request_target:
11+
types:
12+
- opened
13+
- synchronize
14+
- reopened
15+
- labeled
16+
- ready_for_review
17+
# This event runs anytime a comment is added or deleted.
18+
# You cannot filter this event for PR comments only.
19+
# However, the logic below does short-circuit the workflow for issues.
20+
issue_comment:
21+
types:
22+
- created
23+
# This event will run everytime a new PR review is initially submitted.
24+
pull_request_review:
25+
types:
26+
- submitted
27+
# This event runs anytime a PR review comment is created or deleted.
28+
pull_request_review_comment:
29+
types:
30+
- created
3131

3232
# Cancels all previous workflow runs for pull requests that have not completed.
3333
concurrency:
34-
# The concurrency group contains the workflow name and the branch name for pull requests
35-
# or the commit hash for any other events.
36-
group: ${{ github.workflow }}-${{ contains( fromJSON( '["pull_request_target", "pull_request_review", "pull_request_review_comment"]' ), github.event_name ) && github.head_ref || github.sha }}
37-
cancel-in-progress: true
34+
# The concurrency group contains the workflow name and the branch name for pull requests
35+
# or the commit hash for any other events.
36+
group: ${{ github.workflow }}-${{ contains( fromJSON( '["pull_request_target", "pull_request_review", "pull_request_review_comment"]' ), github.event_name ) && github.head_ref || github.sha }}
37+
cancel-in-progress: true
3838

3939
# Disable permissions for all available scopes by default.
4040
# Any needed permissions should be configured at the job level.
4141
permissions: {}
4242

4343
jobs:
44-
# Compiles a list of props for a pull request.
45-
#
46-
# Performs the following steps:
47-
# - Collects a list of contributor props and leaves a comment.
48-
# - Removes the props-bot label, if necessary.
49-
props-bot:
50-
name: Generate a list of props
51-
runs-on: ubuntu-24.04
52-
permissions:
53-
# The action needs permission `write` permission for PRs in order to add a comment.
54-
pull-requests: write
55-
contents: read
56-
timeout-minutes: 20
57-
# The job will run when pull requests are open, ready for review and:
44+
# Compiles a list of props for a pull request.
5845
#
59-
# - A comment is added to the pull request.
60-
# - A review is created or commented on (unless PR originates from a fork).
61-
# - The pull request is opened, synchronized, marked ready for review, or reopened.
62-
# - The `props-bot` label is added to the pull request.
63-
if: |
64-
(
65-
github.event_name == 'issue_comment' && github.event.issue.pull_request ||
66-
( contains( fromJSON( '["pull_request_review", "pull_request_review_comment"]' ), github.event_name ) && ! github.event.pull_request.head.repo.fork ) ||
67-
github.event_name == 'pull_request_target' && github.event.action != 'labeled' ||
68-
'props-bot' == github.event.label.name
69-
) &&
70-
( ! github.event.pull_request.draft && github.event.pull_request.state == 'open' || ! github.event.issue.draft && github.event.issue.state == 'open' )
46+
# Performs the following steps:
47+
# - Collects a list of contributor props and leaves a comment.
48+
# - Removes the props-bot label, if necessary.
49+
props-bot:
50+
name: Generate a list of props
51+
runs-on: ubuntu-24.04
52+
permissions:
53+
# The action needs permission `write` permission for PRs in order to add a comment.
54+
pull-requests: write
55+
contents: read
56+
timeout-minutes: 20
57+
# The job will run when pull requests are open, ready for review and:
58+
#
59+
# - A comment is added to the pull request.
60+
# - A review is created or commented on (unless PR originates from a fork).
61+
# - The pull request is opened, synchronized, marked ready for review, or reopened.
62+
# - The `props-bot` label is added to the pull request.
63+
if: |
64+
(
65+
github.event_name == 'issue_comment' && github.event.issue.pull_request ||
66+
( contains( fromJSON( '["pull_request_review", "pull_request_review_comment"]' ), github.event_name ) && ! github.event.pull_request.head.repo.fork ) ||
67+
github.event_name == 'pull_request_target' && github.event.action != 'labeled' ||
68+
'props-bot' == github.event.label.name
69+
) &&
70+
( ! github.event.pull_request.draft && github.event.pull_request.state == 'open' || ! github.event.issue.draft && github.event.issue.state == 'open' )
7171
72-
steps:
73-
- name: Gather a list of contributors
74-
uses: WordPress/props-bot-action@trunk
75-
with:
76-
format: 'git'
72+
steps:
73+
- name: Gather a list of contributors
74+
uses: WordPress/props-bot-action@trunk
75+
with:
76+
format: 'git'
7777

78-
- name: Remove the props-bot label
79-
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
80-
if: ${{ github.event.action == 'labeled' && 'props-bot' == github.event.label.name }}
81-
with:
82-
retries: 2
83-
retry-exempt-status-codes: 418
84-
script: |
85-
github.rest.issues.removeLabel({
86-
owner: context.repo.owner,
87-
repo: context.repo.repo,
88-
issue_number: process.env.ISSUE_NUMBER,
89-
name: 'props-bot'
90-
});
91-
env:
92-
ISSUE_NUMBER: ${{ github.event.number }}
78+
- name: Remove the props-bot label
79+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
80+
if: ${{ github.event.action == 'labeled' && 'props-bot' == github.event.label.name }}
81+
with:
82+
retries: 2
83+
retry-exempt-status-codes: 418
84+
script: |
85+
github.rest.issues.removeLabel({
86+
owner: context.repo.owner,
87+
repo: context.repo.repo,
88+
issue_number: process.env.ISSUE_NUMBER,
89+
name: 'props-bot'
90+
});
91+
env:
92+
ISSUE_NUMBER: ${{ github.event.number }}

0 commit comments

Comments
 (0)