Skip to content

Commit 012c99c

Browse files
Merge pull request #39 from OutSystems/feat/RMET-4190/capacitor-support
RMET-4190 :: Capacitor support + Prepare release of 2.2.0
2 parents e16b5c0 + 05c64da commit 012c99c

File tree

6 files changed

+117
-1
lines changed

6 files changed

+117
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [2.2.0] - 2025-06-20
8+
- Feat: Support for Capacitor apps with OutSystems.
9+
- Chore: Update dependency to KeyStore plugin to use version `2.6.8-OS22`.
10+
711
## [2.1.7] - 2025-02-07
812
- Chore: Update dependency to KeyStore plugin to use version `2.6.8-OS21`.
913

build-actions/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
# Build Actions
3+
4+
This folder contains a .yaml file for configuring build actions to use in a plugin on ODC with Capacitor. The purpose of these build actions is to provide the same functionality as cordova hooks, but in a Capacitor shell for OutSystems apps.
5+
6+
## Contents
7+
8+
The file [disable_auto_backups.yaml](./disable_auto_backups.yaml) contains 1 build action:
9+
10+
1. Android specific. Disable auto-backup for the Android application, by changing the `AndroidManifest.xml` file.
11+
12+
13+
Furthermore, there are changes that can't be accomplished with build actions, and we used [Capacitor hooks](https://capacitorjs.com/docs/cli/hooks) for this. We have one JavaScript file for hooks:
14+
15+
- [update_strings_for_keystore.js](./update_strings_for_keystore.js) - Update the application's `strings.xml` file that are used for the [KeyStore Plugin](https://github.com/OutSystems/cordova-plugin-secure-storage), which is a dependency of this Cordova plugin.
16+
17+
Reasoning for this hook: The KeyStore plugin has its own build actions to update these strings, which only triggers from OutSystems apps. The dependency exists only at the Cordova-level, not OutSystems level, and the actual strings aren't meant to be configured here, since they won't actually be used in the plugin, it's just required for the KeyStore plugin initialization. Therefore, this hook only adds the strings to `strings.xml` if they don't already exist yet, to avoid modifying custom strings from the KeyStore Plugin (which can happen if users have an OutSystems app with both Ciphered and KeyStore plugins). [The Key Store's build actions](https://github.com/OutSystems/cordova-plugin-secure-storage/blob/outsystems/build-actions/setStringsAndroid.yaml) will run after this hook as well, and they will modify existing strings.
18+
19+
20+
## Outsystems' Usage
21+
22+
1. Copy the build action yaml file (which can contain multiple build actions inside) into the ODC Plugin, placing them in "Data" -> "Resources" and set "Deploy Action" to "Deploy to Target Directory", with target directory empty.
23+
2. Update the Plugin's Extensibility configuration to use the build action.
24+
25+
```json
26+
{
27+
"buildConfigurations": {
28+
"buildAction": {
29+
"config": $resources.buildActionFileName.yaml,
30+
"parameters": {
31+
// parameters go here; if there are no parameters then the block can be ommited
32+
}
33+
}
34+
}
35+
}
36+
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
platforms:
2+
android:
3+
manifest:
4+
- file: AndroidManifest.xml
5+
target: manifest/application
6+
attrs:
7+
android:allowBackup: "false"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
const path = require('path');
2+
const fs = require('fs');
3+
const { DOMParser, XMLSerializer } = require('xmldom');
4+
5+
const parser = new DOMParser();
6+
const platform = process.env.CAPACITOR_PLATFORM_NAME;
7+
const projectRoot = process.env.CAPACITOR_ROOT_DIR;
8+
9+
if (platform != 'android') {
10+
// hook only needs to run for Android
11+
return
12+
}
13+
14+
console.log("\nCiphered Local Storage Plugin - running hook before update - for " + platform);
15+
16+
const stringsXmlPath = path.join(projectRoot, 'android/app/src/main/res/values/strings.xml');
17+
if (!fs.existsSync(stringsXmlPath)) {
18+
console.error("\t[ERROR] - strings.xml file does not exist, and is required by this hook - " + stringsXmlPath);
19+
process.exit(1);
20+
}
21+
22+
// read and parse files
23+
const stringsXmlDoc = parser.parseFromString(fs.readFileSync(stringsXmlPath, 'utf-8'), 'text/xml');
24+
let writtenValuesCount = 0;
25+
26+
// Add entries only if they are not present
27+
const valuesToAdd = [
28+
{ stringsXmlName: 'migration_auth', value: 'false', type: 'bool' },
29+
{ stringsXmlName: 'biometric_prompt_title', value: 'Authentication required', type: 'string' },
30+
{ stringsXmlName: 'biometric_prompt_subtitle', value: 'Please authenticate to continue', type: 'string' },
31+
{ stringsXmlName: 'biometric_prompt_negative_button', value: 'Cancel', type: 'string' }
32+
];
33+
for (const { stringsXmlName, value, type } of valuesToAdd) {
34+
if (!elementExistsInStringsXml(type, stringsXmlName)) {
35+
const stringElement = stringsXmlDoc.createElement(type);
36+
stringElement.setAttribute('name', stringsXmlName);
37+
stringElement.textContent = value;
38+
stringsXmlDoc.documentElement.appendChild(stringElement);
39+
writtenValuesCount = writtenValuesCount + 1;
40+
}
41+
}
42+
43+
if (writtenValuesCount > 0) {
44+
// Serialize and write the updated XML file
45+
const serializer = new XMLSerializer();
46+
let updatedXmlString = serializer.serializeToString(stringsXmlDoc);
47+
// XMLSerializer doesn't properly indent the content, so it is manually done here
48+
updatedXmlString = updatedXmlString
49+
.replace(/>(\s*)</g, '>\n<') // put each tag on its own line
50+
.replace(/<([^?\/][^>]*)>/g, ' <$1>') // indent all opening tags except <?xml ...?>
51+
.replace(/ {4}(<\/?resources>)/g, '$1') // remove indentation from initial <resources> tag
52+
fs.writeFileSync(stringsXmlPath, updatedXmlString, 'utf-8');
53+
console.log("\t[SUCESSS] Added " + writtenValuesCount + " out of expected " + valuesToAdd.length + " values into strings.xml");
54+
} else {
55+
console.log("\t[SKIPPED] Values already exist in strings.xml");
56+
}
57+
58+
function elementExistsInStringsXml(tagName, nameValue) {
59+
const elements = stringsXmlDoc.getElementsByTagName(tagName);
60+
for (let i = 0; i < elements.length; i++) {
61+
if (elements[i].getAttribute('name') === nameValue) {
62+
return true;
63+
}
64+
}
65+
return false;
66+
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
"version": ">=3.3.0"
2929
}
3030
],
31+
"scripts": {
32+
"capacitor:update:before": "node build-actions/update_strings_for_keystore.js"
33+
},
3134
"author": "OutSystems",
3235
"license": "MIT",
3336
"bugs": {

plugin.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</js-module>
1616

1717
<dependency id="cordova-sqlcipher-adapter" url="https://github.com/OutSystems/cordova-sqlcipher-adapter.git#0.1.7-OS9" />
18-
<dependency id="cordova-plugin-secure-storage" url="https://github.com/OutSystems/cordova-plugin-secure-storage.git#2.6.8-OS21" />
18+
<dependency id="cordova-plugin-secure-storage" url="https://github.com/OutSystems/cordova-plugin-secure-storage.git#2.6.8-OS22" />
1919

2020
<dependency id="outsystems-plugin-disable-backup" url="https://github.com/OutSystems/outsystems-plugin-disable-backup.git#1.0.2" />
2121

0 commit comments

Comments
 (0)