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 Jul 4, 2024
1 parent e5cc1db commit baa9d05
Show file tree
Hide file tree
Showing 7 changed files with 66 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
33 changes: 24 additions & 9 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
<!--
SPDX-FileLicenseText: 2024 Thomas Lehmann <t.lehmann@strato.de>
SPDX-License-Identifier: AGPL-3.0-or-later

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<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 baa9d05

Please sign in to comment.