From abbd0b48c540f1f4928d5ec62f585220352bd0cc Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Sun, 23 Aug 2026 11:58:13 +0200 Subject: [PATCH] feat: basic initial types --- .gitignore | 2 + MusicKit.d.ts | 38 +++ MusicKitInstance.d.ts | 3 + README.md | 7 +- enums.d.ts | 36 ++ eslint.config.mjs | 744 ++++++++++++++++++++++++++++++++++++++++++ events.d.ts | 6 + index.d.ts | 0 package.json | 10 + 9 files changed, 845 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 MusicKit.d.ts create mode 100644 MusicKitInstance.d.ts create mode 100644 enums.d.ts create mode 100644 eslint.config.mjs create mode 100644 events.d.ts create mode 100644 index.d.ts create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5f19d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json diff --git a/MusicKit.d.ts b/MusicKit.d.ts new file mode 100644 index 0000000..5d4387a --- /dev/null +++ b/MusicKit.d.ts @@ -0,0 +1,38 @@ +declare namespace MusicKit { + interface MusicKitConfiguration { + /** + * See https://js-cdn.music.apple.com/musickit/v3/docs/iframe.html?path=/story/get-started--page#configuring-musickit-on-the-web + */ + 'developerToken': string; + + /** + * Your application configuration + */ + 'app': { + /** + * The name of your application + */ + 'name': string; + + /** + * Build or version number of application + */ + 'build'?: string; + + /** + * A URL to your application logo. Should be square at 152x152px + */ + 'icon'?: string; + }; + + 'bitrate'?: PlaybackBitrate; + + /** + * Set the storefront, which is set for the API requests. + * If unset, then the authenticated user's storefrontId will be used. + */ + 'storefrontId'?: string; + } + + function configure ( config: MusicKitConfiguration ): Promise; +} diff --git a/MusicKitInstance.d.ts b/MusicKitInstance.d.ts new file mode 100644 index 0000000..a8642bc --- /dev/null +++ b/MusicKitInstance.d.ts @@ -0,0 +1,3 @@ +declare namespace MusicKit { + interface MusicKitInstance {} +} diff --git a/README.md b/README.md index dc386a5..2b55d7d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # musickitjs-v3-types -TypeScript Type Declarations for MusicKit JS V3 +TypeScript Type Declarations for [MusicKit JS V3](https://js-cdn.music.apple.com/musickit/v3/docs/index.html?path=/story/introduction--page) + +## Docs only +The below URL could be used in the future to auto-generate these types + +https://js-cdn.music.apple.com/musickit/v3/docs/iframe.html?viewMode=story&id=reference-javascript-musickit-instance--page diff --git a/enums.d.ts b/enums.d.ts new file mode 100644 index 0000000..50126f3 --- /dev/null +++ b/enums.d.ts @@ -0,0 +1,36 @@ +declare namespace MusicKit { + /** + * The bitrate to choose for playback. HIGH is 256kbps, STANDARD is 64kbps + */ + enum PlaybackBitrate { + 'HIGH', + 'STANDARD' + } + + /** + * State of the player. See https://js-cdn.music.apple.com/musickit/v3/docs/iframe.html?id=reference-javascript-musickit--page&viewMode=story&args=#playbackstates + */ + enum PlaybackStates { + 'none', + 'loading', + 'playing', + 'paused', + 'stopped', + 'ended', + 'seeking', + 'waiting', + 'stalled', + 'completed' + } + + enum PlayerRepeatMode { + 'all', + 'none', + 'one' + } + + enum PlayerShuffleMode { + 'on', + 'off' + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..48eb7aa --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,744 @@ +import eslint from '@eslint/js'; +import globals from 'globals'; +import stylistic from '@stylistic/eslint-plugin'; +import tseslint from 'typescript-eslint'; +import typescript from '@typescript-eslint/eslint-plugin'; +import vue from 'eslint-plugin-vue'; + +const style = { + 'plugins': { + '@stylistic': stylistic, + '@stylistic/js': stylistic, + '@stylistic/ts': stylistic + }, + 'files': [ + '**/*.ts', + '**/*.js', + '**/*.mjs', + '**/*.cjs', + '**/*.tsx', + '**/*.jsx' + ], + 'rules': { + 'sort-imports': [ + 'warn', + { + 'ignoreCase': false, + 'ignoreDeclarationSort': false, + 'ignoreMemberSort': false, + 'memberSyntaxSortOrder': [ + 'none', + 'all', + 'multiple', + 'single' + ], + 'allowSeparatedGroups': false + } + ], + // Formatting + '@stylistic/array-bracket-newline': [ + 'error', + { + 'multiline': false, + 'minItems': 2 + } + ], + '@stylistic/array-bracket-spacing': [ + 'error', + 'always' + ], + '@stylistic/array-element-newline': [ + 'error', + { + 'consistent': false, + 'multiline': false, + 'minItems': 2 + } + ], + '@stylistic/arrow-parens': [ + 'error', + 'as-needed' + ], + '@stylistic/arrow-spacing': [ + 'error', + { + 'before': true, + 'after': true + } + ], + '@stylistic/block-spacing': [ + 'error', + 'always' + ], + '@stylistic/brace-style': [ + 'error', + '1tbs', + { + 'allowSingleLine': false + } + ], + '@stylistic/comma-dangle': [ + 'error', + 'never' + ], + '@stylistic/comma-spacing': [ + 'error', + { + 'before': false, + 'after': true + } + ], + '@stylistic/comma-style': [ + 'error', + 'last' + ], + '@stylistic/dot-location': [ + 'error', + 'property' + ], + '@stylistic/function-call-argument-newline': [ + 'error', + 'consistent' + ], + '@stylistic/function-call-spacing': [ + 'error', + 'never' + ], + '@stylistic/function-paren-newline': [ + 'error', + 'multiline-arguments' + ], + '@stylistic/implicit-arrow-linebreak': [ + 'error', + 'beside' + ], + '@stylistic/indent': [ + 'error', + 4 + ], + '@stylistic/indent-binary-ops': [ + 'error', + 4 + ], + '@stylistic/key-spacing': [ + 'error', + { + 'beforeColon': false, + 'afterColon': true + } + ], + '@stylistic/keyword-spacing': [ + 'error', + { + 'before': true, + 'after': true + } + ], + '@stylistic/lines-between-class-members': [ + 'error', + 'always' + ], + '@stylistic/max-len': [ + 'warn', + { + 'code': 140, + 'comments': 160, + 'ignoreComments': false, + 'ignoreUrls': true, + 'ignoreStrings': true, + 'ignoreTemplateLiterals': true, + 'ignoreRegExpLiterals': true + } + ], + '@stylistic/max-statements-per-line': [ + 'error', + { + 'max': 1 + } + ], + '@stylistic/multiline-ternary': [ + 'error', + 'always-multiline' + ], + '@stylistic/new-parens': [ + 'error', + 'always' + ], + '@stylistic/newline-per-chained-call': 'error', + '@stylistic/no-confusing-arrow': 'error', + '@stylistic/no-extra-parens': [ + 'error', + 'all', + { + 'nestedBinaryExpressions': false, + 'ternaryOperandBinaryExpressions': false, + 'ignoreJSX': 'multi-line', + 'nestedConditionalExpressions': false + } + ], + '@stylistic/no-extra-semi': 'error', + '@stylistic/no-floating-decimal': 'error', + '@stylistic/no-mixed-operators': 'error', + '@stylistic/no-mixed-spaces-and-tabs': 'error', + '@stylistic/no-multi-spaces': 'error', + '@stylistic/no-multiple-empty-lines': [ + 'error', + { + 'max': 3, + 'maxEOF': 2 + } + ], + '@stylistic/no-tabs': 'error', + '@stylistic/no-trailing-spaces': 'error', + '@stylistic/no-whitespace-before-property': 'error', + '@stylistic/object-curly-newline': [ + 'error', + { + 'multiline': true, + 'minProperties': 1 + } + ], + '@stylistic/object-curly-spacing': [ + 'error', + 'always' + ], + '@stylistic/object-property-newline': 'error', + '@stylistic/one-var-declaration-per-line': 'error', + '@stylistic/operator-linebreak': [ + 'error', + 'before' + ], + '@stylistic/padded-blocks': [ + 'error', + { + 'blocks': 'never', + 'classes': 'always', + 'switches': 'never' + } + ], + + // Padding lines. The most in-depth part of this config + '@stylistic/padding-line-between-statements': [ + 'error', + // Variables, Constants + { + 'blankLine': 'never', + 'prev': 'var', + 'next': 'var' + }, + { + 'blankLine': 'never', + 'prev': 'let', + 'next': 'let' + }, + { + 'blankLine': 'never', + 'prev': 'const', + 'next': 'const' + }, + { + 'blankLine': 'always', + 'prev': 'var', + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'cjs-import', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'import', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'with' + ] + }, + { + 'blankLine': 'always', + 'prev': 'let', + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'cjs-import', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'import', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] + }, + { + 'blankLine': 'always', + 'prev': 'const', + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'cjs-import', + 'class', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'import', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] + }, + // Import + { + 'blankLine': 'never', + 'prev': 'import', + 'next': 'import' + }, + { + 'blankLine': 'never', + 'prev': 'cjs-import', + 'next': 'cjs-import' + }, + { + 'blankLine': 'always', + 'prev': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ], + 'next': 'cjs-import' + }, + { + 'blankLine': 'always', + 'prev': 'cjs-import', + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] + }, + { + 'blankLine': 'always', + 'prev': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ], + 'next': 'import' + }, + { + 'blankLine': 'always', + 'prev': 'import', + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] + }, + // If + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'if' + }, + { + 'blankLine': 'always', + 'prev': 'if', + 'next': '*' + }, + // For + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'for' + }, + { + 'blankLine': 'always', + 'prev': 'for', + 'next': '*' + }, + // While + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'while' + }, + { + 'blankLine': 'always', + 'prev': 'while', + 'next': '*' + }, + // Functions + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'function' + }, + { + 'blankLine': 'always', + 'prev': 'function', + 'next': '*' + }, + // Block Statements + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'block-like' + }, + { + 'blankLine': 'always', + 'prev': 'block-like', + 'next': '*' + }, + // Switch + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'switch' + }, + { + 'blankLine': 'always', + 'prev': 'switch', + 'next': '*' + }, + // Try-Catch + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'try' + }, + { + 'blankLine': 'always', + 'prev': 'try', + 'next': '*' + }, + // Throw + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'throw' + }, + { + 'blankLine': 'always', + 'prev': 'throw', + 'next': '*' + }, + // Return + { + 'blankLine': 'never', + 'prev': 'return', + 'next': '*' + }, + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'return' + }, + // Export + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'export' + }, + { + 'blankLine': 'always', + 'prev': 'export', + 'next': '*' + }, + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'cjs-export' + }, + { + 'blankLine': 'always', + 'prev': 'cjs-export', + 'next': '*' + }, + // Classes + { + 'blankLine': 'always', + 'prev': '*', + 'next': 'class' + }, + { + 'blankLine': 'always', + 'prev': 'class', + 'next': '*' + } + ], + '@stylistic/quote-props': [ + 'error', + 'always' + ], + '@stylistic/quotes': [ + 'error', + 'single' + ], + '@stylistic/rest-spread-spacing': [ + 'error', + 'never' + ], + '@stylistic/semi': [ + 'error', + 'always' + ], + '@stylistic/semi-spacing': [ + 'error', + { + 'before': false, + 'after': true + } + ], + '@stylistic/semi-style': [ + 'error', + 'last' + ], + '@stylistic/space-before-blocks': [ + 'error', + 'always' + ], + '@stylistic/space-before-function-paren': [ + 'error', + 'always' + ], + '@stylistic/space-in-parens': [ + 'error', + 'always' + ], + '@stylistic/space-infix-ops': [ + 'error', + { + 'int32Hint': false + } + ], + '@stylistic/space-unary-ops': 'error', + '@stylistic/spaced-comment': [ + 'error', + 'always' + ], + '@stylistic/switch-colon-spacing': 'error', + '@stylistic/template-curly-spacing': [ + 'error', + 'always' + ], + '@stylistic/template-tag-spacing': [ + 'error', + 'always' + ], + '@stylistic/type-generic-spacing': 'error', + '@stylistic/type-named-tuple-spacing': 'error', + '@stylistic/wrap-iife': [ + 'error', + 'inside' + ], + '@stylistic/wrap-regex': 'error', + '@stylistic/ts/type-annotation-spacing': 'error' + } +}; + +/** @type {import('eslint').Linter.Config} */ +export default tseslint.config( + // Base JavaScript rules + eslint.configs.recommended, + tseslint.configs.recommended, + style, + + // Vue support (including TS and JSX inside SFCs) + { + 'files': [ '**/*.vue' ], + 'languageOptions': { + 'sourceType': 'module', + 'ecmaVersion': 'latest', + 'globals': globals.browser, + 'parserOptions': { + 'parser': tseslint.parser + } + }, + 'plugins': { + 'vue': vue, + '@stylistic': stylistic, + '@stylistic/js': stylistic, + '@stylistic/ts': stylistic, + '@typescript-eslint': typescript + }, + 'extends': [ + eslint.configs.recommended, + ...vue.configs['flat/recommended'] + ], + 'rules': { + ...typescript.configs.recommended.rules, + ...style.rules, + + // Vue specific rules + '@stylistic/indent': 'off', + 'vue/html-indent': [ + 'error', + 4 + ], + 'vue/html-comment-indent': [ + 'error', + 4 + ], + 'vue/script-indent': [ + 'error', + 4, + { + 'baseIndent': 1, + 'switchCase': 1 + } + ], + 'vue/html-self-closing': [ + 'error', + { + 'html': { + 'void': 'never', + 'normal': 'never', + 'component': 'always' + }, + 'svg': 'always', + 'math': 'never' + } + ], + 'vue/max-attributes-per-line': [ + 'error', + { + 'singleline': 3, + 'multiline': 1 + } + ] + } + } +); diff --git a/events.d.ts b/events.d.ts new file mode 100644 index 0000000..fcb2a21 --- /dev/null +++ b/events.d.ts @@ -0,0 +1,6 @@ +// FIXME: TS error +declare global { + interface GlobalEventHandlersEventMap { + 'musickitloaded': CustomEvent; + } +} diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..a5b8ec0 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "devDependencies": { + "@eslint/js": "^10.0.1", + "@stylistic/eslint-plugin": "^5.10.0", + "eslint": "^10.9.0", + "eslint-plugin-vue": "^10.10.0", + "globals": "^17.11.0", + "typescript-eslint": "^8.67.0" + } +}