npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@miaou/back

v6.3.0

Published

Back utilities for Firebase

Downloads

139

Readme

@miaou/back back utilities for Firebase

This library use : firebase

Install

yarn add --exact @miaou/back

Documentation

Mail

Generate Email using mjml and handlebars

Requirements

  • yarn add --dev --exact copyfiles
  • mjml plugin for intelliJ

How to

Files structure

Files must be in src folder and must be named with the following pattern {template_name}.{mjml|i18n.yml}

    ├── src
    │   ├── user
    │   │   ├── signin.mjml
    │   │   └── signin.i18n.yml

Create your signin.i18n.yml

en:
  subject: Welcome {{email}}!
  subtitle: GETTING STARTED
  title: Let's get you up and running smoothly
fr:
  subject: Bienvenue  {{email}}!
  subtitle: DÉMARRAGE
  title: Laissez-nous vous mettre en route en douceur

Create your signin.mjml

<mjml>
  <mj-head>
    <mj-attributes>
      <mj-all font-family="'Cabin', 'Helvetica', 'Arial', sans-serif"></mj-all>
      <mj-text color="#515151"></mj-text>
    </mj-attributes>
    <mj-font href="https://fonts.googleapis.com/css?family=Cabin:normal,italic,bold&display=swap" name="Cabin"></mj-font>
  </mj-head>
  <mj-body background-color="#f8f8f8">
    <mj-section background-color="#292D4D" padding-bottom="48px" padding-left="48px" padding-right="48px" padding-top="24px" padding="48px">
      <mj-column padding="0">
        <mj-text color="rgba(255,255,255,0.5)" font-size="14px" line-height="1.6" padding="0px">
          {{$t "subtitle"}}
        </mj-text>
        <mj-text color="#ffffff" font-size="38px" line-height="1.375" padding="0px">
          <strong>{{$t "title"}}</strong>
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>
const { html, subject } = await generateMail({
    srcPath: path.join(__dirname, '..'),
    locale,
    templateFileName: template,
    variables,
})

Add script into package.json

Add yarn copyfiles -u 1 src/**/*.mjml src/**/*.i18n.yml lib/ before to build to push your mjml files to your build folder

// package.json
{
  "scripts": {
    "build": "yarn copyfiles -u 1 src/**/*.mjml src/**/*.i18n.yml lib/ && tsc",
    ...
  },
  ...
}

Firestore

Backup for firestore

Requirements

You must set the right for the default app engine service account.

gcloud auth login
gcloud config set project PROJECT_ID
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member serviceAccount:[email protected] \
    --role roles/datastore.importExportAdmin
gsutil iam ch serviceAccount:[email protected]:admin \
    gs://PROJECT_ID.appspot.com

Usage for backup

You could configure your backup as you want. You can set folderName and expiration time with your preferences

// index.ts
import {getStorage} from 'firebase-admin/storage'
import {backup} from '@miaou/back/lib/firestore'
import {Day} from "@miaou/types";

const app = initializeApp()
const storage = getStorage(app)

export const myBackup = backup(
    pubsub.schedule('every 24 hours').timeZone('Europe/Paris'),
    storage.bucket(),
    {folderName: 'backup', expirationIn: 2 as Day, dryRun: process.env.ENVIRONMENT !== 'production'})

Usage for restore

This example is for restore backup when folder name is backup. If you have another folder name you can replace it with yours

gcloud firestore import gs://PROJECT_ID.appspot.com/backup/YYYY-MM-DD

Fireway

You must name your file with the following pattern v{version_number}-{file_name}.migration.ts.

  • v001-orders-validated.migration.ts
  • v002-deleted-commands.migration.ts
  • v003-users.migration.ts
// v001-orders.migration.ts
import {BigBatch} from '@qualdesk/firestore-big-batch'

const database = getFirestore()

