Code Monkey home page Code Monkey logo

serverless-cloud-notepad's Introduction

☁ Serverless Cloud Notepad

cloudflare workers example workflow jsdelivr MIT License

English | 简体中文

Build for recording text or sharing between friends.

Powered by Cloudflare Workers、KV & Github Actions, Easy to deploy privately.

✨ Features

  • ✏ No login/register required, start writing right away.
  • 💾 Auto saving.
  • ❌ No backend/server or database required.
  • ⚡ High available & High performance in worldwide.
  • 📦 One-click deployment for your own site.
  • 🌍 i18n support for pathname.

🔨 Usage

  • Enter / root path will generate a new note with random path.

  • Enter /any-custom-name-you-like view/edit custom note.

Try it out! https://note.src.moe/example

Note

According to Cloudflare's free policy, KV has a daily limit of 1,000 write/delete operations. It is highly recommended to deploy your own.

💻 Compatibility

  • Modern browsers (both PC & Mobile)

📦 Deployment

  • Create your Cloudflare API token in here, choose Cloudflare Workers Template to complete create.
  • Fork this repository and add 3 Secret in Settings -> Secrets and variables -> Actions:
CLOUDFLARE_API_TOKEN # your Cloudflare API token

SCN_SALT # whatever you like(for security reason)

SCN_SECRET # whatever you like(for security reason)
  • Go to Actions tab, run Deploy cloud-notepad workflow.
  • After a while, you will see the deployment-url in Annotations.
  • CNAME deployment-url to your domain if you like.(optional)

👀 Roadmap

  • password protection.
  • support URL/Image (Markdown mode).
  • read only mode (share link).
  • show last modify date.

☕ Donate

maybe, buy me a coffee?

Buy Me A Coffee

https://src.moe/donate

serverless-cloud-notepad's People

Contributors

guohanli avatar s0urcelab avatar sunsetmkt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

serverless-cloud-notepad's Issues

请问如何部署?

按文档报错

  pwsh  npm run publish

> [email protected] publish
> wrangler publish

Proxy environment variables detected. We'll use your proxy for fetch requests.

 ⛅️ wrangler 3.60.3
-------------------

▲ [WARNING] `wrangler publish` is deprecated and will be removed in the next major version.

  Please use `wrangler deploy` instead, which accepts exactly the same arguments.


Total Upload: 39.15 KiB / gzip: 11.42 KiB
Your worker has access to the following bindings:
- KV Namespaces:
  - NOTES: 82faa7b7043c4a04b0db7cae1fea637b
  - SHARE: da3d6dc4a5874f5a8229327d9aa9d11d

