├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── 10-bug-report.yml │ ├── 20-feature-request.yml │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md ├── labeler-config.yml └── workflows │ ├── labeler.yml │ ├── license.yml │ ├── lint.yml │ ├── lint_pr.yml │ ├── release.yml │ ├── test-e2e.yml │ ├── test.yml │ └── yamory.yml ├── .gitignore ├── .prettierignore ├── .release-please-manifest.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── __tests__ ├── lib │ └── workspace.ts ├── npmScripts.test.ts └── projectReferences.test.ts ├── babel.config.js ├── eslint.config.mjs ├── jest.config.js ├── license-manager.config.js ├── package.json ├── packages ├── create-plugin │ ├── .gitignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── JestCustomEnvironment.js │ ├── LICENSE │ ├── README.md │ ├── __e2e__ │ │ ├── e2e.test.ts │ │ ├── fixtures │ │ │ ├── allOptions.ts │ │ │ ├── createKintonePluginCommand.ts │ │ │ ├── emptyOutputDir.ts │ │ │ ├── existOutputDir.ts │ │ │ ├── forbiddenCharacters.ts │ │ │ ├── index.ts │ │ │ ├── languageEN.ts │ │ │ ├── languageJA.ts │ │ │ ├── minimumTemplate.ts │ │ │ ├── modernTemplate.ts │ │ │ ├── pluginDescriptionContain200Chars.ts │ │ │ ├── pluginDescriptionContain201Chars.ts │ │ │ ├── pluginNameContain64Chars.ts │ │ │ ├── pluginNameContain65Chars.ts │ │ │ └── requiredOptions.ts │ │ ├── setup.ts │ │ └── utils │ │ │ ├── CreatePlugin.ts │ │ │ ├── constants.ts │ │ │ ├── executeCommand.ts │ │ │ ├── helper.ts │ │ │ └── verification.ts │ ├── babel.config.js │ ├── bin │ │ └── cli.js │ ├── eslint.config.mjs │ ├── jest.config.js │ ├── jest.e2e.config.js │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── fixtures │ │ │ │ └── manifest.json │ │ │ ├── generator.test.ts │ │ │ ├── helpers │ │ │ │ └── baseManifest.ts │ │ │ ├── lang.test.ts │ │ │ ├── manifest.test.ts │ │ │ ├── privateKey.test.ts │ │ │ ├── qa.test.ts │ │ │ └── template.test.ts │ │ ├── deps.ts │ │ ├── generator.ts │ │ ├── index.ts │ │ ├── lang.ts │ │ ├── logger.ts │ │ ├── manifest.ts │ │ ├── messages.ts │ │ ├── privateKey.ts │ │ ├── qa.ts │ │ ├── qa │ │ │ ├── prompt.ts │ │ │ └── validator.ts │ │ └── template.ts │ ├── templates │ │ ├── minimum │ │ │ ├── .gitignore │ │ │ ├── eslint.config.mjs │ │ │ ├── package.json │ │ │ ├── scripts │ │ │ │ └── npm-start.js │ │ │ ├── src │ │ │ │ ├── css │ │ │ │ │ ├── 51-modern-default.css │ │ │ │ │ ├── config.css │ │ │ │ │ ├── desktop.css │ │ │ │ │ └── mobile.css │ │ │ │ ├── html │ │ │ │ │ └── config.html.tmpl │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ └── js │ │ │ │ │ ├── config.js │ │ │ │ │ ├── desktop.js │ │ │ │ │ └── mobile.js │ │ │ └── with-plugin-uploader.json │ │ └── modern │ │ │ ├── .gitignore │ │ │ ├── eslint.config.mjs │ │ │ ├── package.json │ │ │ ├── plugin │ │ │ ├── css │ │ │ │ ├── 51-modern-default.css │ │ │ │ ├── config.css │ │ │ │ ├── desktop.css │ │ │ │ └── mobile.css │ │ │ ├── html │ │ │ │ └── config.html.tmpl │ │ │ └── image │ │ │ │ └── icon.png │ │ │ ├── scripts │ │ │ └── npm-start.js │ │ │ ├── src │ │ │ └── js │ │ │ │ ├── config.ts │ │ │ │ ├── desktop.ts │ │ │ │ └── mobile.ts │ │ │ ├── tsconfig.json │ │ │ ├── webpack.config.template.js │ │ │ ├── webpack.entry.json │ │ │ └── with-plugin-uploader.json │ ├── tsconfig.json │ └── types │ │ └── global │ │ └── index.d.ts ├── customize-uploader │ ├── .editorconfig │ ├── .gitignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── bin │ │ └── cli.js │ ├── docs │ │ └── example_setting.PNG │ ├── eslint.config.mjs │ ├── jest.config.js │ ├── package.json │ ├── sample │ │ ├── 51-modern-default.css │ │ ├── customize-manifest.json │ │ └── customize.js │ ├── src │ │ ├── KintoneApiClient.ts │ │ ├── __tests__ │ │ │ └── util.test.ts │ │ ├── commands │ │ │ ├── __tests__ │ │ │ │ ├── MockKintoneApiClient.ts │ │ │ │ ├── fixtures │ │ │ │ │ ├── a.css │ │ │ │ │ ├── a.js │ │ │ │ │ ├── b.js │ │ │ │ │ ├── c.js │ │ │ │ │ ├── d.css │ │ │ │ │ ├── get-appcustomize-init.json │ │ │ │ │ └── get-appcustomize-response.json │ │ │ │ ├── import.test.ts │ │ │ │ ├── index.test.ts │ │ │ │ └── init.test.ts │ │ │ ├── import.ts │ │ │ ├── index.ts │ │ │ └── init.ts │ │ ├── constants.ts │ │ ├── lang.ts │ │ ├── messages.ts │ │ ├── params │ │ │ ├── index.ts │ │ │ ├── init.ts │ │ │ └── prompts │ │ │ │ ├── index.ts │ │ │ │ └── init.ts │ │ └── util.ts │ └── tsconfig.json ├── dts-gen │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── bin │ │ └── npm-build.js │ ├── docs │ │ ├── .nojekyll │ │ ├── call-function.gif │ │ ├── compile-error.gif │ │ ├── field-type-definition-guide.md │ │ ├── how-to-use.md │ │ ├── index.html │ │ ├── maintenance-guide.md │ │ ├── sidebar.md │ │ ├── subtable.gif │ │ └── typescript-interface.gif │ ├── eslint.config.mjs │ ├── jest.config.js │ ├── kintone.d.ts │ ├── package.json │ ├── resources │ │ ├── shebang.txt │ │ ├── test-convertToTsExpression-fields.d.ts │ │ └── test-fullWidthSymbol-fields.d.ts │ ├── src │ │ ├── cli-parser.test.ts │ │ ├── cli-parser.ts │ │ ├── converters │ │ │ ├── fieldtype-converters.test.ts │ │ │ └── fileldtype-converter.ts │ │ ├── index.ts │ │ ├── integration-tests │ │ │ ├── dts-gen-api-test.ts │ │ │ ├── dts-gen-fields-test.ts │ │ │ ├── dts-gen-integration-test.ts │ │ │ ├── setup-test-app.ts │ │ │ ├── setup-test-utils.ts │ │ │ └── testfields.d.ts │ │ ├── kintone │ │ │ └── clients │ │ │ │ ├── axios-utils.test.ts │ │ │ │ ├── axios-utils.ts │ │ │ │ ├── demo-client.ts │ │ │ │ ├── demo-datas.ts │ │ │ │ ├── demo-fullwidth-symbol-client.ts │ │ │ │ ├── demo-fullwidth-symbols-datas.ts │ │ │ │ ├── forms-client-impl.test.ts │ │ │ │ ├── forms-client-impl.ts │ │ │ │ ├── forms-client.ts │ │ │ │ └── setup-test-app-client.ts │ │ ├── templates │ │ │ ├── converter.ts │ │ │ ├── expressions │ │ │ │ ├── expression.test.ts │ │ │ │ ├── expression.ts │ │ │ │ ├── fields.test.ts │ │ │ │ ├── fields.ts │ │ │ │ ├── namespace.test.ts │ │ │ │ ├── namespace.ts │ │ │ │ ├── typedefinitions.test.ts │ │ │ │ ├── typedefinitions.ts │ │ │ │ └── typescriptfieldtypeconverter.ts │ │ │ ├── template.test.ts │ │ │ └── template.ts │ │ ├── utils │ │ │ ├── logger.ts │ │ │ └── objectvalues.ts │ │ └── validators │ │ │ ├── __tests__ │ │ │ └── args.test.ts │ │ │ └── args.ts │ ├── tsconfig.json │ └── webpack.config.js ├── eslint-plugin │ ├── .gitignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── docs │ │ └── rules │ │ │ └── only-allowed-js-api.md │ ├── eslint.config.mjs │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── rules │ │ │ ├── index.ts │ │ │ └── only-allowed-js-api.ts │ │ └── utils │ │ │ ├── create-rule.ts │ │ │ ├── js-api.ts │ │ │ ├── manifest.ts │ │ │ └── settings.ts │ ├── tests │ │ ├── index.test.ts │ │ ├── rules │ │ │ └── only-allowed-js-api.test.ts │ │ └── setup.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsconfig.typecheck.json │ └── vitest.config.ts ├── plugin-manifest-validator │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── eslint.config.mjs │ ├── examples │ │ └── manifest.json │ ├── jest.config.js │ ├── manifest-schema.d.ts │ ├── manifest-schema.json │ ├── package.json │ ├── script │ │ └── generate-dts.js │ ├── src │ │ ├── __tests__ │ │ │ ├── check-required-properties.ts │ │ │ ├── index.ts │ │ │ └── validate-https-url.ts │ │ ├── check-required-properties.ts │ │ ├── index.ts │ │ ├── manifest-schema-test.ts │ │ └── validate-https-url.ts │ └── tsconfig.json ├── plugin-packer │ ├── .gitattributes │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── bin │ │ ├── cli.js │ │ └── eslint.config.mjs │ ├── docs │ │ ├── dist │ │ │ └── .gitkeep │ │ ├── index-ja.html │ │ ├── index.html │ │ └── style.css │ ├── eslint.config.mjs │ ├── from-manifest.js │ ├── jest.config.js │ ├── package.json │ ├── postcss.config.js │ ├── site │ │ ├── action.js │ │ ├── dom.js │ │ ├── eslint.config.mjs │ │ ├── index.js │ │ ├── jest.config.js │ │ ├── plugin.js │ │ ├── reducer.js │ │ ├── test │ │ │ ├── action-test.js │ │ │ └── reducer-test.js │ │ └── view.js │ ├── src │ │ ├── cli.ts │ │ ├── console.ts │ │ ├── create-contents-zip.ts │ │ ├── gen-error-msg.ts │ │ ├── hex2a.ts │ │ ├── index.ts │ │ ├── pack-plugin-from-manifest.ts │ │ ├── sign.ts │ │ ├── sourcelist.ts │ │ ├── uuid.ts │ │ └── zip.ts │ ├── test │ │ ├── bin.spec.ts │ │ ├── cli.spec.ts │ │ ├── create-contents-zip.spec.ts │ │ ├── fixtures │ │ │ ├── aaa.ppk │ │ │ ├── contents.zip │ │ │ ├── invalid-maxFileSize-contents.zip │ │ │ ├── plugin-full-manifest │ │ │ │ ├── css │ │ │ │ │ ├── config.css │ │ │ │ │ ├── desktop.css │ │ │ │ │ ├── mobile.css │ │ │ │ │ └── should-not-be-included.css │ │ │ │ ├── html │ │ │ │ │ ├── config.html │ │ │ │ │ └── should-not-be-included.html │ │ │ │ ├── image │ │ │ │ │ ├── icon.png │ │ │ │ │ └── should-not-be-included.png │ │ │ │ ├── js │ │ │ │ │ ├── config.js │ │ │ │ │ ├── desktop.js │ │ │ │ │ ├── mobile.js │ │ │ │ │ └── should-not-be-included.js │ │ │ │ ├── manifest.json │ │ │ │ └── should-not-be-included.json │ │ │ ├── plugin-invalid-https-url │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ └── manifest.json │ │ │ ├── plugin-invalid-maxFileSize │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ └── manifest.json │ │ │ ├── plugin-invalid-relative-path │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ └── manifest.json │ │ │ ├── plugin-invalid-url │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ └── manifest.json │ │ │ ├── plugin-non-file-exists │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ ├── js │ │ │ │ │ ├── config.js │ │ │ │ │ └── desktop.js │ │ │ │ └── manifest.json │ │ │ ├── plugin.zip │ │ │ ├── private.ppk │ │ │ └── sample-plugin │ │ │ │ └── plugin-dir │ │ │ │ ├── image │ │ │ │ └── icon.png │ │ │ │ └── manifest.json │ │ ├── helper │ │ │ └── zip.ts │ │ ├── hex2a.spec.ts │ │ ├── pack-plugin-from-manifest.spec.ts │ │ ├── packer.spec.ts │ │ └── sourcelist.spec.ts │ ├── tsconfig.json │ └── webpack.config.js ├── plugin-uploader │ ├── .editorconfig │ ├── .gitignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── bin │ │ └── cli.js │ ├── eslint.config.mjs │ ├── package.json │ ├── src │ │ ├── cli.ts │ │ ├── controllers │ │ │ ├── ControllerBase.ts │ │ │ └── PluginSystemController.ts │ │ ├── index.ts │ │ ├── lang.ts │ │ ├── messages.ts │ │ ├── pages │ │ │ ├── OldPluginSystemPage.ts │ │ │ ├── PluginSystemPageInterface.ts │ │ │ └── ReactPluginSystemPage.ts │ │ ├── params.ts │ │ └── prompts │ │ │ └── params.ts │ └── tsconfig.json ├── profile-loader │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── eslint.config.mjs │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── fixtures │ │ │ │ ├── config │ │ │ │ └── credentials │ │ │ └── index.test.ts │ │ ├── config.ts │ │ ├── env.ts │ │ ├── index.ts │ │ └── profile.ts │ └── tsconfig.json ├── rest-api-client │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── docs │ │ ├── app.md │ │ ├── bulkRequest.md │ │ ├── errorHandling.md │ │ ├── file.md │ │ ├── images │ │ │ └── example-of-KintoneAllRecordsError.png │ │ ├── plugin.md │ │ ├── record.md │ │ ├── space.md │ │ └── typescript.md │ ├── eslint.config.mjs │ ├── index.mjs │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.mjs │ ├── src │ │ ├── KintoneFields │ │ │ ├── exportTypes │ │ │ │ ├── __checks__ │ │ │ │ │ └── usecases │ │ │ │ │ │ ├── field.ts │ │ │ │ │ │ ├── layout.ts │ │ │ │ │ │ └── property.ts │ │ │ │ ├── field.ts │ │ │ │ ├── layout.ts │ │ │ │ └── property.ts │ │ │ └── types │ │ │ │ ├── __checks__ │ │ │ │ ├── field.ts │ │ │ │ ├── layout.ts │ │ │ │ └── property.ts │ │ │ │ ├── field.ts │ │ │ │ ├── fieldLayout.ts │ │ │ │ ├── layout.ts │ │ │ │ └── property.ts │ │ ├── KintoneRequestConfigBuilder.ts │ │ ├── KintoneResponseHandler.ts │ │ ├── KintoneRestAPIClient.ts │ │ ├── __tests__ │ │ │ ├── KintoneRequestConfigBuilder.test.ts │ │ │ ├── KintoneResponseHandler.test.ts │ │ │ ├── KintoneRestAPIClient.test.ts │ │ │ ├── e2e.rollup.test.ts │ │ │ ├── e2e.vite.test.ts │ │ │ ├── e2e.webpack.test.ts │ │ │ ├── fixtures │ │ │ │ ├── index.ts │ │ │ │ └── vite.config.mjs │ │ │ ├── index.browser.test.ts │ │ │ ├── index.test.ts │ │ │ ├── setup.ts │ │ │ └── url.test.ts │ │ ├── client │ │ │ ├── AppClient.ts │ │ │ ├── BaseClient.ts │ │ │ ├── BulkRequestClient.ts │ │ │ ├── FileClient.ts │ │ │ ├── PluginClient.ts │ │ │ ├── RecordClient.ts │ │ │ ├── SpaceClient.ts │ │ │ ├── __tests__ │ │ │ │ ├── AppClient.test.ts │ │ │ │ ├── BulkRequestClient.test.ts │ │ │ │ ├── File.test.ts │ │ │ │ ├── PluginClient.test.ts │ │ │ │ ├── RecordClient.test.ts │ │ │ │ ├── SpaceClient.test.ts │ │ │ │ ├── app │ │ │ │ │ ├── Acl.test.ts │ │ │ │ │ ├── Actions.test.ts │ │ │ │ │ ├── App.test.ts │ │ │ │ │ ├── AppCustomize.test.ts │ │ │ │ │ ├── AppSettings.test.ts │ │ │ │ │ ├── Deploy.test.ts │ │ │ │ │ ├── FormField.test.ts │ │ │ │ │ ├── FormLayout.test.ts │ │ │ │ │ ├── Notifications.test.ts │ │ │ │ │ ├── Plugins.test.ts │ │ │ │ │ ├── ProcessManagement.test.ts │ │ │ │ │ ├── Reports.test.ts │ │ │ │ │ └── Views.test.ts │ │ │ │ ├── fixtures │ │ │ │ │ ├── AppClientFixture.ts │ │ │ │ │ └── RecordClientFixture.ts │ │ │ │ └── record │ │ │ │ │ ├── AllRecords.test.ts │ │ │ │ │ ├── Cursor.test.ts │ │ │ │ │ ├── Record.test.ts │ │ │ │ │ ├── RecordAssignees.test.ts │ │ │ │ │ ├── RecordComment.test.ts │ │ │ │ │ └── RecordStatus.test.ts │ │ │ └── types │ │ │ │ ├── app │ │ │ │ ├── action.ts │ │ │ │ ├── adminNotes.ts │ │ │ │ ├── customize.ts │ │ │ │ ├── form.ts │ │ │ │ ├── index.ts │ │ │ │ ├── notification.ts │ │ │ │ ├── plugin.ts │ │ │ │ ├── processManagement.ts │ │ │ │ ├── report.ts │ │ │ │ ├── right.ts │ │ │ │ ├── setting.ts │ │ │ │ └── view.ts │ │ │ │ ├── entity.ts │ │ │ │ ├── index.ts │ │ │ │ ├── plugin │ │ │ │ └── index.ts │ │ │ │ ├── record │ │ │ │ └── index.ts │ │ │ │ └── space │ │ │ │ └── index.ts │ │ ├── error │ │ │ ├── KintoneAbortSearchError.ts │ │ │ ├── KintoneAllRecordsError.ts │ │ │ ├── KintoneRestAPIError.ts │ │ │ ├── __tests__ │ │ │ │ ├── KintoneAbortSearchError.test.ts │ │ │ │ ├── KintoneAllRecordsError.test.ts │ │ │ │ └── KintoneRestAPIError.test.ts │ │ │ └── index.ts │ │ ├── http │ │ │ ├── AxiosClient.ts │ │ │ ├── HttpClientInterface.ts │ │ │ ├── MockClient.ts │ │ │ └── index.ts │ │ ├── index.browser.ts │ │ ├── index.ts │ │ ├── platform │ │ │ ├── UnsupportedPlatformError.ts │ │ │ ├── __tests__ │ │ │ │ └── browser.test.ts │ │ │ ├── browser.ts │ │ │ ├── index.ts │ │ │ └── node.ts │ │ ├── types │ │ │ └── auth.ts │ │ └── url.ts │ ├── tsconfig.build.esm.json │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsconfig.typecheck.json │ ├── tsconfig.typecheck.node.json │ └── types │ │ └── global │ │ └── index.d.ts ├── rest │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── __e2e__ │ │ └── e2e.test.ts │ ├── docs │ │ └── migration-from-rest-api-client.md │ ├── eslint.config.mjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── helpers │ │ │ │ └── iterator.test.ts │ │ │ └── index.browser.test.ts │ │ ├── client │ │ │ ├── BodySerializer │ │ │ │ ├── FormDataBodySerializer.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── FormDataBodySerializer.test.ts │ │ │ ├── KintoneClientOptions │ │ │ │ ├── Auth.ts │ │ │ │ ├── HttpsAgent.ts │ │ │ │ ├── Proxy.ts │ │ │ │ ├── SocketTimeout.ts │ │ │ │ ├── index.ts │ │ │ │ └── types │ │ │ │ │ ├── Auth.ts │ │ │ │ │ ├── CertAuth.ts │ │ │ │ │ └── Proxy.ts │ │ │ ├── Middlewares │ │ │ │ ├── CsrfMiddleware.ts │ │ │ │ └── HttpMethodOverrideMiddleware.ts │ │ │ └── index.ts │ │ ├── helpers │ │ │ └── iterator.ts │ │ ├── index.browser.ts │ │ ├── index.ts │ │ ├── package.cjs.json │ │ ├── package.esm.json │ │ ├── platform │ │ │ ├── UnsupportedPlatformError.ts │ │ │ ├── browser.ts │ │ │ ├── index.ts │ │ │ └── node.ts │ │ └── schemas │ │ │ └── schema.ts │ ├── tsconfig.json │ ├── vite.config.ts │ ├── vite.config.umd.ts │ ├── vitest.config.ts │ └── vitest.e2e.config.ts ├── tsconfig-base.json ├── tsconfig.json └── webpack-plugin-kintone-plugin │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── eslint.config.mjs │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── __tests__ │ │ ├── cli.test.ts │ │ ├── fixtures │ │ │ └── sample │ │ │ │ ├── .gitignore │ │ │ │ ├── dist │ │ │ │ └── .gitkeep │ │ │ │ ├── plugin │ │ │ │ ├── css │ │ │ │ │ ├── config.css │ │ │ │ │ ├── desktop.css │ │ │ │ │ └── mobile.css │ │ │ │ ├── html │ │ │ │ │ └── config.html │ │ │ │ ├── image │ │ │ │ │ └── icon.png │ │ │ │ └── manifest.json │ │ │ │ ├── private.ppk │ │ │ │ ├── src │ │ │ │ ├── config.js │ │ │ │ ├── desktop.js │ │ │ │ └── mobile.js │ │ │ │ └── webpack.config.js │ │ ├── helpers │ │ │ └── index.ts │ │ ├── index.test.ts │ │ ├── plugin.test.ts │ │ └── watch.test.ts │ ├── index.ts │ └── plugin.ts │ ├── tsconfig.json │ └── types │ └── global │ └── index.d.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── release-please-config.json ├── renovate.json5 ├── scripts └── update-contributors.ts └── tsconfig.json /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This file controls default reviewers. 2 | * @kintone/extensions-platform 3 | 4 | # CODEOWNERS prevent automerge of Renovate 5 | # Following files should be owned by everyone 6 | **/*/package.json 7 | **/*/pnpm-lock.yaml 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/20-feature-request.yml: -------------------------------------------------------------------------------- 1 | name: "🚀 Feature Request" 2 | description: Propose a feature improvement of cli-kintone 3 | labels: ["feature request"] 4 | title: "[Feature Request] " 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for sending a feature request! Please fill out the followings. 10 | - type: dropdown 11 | id: package 12 | attributes: 13 | label: Target Package 14 | description: Which package do you want to add a feature for? 15 | multiple: true 16 | options: 17 | - "@kintone/rest-api-client" 18 | - "@kintone/customize-uploader" 19 | - "@kintone/plugin-manifest-validator" 20 | - "@kintone/create-plugin" 21 | - "@kintone/plugin-packer" 22 | - "@kintone/webpack-plugin-kintone-plugin" 23 | - "@kintone/plugin-uploader" 24 | - "@kintone/dts-gen" 25 | validations: 26 | required: true 27 | - type: textarea 28 | id: why 29 | attributes: 30 | label: Why 31 | description: Why do you want the feature, and why should it be in the package? 32 | validations: 33 | required: true 34 | - type: textarea 35 | id: what 36 | attributes: 37 | label: What 38 | description: What is a solution you want to add? 39 | validations: 40 | required: true 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true # Only for maintainers 2 | contact_links: 3 | - name: 🇯🇵 日本語はこちら 4 | url: https://github.com/kintone/js-sdk-ja 5 | about: 日本語でのバグ報告・機能提案はこちら 6 | - name: 💬 Questions and Help (ja) 7 | url: https://community.cybozu.dev/c/kintone/5 8 | about: Ask questions and discuss with other users in Cybozu Developer Community 9 | - name: 🌏 Questions and Help (en) 10 | url: https://forum.kintone.dev/ 11 | about: Ask questions and discuss with other users in Kintone Developer Forum 12 | - name: 📤 API Support 13 | url: https://jp.cybozu.help/k/ja/trouble_shooting/developer/developer_qa.html 14 | about: Contact with our API support. Suitable for API inquiries or inquiries including closed information. 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Why 4 | 5 | 6 | 7 | ## What 8 | 9 | 10 | 11 | ## How to test 12 | 13 | 14 | 15 | ## Checklist 16 | 17 | - [ ] Read [CONTRIBUTING.md](https://github.com/kintone/js-sdk/blob/main/CONTRIBUTING.md) 18 | - [ ] Updated documentation if it is required. 19 | - [ ] Added tests if it is required. 20 | - [ ] Passed `pnpm lint` and `pnpm test` on the root directory. 21 | -------------------------------------------------------------------------------- /.github/labeler-config.yml: -------------------------------------------------------------------------------- 1 | "pkg: create-plugin": 2 | - changed-files: 3 | - any-glob-to-any-file: "packages/create-plugin/**/*" 4 | 5 | "pkg: customize-uploader": 6 | - changed-files: 7 | - any-glob-to-any-file: "packages/customize-uploader/**/*" 8 | 9 | "pkg: dts-gen": 10 | - changed-files: 11 | - any-glob-to-any-file: "packages/dts-gen/**/*" 12 | 13 | "pkg: plugin-manifest-validator": 14 | - changed-files: 15 | - any-glob-to-any-file: "packages/plugin-manifest-validator/**/*" 16 | 17 | "pkg: plugin-packer": 18 | - changed-files: 19 | - any-glob-to-any-file: "packages/plugin-packer/**/*" 20 | 21 | "pkg: plugin-uploader": 22 | - changed-files: 23 | - any-glob-to-any-file: "packages/plugin-uploader/**/*" 24 | 25 | "pkg: profile-loader": 26 | - changed-files: 27 | - any-glob-to-any-file: "packages/profile-loader/**/*" 28 | 29 | "pkg: rest-api-client": 30 | - changed-files: 31 | - any-glob-to-any-file: "packages/rest-api-client/**/*" 32 | 33 | "pkg: webpack-plugin-kintone-plugin": 34 | - changed-files: 35 | - any-glob-to-any-file: "packages/webpack-plugin-kintone-plugin/**/*" 36 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | - pull_request_target 4 | 5 | jobs: 6 | triage: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | contents: read 10 | pull-requests: write 11 | steps: 12 | - uses: Kesin11/actions-timeline@da70beff098ff89b15d279e8bf2f60519a8dadd7 # v2 13 | - uses: actions/labeler@v5 14 | with: 15 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 16 | configuration-path: .github/labeler-config.yml 17 | -------------------------------------------------------------------------------- /.github/workflows/license.yml: -------------------------------------------------------------------------------- 1 | name: License 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | analyze: 11 | name: Analyze the licenses 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: Kesin11/actions-timeline@da70beff098ff89b15d279e8bf2f60519a8dadd7 # v2 15 | - name: Check out repository 16 | uses: actions/checkout@v4 17 | - uses: pnpm/action-setup@v3 18 | - name: Use Node.js 18.x 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: 18.x 22 | cache: "pnpm" 23 | 24 | - name: Install dependencies 25 | run: pnpm install --frozen-lockfile 26 | 27 | - name: Check licenses 28 | run: | 29 | pnpm license:analyze 30 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - "renovate/**" 8 | pull_request: 9 | 10 | jobs: 11 | lint: 12 | name: Node.js ubuntu-latest 18.x 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: Kesin11/actions-timeline@da70beff098ff89b15d279e8bf2f60519a8dadd7 # v2 16 | 17 | - uses: actions/checkout@v4 18 | 19 | - uses: pnpm/action-setup@v3 20 | 21 | - uses: actions/setup-node@v4 22 | with: 23 | node-version: "18" 24 | cache: "pnpm" 25 | 26 | - run: pnpm install --frozen-lockfile 27 | - run: pnpm build 28 | - run: pnpm lint 29 | -------------------------------------------------------------------------------- /.github/workflows/lint_pr.yml: -------------------------------------------------------------------------------- 1 | name: "Lint PR" 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | - reopened 10 | 11 | permissions: 12 | pull-requests: read 13 | 14 | jobs: 15 | main: 16 | name: Validate PR title 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: amannn/action-semantic-pull-request@v5 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - "renovate/**" 8 | pull_request: 9 | 10 | jobs: 11 | test: 12 | name: Node.js ${{ matrix.os }} ${{ matrix.node-version }} 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | matrix: 17 | node-version: [18.x, 20.x] 18 | os: [ubuntu-latest, windows-latest, macos-latest] 19 | 20 | steps: 21 | - run: git config --global core.autocrlf false 22 | - uses: actions/checkout@v4 23 | 24 | - uses: pnpm/action-setup@v3 25 | 26 | - name: Use Node.js ${{ matrix.node-version }} 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: ${{ matrix.node-version }} 30 | cache: "pnpm" 31 | 32 | - run: pnpm install --fetch-timeout 900000 --frozen-lockfile 33 | - run: pnpm build 34 | - run: pnpm test:ci 35 | 36 | actions-timeline: 37 | needs: [test] 38 | runs-on: ubuntu-latest 39 | if: ${{ !cancelled() }} 40 | steps: 41 | - uses: Kesin11/actions-timeline@da70beff098ff89b15d279e8bf2f60519a8dadd7 # v2 42 | -------------------------------------------------------------------------------- /.github/workflows/yamory.yml: -------------------------------------------------------------------------------- 1 | name: yamory 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - yamory-* 8 | jobs: 9 | check: 10 | name: Node.js ubuntu-latest 18.x 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: Kesin11/actions-timeline@da70beff098ff89b15d279e8bf2f60519a8dadd7 # v2 14 | 15 | - uses: actions/checkout@v4 16 | 17 | - uses: pnpm/action-setup@v3 18 | 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: "18" 22 | 23 | - name: download and validate Yamory script 24 | working-directory: /tmp 25 | run: | 26 | curl -sSf -L -o ./yamory-pnpm.sh https://localscanner.yamory.io/script/pnpm 27 | curl -sSf -L -o ./yamory-pnpm-sha512sum.txt \ 28 | https://cli.yamory.io/yamory-app-library-scan-scripts/yamory-pnpm-sha512sum.txt 29 | sha512sum --check yamory-pnpm-sha512sum.txt 30 | chmod +x ./yamory-pnpm.sh 31 | - name: run Yamory 32 | run: | 33 | ls -d packages/*/ | xargs -I {} /tmp/yamory-pnpm.sh --manifest {}/package.json 34 | ls -d examples/*/ | xargs -I {} /tmp/yamory-pnpm.sh --manifest {}/package.json 35 | env: 36 | CI: true 37 | PROJECT_GROUP_KEY: js-sdk 38 | YAMORY_API_KEY: ${{ secrets.YAMORY_API_KEY }} 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.tsbuildinfo 3 | /.idea/ 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | /packages/*/lib 3 | /packages/*/dist 4 | /packages/*/esm 5 | 6 | # Ignore tsconfig file 7 | tsconfig.json 8 | tsconfig-base.json 9 | 10 | # Ignore auto generated files 11 | pnpm-lock.yaml 12 | CHANGELOG.md 13 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages/create-plugin": "8.2.5", 3 | "packages/customize-uploader": "8.0.14", 4 | "packages/dts-gen": "8.1.2", 5 | "@kintone/eslint-plugin": "0.0.0", 6 | "packages/plugin-manifest-validator": "10.3.1", 7 | "packages/plugin-packer": "8.2.1", 8 | "packages/plugin-uploader": "9.1.5", 9 | "packages/profile-loader": "5.0.2", 10 | "packages/rest-api-client": "5.7.4", 11 | "packages/webpack-plugin-kintone-plugin": "8.0.11", 12 | "packages/eslint-plugin": "0.0.3", 13 | "packages/rest": "0.2.1" 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Cybozu, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__tests__/npmScripts.test.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import assert from "assert"; 3 | 4 | import { getWorkspaces } from "./lib/workspace"; 5 | 6 | const REQUIRED_NPMSCRIPTS = ["build", "lint", "test", "test:ci"]; 7 | 8 | describe("npmScripts", () => { 9 | it("should define all required npm-scripts in all pacakges", () => { 10 | const workspaces = getWorkspaces().filter(({ packagePath }) => 11 | /\/packages\//.test(packagePath) 12 | ); 13 | for (const { packageName, packagePath } of workspaces) { 14 | const { scripts } = require(path.resolve(packagePath, "package.json")); 15 | for (const requiredScript of REQUIRED_NPMSCRIPTS) { 16 | assert.strictEqual( 17 | typeof scripts[requiredScript], 18 | "string", 19 | `${packageName} doesn't have "${requiredScript}" as a npm-scripts.` 20 | ); 21 | } 22 | } 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ["@babel/preset-env", { targets: { node: "current" } }], 4 | "@babel/preset-typescript", 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import presetsNodeTypescriptPrettier from "@cybozu/eslint-config/flat/presets/node-typescript-prettier.js"; 2 | import eslintPluginPackageJson from "eslint-plugin-package-json"; 3 | 4 | /** @type {import("eslint").Linter.Config[]} */ 5 | export default [ 6 | ...presetsNodeTypescriptPrettier, 7 | { 8 | rules: { 9 | curly: ["error", "all"], 10 | "func-style": ["error"], 11 | 12 | "@typescript-eslint/no-empty-object-type": "off", 13 | 14 | "@typescript-eslint/no-wrapper-object-types": "off", 15 | 16 | "@typescript-eslint/consistent-type-imports": [ 17 | "error", 18 | { 19 | prefer: "type-imports", 20 | }, 21 | ], 22 | 23 | "n/no-missing-import": "off", 24 | }, 25 | }, 26 | { 27 | ...eslintPluginPackageJson.configs.recommended, 28 | rules: { 29 | ...eslintPluginPackageJson.configs.recommended.rules, 30 | "@typescript-eslint/consistent-type-imports": "off", 31 | }, 32 | }, 33 | ]; 34 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@jest/types').Config.InitialOptions} */ 2 | const config = { 3 | roots: ["/__tests__"], 4 | testPathIgnorePatterns: ["/node_modules/", "lib/"], 5 | }; 6 | module.exports = config; 7 | -------------------------------------------------------------------------------- /license-manager.config.js: -------------------------------------------------------------------------------- 1 | const { createConfig } = require("@cybozu/license-manager"); 2 | 3 | const config = createConfig({ 4 | analyze: { 5 | allowLicenses: [ 6 | "MIT", 7 | "Apache-2.0", 8 | "BSD-2-Clause", 9 | "BSD-3-Clause", 10 | "BSD-3-Clause OR MIT", 11 | "ISC", 12 | "0BSD", 13 | "Python-2.0", 14 | "MPL-2.0", 15 | "CC0-1.0", 16 | "CC-BY-3.0", 17 | "CC-BY-4.0", 18 | "(MIT OR CC0-1.0)", 19 | "(MIT AND Zlib)", 20 | "(MIT AND BSD-3-Clause)", 21 | "(MIT AND CC-BY-3.0)", 22 | "BlueOak-1.0.0", 23 | "(BSD-3-Clause OR GPL-2.0)", 24 | "Unlicense", 25 | ], 26 | allowPackages: ["indexof"], 27 | }, 28 | overrideLicense: (dep) => { 29 | // https://github.com/mafintosh/browserify-fs?tab=readme-ov-file#license 30 | if (dep.name === "browserify-fs") { 31 | return "MIT"; 32 | } 33 | // https://github.com/mafintosh/fwd-stream?tab=readme-ov-file#license 34 | if (dep.name === "fwd-stream") { 35 | return "MIT"; 36 | } 37 | // https://github.com/dominictarr/level-hooks/blob/master/LICENSE 38 | if (dep.name === "level-hooks") { 39 | return "MIT"; 40 | } 41 | // https://www.npmjs.com/package/@braidai/lang?activeTab=code 42 | if (dep.name === "@braidai/lang") { 43 | return "MIT"; 44 | } 45 | return undefined; 46 | }, 47 | packageManager: "pnpm", 48 | }); 49 | 50 | module.exports = config; 51 | -------------------------------------------------------------------------------- /packages/create-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | .vscode/ 4 | -------------------------------------------------------------------------------- /packages/create-plugin/.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | templates/ 3 | CHANGELOG.md -------------------------------------------------------------------------------- /packages/create-plugin/JestCustomEnvironment.js: -------------------------------------------------------------------------------- 1 | const { TestEnvironment } = require("jest-environment-node"); 2 | 3 | class JestCustomEnvironment extends TestEnvironment { 4 | handleTestEvent(event) { 5 | if (event.name === "test_start") { 6 | const testName = event.test.name; 7 | console.log(`Running test: ${testName}`); 8 | } 9 | 10 | if (!this.global.testStatuses) { 11 | this.global.testStatuses = {}; 12 | } 13 | 14 | if (event.name === "test_fn_success") { 15 | const testName = event.test.name; 16 | this.global.testStatuses[testName] = "passed"; 17 | } 18 | } 19 | } 20 | 21 | module.exports = JestCustomEnvironment; 22 | -------------------------------------------------------------------------------- /packages/create-plugin/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Cybozu, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/fixtures/emptyOutputDir.ts: -------------------------------------------------------------------------------- 1 | import type { TestPattern } from "../e2e.test"; 2 | import { CREATE_PLUGIN_COMMAND } from "../utils/constants"; 3 | 4 | export const pattern: TestPattern = { 5 | description: 6 | "#JsSdkTest-9 Should throw an error when the output directory is empty", 7 | input: { 8 | command: CREATE_PLUGIN_COMMAND, 9 | outputDir: "", 10 | questionsInput: [], 11 | }, 12 | expected: { 13 | failure: { stderr: "Please specify the output directory" }, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/fixtures/existOutputDir.ts: -------------------------------------------------------------------------------- 1 | import type { TestPattern } from "../e2e.test"; 2 | import { CREATE_PLUGIN_COMMAND } from "../utils/constants"; 3 | import fs from "fs"; 4 | 5 | const outputDir = "test10"; 6 | export const pattern: TestPattern = { 7 | description: 8 | "#JsSdkTest-10 Should throw an error when the output directory is duplicated with the existent directory", 9 | prepareFn: (settings: { workingDir: string }) => { 10 | fs.mkdirSync(`${settings.workingDir}/${outputDir}`); 11 | }, 12 | input: { 13 | command: CREATE_PLUGIN_COMMAND, 14 | outputDir: outputDir, 15 | questionsInput: [], 16 | }, 17 | expected: { 18 | failure: { 19 | stderr: `Error: ${outputDir} already exists. Choose a different directory`, 20 | }, 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/fixtures/index.ts: -------------------------------------------------------------------------------- 1 | export { pattern as requiredOptions } from "./requiredOptions"; 2 | export { pattern as pluginNameContain64Chars } from "./pluginNameContain64Chars"; 3 | export { pattern as pluginDescriptionContain200Chars } from "./pluginDescriptionContain200Chars"; 4 | export { pattern as allOptions } from "./allOptions"; 5 | export { pattern as languageEN } from "./languageEN"; 6 | export { pattern as languageJA } from "./languageJA"; 7 | export { pattern as emptyOutputDir } from "./emptyOutputDir"; 8 | export { pattern as existOutputDir } from "./existOutputDir"; 9 | export { pattern as forbiddenCharacters } from "./forbiddenCharacters"; 10 | export { pattern as pluginNameContain65Chars } from "./pluginNameContain65Chars"; 11 | export { pattern as pluginDescriptionContain201Chars } from "./pluginDescriptionContain201Chars"; 12 | export { pattern as createKintonePluginCommand } from "./createKintonePluginCommand"; 13 | export { pattern as minimumTemplate } from "./minimumTemplate"; 14 | export { pattern as modernTemplate } from "./modernTemplate"; 15 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/fixtures/pluginDescriptionContain201Chars.ts: -------------------------------------------------------------------------------- 1 | import type { TestPattern } from "../e2e.test"; 2 | import { CREATE_PLUGIN_COMMAND } from "../utils/constants"; 3 | import { generateRandomString } from "../utils/helper"; 4 | import { getBoundMessage } from "../../src/messages"; 5 | 6 | const m = getBoundMessage("en"); 7 | 8 | export const pattern: TestPattern = { 9 | description: 10 | "#JsSdkTest-13 Should throw an error when creating plugin with plugin-in description contains 201 characters", 11 | input: { 12 | command: CREATE_PLUGIN_COMMAND, 13 | outputDir: "test13", 14 | questionsInput: [ 15 | { 16 | question: m("Q_NameEn"), 17 | answer: "test13", 18 | }, 19 | { 20 | question: m("Q_DescriptionEn"), 21 | answer: generateRandomString(201), 22 | }, 23 | ], 24 | }, 25 | expected: { 26 | validation: { stdout: "> Plug-in description must be 1-200chars" }, 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/fixtures/pluginNameContain65Chars.ts: -------------------------------------------------------------------------------- 1 | import type { TestPattern } from "../e2e.test"; 2 | import { CREATE_PLUGIN_COMMAND } from "../utils/constants"; 3 | import { generateRandomString } from "../utils/helper"; 4 | import { getBoundMessage } from "../../src/messages"; 5 | 6 | const m = getBoundMessage("en"); 7 | 8 | export const pattern: TestPattern = { 9 | description: 10 | "#JsSdkTest-12 Should throw an error when creating plugin with plugin-in name contains 65 characters", 11 | input: { 12 | command: CREATE_PLUGIN_COMMAND, 13 | outputDir: "test12", 14 | questionsInput: [ 15 | { 16 | question: m("Q_NameEn"), 17 | answer: generateRandomString(65), 18 | }, 19 | ], 20 | }, 21 | expected: { 22 | validation: { stdout: "> Plug-in name must be 1-64chars" }, 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/setup.ts: -------------------------------------------------------------------------------- 1 | const isRunOnActions = () => !!process.env.GITHUB_ACTIONS; 2 | 3 | if (isRunOnActions()) { 4 | jest.retryTimes(3, { logErrorsBeforeRetry: true }); 5 | } 6 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/utils/constants.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_ANSWER = ""; 2 | export const ANSWER_YES = "Yes"; 3 | export const ANSWER_NO = "No"; 4 | 5 | export const CREATE_PLUGIN_COMMAND = "create-plugin"; 6 | export const CREATE_KINTONE_PLUGIN_COMMAND = "create-kintone-plugin"; 7 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/utils/helper.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | import os from "os"; 4 | 5 | export const generateRandomString = (length: number) => { 6 | let result = ""; 7 | const characters = 8 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 9 | const charactersLength = characters.length; 10 | let counter = 0; 11 | while (counter < length) { 12 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 13 | counter += 1; 14 | } 15 | return result; 16 | }; 17 | 18 | export const generateWorkingDir = (): string => { 19 | return fs.mkdtempSync( 20 | path.join(os.tmpdir(), `create-plugin-e2e-test-${new Date().valueOf()}-`), 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/create-plugin/__e2e__/utils/verification.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | import assert from "assert"; 4 | 5 | export type PluginTemplate = "minimum" | "modern"; 6 | 7 | export const readPluginManifestJson = ( 8 | pluginDir: string, 9 | template: PluginTemplate = "minimum", 10 | ) => { 11 | try { 12 | const manifestJsonPath = path.resolve( 13 | pluginDir, 14 | template === "modern" ? "plugin" : "src", 15 | "manifest.json", 16 | ); 17 | 18 | const fileContent = fs.readFileSync(manifestJsonPath, "utf8"); 19 | return JSON.parse(fileContent); 20 | } catch (e) { 21 | throw new Error(`Failed to read manifest.json\n${e}`); 22 | } 23 | }; 24 | 25 | export const assertObjectIncludes = ( 26 | actual: { [key: PropertyKey]: unknown }, 27 | expected: { [key: PropertyKey]: unknown }, 28 | message?: string | Error, 29 | ) => { 30 | for (const key in expected) { 31 | if (Object.prototype.hasOwnProperty.call(expected, key)) { 32 | assert.deepStrictEqual(actual[key], expected[key], message); 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /packages/create-plugin/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ["@babel/preset-env", { targets: { node: "current" } }], 4 | "@babel/preset-typescript", 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /packages/create-plugin/bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict"; 4 | 5 | const osLocale = require("os-locale"); 6 | const meow = require("meow"); 7 | const run = require("../dist/src/index"); 8 | const { getDefaultLang } = require("../dist/src/lang"); 9 | const { 10 | isValidTemplateType, 11 | SUPPORT_TEMPLATE_TYPE, 12 | } = require("../dist/src/template"); 13 | 14 | const cli = meow( 15 | ` 16 | Usage 17 | $ create-kintone-plugin 18 | Options 19 | --lang Using language (en or ja) 20 | --template A template for a generated plug-in (${SUPPORT_TEMPLATE_TYPE.join( 21 | "," 22 | )}: the default value is minimum) 23 | `, 24 | { 25 | flags: { 26 | lang: { 27 | type: "string", 28 | default: getDefaultLang(osLocale.sync()), 29 | }, 30 | template: { 31 | type: "string", 32 | default: "minimum", 33 | }, 34 | }, 35 | } 36 | ); 37 | 38 | const directory = cli.input[0]; 39 | const { lang, template } = cli.flags; 40 | 41 | if (!directory) { 42 | console.error("Please specify the output directory"); 43 | cli.showHelp(); 44 | } 45 | 46 | if (lang !== "ja" && lang !== "en") { 47 | console.error("--lang option only supports en or ja"); 48 | cli.showHelp(); 49 | } 50 | 51 | if (!isValidTemplateType(template)) { 52 | console.error( 53 | `--template option only supports ${SUPPORT_TEMPLATE_TYPE.join(",")}` 54 | ); 55 | cli.showHelp(); 56 | } 57 | 58 | run(directory, lang, template); 59 | -------------------------------------------------------------------------------- /packages/create-plugin/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import rootConfig from "../../eslint.config.mjs"; 2 | 3 | /** @type {import("eslint").Linter.Config[]} */ 4 | export default [...rootConfig]; 5 | -------------------------------------------------------------------------------- /packages/create-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@jest/types').Config.InitialOptions} */ 2 | const config = { 3 | roots: ["/src"], 4 | testRegex: "/__tests__/.*\\.test\\.ts$", 5 | testEnvironment: "node", 6 | }; 7 | module.exports = config; 8 | -------------------------------------------------------------------------------- /packages/create-plugin/jest.e2e.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@jest/types').Config.InitialOptions} */ 2 | const config = { 3 | roots: [""], 4 | testRegex: "/__e2e__/.*\\.test\\.ts$", 5 | testEnvironment: "./JestCustomEnvironment.js", 6 | setupFilesAfterEnv: ["/__e2e__/setup.ts"], 7 | testTimeout: 120000, 8 | }; 9 | module.exports = config; 10 | -------------------------------------------------------------------------------- /packages/create-plugin/src/__tests__/fixtures/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/kintone/js-sdk/%40kintone/plugin-manifest-validator%4010.2.0/packages/plugin-manifest-validator/manifest-schema.json", 3 | "manifest_version": 1, 4 | "version": 1, 5 | "type": "APP", 6 | "desktop": { 7 | "js": ["js/desktop.js"], 8 | "css": ["css/51-modern-default.css", "css/desktop.css"] 9 | }, 10 | "icon": "image/icon.png", 11 | "name": { 12 | "en": "kintone-plugin-demo" 13 | }, 14 | "description": { 15 | "en": "kintone-plugin-demo" 16 | }, 17 | "mobile": { 18 | "js": ["js/mobile.js"] 19 | }, 20 | "config": { 21 | "html": "html/config.html", 22 | "js": ["js/config.js"], 23 | "css": ["css/51-modern-default.css", "css/config.css"], 24 | "required_params": [] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/create-plugin/src/__tests__/helpers/baseManifest.ts: -------------------------------------------------------------------------------- 1 | import type { Manifest } from "../../manifest"; 2 | 3 | export default function createBaseManifest(): Manifest { 4 | return { 5 | manifest_version: 1, 6 | version: 1, 7 | type: "APP", 8 | name: { 9 | en: "sample", 10 | }, 11 | icon: "image/icon.png", 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/create-plugin/src/__tests__/lang.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from "assert"; 2 | import { getDefaultLang } from "../lang"; 3 | 4 | describe("lang", () => { 5 | describe("getDefaultLang", () => { 6 | it('should return "ja" or "en" based the passed value', () => { 7 | assert.strictEqual(getDefaultLang("ja_JP.UTF-8"), "ja"); 8 | assert.strictEqual(getDefaultLang("C"), "en"); 9 | }); 10 | it('should return "en" as the default value if the passed value is undefined', () => { 11 | assert.strictEqual(getDefaultLang(), "en"); 12 | assert.strictEqual(getDefaultLang(undefined), "en"); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/create-plugin/src/__tests__/privateKey.test.ts: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import { generatePrivateKey } from "../privateKey"; 3 | 4 | describe("privateKey", () => { 5 | describe("generatePrivateKey", () => { 6 | it("should be able to create a private key", () => { 7 | const key = generatePrivateKey(); 8 | assert(key.startsWith("-----BEGIN RSA PRIVATE KEY-----")); 9 | }); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/create-plugin/src/deps.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import { spawnSync } from "child_process"; 4 | import type { Lang } from "./lang"; 5 | import { printLog } from "./logger"; 6 | import { getMessage } from "./messages"; 7 | 8 | /** 9 | * Install specified dependencies 10 | * @param outputDirectory 11 | * @param lang 12 | */ 13 | export const installDependencies = ( 14 | outputDirectory: string, 15 | lang: Lang, 16 | ): void => { 17 | printLog(getMessage(lang, "installDependencies")); 18 | 19 | const result = spawnSync("npm", ["install"], { 20 | cwd: outputDirectory, 21 | stdio: "inherit", 22 | shell: true, 23 | }); 24 | if (result.status !== 0) { 25 | throw new Error("Installing dependencies were failed"); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /packages/create-plugin/src/lang.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export type Lang = "ja" | "en"; 4 | 5 | /** 6 | * Get a default language based on LANG environment value 7 | * @param lang 8 | */ 9 | export const getDefaultLang = (lang?: string): Lang => { 10 | return lang && lang.startsWith("ja") ? "ja" : "en"; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/create-plugin/src/logger.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Print logs 5 | * @param texts 6 | */ 7 | export const printLog = (...texts: string[]) => { 8 | texts.forEach((t) => console.log(t)); 9 | }; 10 | 11 | /** 12 | * Print errors 13 | * @param errors 14 | */ 15 | export const printError = (...errors: string[]) => { 16 | errors.forEach((e) => console.error(e)); 17 | }; 18 | -------------------------------------------------------------------------------- /packages/create-plugin/src/privateKey.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import RSA from "node-rsa"; 4 | 5 | /** 6 | * Create a private key for a kintone plugin 7 | */ 8 | export const generatePrivateKey = () => { 9 | const key = new RSA({ b: 1024 }); 10 | return key.exportKey("pkcs1-private"); 11 | }; 12 | -------------------------------------------------------------------------------- /packages/create-plugin/src/qa/validator.ts: -------------------------------------------------------------------------------- 1 | const NAME_MAX_LENGTH = 64; 2 | const DESCRIPTION_MAX_LENGTH = 200; 3 | 4 | export const validateForName = (value: string) => 5 | value.length > 0 && value.length <= NAME_MAX_LENGTH; 6 | 7 | export const validateForDescription = (value: string) => 8 | value.length > 0 && value.length <= DESCRIPTION_MAX_LENGTH; 9 | 10 | export const validateForOptionalName = (value: string) => 11 | value.length === 0 || value.length <= NAME_MAX_LENGTH; 12 | 13 | export const validateForOptionalDescription = (value: string) => 14 | value.length === 0 || value.length <= DESCRIPTION_MAX_LENGTH; 15 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import kintoneGlobalConfig from "@cybozu/eslint-config/flat/globals/kintone.js"; 2 | import baseConfig from "@cybozu/eslint-config/flat/lib/base.js"; 3 | import kintoneConfig from "@cybozu/eslint-config/flat/lib/kintone.js"; 4 | import prettierConfig from "@cybozu/eslint-config/flat/lib/prettier.js"; 5 | 6 | /** @type {import("eslint").Linter.Config[]} */ 7 | export default [ 8 | ...kintoneGlobalConfig, 9 | ...baseConfig, 10 | ...kintoneConfig, 11 | ...prettierConfig, 12 | { 13 | rules: { 14 | "prettier/prettier": ["error", { singleQuote: true }], 15 | "space-before-function-paren": 0, 16 | "object-curly-spacing": 0, 17 | }, 18 | }, 19 | ]; 20 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kintone-plugin-template-minimum", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "start": "npm run develop", 6 | "develop": "npm run build -- --watch", 7 | "build": "kintone-plugin-packer --ppk private.ppk --out dist/plugin.zip src", 8 | "lint": "eslint src" 9 | }, 10 | "devDependencies": { 11 | "@cybozu/eslint-config": "^24.0.0", 12 | "@kintone/plugin-packer": "^8.1.3", 13 | "eslint": "^9.18.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/scripts/npm-start.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const runAll = require("npm-run-all"); 3 | 4 | runAll(["develop", "upload"], { 5 | parallel: true, 6 | stdout: process.stdout, 7 | stdin: process.stdin 8 | }).catch(({results}) => { 9 | results 10 | .filter(({code}) => code) 11 | .forEach(({name}) => { 12 | console.log(`"npm run ${name}" was failed`); 13 | }) 14 | ; 15 | }); 16 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/css/config.css: -------------------------------------------------------------------------------- 1 | .settings-heading { 2 | padding: 1em 0; 3 | } 4 | 5 | .kintoneplugin-input-text { 6 | width: 20em; 7 | } -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/css/desktop.css: -------------------------------------------------------------------------------- 1 | .plugin-space-heading { 2 | font-size: 1.5rem; 3 | margin: 0.8rem; 4 | } 5 | .plugin-space-message { 6 | display: inline-block; 7 | font-size: 1.2em; 8 | margin: 0.8rem; 9 | margin-top: 0; 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/css/mobile.css: -------------------------------------------------------------------------------- 1 | .plugin-space-heading { 2 | font-size: 1.5rem; 3 | margin: 0.8rem; 4 | } 5 | .plugin-space-message { 6 | display: inline-block; 7 | font-size: 1.2em; 8 | margin: 0.8rem; 9 | margin-top: 0; 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/html/config.html.tmpl: -------------------------------------------------------------------------------- 1 |
2 |

