Skip to content

Commit

Permalink
Use AuthTokenSection in App (build fails with TS errors)
Browse files Browse the repository at this point in the history
* package.json: add Nextcloud, Vue, typescipt dependencies
  (from Nextcloud)
* remove .ts suffix from import paths (causes build error otherwise)
* add declare global to define Nextcloud types. This should be changed
  to @nextcloud/typings.
* annotated import of Nextcloud components (JS) with @ts-expect-error
  to solve tsc errors. This is most likely due to missing type
  definitions. Unclear how Nextcloud core made this working.
* tsconfig: extend from @vue/tsconfig/tsconfig.json as documented
  elsewhere and as done in Nextcloud's core tsconfig.json
* the eslint rule set @nextcloud/eslint-config/typescript was added to
prevent:

     ERROR in [eslint]
     /app/src/components/AuthTokenSection.vue
       35:27  error  "@nextcloud/initial-state" is not published  n/no-unpublished-import
       36:32  error  "@nextcloud/l10n" is not published           n/no-unpublished-import

  I can only assume that that rule is disabled in the rule set we
  extend from or that the module resolution "node" can not find the
  files.

  The error actually complains about the module not being part of
  "dependencies" in package.json, which is the case, however.

  The internet calls for allowing such modules, which IMO defeats the
  purpose.

   The rule is also present in Nextcloud's core config.

Build fails with errors like

   ERROR in /app/src/components/AuthTokenSetup.vue.ts
   47:9-14
   [tsl] ERROR in /app/src/components/AuthTokenSetup.vue.ts(47,10)
         TS2339: Property 'reset' does not exist on type 'CreateComponentPublicInstance<{}, { authTokenStore: Store<"auth-token", { tokens: IToken[]; }, {}, { updateToken(token: IToken): Promise<any>; addToken(name: string): Promise<ITokenResponse | null>; deleteToken(token: IToken): Promise<...>; wipeToken(token: IToken): Promise<...>; renameToken(token: IToken, newName: ...'.

This hints at Typescript not being able to infer types from the
component definition.

Related issues:

* vuejs/vue#9873
* vuejs/vue#12628
* vuejs/vue#8721

Unsuccessfully attempted proposed solutions:

* Declaring return types on methods like:

  reset(): void {
  async submit(): Promise<void> {

* Using arrow functions

  Did not work and would introduce new errors anyway

* Defining interfaces for the returned component

  Caused another rabbit hole of more and more required type
  definitions, that should be infered by the Vue typings anyway
  • Loading branch information
tholewebgods committed May 30, 2024
1 parent ca09567 commit 4ac4513
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 14 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
extends: [
'@nextcloud',
'@nextcloud/eslint-config/typescript',
],
rules: {
'jsdoc/require-jsdoc': 'off',
Expand Down
15 changes: 6 additions & 9 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
<template>
<NcAppContent>
<div id="simplesettings">
<h1>Hello world!</h1>
</div>
</NcAppContent>
<AuthTokenSection />
</template>

<script lang="ts">
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
import AuthTokenSection from './components/AuthTokenSection.vue'
import { defineComponent } from 'vue'
export default {
export default defineComponent({
name: 'App',
components: {
NcAppContent,
AuthTokenSection,
},
}
})
</script>

<style scoped lang="scss">
Expand Down
27 changes: 26 additions & 1 deletion src/components/AuthToken.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,41 @@ import type { IToken } from '../store/authtoken'
import { mdiCheck, mdiCellphone, mdiTablet, mdiMonitor, mdiWeb, mdiKey, mdiMicrosoftEdge, mdiFirefox, mdiGoogleChrome, mdiAppleSafari, mdiAndroid, mdiAppleIos } from '@mdi/js'
import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
import { TokenType, useAuthTokenStore } from '../store/authtoken.ts'
import { TokenType, useAuthTokenStore } from '../store/authtoken'

// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcActionCheckbox from '@nextcloud/vue/dist/Components/NcActionCheckbox.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcDateTime from '@nextcloud/vue/dist/Components/NcDateTime.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

declare global {
interface Window {
oc_defaults: {
baseUrl: string;
docBaseUrl: string;
docPlaceholderUrl: string;
entity: string;
folder: string;
logoClaim: string;
name: string;
productName: string;
slogan: string;
syncClientUrl: string;
title: string;
};
}
}

// When using capture groups the following parts are extracted the first is used as the version number, the second as the OS
const userAgentMap = {
ie: /(?:MSIE|Trident|Trident\/7.0; rv)[ :](\d+)/,
Expand Down
2 changes: 2 additions & 0 deletions src/components/AuthTokenSetup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
import { useAuthTokenStore, type ITokenResponse } from '../store/authtoken'

// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

import AuthTokenSetupDialog from './AuthTokenSetupDialog.vue'
Expand Down
4 changes: 4 additions & 0 deletions src/components/AuthTokenSetupDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ import { getRootUrl } from '@nextcloud/router'
import { defineComponent, type PropType } from 'vue'

import QR from '@chenfengyuan/vue-qrcode'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

import logger from '../logger'
Expand Down
5 changes: 5 additions & 0 deletions src/store/authtoken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import { defineStore } from 'pinia'
import axios from '@nextcloud/axios'
import logger from '../logger'

declare global {
// TODO find matching typedef in the @nextcloud/dialogs package
interface Window { OC: any; }
}

const BASE_URL = generateUrl('/simplesettings/authtokens')

const confirm = () => {
Expand Down
8 changes: 4 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// Mostly based on Nextcloud's tsconfig.json with some modifications
// (includes, allowImportingTsExtensions, noEmit)
"extends": "@vue/tsconfig/tsconfig.json",
"include": ["./src/**/*.ts", "./src/**/*.vue"],
"include": ["./src/**/*.ts", "./src/**/*.vue", "./src/**/*.d.ts"],
"compilerOptions": {
"types": ["node", "vue", "vue-router"],
"outDir": "./dist/",
"target": "ESNext",
"module": "esnext",
// Set module resolution to bundler and `noEmit` to be able to set `allowImportingTsExtensions`, so we can import Typescript with .ts extension
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"moduleResolution": "node",
// Must be false because noEmit is false (reason see below)
"allowImportingTsExtensions": false,
// noEmit shall be false to prevent the error
// "Error: TypeScript emitted no output for /app/src/main.ts."
"noEmit": false,
Expand Down

0 comments on commit 4ac4513

Please sign in to comment.