# Basics

## Creating Stamps

Stampit gives you several ways to create your stamps (aka factory functions).

> ***NOTE!***
>
> Any time you compose - you create a **NEW** stamp. Every function below always returns a **NEW** stamp.

### Pass plain descriptor

You can pass standard [stamp descriptor](/essentials/what-is-a-stamp.md#stamps-metadata-descriptor) to stampit.

```javascript
const descriptor = {
  methods: ...,
  properties: ...,
  deepProperties: ...,
  propertyDescriptors: ...,
  initializers: ...,
  staticProperties: ...,
  staticDeepProperties: ...,
  staticPropertyDescriptors: ...,
  composers: ...,
  configuration: ...,
  deepConfiguration: ...,
  name: ...
}

const MyStamp = stampit(descriptor) // passing the descriptor
```

Or you can pass *stampit-flavoured* descriptor (shorter version of the standard descriptor).

```javascript
const shorterDescriptor = {
  methods: ...,
  props: ...,
  deepProps: ...,
  propertyDescriptors: ...,
  init: ...,
  statics: ...,
  deepStatics: ...,
  staticPropertyDescriptors: ...,
  composers: ...,
  conf: ...,
  deepConf: ...,
  name: ...
}

const MyStamp = stampit(shorterDescriptor)
```

### Shortcut functions

Stampit has 18 shortcut functions attached to it. For example:

```javascript
const { props, methods, init } = stampit
```

You can create stamps from them too.

```javascript
const DefaultFoo = props({ foo: null })
const PrintFoo = methods({ printFoo() { console.log(this.foo) } })
const PassFoo = init(funciton ({ foo }) { this.foo = foo })

const Foo = DefaultFoo.compose(PrintFoo, PassFoo)
```

The full list of the shortcut functions matches the list of keys you can pass as stamp descriptor (see above).

```javascript
const {     // destructuring
  methods,

  props, properties,

  deepProps, deepProperties,

  init, initializers,

  propertyDescriptors,

  statics, staticProperties,

  deepStatics, staticDeepProperties,

  staticPropertyDescriptors,

  conf, configuration,

  deepConf, deepConfiguration,

  composers
} = stampit
```

### Creating same stamp in few ways

All the examples below create *exactly the same stamp*.

#### Classic way

```javascript
const logger = require('bunyan').createLogger({ name: 'log' })

const HasLog = stampit({
  properties: {
    log: logger
  }
})
```

#### Classic way using shorter API

```javascript
const HasLog = stampit({
  props: {
    log: logger
  }
})
```

#### Shortcut way

```javascript
const HasLog = stampit.props({
  log: logger
})

// OR

const { props } = stampit

const HasLog = props({
  log: logger
})
```

#### Composition way

```javascript
const HasLog = stampit().props({
  log: logger
})
```

### Chaining

You can chain all the shortcut functions (see the full list above).

Below is just an example of what you can do. It is a utility stamp. If you compose it to any of your stamps then it will *count the number of object instances* created from your stamp. Feel free to remove unwanted parts.

{% code title="InstanceCounter.js" %}

```javascript
const InstanceCounter = stampit()
.conf({
  instanceCounter: 0 // number of instances of a particular stamp, incremental
})
.props({
  instanceIndex: -1 // an instance number, incremental
})
.methods({
  printInstanceIndex() {
    console.log('I am instance #', this.instanceIndex)
  } 
})
.init(function (_, { stamp }) {
  this.instanceIndex = stamp.compose.configuration.instanceCounter // instance number
  stamp.compose.configuration.instanceCounter += 1 // increment the counter
})
.staticPropertyDescriptors({ // give the Stamp.name a non-default name. ES6 only.
  name: { value: 'InstanceCounter' }
})
.statics({ 
  printTotalInstanceCount() {
    console.log(this.compose.configuration.instanceCounter)
  } 
})
.composers(function ({ stamp }) {
  // We need to reset the counter each time the InstanceCounter is composed with.
  stamp.compose.configuration.instanceCounter = 0
})
```

{% endcode %}

Same `InstanceCounter` stamp but using the classic stampit way.

{% code title="InstanceCounter.js" %}

```javascript
const InstanceCounter = stampit({
  conf: {
    instanceCounter: 0 // number of instances of a particular stamp, incremental
  },
  props: {
    instanceIndex: -1 // an instance number, incremental
  },
  methods: {
    printInstanceIndex() {
      console.log('I am instance #', this.instanceIndex)
    } 
  },
  init(_, { stamp }) {
    this.instanceIndex = stamp.compose.configuration.instanceCounter // instance number
    stamp.compose.configuration.instanceCounter += 1 // increment the counter
  },
  staticPropertyDescriptors: { // give the Stamp.name a non-default name. ES6 only.
    name: { value: 'InstanceCounter' }
  },
  statics: { 
    printTotalInstanceCount() {
      console.log(this.compose.configuration.instanceCounter)
    } 
  },
  composers({ stamp }) {
    // We need to reset the counter each time the InstanceCounter is composed with.
    stamp.compose.configuration.instanceCounter = 0
  }
});
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://stampit.js.org/api/basics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
