-
Couldn't load subscription status.
- Fork 1
Add TypeScript checking via JSDoc type annotations #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
(Let me know if this is something you’re interested in at all -- I like having type safety for the project but I know TypeScript imposes some additional burden on contributors and maintainers.) I started this because while working on Jigsaw-Code#472 I noticed getYAMLFileConfig had some additional edge cases where undefined could get returned, but figured I could fully implement type safety in wrapper_app_project while I was at it. Some notes: * Adds a basic tsconfig.json with "strict" enabled, but type checking in basic_navigator_example disabled for now. You can run type checking with a new "typescript:check" script. * Adds .vscode/settings.json to configure VS Code to do type checking and match the existing code style * I’m not super familiar with the config format so I may be making some incorrect assumptions here.
* Move Config type to config.mjs * Move resolveConfiguration to config.mjs, rename to validateAndNormalizeConfig, change argument names for clarity. * Move zip function to zip.mjs, rename to compress, change argument names for clarity.
…ring from resolvedConfig.entryDomain if necessary)
# Conflicts: # package-lock.json
…r.config.json.handlebars)
…nfig.entryUrl).hostname}`
…ipts directories to scripts)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, but we need to figure out the vscode stuff
…fig) types; separate Config validation (validateConfig) from InternalConfig generation (makeInternalConfig)
…alerConfigBase64"] for clarity
…iling whitespace, apply to PR files
| * | ||
| * @returns {ValidConfig | { error: string }} | ||
| */ | ||
| export function validateConfig(args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"config" must be qualified. What is it is that you are configuring?
It looks like the app, so perhaps AppConfig?
But Capacitor already provides an app config, so why do we need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, is this a build config, or a runtime config? Those are different things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a build config, but the thing being built is the Capacitor project (not the Capacitor app itself).
So technically there are 3 configs:
*BuildConfig: the configuration used to processwrapper_app_project/templateintooutput/${projectName}capacitor.config.json.handlebars: Capacitor build configConfig.kt.handlebars/Config.swift.handlebars: app runtime configs
Maybe something like MakeConfig would make sense, but only if we renamed the build script to make. And the user could confuse this for the Unix make command?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that I would like for us to either use the GTS cli directly or parts of it. We were discussing this to an extent in the CI pr (#12). Try to use those configurations where you can.
…lidRawBuildConfig, InternalConfig → ResolvedBuildConfig
… .vscode to .gitignore
|
BTW @GrantASL19 - re-requesting the review at the top lets @fortuna and I know that you're ready for another look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would, at the least, extend the official https://github.com/google/gts/blob/main/tsconfig-google.json
Also, let me know if you need any help with @fortuna's comments.
… .prettierrc.js now extend it)
| await promisify(exec)(` | ||
| cd ${APP_TARGET_DIR.replaceAll(/\s+/g, '\\ ')} | ||
| npm install --no-warnings | ||
| npx cap sync ${internalConfig.platform} | ||
| `); |
Check warning
Code scanning / CodeQL
Shell command built from environment values Medium
absolute path
This shell command depends on an uncontrolled
absolute path
|
@daniellacosse Added GTS in 32519eb. At this point I could convert the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding GTS, I can hook that up in #12 one we merge this! We can rewrite to TS later if needed, prefer to not have to preprocess the scripts if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple config formats is a recipe for headache. Prefer to have a single format here with the derivations dynamically computed and no redundancy.
…nd returns config. Note: 1. I added config file validation using a combination of ts-json-schema-generator (to generate a JSON schema from the ConfigFile type) and ajv (to validate that the config file matches it). This way we don’t need to include a bunch of custom validation logic for each config property. One trade-off here is that SmartDialerConfig isn’t based on the underlying Go code, so it could fall out of sync. If we convert all the scripts to TypeScript we can replace this with e.g. zod or ts-pattern (which I’m familiar with) by starting with a pattern and deriving both a type and validator function, rather than starting with the type and deriving a validator function. 2. To simplify things I made a decision to only accept two CLI arguments: config (for passing in custom config locations) and platform (to choose build platform without creating redundant platform-specific configs). This sidesteps the issues with e.g. passing in additionalDomains (do we accept a comma-separated list?) and smartDialerConfig (do we accept a JSON string then parse it?). 3. There are still two types: Config and ConfigFile. ConfigFile (used for config file validation) is based on Config, but with derived properties (entryDomain, domainList, and smartDialerConfigBase64) removed, and the remaining properties other than entryUrl optional. I don’t see any way to avoid this unless we require that the config file contains all config properties (including the derived properties). Also note that I renamed these from "BuildConfig*" to "Config*". I think "Config" conveys "app maker config" given the name of the project, and having "build" or "make" in the type name might be more confusing since both could be read as a verb. 4. I tried replacing the derived properties with getters as suggested in [1], but to be compatible with the Handlebars template compilation [2] I think we would need to add a custom toJSON method to the class for the derived properties, which was making the class increasingly harder to read and understand vs. just outputting a config object including the derived properties as I did. IMO this is an acceptable trade-off given the config object isn’t really a user-facing thing, but let me know if there’s a better way here. [1]: #8 (comment) [2]: https://github.com/Jigsaw-Code/outline-app-maker/blob/7fa63ea3539a105e66d8ee43791166ed21c5bef9/wrapper_app_project/scripts/build.mjs#L107-L114
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see my comment on the types of config
| @@ -1,6 +1,6 @@ | |||
| package {{appId}} | |||
|
|
|||
| object Config { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| object Config { | |
| object RuntimeConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also need to rename the file and update references
| @@ -1,8 +1,8 @@ | |||
| import Foundation | |||
|
|
|||
| struct Config { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| struct Config { | |
| struct RuntimeConfig { |
| static var proxyHost: String = "127.0.0.1" | ||
| static var proxyPort: String = "0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need these in the config. The ios and android configs should probably be the same.
| static var proxyHost: String = "127.0.0.1" | |
| static var proxyPort: String = "0" |
| ); | ||
| await fs.writeFile( | ||
| destinationFilepath.replace(/\.handlebars$/, ''), | ||
| template(config), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define a dedicated type TemplateInput for the template input.
It should be derived from the AppMakerConfig with a clear method, like createTemplateInput(appMakerConfig).
| template(config), | |
| template(createTemplateInput(appMakerConfig)), |
|
|
||
| export type Platform = 'android' | 'ios'; | ||
|
|
||
| export type Config = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's replace this with an AppMakerConfig that is entirely defined by the user. It should be the file format. Remove ConfigFile.
| await promisify(exec)(` | ||
| cd ${APP_TARGET_DIR.replaceAll(/\s+/g, '\\ ')} | ||
| npm install --no-warnings | ||
| npx cap sync ${config.platform} | ||
| `); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to properly quote in case of spaces:
| await promisify(exec)(` | |
| cd ${APP_TARGET_DIR.replaceAll(/\s+/g, '\\ ')} | |
| npm install --no-warnings | |
| npx cap sync ${config.platform} | |
| `); | |
| await promisify(exec)(` | |
| cd "${APP_TARGET_DIR.replaceAll(/\s+/g, '\\ ')}" | |
| npm install --no-warnings | |
| npx cap sync "${config.platform}" | |
| `); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not safe: npx cap sync ${config.platform}. You need to shell-escape the parameter, or test that they are in a safe set of values.
The safe way to run commands is to use the exec version that takes the args in a list..
Note: I’ve copied this as-is from Jigsaw-Code/outline-sdk#473 but currently the
buildscript fails due to unrelated issues (will investigate further and open an issue/PR).(Let me know if this is something you’re interested in at all -- I like having type safety for the project but I know TypeScript imposes some additional burden on contributors and maintainers.)
I started this because while working on Jigsaw-Code#472 I noticed getYAMLFileConfig had some additional edge cases where undefined could get returned, but figured I could fully implement type safety in wrapper_app_project while I was at it.
Some notes:
Adds a basic tsconfig.json with "strict" enabled, but type checking in basic_navigator_example disabled for now. You can run type checking with a new "typescript:check" script.
Adds .vscode/settings.json to configure VS Code to do type checking and match the existing code style
I’m not super familiar with the config format so I may be making some incorrect assumptions here.