diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..5f7b681 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,16 @@ +**/lwc/**/*.css +**/lwc/**/*.html +**/lwc/**/*.json +**/lwc/**/*.svg +**/lwc/**/*.xml +**/aura/**/*.auradoc +**/aura/**/*.cmp +**/aura/**/*.css +**/aura/**/*.design +**/aura/**/*.evt +**/aura/**/*.json +**/aura/**/*.svg +**/aura/**/*.tokens +**/aura/**/*.xml +**/aura/**/*.app +.sfdx diff --git a/.forceignore b/.forceignore new file mode 100755 index 0000000..7b5b5a7 --- /dev/null +++ b/.forceignore @@ -0,0 +1,12 @@ +# List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status +# More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm +# + +package.xml + +# LWC configuration files +**/jsconfig.json +**/.eslintrc.json + +# LWC Jest +**/__tests__/** \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f891339 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# This file is used for Git repositories to specify intentionally untracked files that Git should ignore. +# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore +# For useful gitignore templates see: https://github.com/github/gitignore + +# Salesforce cache +.sf/ +.sfdx/ +.localdevserver/ +deploy-options.json + +# LWC VSCode autocomplete +**/lwc/jsconfig.json + +# LWC Jest coverage reports +coverage/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Dependency directories +node_modules/ + +# Eslint cache +.eslintcache + +# MacOS system files +.DS_Store + +# Windows system files +Thumbs.db +ehthumbs.db +[Dd]esktop.ini +$RECYCLE.BIN/ + +# Local environment variables +.env \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..feac116 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run precommit \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100755 index 0000000..f3720b2 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,10 @@ +# List files or directories below to ignore them when running prettier +# More information: https://prettier.io/docs/en/ignore.html +# + +**/staticresources/** +.localdevserver +.sfdx +.vscode + +coverage/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100755 index 0000000..15683b6 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "trailingComma": "none", + "overrides": [ + { + "files": "**/lwc/**/*.html", + "options": { "parser": "lwc" } + }, + { + "files": "*.{cmp,page,component}", + "options": { "parser": "html" } + } + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..7e6cb10 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "salesforce.salesforcedx-vscode", + "redhat.vscode-xml", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "financialforce.lana" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e07e391 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Apex Replay Debugger", + "type": "apex-replay", + "request": "launch", + "logFile": "${command:AskForLogFileName}", + "stopOnEntry": true, + "trace": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..76decfb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/.sfdx": true + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4c80f38 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Dogeforce + +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 new file mode 100644 index 0000000..afcda4a --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Salesforce DX Project: Next Steps + +Now that you’ve created a Salesforce DX project, what’s next? Here are some documentation resources to get you started. + +## How Do You Plan to Deploy Your Changes? + +Do you want to deploy a set of changes, or create a self-contained application? Choose a [development model](https://developer.salesforce.com/tools/vscode/en/user-guide/development-models). + +## Configure Your Salesforce DX Project + +The `sfdx-project.json` file contains useful configuration information for your project. See [Salesforce DX Project Configuration](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_config.htm) in the _Salesforce DX Developer Guide_ for details about this file. + +## Read All About It + +- [Salesforce Extensions Documentation](https://developer.salesforce.com/tools/vscode/) +- [Salesforce CLI Setup Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_intro.htm) +- [Salesforce DX Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_intro.htm) +- [Salesforce CLI Command Reference](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference.htm) diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json new file mode 100644 index 0000000..e9ab33d --- /dev/null +++ b/config/project-scratch-def.json @@ -0,0 +1,14 @@ +{ + "orgName": "JSONPath", + "edition": "Developer", + "features": ["EnableSetPasswordInApi"], + "settings": { + "lightningExperienceSettings": { + "enableS1DesktopEnabled": true + }, + "mobileSettings": { + "enableS1EncryptedStoragePref2": false + } + }, + "language": "en_US" +} diff --git a/force-app/main/default/classes/JSONPath.cls b/force-app/main/default/classes/JSONPath.cls new file mode 100644 index 0000000..c324517 --- /dev/null +++ b/force-app/main/default/classes/JSONPath.cls @@ -0,0 +1,73 @@ +public class JSONPath { + private String raw; + private Object data; + + public JSONPath(String rawJson) { + this.raw = rawJson; + this.data = JSON.deserializeUntyped(rawJson); + } + + public Object get(String path) { + return this.get(path.removeStart('$'), this.data); + } + + private Object get(String path, Object data) { + Boolean isObject = data instanceof Map; + Boolean isList = data instanceof List; + + List levels = path.removeStart('.').split('\\.'); + String currentLevel = levels.remove(0); + + + if (isObject) { + Map d = (Map) data; + + if (currentLevel.endsWith(']')) { + return this.get( + ('[' + + currentLevel.reverse().substringBetween(']', '[') + + '].' + + String.join(levels, '.')), + d.get(currentLevel.split('\\[').remove(0)) + ); + } + + return levels.size() == 0 + ? d.get(currentLevel) + : this.get(String.join(levels, '.'), d.get(currentLevel)); + } + + if (isList) { + List d = (List) data; + + if (currentLevel.startsWith('[]')) { + // return the array + return d; + } + + Integer index = getIndex(currentLevel); + + return levels.size() == 0 + ? d.get(index) + : this.get(String.join(levels, '.'), d.get(index)); + } + + return null; + } + + private Integer getIndex(String currentLevel) { + String indexStr = currentLevel.substringBetween('[', ']'); + + if (indexStr == null) { + String m = 'Invalid path.'; + JSONPathException e = new JSONPathException(m); + e.setMessage(m); + throw e; + } + + return Integer.valueOf(indexStr); + } + + public class JSONPathException extends Exception { + } +} diff --git a/force-app/main/default/classes/JSONPath.cls-meta.xml b/force-app/main/default/classes/JSONPath.cls-meta.xml new file mode 100644 index 0000000..40d6793 --- /dev/null +++ b/force-app/main/default/classes/JSONPath.cls-meta.xml @@ -0,0 +1,5 @@ + + + 54.0 + Active + diff --git a/force-app/main/default/classes/JSONPathTest.cls b/force-app/main/default/classes/JSONPathTest.cls new file mode 100644 index 0000000..57ca3d3 --- /dev/null +++ b/force-app/main/default/classes/JSONPathTest.cls @@ -0,0 +1,43 @@ +@IsTest +private class JSONPathTest { + @IsTest + static void test() { + JSONPath jpObject = new JSONPath( + '{"name":"John","company":{"name":"Company"}}' + ); + System.assertEquals( + 'John', + jpObject.get('$.name'), + 'Incorrect data.' + ); + System.assertEquals( + 'Company', + jpObject.get('$.company.name'), + 'Incorrect data.' + ); + JSONPath jpList = new JSONPath( + '[{"name":"John","company":{"name":"Company"}}]' + ); + System.assertEquals( + 'John', + jpList.get('$[0].name'), + 'Incorrect data.' + ); + System.assert( + jpList.get('$[]') instanceof List, + 'Should be a list.' + ); + System.assert( + jpList.get('$[0]') instanceof Map, + 'Should be an object.' + ); + JSONPath jpListNested = new JSONPath( + '[{"attr":[{"name":"John"},{"name":"Mary"}]}]' + ); + System.assertEquals( + 'Mary', + jpListNested.get('$[0].attr[1].name'), + 'Incorrect data.' + ); + } +} diff --git a/force-app/main/default/classes/JSONPathTest.cls-meta.xml b/force-app/main/default/classes/JSONPathTest.cls-meta.xml new file mode 100644 index 0000000..40d6793 --- /dev/null +++ b/force-app/main/default/classes/JSONPathTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 54.0 + Active + diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..f5a9fed --- /dev/null +++ b/jest.config.js @@ -0,0 +1,6 @@ +const { jestConfig } = require('@salesforce/sfdx-lwc-jest/config'); + +module.exports = { + ...jestConfig, + modulePathIgnorePatterns: ['/.localdevserver'] +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..4b61632 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "salesforce-app", + "private": true, + "version": "1.0.0", + "description": "Salesforce App", + "scripts": { + "lint": "eslint **/{aura,lwc}/**", + "test": "npm run test:unit", + "test:unit": "sfdx-lwc-jest", + "test:unit:watch": "sfdx-lwc-jest --watch", + "test:unit:debug": "sfdx-lwc-jest --debug", + "test:unit:coverage": "sfdx-lwc-jest --coverage", + "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "postinstall": "husky install", + "precommit": "lint-staged" + }, + "devDependencies": { + "@lwc/eslint-plugin-lwc": "^1.1.2", + "@prettier/plugin-xml": "^2.0.1", + "@salesforce/eslint-config-lwc": "^3.2.3", + "@salesforce/eslint-plugin-aura": "^2.0.0", + "@salesforce/eslint-plugin-lightning": "^1.0.0", + "@salesforce/sfdx-lwc-jest": "^1.1.0", + "eslint": "^8.11.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.2", + "husky": "^7.0.4", + "lint-staged": "^12.3.7", + "prettier": "^2.6.0", + "prettier-plugin-apex": "^1.10.0" + }, + "lint-staged": { + "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ + "prettier --write" + ], + "**/{aura,lwc}/**": [ + "eslint" + ] + } +} diff --git a/sfdx-project.json b/sfdx-project.json new file mode 100644 index 0000000..a187232 --- /dev/null +++ b/sfdx-project.json @@ -0,0 +1,12 @@ +{ + "packageDirectories": [ + { + "path": "force-app", + "default": true + } + ], + "name": "ApexJsonPath", + "namespace": "", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "54.0" +}