✘ [ERROR] A request to the Cloudflare API (/accounts/5af061ede7b10b1738bd475c1bc74a97/workers/scripts/cloud-notepad) failed.

  Uncaught ReferenceError: SCN_SALT is not defined
    at null.<anonymous> (file:///E:/gh/serverless-cloud-notepad/src/constant.js:5:21)
    at null.<anonymous> (worker.js:921:3)
   [code: 10021]


  If you think this is a bug, please open an issue at:
  https://github.com/cloudflare/workers-sdk/issues/new/choose

Unexpected fields found in top-level field: "SCN_SALT"

 [WARNING] Processing wrangler.toml configuration:

    - Unexpected fields found in top-level field: "SCN_SALT"


Attempting to login via OAuth...
F:\js\serverless-cloud-notepad\node_modules\wrangler\wrangler-dist\cli.js:16259
            throw ex;
            ^

SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
    at JSON.parse (<anonymous>)
    at Response.json (F:\js\serverless-cloud-notepad\node_modules\wrangler\wrangler-dist\cli.js:72475:21)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async exchangeAuthCodeForAccessToken (F:\js\serverless-cloud-notepad\node_modules\wrangler\wrangler-dist\cli.js:105671:23)
    at async Server.<anonymous> (F:\js\serverless-cloud-notepad\node_modules\wrangler\wrangler-dist\cli.js:105807:30)

Node.js v20.10.0

这是个什么问题,我搞不懂。

加个手动保存的选项

每1s都检查输入时,字还没打完就上传了,使得KV写比较频繁

自己改了一下,添加了保存按钮和自动保存(换成每5s)开关,页面如下
image

但是把这个代码放入https://note.src.moe,网址分享,分享页面会出现页面错误
image

修改的代码如下:

src/constant.js
// supported language
export const SUPPORTED_LANG = {
    'en': {
        //
        save: 'Save',
        autoSave: 'autoSave',
    },
    'zh': {
        //
        save: '保存',
        autoSave: '自动保存',
    }
}

src/template.js
const FOOTER = ({ lang, isEdit, updateAt, pw, mode, share, save, autoSave }) => `
    <div class="footer">
        ${isEdit ? `
            <div class="opt">
                <button class="opt-button opt-pw">${pw ? SUPPORTED_LANG[lang].changePW : SUPPORTED_LANG[lang].setPW}</button>
                <button class="opt-button opt-save">${SUPPORTED_LANG[lang].save}</button>
                ${SWITCHER('Markdown', mode === 'md', 'opt-mode')}
                ${SWITCHER(SUPPORTED_LANG[lang].share, share, 'opt-share')}
                ${SWITCHER(SUPPORTED_LANG[lang].autoSave, autoSave, 'opt-autoSave')}
            </div>
            ` : ''
    }
    </div>
`

static/css/app.css
.opt-button {
    //
    margin-right: 10px;
}

static/js/app.js
window.addEventListener('DOMContentLoaded', function () {
    const $saveBtn = document.querySelector('.opt-save')    //保存按钮
    const $autosaveBtn = document.querySelector('.opt-autoSave > input')        //自动保存选项
//略

    if ($textarea) {
        // 只在自动保存按钮被选中时设置 oninput 事件
        if ($autosaveBtn) { // 自动保存
            const autosaveHandler = throttle(function () {
                renderMarkdown($previewMd, $textarea.value);

                if ($autosaveBtn.checked) { // 检查自动保存开关状态
                    $loading.style.display = 'inline-block';
                    const data = { t: $textarea.value };

                    window.fetch('', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                        body: new URLSearchParams(data),
                    })
                    .then(res => res.json())
                    .then(res => {
                        if (res.err !== 0) { errHandle(res.msg); }
                    })
                    .catch(err => errHandle(err))
                    .finally(() => { $loading.style.display = 'none'; });
                }
            }, 5000); 

            $textarea.oninput = autosaveHandler;
        }
        if($saveBtn){
            $saveBtn.onclick = function(){
                $saveBtn.disabled = true;
                renderMarkdown($previewMd, $textarea.value)
    
                $loading.style.display = 'inline-block'
                const data = {t: $textarea.value,}
    
                window.fetch('', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/x-www-form-urlencoded',},
                    body: new URLSearchParams(data),
                })
                    .then(res => res.json())
                    .then(res => {
                        if (res.err !== 0) {errHandle(res.msg)}
                    })
                    .catch(err => errHandle(err))
                    .finally(() => {$loading.style.display = 'none'})
        
                setTimeout(function() {
                    $saveBtn.disabled = false;
                }, 3000); 
            }
        }
        
    }

preview_id 这个要不要填

大佬,新版的 preview_id这个我删掉有影响吗
kv_namespaces = [
{ binding = "NOTES", id = "b3afc649c15247c9962346b3de4730cc", preview_id = "01083e57f68046079a62015c3ea4a145" },
{ binding = "SHARE", id = "c075feeec9b6414296e6a3df7404e6a8", preview_id = "f89caa54860940709800dc6ed3ff920a" }
]
我填写的是
kv_namespaces = [
{ binding = "NOTES", id = "我的ID" },
{ binding = "SHARE", id = "我的ID2" }
]
preview_id这个没说明我就没有填写了

增加了一个 /list 界面,汇总已创建的笔记

代码比较粗糙,效果属于可用
image
修改 src/index.js文件在11-15行片段之后添加以下代码:

// 处理 /list 路由
router.get('/list', async () => {
    const keys = await NOTES.list() // 获取所有笔记的键

    // 生成表格行,每行显示每个键的所有字段信息
    const rows = keys.keys.map(key => `
      <tr>
        <td><a href="/${key.name}">${key.name}</a></td>
        <td>${key.metadata ? (() => {
            const date = new Date(key.metadata.updateAt * 1000);
            const pad = num => num.toString().padStart(2, '0');
            return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
        })() : 'N/A'}
        </td>
      </tr>
    `).join('<br>')

    // 生成包含表格的HTML
    const html = `
      <!DOCTYPE html>
      <html>
        <head>
          <title>Note List</title>
          <style>
            body { font-family: Arial, sans-serif; padding: 20px; }
            table { width: 100%; border-collapse: collapse; }
            th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
            th { background-color: #f4f4f4; }
          </style>
        </head>
        <body>
          <h1>Note List</h1>
          <table>
            <thead>
              <tr>
                <th>Note Link</th>
                <th>Modify Time</th>
              </tr>
            </thead>
            <tbody>
              ${rows}
            </tbody>
          </table>
        </body>
      </html>`

    return new Response(html, {
        headers: { 'Content-Type': 'text/html' },
    })
})

然后wrangler publish即可重新部署

有没有类似管理员权限的方式管理密码

项目使用感觉很好,但是请问如果有人恶意设置密码或者修改密码怎么解决,如果重新部署数据都消失了.
我的想法是增加一个pwd的环境变量,使用这个pwd作为root密码,无论什么密码 认证时输入pwd就直接通过

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.