export const migrate = async () => {
    const batch = new BigBatch({firestore: database})
    const db = database.collection('order')

    Object.values(inventory).forEach((inventoryProduct) => {
        const ref = db.doc(inventoryProduct.id)
        batch.set(ref, {
            id: inventoryProduct.id,
            productId: inventoryProduct.productId,
            quantity: inventoryProduct.quantity,
        })
    })

    await batch.commit()
}
import {region} from 'firebase-functions'
import {getFirestore} from 'firebase-admin/firestore'
// Do not forget to call your function export * as system from './infra/spi/migration' in your index.ts
export const migrate = migrateFirestore(
    region('europe-west1'),
    getFirestore(), { migrationFolderPath: __dirname })

Best practices

Do not import functions or types from other package/folder (expect firebase packages). Your migration code should be isolated.

Functions

Middleware

const sentryInstance = Sentry.init({
    dsn: 'https://...',
    tracesSampleRate: 1.0,
});
const isProduction = process.env.ENVIRONMENT === 'production'
const isAdmin = (id: UserId) => Promise.resolve(true)

export const publicOnCall = <T extends (...args: any) => any>() =>
    typedOnCallWithMiddlewares<T>([
        sentry(sentryInstance),
        appCheck(isProduction),
        dateSerializer
    ])

export const authenticatedOnCall = <T extends (...args: any) => any>() =>
    typedOnCallWithMiddlewares<T>([
        sentry(sentryInstance),
        appCheck(isProduction),
        authenticated,
        dateSerializer
    ])

export const adminOnCall = <T extends (...args: any) => any>() =>
    typedOnCallWithMiddlewares<T>([
        sentry(sentryInstance),
        appCheck(isProduction),
        admin(isAdmin),
        dateSerializer
    ])
export type LastNewsQuery = (locale: Locale) => Promise<New[]>

export const lastNews = authenticatedOnCall<LastNewsQuery>()((locale) =>
    findAllNews(locale, 3)
)

Testing

import {firestoreTest, testableHttp} from '@miaou/back'
import 'chai/register-should.js'

// my-test.int.test.ts
describe('My test ', () => {
    it('Is order pending', async () => {
        // Given
        const db = firestoreTest()
        const isOrderPending = testableHttp<OrderCommand>('app-is-order-pending', 'tibo')
        await saveOrder(db)<Order>({userId: 'tibo' as UserId})

        // When
        const {data} = await orderCommand('XXXX-XXXX' as OrderId)

        // Then
        data.should.be.false
    })
})

Triggers

Middleware

const sentryInstance = Sentry.init({
    dsn: 'https://...',
    tracesSampleRate: 1.0,
});

export const onWrite = typedOnWriteTriggerWithMiddlewares([
    sentry(sentryInstance),
    dateSerializer,
])

export const onUpdate = typedOnUpdateTriggerWithMiddlewares([
    sentry(sentryInstance),
    dateSerializer,
])

export const onDelete = typedOnDeleteTriggerWithMiddlewares([
    sentry(sentryInstance),
    dateSerializer,
])

export const onCreate = typedOnCreateTriggerWithMiddlewares([
    sentry(sentryInstance),
    dateSerializer,
])
export const onOrderWrite = onWrite<Order>(
    'orders/{oderId}',
    async (orderChange) => {
        const beforeOrder = orderChange.before.data()
        const afterOrder = orderChange.after.data()

        // Delete
        if (!afterOrder && beforeOrder) {
            await deleteOrderView(database)(beforeOrder.id)
            return
        }

        // Create and Update
        if (afterOrder) {
            const order = await getOrder(afterOrder.id)
            const user = await getUser(afterOrder.userId)
            const licence = await getLicence(order.licenceId)
            const transaction = await getTransaction(order.transactionId)
            await saveOrderView(database)({
                ...order,
                user,
                licence,
                transaction,
            })
        }
    }
)


Development

How to use

yarn install

Test

You can use yarn link to debug the module

Release commit semantic

The release is automated by release-semantic plugin. When merge to master:

  • Generate tag version
  • Automate library versioning based on commit history
  • Generate changelog based on commit history
<type>(<scope>): <short summary>
  │       │             │
  │       │             └─⫸ Summary in present tense. Not capitalized. No period at the end.
  │       │
  │       └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|ect.
  │
  └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test
Usage
fix: testing patch releases
feat: testing minor releases
feat: testing major releases

BREAKING CHANGE: This is a breaking change.