Settings for <%= name.en %>

3 |

This message is displayed on the app page after the app has been updated.

4 |
5 |

6 | 10 |

11 |

12 | 13 | 14 |

15 |
16 |
-------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/image/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kintone/js-sdk/51c7c03a6c2a1fb91af7b7d8cac48d32de757a67/packages/create-plugin/templates/minimum/src/image/icon.png -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/js/config.js: -------------------------------------------------------------------------------- 1 | (function (PLUGIN_ID) { 2 | const formEl = document.querySelector('.js-submit-settings'); 3 | const cancelButtonEl = document.querySelector('.js-cancel-button'); 4 | const messageEl = document.querySelector('.js-text-message'); 5 | if (!(formEl && cancelButtonEl && messageEl)) { 6 | throw new Error('Required elements do not exist.'); 7 | } 8 | 9 | const config = kintone.plugin.app.getConfig(PLUGIN_ID); 10 | if (config.message) { 11 | messageEl.value = config.message; 12 | } 13 | 14 | formEl.addEventListener('submit', (e) => { 15 | e.preventDefault(); 16 | kintone.plugin.app.setConfig({ message: messageEl.value }, () => { 17 | alert('The plug-in settings have been saved. Please update the app!'); 18 | window.location.href = '../../flow?app=' + kintone.app.getId(); 19 | }); 20 | }); 21 | 22 | cancelButtonEl.addEventListener('click', () => { 23 | window.location.href = '../../' + kintone.app.getId() + '/plugin/'; 24 | }); 25 | })(kintone.$PLUGIN_ID); 26 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/js/desktop.js: -------------------------------------------------------------------------------- 1 | (function (PLUGIN_ID) { 2 | kintone.events.on('app.record.index.show', () => { 3 | const spaceEl = kintone.app.getHeaderSpaceElement(); 4 | if (spaceEl === null) { 5 | throw new Error('The header element is unavailable on this page.'); 6 | } 7 | 8 | const fragment = document.createDocumentFragment(); 9 | const headingEl = document.createElement('h3'); 10 | const messageEl = document.createElement('p'); 11 | 12 | const config = kintone.plugin.app.getConfig(PLUGIN_ID); 13 | messageEl.textContent = config.message; 14 | messageEl.classList.add('plugin-space-message'); 15 | headingEl.textContent = 'Hello kintone plugin!'; 16 | headingEl.classList.add('plugin-space-heading'); 17 | 18 | fragment.appendChild(headingEl); 19 | fragment.appendChild(messageEl); 20 | spaceEl.appendChild(fragment); 21 | }); 22 | })(kintone.$PLUGIN_ID); 23 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/src/js/mobile.js: -------------------------------------------------------------------------------- 1 | (function (PLUGIN_ID) { 2 | kintone.events.on('mobile.app.record.index.show', () => { 3 | const spaceEl = kintone.mobile.app.getHeaderSpaceElement(); 4 | if (spaceEl === null) { 5 | throw new Error('The header element is unavailable on this page.'); 6 | } 7 | 8 | const fragment = document.createDocumentFragment(); 9 | const headingEl = document.createElement('h3'); 10 | const messageEl = document.createElement('p'); 11 | 12 | const config = kintone.plugin.app.getConfig(PLUGIN_ID); 13 | messageEl.textContent = config.message; 14 | messageEl.classList.add('plugin-space-message'); 15 | headingEl.textContent = 'Hello kintone plugin!'; 16 | headingEl.classList.add('plugin-space-heading'); 17 | 18 | fragment.appendChild(headingEl); 19 | fragment.appendChild(messageEl); 20 | spaceEl.appendChild(fragment); 21 | }); 22 | })(kintone.$PLUGIN_ID); 23 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/minimum/with-plugin-uploader.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "node scripts/npm-start.js", 4 | "upload": "kintone-plugin-uploader dist/plugin.zip --watch --waiting-dialog-ms 3000" 5 | }, 6 | "devDependencies": { 7 | "@kintone/plugin-uploader": "^9.1.5", 8 | "npm-run-all": "^4.1.5" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | plugin/js/ -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import presetsPrettier from "@cybozu/eslint-config/flat/presets/prettier.js"; 2 | 3 | /** @type {import("eslint").Linter.Config[]} */ 4 | export default [...presetsPrettier]; 5 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kintone-plugin-template-modern", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "start": "npm run develop", 6 | "develop": "npm run build -- --watch", 7 | "build": "cross-env NODE_ENV=development webpack", 8 | "build:prod": "cross-env NODE_ENV=production webpack", 9 | "dts-gen": "kintone-dts-gen", 10 | "lint": "eslint src" 11 | }, 12 | "dependencies": { 13 | "core-js": "^3.40.0", 14 | "@kintone/rest-api-client": "^5.5.2" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.27.4", 18 | "@babel/preset-env": "^7.27.2", 19 | "@babel/preset-react": "^7.27.1", 20 | "@babel/preset-typescript": "^7.27.1", 21 | "@cybozu/eslint-config": "^24.0.0", 22 | "@kintone/dts-gen": "^8.1.2", 23 | "@kintone/webpack-plugin-kintone-plugin": "^8.0.11", 24 | "ajv": "^8.17.1", 25 | "babel-loader": "^9.2.1", 26 | "cross-env": "^7.0.3", 27 | "eslint": "^9.18.0", 28 | "npm-run-all": "^4.1.5", 29 | "prettier": "^3.4.2", 30 | "typescript": "^5.8.2", 31 | "webpack": "^5.98.0", 32 | "webpack-cli": "^5.1.4" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/plugin/css/config.css: -------------------------------------------------------------------------------- 1 | .settings-heading { 2 | padding: 1em 0; 3 | } 4 | 5 | .kintoneplugin-input-text { 6 | width: 20em; 7 | } -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/plugin/css/desktop.css: -------------------------------------------------------------------------------- 1 | .plugin-space-heading { 2 | font-size: 1.5rem; 3 | margin: 0.8rem; 4 | } 5 | .plugin-space-message { 6 | display: inline-block; 7 | font-size: 1.2em; 8 | margin: 0.8rem; 9 | margin-top: 0; 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/plugin/css/mobile.css: -------------------------------------------------------------------------------- 1 | .plugin-space-heading { 2 | font-size: 1.5rem; 3 | margin: 0.8rem; 4 | } 5 | .plugin-space-message { 6 | display: inline-block; 7 | font-size: 1.2em; 8 | margin: 0.8rem; 9 | margin-top: 0; 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/plugin/html/config.html.tmpl: -------------------------------------------------------------------------------- 1 |
2 |

Settings for <%= name.en %>

3 |

This message is displayed on the app page after the app has been updated.

4 |
5 |

6 | 10 |

11 |

12 | 13 | 14 |

15 |
16 |
-------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/plugin/image/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kintone/js-sdk/51c7c03a6c2a1fb91af7b7d8cac48d32de757a67/packages/create-plugin/templates/modern/plugin/image/icon.png -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/scripts/npm-start.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | "use strict"; 3 | 4 | const runAll = require("npm-run-all"); 5 | 6 | runAll(["develop", "upload"], { 7 | parallel: true, 8 | stdout: process.stdout, 9 | stdin: process.stdin, 10 | }).catch(({ results }) => { 11 | results 12 | .filter(({ code }) => code) 13 | .forEach(({ name }) => { 14 | console.log(`"npm run ${name}" was failed`); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/src/js/config.ts: -------------------------------------------------------------------------------- 1 | // You can use the ESModules syntax and @kintone/rest-api-client without additional settings. 2 | // import { KintoneRestAPIClient } from "@kintone/rest-api-client"; 3 | 4 | // @ts-expect-error 5 | const PLUGIN_ID = kintone.$PLUGIN_ID; 6 | 7 | const form = document.querySelector(".js-submit-settings"); 8 | const cancelButton = document.querySelector(".js-cancel-button"); 9 | const messageInput = 10 | document.querySelector(".js-text-message"); 11 | if (!(form && cancelButton && messageInput)) { 12 | throw new Error("Required elements do not exist."); 13 | } 14 | const config = kintone.plugin.app.getConfig(PLUGIN_ID); 15 | 16 | if (config.message) { 17 | messageInput.value = config.message; 18 | } 19 | 20 | form.addEventListener("submit", (e) => { 21 | e.preventDefault(); 22 | kintone.plugin.app.setConfig({ message: messageInput.value }, () => { 23 | alert("The plug-in settings have been saved. Please update the app!"); 24 | window.location.href = "../../flow?app=" + kintone.app.getId(); 25 | }); 26 | }); 27 | cancelButton.addEventListener("click", () => { 28 | window.location.href = "../../" + kintone.app.getId() + "/plugin/"; 29 | }); 30 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/src/js/desktop.ts: -------------------------------------------------------------------------------- 1 | // You can use the ESModules syntax and @kintone/rest-api-client without additional settings. 2 | // import { KintoneRestAPIClient } from "@kintone/rest-api-client"; 3 | 4 | // @ts-expect-error 5 | const PLUGIN_ID = kintone.$PLUGIN_ID; 6 | 7 | kintone.events.on("app.record.index.show", () => { 8 | const config = kintone.plugin.app.getConfig(PLUGIN_ID); 9 | 10 | const spaceElement = kintone.app.getHeaderSpaceElement(); 11 | if (spaceElement === null) { 12 | throw new Error("The header element is unavailable on this page"); 13 | } 14 | const fragment = document.createDocumentFragment(); 15 | const headingEl = document.createElement("h3"); 16 | const messageEl = document.createElement("p"); 17 | 18 | messageEl.classList.add("plugin-space-message"); 19 | messageEl.textContent = config.message; 20 | headingEl.classList.add("plugin-space-heading"); 21 | headingEl.textContent = "Hello kintone plugin!"; 22 | 23 | fragment.appendChild(headingEl); 24 | fragment.appendChild(messageEl); 25 | spaceElement.appendChild(fragment); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/src/js/mobile.ts: -------------------------------------------------------------------------------- 1 | // You can use the ESModules syntax and @kintone/rest-api-client without additional settings. 2 | // import { KintoneRestAPIClient } from "@kintone/rest-api-client"; 3 | 4 | // @ts-expect-error 5 | const PLUGIN_ID = kintone.$PLUGIN_ID; 6 | 7 | kintone.events.on("mobile.app.record.index.show", () => { 8 | const config = kintone.plugin.app.getConfig(PLUGIN_ID); 9 | 10 | const spaceElement = kintone.mobile.app.getHeaderSpaceElement(); 11 | if (spaceElement === null) { 12 | throw new Error("The header element is unavailable on this page"); 13 | } 14 | const fragment = document.createDocumentFragment(); 15 | const headingEl = document.createElement("h3"); 16 | const messageEl = document.createElement("p"); 17 | 18 | messageEl.classList.add("plugin-space-message"); 19 | messageEl.textContent = config.message; 20 | headingEl.classList.add("plugin-space-heading"); 21 | headingEl.textContent = "Hello kintone plugin!"; 22 | 23 | fragment.appendChild(headingEl); 24 | fragment.appendChild(messageEl); 25 | spaceElement.appendChild(fragment); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/webpack.config.template.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | const path = require("path"); 3 | const KintonePlugin = require("@kintone/webpack-plugin-kintone-plugin"); 4 | 5 | const isProduction = process.env.NODE_ENV === "production"; 6 | 7 | module.exports = { 8 | mode: isProduction ? "production" : "development", 9 | devtool: isProduction ? false : "inline-cheap-module-source-map", 10 | entry: '%%placeholder_webpack_entry%%', 11 | output: { 12 | path: path.resolve(__dirname, "plugin", "js"), 13 | filename: "[name].js", 14 | }, 15 | resolve: { 16 | extensions: [".ts", ".tsx", ".js"], 17 | }, 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.[t|j]sx?$/, 22 | loader: "babel-loader", 23 | exclude: /node_modules/, 24 | options: { 25 | presets: [ 26 | [ 27 | "@babel/preset-env", 28 | { 29 | useBuiltIns: "usage", 30 | corejs: 3, 31 | modules: false, 32 | }, 33 | ], 34 | "@babel/preset-typescript", 35 | "@babel/preset-react", 36 | ], 37 | }, 38 | }, 39 | ], 40 | }, 41 | plugins: [ 42 | new KintonePlugin({ 43 | manifestJSONPath: "./plugin/manifest.json", 44 | privateKeyPath: "./private.ppk", 45 | pluginZipPath: "./dist/plugin.zip", 46 | }), 47 | ], 48 | }; 49 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/webpack.entry.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": { 3 | "config": "./src/js/config.ts", 4 | "desktop": "./src/js/desktop.ts" 5 | }, 6 | "mobile": { 7 | "config": "./src/js/config.ts", 8 | "desktop": "./src/js/desktop.ts", 9 | "mobile": "./src/js/mobile.ts" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/create-plugin/templates/modern/with-plugin-uploader.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "prestart": "npm run build", 4 | "start": "node scripts/npm-start.js", 5 | "upload": "kintone-plugin-uploader dist/plugin.zip --watch --waiting-dialog-ms 3000" 6 | }, 7 | "devDependencies": { 8 | "@kintone/plugin-uploader": "^9.1.5" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig-base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./", 6 | "typeRoots": [ 7 | "node_modules/@types", 8 | "../../node_modules/@types", 9 | "types" 10 | ], 11 | }, 12 | "include": ["src/**/*.ts"], 13 | "references": [] 14 | } 15 | -------------------------------------------------------------------------------- /packages/create-plugin/types/global/index.d.ts: -------------------------------------------------------------------------------- 1 | // see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/24419 2 | declare interface Element {} 3 | declare interface Document {} 4 | declare interface NodeListOf {} 5 | 6 | /* eslint-disable no-var,vars-on-top */ 7 | // We cannot use let,const to declare global object:( 8 | // https://stackoverflow.com/a/69230938 9 | declare global { 10 | var testStatuses: { [testPath: string]: "failed" | "passed" | "running" }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/customize-uploader/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /packages/customize-uploader/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | manifest-test.json 4 | -------------------------------------------------------------------------------- /packages/customize-uploader/.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | -------------------------------------------------------------------------------- /packages/customize-uploader/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2018 Cybozu, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /packages/customize-uploader/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ["@babel/preset-env", { targets: { node: "current" } }], 4 | "@babel/preset-typescript", 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /packages/customize-uploader/docs/example_setting.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kintone/js-sdk/51c7c03a6c2a1fb91af7b7d8cac48d32de757a67/packages/customize-uploader/docs/example_setting.PNG -------------------------------------------------------------------------------- /packages/customize-uploader/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import rootConfig from "../../eslint.config.mjs"; 2 | 3 | /** @type {import("eslint").Linter.Config[]} */ 4 | export default [...rootConfig]; 5 | -------------------------------------------------------------------------------- /packages/customize-uploader/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@jest/types').Config.InitialOptions} */ 2 | const config = { 3 | roots: ["/src"], 4 | testRegex: "/__tests__/.*\\.test\\.ts$", 5 | testEnvironment: "node", 6 | }; 7 | module.exports = config; 8 | -------------------------------------------------------------------------------- /packages/customize-uploader/sample/customize-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "2", 3 | "scope": "ALL", 4 | "desktop": { 5 | "js": [ 6 | "https://js.cybozu.com/jquery/3.3.1/jquery.min.js", 7 | "sample/customize.js" 8 | ], 9 | "css": ["sample/51-modern-default.css"] 10 | }, 11 | "mobile": { 12 | "js": ["https://js.cybozu.com/jquery/3.3.1/jquery.min.js"], 13 | "css": ["sample/51-modern-default.css"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/customize-uploader/sample/customize.js: -------------------------------------------------------------------------------- 1 | jQuery.noConflict(); 2 | (function($) { 3 | 'use strict'; 4 | kintone.events.on('app.record.index.show', function(event) { 5 | var $header = $(kintone.app.getHeaderMenuSpaceElement()); 6 | var $button = $('